mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-03 04:23:39 +00:00
根据LL重构文件结构
This commit is contained in:
parent
125df0725f
commit
690132ce0f
@ -1,34 +1,34 @@
|
|||||||
# Documents: https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
# Documents: https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
# BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: false
|
AlignConsecutiveAssignments: None
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveDeclarations: None
|
||||||
AlignEscapedNewlinesLeft: true
|
|
||||||
AlignOperands: Align
|
AlignOperands: Align
|
||||||
AlwaysBreakTemplateDeclarations : true
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
AllowAllArgumentsOnNextLine: true
|
AllowAllArgumentsOnNextLine: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
AllowShortBlocksOnASingleLine : true
|
AllowShortBlocksOnASingleLine: Always
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: Inline
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
AllowShortLoopsOnASingleLine: false
|
AllowShortLoopsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: false
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
AllowShortLambdasOnASingleLine: true
|
AllowShortLambdasOnASingleLine: All
|
||||||
AllowShortEnumsOnASingleLine: false
|
AllowShortEnumsOnASingleLine: false
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
BinPackArguments: true
|
BinPackArguments: true
|
||||||
BinPackParameters: true
|
BinPackParameters: true
|
||||||
ConstructorInitializerIndentWidth: 0
|
ConstructorInitializerIndentWidth: 0
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
ColumnLimit: 0
|
BreakBeforeConceptDeclarations: Always
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
|
ColumnLimit: 120
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
SortIncludes: false
|
SortIncludes: Never
|
||||||
MaxEmptyLinesToKeep: 2
|
MaxEmptyLinesToKeep: 2
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
@ -36,20 +36,18 @@ SpaceBeforeAssignmentOperators: true
|
|||||||
SpacesInContainerLiterals: true
|
SpacesInContainerLiterals: true
|
||||||
IndentWrappedFunctionNames: true
|
IndentWrappedFunctionNames: true
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
SeparateDefinitionBlocks: Always
|
||||||
BreakConstructorInitializersBeforeComma: true
|
BreakConstructorInitializersBeforeComma: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
|
||||||
BreakBeforeBraces: Custom
|
BreakBeforeBraces: Custom
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
# case 语句后面
|
# case 语句后面
|
||||||
AfterCaseLabel: false
|
AfterCaseLabel: false
|
||||||
# class定义后面
|
# class定义后面
|
||||||
AfterClass: false
|
AfterClass: false
|
||||||
# 控制语句后面
|
|
||||||
AfterControlStatement: false
|
|
||||||
# enum定义后面
|
# enum定义后面
|
||||||
AfterEnum: false
|
AfterEnum: false
|
||||||
# 函数定义后面
|
# 函数定义后面
|
||||||
|
4
.clangd
Normal file
4
.clangd
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Diagnostics:
|
||||||
|
Suppress: ["-Wmicrosoft-enum-forward-reference", "-Wc++11-narrowing"]
|
||||||
|
CompileFlags:
|
||||||
|
Add: ["-ferror-limit=0", "-D__FUNCTION__=\"dummy\"", "-D_CRT_USE_BUILTIN_OFFSETOF"]
|
194
.github/workflows/build.yml
vendored
Normal file
194
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
# runs-on: self-hosted
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3.2.0
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Cache BDS libraries
|
||||||
|
id: cache-bds-lib
|
||||||
|
uses: actions/cache@v3
|
||||||
|
env:
|
||||||
|
cache-name: cache-bds-lib
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
${{ env.GITHUB_WORKSPACE }}LiteLoader/Lib/bedrock_server_api.lib
|
||||||
|
${{ env.GITHUB_WORKSPACE }}LiteLoader/Lib/bedrock_server_var.lib
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('scripts/LINK.txt') }}
|
||||||
|
|
||||||
|
- name: Download BDS if not cached
|
||||||
|
if: steps.cache-bds-lib.outputs.cache-hit != 'true'
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
mkdir Tools/Server
|
||||||
|
ServerLink=$(cat 'scripts/LINK.txt')
|
||||||
|
curl -L -o Tools/Server/server.zip "$ServerLink"
|
||||||
|
unzip Tools/Server/server.zip -d Tools/Server/ > /dev/null
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Build libraries if not cached
|
||||||
|
if: steps.cache-bds-lib.outputs.cache-hit != 'true'
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
cd Tools
|
||||||
|
LibraryBuilder.exe Server
|
||||||
|
mkdir ..\LiteLoader\lib
|
||||||
|
move bedrock_server_api.lib ..\LiteLoader\lib
|
||||||
|
move bedrock_server_var.lib ..\LiteLoader\lib
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Get short SHA
|
||||||
|
id: sha_short
|
||||||
|
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set LITELOADER_VERSION_COMMIT_SHA
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
sed -r -i 's/#define\s+LITELOADER_VERSION_COMMIT_SHA\s+.*/#define LITELOADER_VERSION_COMMIT_SHA ${{ steps.sha_short.outputs.sha_short }}\r/' LiteLoader/include/liteloader/Version.h
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Configure CMake (MSVC)
|
||||||
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Build all
|
||||||
|
run: |
|
||||||
|
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Pack output
|
||||||
|
run: |
|
||||||
|
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target PackOutput
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Pack SDK on push event
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
run: |
|
||||||
|
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target PackSDK
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Configure CMake (ClangCL)
|
||||||
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build_clang -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T clangcl
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Build SymDBHelper
|
||||||
|
run: cmake --build ${{github.workspace}}/build_clang --config ${{env.BUILD_TYPE}} --target SymDBHelper
|
||||||
|
|
||||||
|
- name: Compress resource packs for LiteLoaderBDS CUI on push event
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
run: |
|
||||||
|
cd build/output/plugins/LiteLoader/ResourcePacks
|
||||||
|
7z a LiteLoaderBDS-CUI.tar LiteLoaderBDS-CUI
|
||||||
|
rm -r LiteLoaderBDS-CUI
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Update C++ SDK on push event
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
cd scripts
|
||||||
|
./UploadSDK.cmd action
|
||||||
|
env:
|
||||||
|
REPO_KEY: ${{secrets.PUSH_TOKEN}}
|
||||||
|
USERNAME: github-actions[bot]
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
# - name: Download LLMoney
|
||||||
|
# working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
# run: |
|
||||||
|
# git clone https://github.com/Tooth-Hub/LLMoney.git LLMoney-bin
|
||||||
|
# cp LLMoney-bin/LLMoney.dll build/output/plugins/
|
||||||
|
# shell: bash
|
||||||
|
|
||||||
|
- name: Upload LiteLoaderBDS
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LiteLoaderBDS
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\LLPeEditor.exe
|
||||||
|
${{ github.workspace }}\build\output\LLPreLoader.dll
|
||||||
|
${{ github.workspace }}\build\output\LiteLoader.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LangPack\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\CrashLogger_Daemon.exe
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Js.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Lua.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.NodeJs.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\7z\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ParticleAPI.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ResourcePacks\LiteLoaderBDS-CUI.tar
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\PermissionAPI.dll
|
||||||
|
# ${{ github.workspace }}\build\output\plugins\LLMoney.dll
|
||||||
|
|
||||||
|
- name: Upload PeEditor
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: PeEditor
|
||||||
|
path: ${{ github.workspace }}\build\output\LLPeEditor.exe
|
||||||
|
|
||||||
|
- name: Upload PreLoader
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: PreLoader
|
||||||
|
path: ${{ github.workspace }}\build\output\LLPreLoader.dll
|
||||||
|
|
||||||
|
- name: Upload LiteLoader
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LiteLoader
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\LiteLoader.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\*.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LangPack\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\7z\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\CrashLogger_Daemon.exe
|
||||||
|
|
||||||
|
- name: Upload ScriptEngine
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: ScriptEngine
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Js.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Lua.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.NodeJs.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\node_modules.tar
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\package.json
|
||||||
|
|
||||||
|
- name: Upload LLParticle
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LLParticle
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ParticleAPI.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ResourcePacks\LiteLoaderBDS-CUI.tar
|
||||||
|
|
||||||
|
- name: Upload LLPermission
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LLPermission
|
||||||
|
path: ${{ github.workspace }}\build\output\plugins\LiteLoader\PermissionAPI.dll
|
||||||
|
|
||||||
|
- name: Upload PDB files
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: PDB
|
||||||
|
path: ${{ github.workspace }}\build\pdb\
|
143
.github/workflows/cmake.yml
vendored
143
.github/workflows/cmake.yml
vendored
@ -1,143 +0,0 @@
|
|||||||
name: CMake
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '**.cpp'
|
|
||||||
- '**.cc'
|
|
||||||
- '**.cxx'
|
|
||||||
- '**.c'
|
|
||||||
- '**.hpp'
|
|
||||||
- '**.hh'
|
|
||||||
- '**.hxx'
|
|
||||||
- '**.h'
|
|
||||||
- '.github/workflows/cmake.yml'
|
|
||||||
- '**/CMakeLists.txt'
|
|
||||||
|
|
||||||
env:
|
|
||||||
BUILD_TYPE: Release
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: windows-2022
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3.0.2
|
|
||||||
with:
|
|
||||||
fetch-depth: 1
|
|
||||||
#submodules: 'true'
|
|
||||||
|
|
||||||
- name: Cache Bedrock Dedicated Server Library
|
|
||||||
id: cache-bds-lib
|
|
||||||
uses: actions/cache@v3
|
|
||||||
env:
|
|
||||||
cache-name: cache-bds-lib
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{ env.GITHUB_WORKSPACE }}LiteLoader/Lib/bedrock_server_api.lib
|
|
||||||
${{ env.GITHUB_WORKSPACE }}LiteLoader/Lib/bedrock_server_var.lib
|
|
||||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('Scripts/LINK.txt') }}
|
|
||||||
|
|
||||||
- name: Download Server
|
|
||||||
if: steps.cache-bds-lib.outputs.cache-hit != 'true'
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
run: |
|
|
||||||
mkdir Tools/Server
|
|
||||||
ServerLink=$(cat 'Scripts/LINK.txt')
|
|
||||||
curl -L -o Tools/Server/server.zip "$ServerLink"
|
|
||||||
unzip Tools/Server/server.zip -d Tools/Server/ > /dev/null
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Build Library
|
|
||||||
if: steps.cache-bds-lib.outputs.cache-hit != 'true'
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
run: |
|
|
||||||
cd Tools
|
|
||||||
LibraryBuilder.exe Server
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Change LITELOADER_VERSION_STATUS_BETA
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
if: false == startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: |
|
|
||||||
sed -r -i 's/#define\s+LITELOADER_VERSION_STATUS\s+LITELOADER_VERSION_\w+/#define LITELOADER_VERSION_STATUS LITELOADER_VERSION_BETA/' LiteLoader/Main/Version.h
|
|
||||||
sed -r -i 's/#define\s+LITELOADER_VERSION_ACTIONS\s+.*/#define LITELOADER_VERSION_ACTIONS ${{ github.run_number }}\r/' LiteLoader/Main/Version.h
|
|
||||||
cat LiteLoader/Main/Version.h
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Change LITELOADER_VERSION_STATUS_RELEASE
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: |
|
|
||||||
sed -r -i 's/#define\s+LITELOADER_VERSION_STATUS\s+LITELOADER_VERSION_\w+/#define LITELOADER_VERSION_STATUS LITELOADER_VERSION_RELEASE/' LiteLoader/Main/Version.h
|
|
||||||
sed -r -i 's/#define\s+LITELOADER_VERSION_ACTIONS\s+.*/#define LITELOADER_VERSION_ACTIONS ${{ github.run_number }}\r/' LiteLoader/Main/Version.h
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Get MSVC Path
|
|
||||||
working-directory: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\
|
|
||||||
run: echo "MSVC_VER=$(ls | tail -n 1)" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Configure CMake(MSVC)
|
|
||||||
run: |
|
|
||||||
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Configure CMake(ClangCL)
|
|
||||||
run: |
|
|
||||||
cmake -B ${{github.workspace}}/build_clang -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T clangcl
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Build SymDBHelper
|
|
||||||
run: cmake --build ${{github.workspace}}/build_clang --config ${{env.BUILD_TYPE}} --target SymDBHelper
|
|
||||||
|
|
||||||
- name: Pack Release
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
run: |
|
|
||||||
cd Scripts
|
|
||||||
./PackRelease.cmd action
|
|
||||||
shell: cmd
|
|
||||||
|
|
||||||
- name: Move PDB to path
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
run: |
|
|
||||||
mkdir PDB
|
|
||||||
cp x64/Release/*.pdb PDB
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Upload LiteLoader
|
|
||||||
uses: actions/upload-artifact@v3.1.0
|
|
||||||
with:
|
|
||||||
name: LiteLoader
|
|
||||||
path: ${{ github.workspace }}\RELEASE\
|
|
||||||
|
|
||||||
- name: Upload PDB
|
|
||||||
uses: actions/upload-artifact@v3.1.0
|
|
||||||
with:
|
|
||||||
name: PDB
|
|
||||||
path: ${{ github.workspace }}\PDB
|
|
||||||
|
|
||||||
- name: Prepare for creating Release
|
|
||||||
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
|
||||||
id: rel
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
run: |
|
|
||||||
echo ::set-output name=tag::${GITHUB_REF#refs/*/}
|
|
||||||
mv LiteLoader.zip LiteLoader-${GITHUB_REF#refs/*/}.zip
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Create New Release
|
|
||||||
uses: softprops/action-gh-release@v0.1.14
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
body_path: ${{ github.workspace }}\CHANGELOG.md
|
|
||||||
files: |
|
|
||||||
${{ github.workspace }}\LiteLoader-${{ steps.rel.outputs.tag }}.zip
|
|
||||||
${{ github.workspace }}\PDB.zip
|
|
||||||
env:
|
|
||||||
GITHUB_REPOSITORY: quizhizhe/LiteLoaderBDS-1.16.40
|
|
267
.github/workflows/publish_release.yml
vendored
Normal file
267
.github/workflows/publish_release.yml
vendored
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
required: true
|
||||||
|
description: 'Release Tag'
|
||||||
|
status:
|
||||||
|
required: true
|
||||||
|
description: 'Release Status (beta, stable)'
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3.2.0
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
submodules: 'true'
|
||||||
|
|
||||||
|
- name: Create tag
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git tag | xargs git tag -d
|
||||||
|
git tag ${{ github.event.inputs.tag }}
|
||||||
|
git push origin ${{ github.event.inputs.tag }}
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Cache BDS libraries
|
||||||
|
id: cache-bds-lib
|
||||||
|
uses: actions/cache@v3
|
||||||
|
env:
|
||||||
|
cache-name: cache-bds-lib
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
${{ env.GITHUB_WORKSPACE }}LiteLoader/Lib/bedrock_server_api.lib
|
||||||
|
${{ env.GITHUB_WORKSPACE }}LiteLoader/Lib/bedrock_server_var.lib
|
||||||
|
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('scripts/LINK.txt') }}
|
||||||
|
|
||||||
|
- name: Download BDS if not cached
|
||||||
|
if: steps.cache-bds-lib.outputs.cache-hit != 'true'
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
mkdir Tools/Server
|
||||||
|
ServerLink=$(cat 'scripts/LINK.txt')
|
||||||
|
curl -L -o Tools/Server/server.zip "$ServerLink"
|
||||||
|
unzip Tools/Server/server.zip -d Tools/Server/ > /dev/null
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Build libraries if not cached
|
||||||
|
if: steps.cache-bds-lib.outputs.cache-hit != 'true'
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
cd Tools
|
||||||
|
LibraryBuilder.exe Server
|
||||||
|
mkdir ..\LiteLoader\lib
|
||||||
|
move bedrock_server_api.lib ..\LiteLoader\lib
|
||||||
|
move bedrock_server_var.lib ..\LiteLoader\lib
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Get short SHA
|
||||||
|
id: sha_short
|
||||||
|
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set LITELOADER_VERSION_COMMIT_SHA
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
sed -r -i 's/#define\s+LITELOADER_VERSION_COMMIT_SHA\s+.*/#define LITELOADER_VERSION_COMMIT_SHA ${{ steps.sha_short.outputs.sha_short }}\r/' LiteLoader/include/liteloader/Version.h
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Set LITELOADER_VERSION_STATUS_BETA
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
if: github.event.inputs.status == 'beta'
|
||||||
|
run: |
|
||||||
|
sed -r -i 's/#define\s+LITELOADER_VERSION_STATUS\s+LITELOADER_VERSION_\w+/#define LITELOADER_VERSION_STATUS LITELOADER_VERSION_BETA/' LiteLoader/include/liteloader/Version.h
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Set LITELOADER_VERSION_STATUS_RELEASE
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
if: github.event.inputs.status == 'stable'
|
||||||
|
run: |
|
||||||
|
sed -r -i 's/#define\s+LITELOADER_VERSION_STATUS\s+LITELOADER_VERSION_\w+/#define LITELOADER_VERSION_STATUS LITELOADER_VERSION_RELEASE/' LiteLoader/include/liteloader/Version.h
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Configure CMake (MSVC)
|
||||||
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Build all
|
||||||
|
run: |
|
||||||
|
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Pack output
|
||||||
|
run: |
|
||||||
|
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target PackOutput
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Pack SDK
|
||||||
|
run: |
|
||||||
|
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target PackSDK
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Configure CMake (ClangCL)
|
||||||
|
run: |
|
||||||
|
cmake -B ${{github.workspace}}/build_clang -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T clangcl
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Build SymDBHelper
|
||||||
|
run: cmake --build ${{github.workspace}}/build_clang --config ${{env.BUILD_TYPE}} --target SymDBHelper
|
||||||
|
|
||||||
|
- name: Compress resource packs for LiteLoaderBDS
|
||||||
|
run: |
|
||||||
|
cd build/output/plugins/LiteLoader/ResourcePacks
|
||||||
|
7z a LiteLoaderBDS-CUI.tar LiteLoaderBDS-CUI
|
||||||
|
rm -r LiteLoaderBDS-CUI
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Update C++ SDK
|
||||||
|
working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
run: |
|
||||||
|
git config --global user.name "github-actions[bot]"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
cd scripts
|
||||||
|
./UploadSDK.cmd action release
|
||||||
|
env:
|
||||||
|
REPO_KEY: ${{secrets.PUSH_TOKEN}}
|
||||||
|
USERNAME: github-actions[bot]
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
# - name: Download LLMoney
|
||||||
|
# working-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||||
|
# run: |
|
||||||
|
# git clone https://github.com/Tooth-Hub/LLMoney.git LLMoney-bin
|
||||||
|
# cp LLMoney-bin/LLMoney.dll build/output/plugins/
|
||||||
|
# shell: bash
|
||||||
|
|
||||||
|
- name: Upload LiteLoaderBDS
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LiteLoaderBDS
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\LLPeEditor.exe
|
||||||
|
${{ github.workspace }}\build\output\LLPreLoader.dll
|
||||||
|
${{ github.workspace }}\build\output\LiteLoader.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LangPack\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\CrashLogger_Daemon.exe
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Js.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Lua.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.NodeJs.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\7z\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ParticleAPI.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ResourcePacks\LiteLoaderBDS-CUI.tar
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\PermissionAPI.dll
|
||||||
|
# ${{ github.workspace }}\build\output\plugins\LLMoney.dll
|
||||||
|
|
||||||
|
- name: Upload PeEditor
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: PeEditor
|
||||||
|
path: ${{ github.workspace }}\build\output\LLPeEditor.exe
|
||||||
|
|
||||||
|
- name: Upload PreLoader
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: PreLoader
|
||||||
|
path: ${{ github.workspace }}\build\output\LLPreLoader.dll
|
||||||
|
|
||||||
|
- name: Upload LiteLoader
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LiteLoader
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\LiteLoader.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\*.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LangPack\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\7z\
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\CrashLogger_Daemon.exe
|
||||||
|
|
||||||
|
- name: Upload ScriptEngine
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: ScriptEngine
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Js.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.Lua.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\LiteLoader.NodeJs.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\node_modules.tar
|
||||||
|
${{ github.workspace }}\build\output\plugins\lib\package.json
|
||||||
|
|
||||||
|
- name: Upload LLParticle
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LLParticle
|
||||||
|
path: |
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ParticleAPI.dll
|
||||||
|
${{ github.workspace }}\build\output\plugins\LiteLoader\ResourcePacks\LiteLoaderBDS-CUI.tar
|
||||||
|
|
||||||
|
- name: Upload LLPermission
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: LLPermission
|
||||||
|
path: ${{ github.workspace }}\build\output\plugins\LiteLoader\PermissionAPI.dll
|
||||||
|
|
||||||
|
- name: Upload PDB files
|
||||||
|
uses: actions/upload-artifact@v3.1.0
|
||||||
|
with:
|
||||||
|
name: PDB
|
||||||
|
path: ${{ github.workspace }}\build\pdb\
|
||||||
|
|
||||||
|
publish_release:
|
||||||
|
name: Publish release
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
path: build/
|
||||||
|
|
||||||
|
- name: Pack artifacts
|
||||||
|
run: |
|
||||||
|
cd build/
|
||||||
|
zip -9r LiteLoaderBDS.zip LiteLoaderBDS/*
|
||||||
|
zip -9r PDB.zip PDB/*
|
||||||
|
zip -9r Modules.zip PeEditor PreLoader LiteLoader ScriptEngine LLParticle LLPermission
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
if: github.event.inputs.status == 'stable'
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
prerelease: false
|
||||||
|
tag: ${{ github.event.inputs.tag }}
|
||||||
|
bodyFile: RELEASE_NOTES.md
|
||||||
|
artifacts: |
|
||||||
|
build/LiteLoaderBDS.zip
|
||||||
|
build/Modules.zip
|
||||||
|
build/PDB.zip
|
||||||
|
env:
|
||||||
|
GITHUB_REPOSITORY: quizhizhe/LiteLoaderBDS-1.16.40
|
||||||
|
|
||||||
|
- name: Create pre-release
|
||||||
|
if: github.event.inputs.status != 'stable'
|
||||||
|
uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
prerelease: true
|
||||||
|
tag: ${{ github.event.inputs.tag }}
|
||||||
|
bodyFile: RELEASE_NOTES.md
|
||||||
|
artifacts: |
|
||||||
|
build/Modules.zip
|
||||||
|
build/PDB.zip
|
||||||
|
env:
|
||||||
|
GITHUB_REPOSITORY: quizhizhe/LiteLoaderBDS-1.16.40
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -7,7 +7,7 @@
|
|||||||
**/bedrock_server_api.lib
|
**/bedrock_server_api.lib
|
||||||
**/bedrock_server_var.lib
|
**/bedrock_server_var.lib
|
||||||
**/SymDB_DelayLoadHelper.lib
|
**/SymDB_DelayLoadHelper.lib
|
||||||
LiteLoader/Lib/SymDBHelper.lib
|
LiteLoader/lib/SymDBHelper.lib
|
||||||
**/*.lastcodeanalysissucceeded
|
**/*.lastcodeanalysissucceeded
|
||||||
*.zip
|
*.zip
|
||||||
|
|
||||||
@ -27,8 +27,8 @@ RELEASE/plugins/LiteLoader/pdb
|
|||||||
|
|
||||||
cmake-build-release/
|
cmake-build-release/
|
||||||
/out
|
/out
|
||||||
LiteLoader/Lib/Demangler.pdb
|
LiteLoader/lib/Demangler.pdb
|
||||||
LiteLoader/Lib/Demangler.lib
|
LiteLoader/lib/Demangler.lib
|
||||||
|
|
||||||
/build
|
/build
|
||||||
**/Directory.build.props
|
**/Directory.build.props
|
||||||
|
10
.gitmodules
vendored
10
.gitmodules
vendored
@ -1,3 +1,9 @@
|
|||||||
[submodule "RELEASE/plugins/LiteLoader/ResourcePacks/LiteLoaderBDS-CUI"]
|
[submodule "assets/plugins/LiteLoader/ResourcePacks/LiteLoaderBDS-CUI"]
|
||||||
path = RELEASE/plugins/LiteLoader/ResourcePacks/LiteLoaderBDS-CUI
|
path = assets/plugins/LiteLoader/ResourcePacks/LiteLoaderBDS-CUI
|
||||||
url = https://github.com/OEOTYAN/LiteLoaderBDS-CUI.git
|
url = https://github.com/OEOTYAN/LiteLoaderBDS-CUI.git
|
||||||
|
[submodule "ParticleAPI-1.16.40"]
|
||||||
|
path = ParticleAPI-1.16.40
|
||||||
|
url = https://github.com/quizhizhe/ParticleAPI-1.16.40
|
||||||
|
[submodule "PermissionAPI-1.16.40"]
|
||||||
|
path = PermissionAPI-1.16.40
|
||||||
|
url = https://github.com/quizhizhe/PermissionAPI-1.16.40
|
||||||
|
8
CMake/CleanOutput.cmake
Normal file
8
CMake/CleanOutput.cmake
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
add_custom_target(
|
||||||
|
CleanOutput
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/output
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/pdb
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/sdk
|
||||||
|
COMMENT "Cleaning output/pdb/sdk directory"
|
||||||
|
VERBATIM
|
||||||
|
)
|
29
CMake/PackOutput.cmake
Normal file
29
CMake/PackOutput.cmake
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/pdb)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/output)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/output/plugins/LiteLoader/)
|
||||||
|
|
||||||
|
add_custom_target(PackOutput)
|
||||||
|
|
||||||
|
# Copy assets to output after build all.
|
||||||
|
add_custom_command(
|
||||||
|
TARGET PackOutput POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets/plugins ${CMAKE_BINARY_DIR}/output/plugins/
|
||||||
|
COMMENT "Copying assets to output"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy ScriptEngine BaseLib to output after build all.
|
||||||
|
add_custom_command(
|
||||||
|
TARGET PackOutput POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/ScriptEngine/assets ${CMAKE_BINARY_DIR}/output/plugins/lib/
|
||||||
|
COMMENT "Copying ScriptEngine BaseLib to output"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy LLPeEditor to output after build all.
|
||||||
|
add_custom_command(
|
||||||
|
TARGET PackOutput POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Tools/LLPeEditor.exe ${CMAKE_BINARY_DIR}/output/
|
||||||
|
COMMENT "Copying LLPeEditor to output"
|
||||||
|
VERBATIM
|
||||||
|
)
|
20
CMake/PackSDK.cmake
Normal file
20
CMake/PackSDK.cmake
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/sdk)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/sdk/include)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/sdk/include/llapi)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/sdk/tools)
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/sdk/lib)
|
||||||
|
|
||||||
|
add_custom_target(PackSDK)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET PackSDK POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LiteLoader_SOURCE_DIR}/include/llapi ${CMAKE_BINARY_DIR}/sdk/include/llapi
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LiteLoader_SOURCE_DIR}/third-party/include ${CMAKE_BINARY_DIR}/sdk/include
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Tools/LibraryBuilder.exe ${CMAKE_BINARY_DIR}/sdk/tools/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Tools/LLPeEditor.exe ${CMAKE_BINARY_DIR}/sdk/tools/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Tools/SDK-submodule-add.cmd ${CMAKE_BINARY_DIR}/sdk/tools/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Tools/SDK-submodule-update.cmd ${CMAKE_BINARY_DIR}/sdk/tools/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/Tools/SDK-subtree.cmd ${CMAKE_BINARY_DIR}/sdk/tools/
|
||||||
|
COMMENT "Copying SDK files"
|
||||||
|
VERBATIM
|
||||||
|
)
|
@ -1,14 +1,25 @@
|
|||||||
cmake_minimum_required(VERSION 3.21)
|
cmake_minimum_required(VERSION 3.21)
|
||||||
project(LL-Parent)
|
project(LiteLoaderBDS)
|
||||||
|
|
||||||
|
set(LiteLoader_SOURCE_DIR ${CMAKE_SOURCE_DIR}/LiteLoader)
|
||||||
|
set(Demangler_SOURCE_DIR ${CMAKE_SOURCE_DIR}/Tools/Demangler)
|
||||||
|
set(SCRIPTENGINE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/ScriptEngine)
|
||||||
|
set(SCRIPTX_SOURCE_DIR ${CMAKE_SOURCE_DIR}/ScriptX)
|
||||||
|
|
||||||
# Add sub directories
|
# Add sub directories
|
||||||
add_subdirectory(PreLoader)
|
add_subdirectory(LLPreLoader)
|
||||||
add_subdirectory(LiteLoader)
|
add_subdirectory(LiteLoader)
|
||||||
add_subdirectory(ScriptEngine/CMake/ScriptEngine-Lua)
|
add_subdirectory(ScriptEngine/CMake/ScriptEngine-Lua)
|
||||||
add_subdirectory(ScriptEngine/CMake/ScriptEngine-QuickJs)
|
add_subdirectory(ScriptEngine/CMake/ScriptEngine-QuickJs)
|
||||||
add_subdirectory(ScriptEngine/CMake/ScriptEngine-NodeJs)
|
add_subdirectory(ScriptEngine/CMake/ScriptEngine-NodeJs)
|
||||||
add_subdirectory(Tools/Demangler)
|
add_subdirectory(Tools/Demangler)
|
||||||
add_subdirectory(ScriptEngine/third-party/ScriptX/CMake/ScriptX-Lua)
|
add_subdirectory(Tools/ScriptX/CMake/ScriptX-Lua)
|
||||||
add_subdirectory(ScriptEngine/third-party/ScriptX/CMake/ScriptX-QuickJs)
|
add_subdirectory(Tools/ScriptX/CMake/ScriptX-QuickJs)
|
||||||
add_subdirectory(ScriptEngine/third-party/ScriptX/CMake/ScriptX-NodeJs)
|
add_subdirectory(Tools/ScriptX/CMake/ScriptX-NodeJs)
|
||||||
add_subdirectory(Tools/SymDBHelper)
|
add_subdirectory(Tools/SymDBHelper)
|
||||||
|
add_subdirectory(ParticleAPI-1.16.40)
|
||||||
|
add_subdirectory(PermissionAPI-1.16.40/PermissionAPI)
|
||||||
|
|
||||||
|
include(${CMAKE_SOURCE_DIR}/CMake/PackOutput.cmake)
|
||||||
|
include(${CMAKE_SOURCE_DIR}/CMake/PackSDK.cmake)
|
||||||
|
include(${CMAKE_SOURCE_DIR}/CMake/CleanOutput.cmake)
|
45
LLPreLoader/CMakeLists.txt
Normal file
45
LLPreLoader/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
project(LLPreLoader)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
|
||||||
|
add_definitions(-D"NDEBUG" -D"_WINDOWS" -D"_USRDLL" -D"_WINDLL" -D"_UNICODE" -D"UNICODE")
|
||||||
|
|
||||||
|
add_compile_options(
|
||||||
|
/permissive- /GS /GL /W0 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Zc:inline /fp:precise
|
||||||
|
/errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /FC /EHsc /nologo /diagnostics:column
|
||||||
|
)
|
||||||
|
|
||||||
|
add_link_options(
|
||||||
|
/MANIFEST /LTCG:incremental /NXCOMPAT /DEBUG /DLL /MACHINE:X64 /OPT:REF /INCREMENTAL:NO
|
||||||
|
/SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
|
||||||
|
)
|
||||||
|
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/third-party/rawpdb DIR_LIB_SRCS)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/src PROJECT_SRCS)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/include PROJECT_INCLUDES)
|
||||||
|
|
||||||
|
add_library(LLPreLoader SHARED ${PROJECT_INCLUDES} ${PROJECT_SRCS} ${DIR_LIB_SRCS})
|
||||||
|
target_link_libraries(
|
||||||
|
LLPreLoader SymDBHelper Demangler
|
||||||
|
"${LiteLoader_SOURCE_DIR}/third-party/lib/detours/detours.lib"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
LLPreLoader
|
||||||
|
PRIVATE ${LiteLoader_SOURCE_DIR}/include
|
||||||
|
PRIVATE ${LiteLoader_SOURCE_DIR}/third-party/include
|
||||||
|
PRIVATE ${PROJECT_SOURCE_DIR}/include
|
||||||
|
PRIVATE ${PROJECT_SOURCE_DIR}/third-party
|
||||||
|
PRIVATE ${Demangler_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy the dll and pdb to the output directory
|
||||||
|
add_custom_command(
|
||||||
|
TARGET LLPreLoader POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:LLPreLoader> ${CMAKE_BINARY_DIR}/output/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PDB_FILE:LLPreLoader> ${CMAKE_BINARY_DIR}/pdb/
|
||||||
|
COMMENT "Copying dll and pdb to output directory"
|
||||||
|
VERBATIM
|
||||||
|
)
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../Tools/Demangler/include/MicrosoftDemangle.h"
|
#include "MicrosoftDemangle.h"
|
||||||
|
|
||||||
namespace FakeSymbol {
|
namespace FakeSymbol {
|
||||||
|
|
@ -2,12 +2,12 @@
|
|||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#endif
|
#endif
|
||||||
#include "../LiteLoader/Header/third-party/FMT/chrono.h"
|
#include "FMT/chrono.h"
|
||||||
#include "../LiteLoader/Header/third-party/FMT/color.h"
|
#include "FMT/color.h"
|
||||||
#include "../LiteLoader/Header/third-party/FMT/core.h"
|
#include "FMT/core.h"
|
||||||
#include "../LiteLoader/Header/third-party/FMT/os.h"
|
#include "FMT/os.h"
|
||||||
#include "../LiteLoader/Header/third-party/FMT/format.h"
|
#include "FMT/format.h"
|
||||||
#include "../LiteLoader/Header/third-party/Nlohmann/json.hpp"
|
#include "Nlohmann/json.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
@ -9,7 +9,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
@ -1,9 +1,9 @@
|
|||||||
#include "pch.h"
|
#include "../include/pch.h"
|
||||||
#include "Logger.h"
|
#include "../include/Logger.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::wstring;
|
using std::wstring;
|
@ -1,4 +1,4 @@
|
|||||||
#include "pch.h"
|
#include "../include/pch.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -10,22 +10,22 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "../LiteLoader/Header/Utils/Hash.h"
|
#include "llapi/utils/Hash.h"
|
||||||
#include "../LiteLoader/Header/third-party/detours/detours.h"
|
#include "detours/detours.h"
|
||||||
#include "../LiteLoader/Lib/third-party/rawpdb/PDB.h"
|
#include "rawpdb/PDB.h"
|
||||||
#include "../LiteLoader/Lib/third-party/rawpdb/PDB_RawFile.h"
|
#include "rawpdb/PDB_RawFile.h"
|
||||||
#include "../LiteLoader/Lib/third-party/rawpdb/PDB_InfoStream.h"
|
#include "rawpdb/PDB_InfoStream.h"
|
||||||
#include "../LiteLoader/Lib/third-party/rawpdb/PDB_DBIStream.h"
|
#include "rawpdb/PDB_DBIStream.h"
|
||||||
#include "../LiteLoader/Lib/third-party/rawpdb/Foundation/PDB_DisableWarningsPop.h"
|
#include "rawpdb/Foundation/PDB_DisableWarningsPop.h"
|
||||||
|
|
||||||
#include "../LiteLoader/Header/third-party/parallel_hashmap/phmap.h"
|
#include "parallel_hashmap/phmap.h"
|
||||||
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "../LiteLoader/Header/third-party/FMT/printf.h"
|
#include "FMT/printf.h"
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include "FakeSymbol.hpp"
|
#include "../include/FakeSymbol.hpp"
|
||||||
|
|
||||||
using std::list;
|
using std::list;
|
||||||
using std::string, std::string_view;
|
using std::string, std::string_view;
|
@ -1,5 +1,5 @@
|
|||||||
#include "pch.h"
|
#include "../include/pch.h"
|
||||||
#include "Utils.h"
|
#include "../include/Utils.h"
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
std::string GetCallerModuleFileName(unsigned long FramesToSkip) {
|
std::string GetCallerModuleFileName(unsigned long FramesToSkip) {
|
||||||
static const int maxFrameCount = 1;
|
static const int maxFrameCount = 1;
|
@ -1,6 +1,6 @@
|
|||||||
// dllmain.cpp : 定义 DLL 应用程序的入口点。
|
// dllmain.cpp : 定义 DLL 应用程序的入口点。
|
||||||
#include "pch.h"
|
#include "../include/pch.h"
|
||||||
#include "Logger.h"
|
#include "../include/Logger.h"
|
||||||
void fixUpLibDir();
|
void fixUpLibDir();
|
||||||
void loadDlls();
|
void loadDlls();
|
||||||
#pragma comment(linker, "/export:GetServerSymbol=LLPreLoader.dlsym_real")
|
#pragma comment(linker, "/export:GetServerSymbol=LLPreLoader.dlsym_real")
|
2
LiteLoader/.gitignore
vendored
2
LiteLoader/.gitignore
vendored
@ -2,4 +2,4 @@
|
|||||||
/cmake-build-release/
|
/cmake-build-release/
|
||||||
/cmake-build-debug/
|
/cmake-build-debug/
|
||||||
/.idea/
|
/.idea/
|
||||||
Lib/LiteLoader.lib
|
lib/LiteLoader.lib
|
@ -4,67 +4,90 @@ project(LiteLoader)
|
|||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_BUILD_TYPE Release) # Always uses Release mode to build BDS plugin for ABI Compatibility
|
set(CMAKE_BUILD_TYPE Release) # Always uses Release mode to build BDS plugin for ABI Compatibility
|
||||||
|
|
||||||
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/x64/)
|
file(
|
||||||
|
GLOB_RECURSE SRC_FILES
|
||||||
set(TARGET_DIR ${CMAKE_SOURCE_DIR}/x64/Release/)
|
${PROJECT_SOURCE_DIR}/third-party/include/*.h
|
||||||
|
${PROJECT_SOURCE_DIR}/third-party/include/*.hpp
|
||||||
file(GLOB_RECURSE SRC_FILES
|
${PROJECT_SOURCE_DIR}/include/*.h
|
||||||
${PROJECT_SOURCE_DIR}/Lib/third-party/nbt-cpp/*.cpp
|
${PROJECT_SOURCE_DIR}/include/*.hpp
|
||||||
${PROJECT_SOURCE_DIR}/Header/*.cpp
|
${PROJECT_SOURCE_DIR}/src/*.cpp
|
||||||
${PROJECT_SOURCE_DIR}/Header/*.hpp
|
${PROJECT_SOURCE_DIR}/src/*.hpp
|
||||||
${PROJECT_SOURCE_DIR}/Header/*.h
|
${PROJECT_SOURCE_DIR}/src/*.h
|
||||||
${PROJECT_SOURCE_DIR}/Kernel/*.cpp
|
${PROJECT_SOURCE_DIR}/src/*.rc
|
||||||
${PROJECT_SOURCE_DIR}/Kernel/*.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/Kernel/*.h
|
|
||||||
${PROJECT_SOURCE_DIR}/Main/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/Main/*.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/Main/*.h
|
|
||||||
${PROJECT_SOURCE_DIR}/Resource/*.rc
|
|
||||||
${PROJECT_SOURCE_DIR}/Resource/*.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(
|
# third-party source files
|
||||||
-DUNICODE -DNDEBUG -DLITELOADER_EXPORTS -DWIN32_LEAN_AND_MEAN
|
file(GLOB_RECURSE THIRD_PARTY_SRC_FILES ${PROJECT_SOURCE_DIR}/third-party/src/*)
|
||||||
-DCPPHTTPLIB_OPENSSL_SUPPORT -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS
|
|
||||||
-D_USRDLL -D_AMD64_ -DNOMINMAX
|
add_library(LiteLoader SHARED ${SRC_FILES} ${THIRD_PARTY_SRC_FILES})
|
||||||
|
|
||||||
|
# Replace Compile Flag /EHsc to /EHa
|
||||||
|
string(REPLACE "/EHsc" "/EHa" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||||
|
|
||||||
|
target_compile_options(
|
||||||
|
LiteLoader
|
||||||
|
PRIVATE /permissive- /MD /MP /analyze:external- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Zc:inline /fp:precise /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /FC /nologo /Ot /diagnostics:column /utf-8
|
||||||
)
|
)
|
||||||
|
|
||||||
add_compile_options(
|
target_compile_definitions(
|
||||||
/permissive /MP /analyze:external- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Zc:inline /fp:precise
|
LiteLoader
|
||||||
/external:W1 /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /FC /EHa /nologo /Ot /diagnostics:column
|
PRIVATE -DUNICODE -DNDEBUG -DLITELOADER_EXPORTS -DWIN32_LEAN_AND_MEAN -DCPPHTTPLIB_OPENSSL_SUPPORT -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -D_USRDLL -D_AMD64_ -DNOMINMAX
|
||||||
/utf-8
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_link_options(
|
# use delayload to import BDS APIs manually(bedrock_server.dll does not need to exist)
|
||||||
/MANIFEST /LTCG:incremental /NXCOMPAT /DEBUG:FULL /DLL /MACHINE:X64 /OPT:REF /INCREMENTAL:NO /SUBSYSTEM:CONSOLE
|
target_link_options(
|
||||||
/MANIFESTUAC:NO /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
|
LiteLoader
|
||||||
/DELAYLOAD:bedrock_server.dll # use delayload to import BDS APIs manually(bedrock_server.dll does not need to exist)
|
PRIVATE /MANIFEST /LTCG:incremental /NXCOMPAT /DEBUG:FULL /DLL /MACHINE:X64 /OPT:REF /INCREMENTAL:NO /SUBSYSTEM:CONSOLE /MANIFESTUAC:NO /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 /DELAYLOAD:bedrock_server.dll
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR})
|
target_link_libraries(
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/Header)
|
LiteLoader
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/Header/third-party)
|
"${PROJECT_SOURCE_DIR}/third-party/lib/leveldb/leveldb.lib"
|
||||||
include_directories(${CMAKE_SOURCE_DIR})
|
"${PROJECT_SOURCE_DIR}/third-party/lib/openssl/libcrypto.lib"
|
||||||
|
"${PROJECT_SOURCE_DIR}/third-party/lib/openssl/libssl.lib"
|
||||||
link_directories(${PROJECT_SOURCE_DIR})
|
"${PROJECT_SOURCE_DIR}/third-party/lib/SQLiteCpp/SQLiteCpp.lib"
|
||||||
link_directories(${CMAKE_SOURCE_DIR}/x64/Release)
|
"${PROJECT_SOURCE_DIR}/third-party/lib/SQLiteCpp/sqlite3.lib"
|
||||||
|
"${PROJECT_SOURCE_DIR}/third-party/lib/mysql/mysqlclient.lib"
|
||||||
add_library(LiteLoader SHARED ${SRC_FILES})
|
"${PROJECT_SOURCE_DIR}/third-party/lib/compact_enc_det/ced.lib"
|
||||||
|
"${PROJECT_SOURCE_DIR}/third-party/lib/dyncall/dyncall_s.lib"
|
||||||
target_link_libraries(LiteLoader LLPreLoader
|
"${PROJECT_SOURCE_DIR}/third-party/lib/dyncall/dyncallback_s.lib"
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/leveldb/leveldb.lib"
|
"${PROJECT_SOURCE_DIR}/third-party/lib/dyncall/dynload_s.lib"
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/openssl/libcrypto.lib"
|
"${PROJECT_SOURCE_DIR}/third-party/lib/dbghelp/dbghelp.lib"
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/openssl/libssl.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/SQLiteCpp/SQLiteCpp.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/SQLiteCpp/sqlite3.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/mysql/mysqlclient.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/compact_enc_det/ced.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/dyncall/dyncall_s.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/dyncall/dyncallback_s.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/dyncall/dynload_s.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/compact_enc_det/ced.lib"
|
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/third-party/dbghelp/dbghelp.lib"
|
|
||||||
# Please make sure that the BDS APIs ImportLibrary is at the bottom of the list to ensure proper linking.
|
# Please make sure that the BDS APIs ImportLibrary is at the bottom of the list to ensure proper linking.
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/bedrock_server_api.lib"
|
"${PROJECT_SOURCE_DIR}/Lib/bedrock_server_api.lib"
|
||||||
"${PROJECT_SOURCE_DIR}/Lib/bedrock_server_var.lib"
|
"${PROJECT_SOURCE_DIR}/Lib/bedrock_server_var.lib"
|
||||||
|
LLPreLoader
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
LiteLoader SYSTEM
|
||||||
|
PRIVATE ${PROJECT_SOURCE_DIR}/third-party/include
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
LiteLoader
|
||||||
|
PRIVATE ${PROJECT_SOURCE_DIR}/include/
|
||||||
|
PRIVATE ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET LiteLoader PRE_BUILD
|
||||||
|
COMMAND ${CMAKE_SOURCE_DIR}/scripts/PrepareLibraries.cmd ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy the built DLL and PDB to the output directory
|
||||||
|
add_custom_command(
|
||||||
|
TARGET LiteLoader POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:LiteLoader> ${CMAKE_BINARY_DIR}/output/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PDB_FILE:LiteLoader> ${CMAKE_BINARY_DIR}/pdb/
|
||||||
|
COMMENT "Copying LiteLoader DLL and PDB to output directory"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy the built lib to the SDK directory
|
||||||
|
add_custom_command(
|
||||||
|
TARGET LiteLoader POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_LINKER_FILE:LiteLoader> ${CMAKE_BINARY_DIR}/sdk/lib/
|
||||||
|
COMMENT "Copying LiteLoader Lib to SDK directory"
|
||||||
|
VERBATIM
|
||||||
)
|
)
|
@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Global.h"
|
|
||||||
|
|
||||||
LIAPI uint64_t NewScoreId();
|
|
@ -1,85 +0,0 @@
|
|||||||
#ifndef ENTT_CONFIG_CONFIG_H
|
|
||||||
#define ENTT_CONFIG_CONFIG_H
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION)
|
|
||||||
# define ENTT_NOEXCEPT noexcept
|
|
||||||
# define ENTT_THROW throw
|
|
||||||
# define ENTT_TRY try
|
|
||||||
# define ENTT_CATCH catch(...)
|
|
||||||
#else
|
|
||||||
# define ENTT_NOEXCEPT
|
|
||||||
# define ENTT_THROW
|
|
||||||
# define ENTT_TRY if(true)
|
|
||||||
# define ENTT_CATCH if(false)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
|
|
||||||
# include <new>
|
|
||||||
# define ENTT_LAUNDER(expr) std::launder(expr)
|
|
||||||
#else
|
|
||||||
# define ENTT_LAUNDER(expr) expr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTT_USE_ATOMIC
|
|
||||||
# define ENTT_MAYBE_ATOMIC(Type) Type
|
|
||||||
#else
|
|
||||||
# include <atomic>
|
|
||||||
# define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTT_ID_TYPE
|
|
||||||
# include <cstdint>
|
|
||||||
# define ENTT_ID_TYPE std::uint32_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENTT_SPARSE_PAGE
|
|
||||||
static_assert(ENTT_SPARSE_PAGE && ((ENTT_SPARSE_PAGE & (ENTT_SPARSE_PAGE - 1)) == 0), "ENTT_SPARSE_PAGE must be a power of two");
|
|
||||||
#else
|
|
||||||
# define ENTT_SPARSE_PAGE 4096
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENTT_PACKED_PAGE
|
|
||||||
static_assert(ENTT_PACKED_PAGE && ((ENTT_PACKED_PAGE & (ENTT_PACKED_PAGE - 1)) == 0), "ENTT_PACKED_PAGE must be a power of two");
|
|
||||||
#else
|
|
||||||
# define ENTT_PACKED_PAGE 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENTT_DISABLE_ASSERT
|
|
||||||
# undef ENTT_ASSERT
|
|
||||||
# define ENTT_ASSERT(...) (void(0))
|
|
||||||
#elif !defined ENTT_ASSERT
|
|
||||||
# include <cassert>
|
|
||||||
# define ENTT_ASSERT(condition, ...) assert(condition)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENTT_NO_ETO
|
|
||||||
# include <type_traits>
|
|
||||||
# define ENTT_IGNORE_IF_EMPTY std::false_type
|
|
||||||
#else
|
|
||||||
# include <type_traits>
|
|
||||||
# define ENTT_IGNORE_IF_EMPTY std::true_type
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTT_STANDARD_CPP
|
|
||||||
# if defined __clang__ || defined __GNUC__
|
|
||||||
# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__
|
|
||||||
# define ENTT_PRETTY_FUNCTION_PREFIX '='
|
|
||||||
# define ENTT_PRETTY_FUNCTION_SUFFIX ']'
|
|
||||||
# elif defined _MSC_VER
|
|
||||||
# define ENTT_PRETTY_FUNCTION __FUNCSIG__
|
|
||||||
# define ENTT_PRETTY_FUNCTION_PREFIX '<'
|
|
||||||
# define ENTT_PRETTY_FUNCTION_SUFFIX '>'
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,10 +0,0 @@
|
|||||||
#ifndef ENTT_CONFIG_VERSION_H
|
|
||||||
#define ENTT_CONFIG_VERSION_H
|
|
||||||
|
|
||||||
|
|
||||||
#define ENTT_VERSION_MAJOR 3
|
|
||||||
#define ENTT_VERSION_MINOR 8
|
|
||||||
#define ENTT_VERSION_PATCH 1
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
456
LiteLoader/Header/third-party/entt/core/any.hpp
vendored
456
LiteLoader/Header/third-party/entt/core/any.hpp
vendored
@ -1,456 +0,0 @@
|
|||||||
#ifndef ENTT_CORE_ANY_HPP
|
|
||||||
#define ENTT_CORE_ANY_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/utility.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
#include "type_info.hpp"
|
|
||||||
#include "type_traits.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A SBO friendly, type-safe container for single values of any type.
|
|
||||||
* @tparam Len Size of the storage reserved for the small buffer optimization.
|
|
||||||
* @tparam Align Optional alignment requirement.
|
|
||||||
*/
|
|
||||||
template<std::size_t Len, std::size_t Align>
|
|
||||||
class basic_any {
|
|
||||||
enum class operation: std::uint8_t { COPY, MOVE, DTOR, COMP, ADDR, CADDR, TYPE };
|
|
||||||
enum class policy: std::uint8_t { OWNER, REF, CREF };
|
|
||||||
|
|
||||||
using storage_type = std::aligned_storage_t<Len + !Len, Align>;
|
|
||||||
using vtable_type = const void *(const operation, const basic_any &, void *);
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
static constexpr bool in_situ = Len && alignof(Type) <= alignof(storage_type) && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v<Type>;
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] static constexpr policy type_to_policy() {
|
|
||||||
if constexpr(std::is_lvalue_reference_v<Type>) {
|
|
||||||
if constexpr(std::is_const_v<std::remove_reference_t<Type>>) {
|
|
||||||
return policy::CREF;
|
|
||||||
} else {
|
|
||||||
return policy::REF;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return policy::OWNER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
|
|
||||||
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
|
|
||||||
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
|
|
||||||
} else {
|
|
||||||
return lhs == rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] void *to) {
|
|
||||||
static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
|
|
||||||
|
|
||||||
if constexpr(!std::is_void_v<Type>) {
|
|
||||||
const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
|
|
||||||
? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
|
|
||||||
: static_cast<const Type *>(from.instance);
|
|
||||||
|
|
||||||
switch(op) {
|
|
||||||
case operation::COPY:
|
|
||||||
if constexpr(std::is_copy_constructible_v<Type>) {
|
|
||||||
static_cast<basic_any *>(to)->emplace<Type>(*instance);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case operation::MOVE:
|
|
||||||
if constexpr(in_situ<Type>) {
|
|
||||||
if(from.mode == policy::OWNER) {
|
|
||||||
return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
|
|
||||||
case operation::DTOR:
|
|
||||||
if(from.mode == policy::OWNER) {
|
|
||||||
if constexpr(in_situ<Type>) {
|
|
||||||
instance->~Type();
|
|
||||||
} else if constexpr(std::is_array_v<Type>) {
|
|
||||||
delete[] instance;
|
|
||||||
} else {
|
|
||||||
delete instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case operation::COMP:
|
|
||||||
return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
|
|
||||||
case operation::ADDR:
|
|
||||||
if(from.mode == policy::CREF) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
[[fallthrough]];
|
|
||||||
case operation::CADDR:
|
|
||||||
return instance;
|
|
||||||
case operation::TYPE:
|
|
||||||
*static_cast<type_info *>(to) = type_id<Type>();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Type, typename... Args>
|
|
||||||
void initialize([[maybe_unused]] Args &&... args) {
|
|
||||||
if constexpr(!std::is_void_v<Type>) {
|
|
||||||
if constexpr(std::is_lvalue_reference_v<Type>) {
|
|
||||||
static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...), "Invalid arguments");
|
|
||||||
instance = (std::addressof(args), ...);
|
|
||||||
} else if constexpr(in_situ<Type>) {
|
|
||||||
if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
|
|
||||||
new (&storage) Type{std::forward<Args>(args)...};
|
|
||||||
} else {
|
|
||||||
new (&storage) Type(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if constexpr(sizeof...(Args) != 0u && std::is_aggregate_v<Type>) {
|
|
||||||
instance = new Type{std::forward<Args>(args)...};
|
|
||||||
} else {
|
|
||||||
instance = new Type(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT
|
|
||||||
: instance{other.data()},
|
|
||||||
vtable{other.vtable},
|
|
||||||
mode{pol}
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Size of the internal storage. */
|
|
||||||
static constexpr auto length = Len;
|
|
||||||
/*! @brief Alignment requirement. */
|
|
||||||
static constexpr auto alignment = Align;
|
|
||||||
|
|
||||||
/*! @brief Default constructor. */
|
|
||||||
basic_any() ENTT_NOEXCEPT
|
|
||||||
: instance{},
|
|
||||||
vtable{&basic_vtable<void>},
|
|
||||||
mode{policy::OWNER}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a wrapper by directly initializing the new object.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @tparam Args Types of arguments to use to construct the new instance.
|
|
||||||
* @param args Parameters to use to construct the instance.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename... Args>
|
|
||||||
explicit basic_any(std::in_place_type_t<Type>, Args &&... args)
|
|
||||||
: instance{},
|
|
||||||
vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
|
|
||||||
mode{type_to_policy<Type>()}
|
|
||||||
{
|
|
||||||
initialize<Type>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a wrapper that holds an unmanaged object.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @param value An instance of an object to use to initialize the wrapper.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
|
|
||||||
: basic_any{}
|
|
||||||
{
|
|
||||||
// invokes deprecated assignment operator (and avoids issues with vs2017)
|
|
||||||
*this = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a wrapper from a given value.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @param value An instance of an object to use to initialize the wrapper.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
|
|
||||||
basic_any(Type &&value)
|
|
||||||
: instance{},
|
|
||||||
vtable{&basic_vtable<std::decay_t<Type>>},
|
|
||||||
mode{policy::OWNER}
|
|
||||||
{
|
|
||||||
initialize<std::decay_t<Type>>(std::forward<Type>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copy constructor.
|
|
||||||
* @param other The instance to copy from.
|
|
||||||
*/
|
|
||||||
basic_any(const basic_any &other)
|
|
||||||
: instance{},
|
|
||||||
vtable{&basic_vtable<void>},
|
|
||||||
mode{policy::OWNER}
|
|
||||||
{
|
|
||||||
other.vtable(operation::COPY, other, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Move constructor.
|
|
||||||
* @param other The instance to move from.
|
|
||||||
*/
|
|
||||||
basic_any(basic_any &&other) ENTT_NOEXCEPT
|
|
||||||
: instance{},
|
|
||||||
vtable{other.vtable},
|
|
||||||
mode{other.mode}
|
|
||||||
{
|
|
||||||
vtable(operation::MOVE, other, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @brief Frees the internal storage, whatever it means. */
|
|
||||||
~basic_any() {
|
|
||||||
vtable(operation::DTOR, *this, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copy assignment operator.
|
|
||||||
* @param other The instance to copy from.
|
|
||||||
* @return This any object.
|
|
||||||
*/
|
|
||||||
basic_any & operator=(const basic_any &other) {
|
|
||||||
reset();
|
|
||||||
other.vtable(operation::COPY, other, this);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Move assignment operator.
|
|
||||||
* @param other The instance to move from.
|
|
||||||
* @return This any object.
|
|
||||||
*/
|
|
||||||
basic_any & operator=(basic_any &&other) ENTT_NOEXCEPT {
|
|
||||||
std::exchange(vtable, other.vtable)(operation::DTOR, *this, nullptr);
|
|
||||||
other.vtable(operation::MOVE, other, this);
|
|
||||||
mode = other.mode;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Value assignment operator.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @param value An instance of an object to use to initialize the wrapper.
|
|
||||||
* @return This any object.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
[[deprecated("Use std::in_place_type<T &>, entt::make_any<T &>, emplace<Type &> or forward_as_any instead")]]
|
|
||||||
basic_any & operator=(std::reference_wrapper<Type> value) ENTT_NOEXCEPT {
|
|
||||||
emplace<Type &>(value.get());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Value assignment operator.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @param value An instance of an object to use to initialize the wrapper.
|
|
||||||
* @return This any object.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>, basic_any &>
|
|
||||||
operator=(Type &&value) {
|
|
||||||
emplace<std::decay_t<Type>>(std::forward<Type>(value));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the type of the contained object.
|
|
||||||
* @return The type of the contained object, if any.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] type_info type() const ENTT_NOEXCEPT {
|
|
||||||
type_info info{};
|
|
||||||
vtable(operation::TYPE, *this, &info);
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an opaque pointer to the contained instance.
|
|
||||||
* @return An opaque pointer the contained instance, if any.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] const void * data() const ENTT_NOEXCEPT {
|
|
||||||
return vtable(operation::CADDR, *this, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc data */
|
|
||||||
[[nodiscard]] void * data() ENTT_NOEXCEPT {
|
|
||||||
return const_cast<void *>(vtable(operation::ADDR, *this, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Replaces the contained object by creating a new instance directly.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @tparam Args Types of arguments to use to construct the new instance.
|
|
||||||
* @param args Parameters to use to construct the instance.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename... Args>
|
|
||||||
void emplace(Args &&... args) {
|
|
||||||
std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>)(operation::DTOR, *this, nullptr);
|
|
||||||
mode = type_to_policy<Type>();
|
|
||||||
initialize<Type>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @brief Destroys contained object */
|
|
||||||
void reset() {
|
|
||||||
std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, nullptr);
|
|
||||||
mode = policy::OWNER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns false if a wrapper is empty, true otherwise.
|
|
||||||
* @return False if the wrapper is empty, true otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
|
|
||||||
return !(vtable(operation::CADDR, *this, nullptr) == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if two wrappers differ in their content.
|
|
||||||
* @param other Wrapper with which to compare.
|
|
||||||
* @return False if the two objects differ in their content, true otherwise.
|
|
||||||
*/
|
|
||||||
bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
|
|
||||||
const basic_any *trampoline = &other;
|
|
||||||
return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Aliasing constructor.
|
|
||||||
* @return A wrapper that shares a reference to an unmanaged object.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
|
|
||||||
return basic_any{*this, (mode == policy::CREF ? policy::CREF : policy::REF)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc as_ref */
|
|
||||||
[[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
|
|
||||||
return basic_any{*this, policy::CREF};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns true if a wrapper owns its object, false otherwise.
|
|
||||||
* @return True if the wrapper owns its object, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool owner() const ENTT_NOEXCEPT {
|
|
||||||
return (mode == policy::OWNER);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
union { const void *instance; storage_type storage; };
|
|
||||||
vtable_type *vtable;
|
|
||||||
policy mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if two wrappers differ in their content.
|
|
||||||
* @tparam Len Size of the storage reserved for the small buffer optimization.
|
|
||||||
* @tparam Align Alignment requirement.
|
|
||||||
* @param lhs A wrapper, either empty or not.
|
|
||||||
* @param rhs A wrapper, either empty or not.
|
|
||||||
* @return True if the two wrappers differ in their content, false otherwise.
|
|
||||||
*/
|
|
||||||
template<std::size_t Len, std::size_t Align>
|
|
||||||
[[nodiscard]] inline bool operator!=(const basic_any<Len, Align> &lhs, const basic_any<Len, Align> &rhs) ENTT_NOEXCEPT {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Performs type-safe access to the contained object.
|
|
||||||
* @tparam Type Type to which conversion is required.
|
|
||||||
* @tparam Len Size of the storage reserved for the small buffer optimization.
|
|
||||||
* @tparam Align Alignment requirement.
|
|
||||||
* @param data Target any object.
|
|
||||||
* @return The element converted to the requested type.
|
|
||||||
*/
|
|
||||||
template<typename Type, std::size_t Len, std::size_t Align>
|
|
||||||
Type any_cast(const basic_any<Len, Align> &data) ENTT_NOEXCEPT {
|
|
||||||
const auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
|
|
||||||
ENTT_ASSERT(instance, "Invalid instance");
|
|
||||||
return static_cast<Type>(*instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! @copydoc any_cast */
|
|
||||||
template<typename Type, std::size_t Len, std::size_t Align>
|
|
||||||
Type any_cast(basic_any<Len, Align> &data) ENTT_NOEXCEPT {
|
|
||||||
// forces const on non-reference types to make them work also with wrappers for const references
|
|
||||||
auto * const instance = any_cast<std::remove_reference_t<const Type>>(&data);
|
|
||||||
ENTT_ASSERT(instance, "Invalid instance");
|
|
||||||
return static_cast<Type>(*instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! @copydoc any_cast */
|
|
||||||
template<typename Type, std::size_t Len, std::size_t Align>
|
|
||||||
Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
|
|
||||||
// forces const on non-reference types to make them work also with wrappers for const references
|
|
||||||
auto * const instance = any_cast<std::remove_reference_t<const Type>>(&data);
|
|
||||||
ENTT_ASSERT(instance, "Invalid instance");
|
|
||||||
return static_cast<Type>(std::move(*instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! @copydoc any_cast */
|
|
||||||
template<typename Type, std::size_t Len, std::size_t Align>
|
|
||||||
const Type * any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
|
|
||||||
return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! @copydoc any_cast */
|
|
||||||
template<typename Type, std::size_t Len, std::size_t Align>
|
|
||||||
Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
|
|
||||||
// last attempt to make wrappers for const references return their values
|
|
||||||
return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a wrapper from a given type, passing it all arguments.
|
|
||||||
* @tparam Type Type of object to use to initialize the wrapper.
|
|
||||||
* @tparam Len Size of the storage reserved for the small buffer optimization.
|
|
||||||
* @tparam Align Optional alignment requirement.
|
|
||||||
* @tparam Args Types of arguments to use to construct the new instance.
|
|
||||||
* @param args Parameters to use to construct the instance.
|
|
||||||
* @return A properly initialized wrapper for an object of the given type.
|
|
||||||
*/
|
|
||||||
template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
|
|
||||||
basic_any<Len, Align> make_any(Args &&... args) {
|
|
||||||
return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Forwards its argument and avoids copies for lvalue references.
|
|
||||||
* @tparam Len Size of the storage reserved for the small buffer optimization.
|
|
||||||
* @tparam Align Optional alignment requirement.
|
|
||||||
* @tparam Type Type of argument to use to construct the new instance.
|
|
||||||
* @param value Parameter to use to construct the instance.
|
|
||||||
* @return A properly initialized and not necessarily owning wrapper.
|
|
||||||
*/
|
|
||||||
template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type>
|
|
||||||
basic_any<Len, Align> forward_as_any(Type &&value) {
|
|
||||||
return basic_any<Len, Align>{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||||||
#ifndef ENTT_CORE_ATTRIBUTE_H
|
|
||||||
#define ENTT_CORE_ATTRIBUTE_H
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTT_EXPORT
|
|
||||||
# if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER
|
|
||||||
# define ENTT_EXPORT __declspec(dllexport)
|
|
||||||
# define ENTT_IMPORT __declspec(dllimport)
|
|
||||||
# define ENTT_HIDDEN
|
|
||||||
# elif defined __GNUC__ && __GNUC__ >= 4
|
|
||||||
# define ENTT_EXPORT __attribute__((visibility("default")))
|
|
||||||
# define ENTT_IMPORT __attribute__((visibility("default")))
|
|
||||||
# define ENTT_HIDDEN __attribute__((visibility("hidden")))
|
|
||||||
# else /* Unsupported compiler */
|
|
||||||
# define ENTT_EXPORT
|
|
||||||
# define ENTT_IMPORT
|
|
||||||
# define ENTT_HIDDEN
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENTT_API
|
|
||||||
# if defined ENTT_API_EXPORT
|
|
||||||
# define ENTT_API ENTT_EXPORT
|
|
||||||
# elif defined ENTT_API_IMPORT
|
|
||||||
# define ENTT_API ENTT_IMPORT
|
|
||||||
# else /* No API */
|
|
||||||
# define ENTT_API
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,269 +0,0 @@
|
|||||||
#ifndef ENTT_CORE_HASHED_STRING_HPP
|
|
||||||
#define ENTT_CORE_HASHED_STRING_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cond TURN_OFF_DOXYGEN
|
|
||||||
* Internal details not to be documented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
struct fnv1a_traits;
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct fnv1a_traits<std::uint32_t> {
|
|
||||||
using type = std::uint32_t;
|
|
||||||
static constexpr std::uint32_t offset = 2166136261;
|
|
||||||
static constexpr std::uint32_t prime = 16777619;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct fnv1a_traits<std::uint64_t> {
|
|
||||||
using type = std::uint64_t;
|
|
||||||
static constexpr std::uint64_t offset = 14695981039346656037ull;
|
|
||||||
static constexpr std::uint64_t prime = 1099511628211ull;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal details not to be documented.
|
|
||||||
* @endcond
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Zero overhead unique identifier.
|
|
||||||
*
|
|
||||||
* A hashed string is a compile-time tool that allows users to use
|
|
||||||
* human-readable identifers in the codebase while using their numeric
|
|
||||||
* counterparts at runtime.<br/>
|
|
||||||
* Because of that, a hashed string can also be used in constant expressions if
|
|
||||||
* required.
|
|
||||||
*
|
|
||||||
* @tparam Char Character type.
|
|
||||||
*/
|
|
||||||
template<typename Char>
|
|
||||||
class basic_hashed_string {
|
|
||||||
using traits_type = internal::fnv1a_traits<id_type>;
|
|
||||||
|
|
||||||
struct const_wrapper {
|
|
||||||
// non-explicit constructor on purpose
|
|
||||||
constexpr const_wrapper(const Char *curr) ENTT_NOEXCEPT: str{curr} {}
|
|
||||||
const Char *str;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fowler–Noll–Vo hash function v. 1a - the good
|
|
||||||
[[nodiscard]] static constexpr id_type helper(const Char *curr) ENTT_NOEXCEPT {
|
|
||||||
auto value = traits_type::offset;
|
|
||||||
|
|
||||||
while(*curr != 0) {
|
|
||||||
value = (value ^ static_cast<traits_type::type>(*(curr++))) * traits_type::prime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Character type. */
|
|
||||||
using value_type = Char;
|
|
||||||
/*! @brief Unsigned integer type. */
|
|
||||||
using hash_type = id_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns directly the numeric representation of a string view.
|
|
||||||
* @param str Human-readable identifer.
|
|
||||||
* @param size Length of the string to hash.
|
|
||||||
* @return The numeric representation of the string.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static constexpr hash_type value(const value_type *str, std::size_t size) ENTT_NOEXCEPT {
|
|
||||||
id_type partial{traits_type::offset};
|
|
||||||
while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
|
|
||||||
return partial;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns directly the numeric representation of a string.
|
|
||||||
*
|
|
||||||
* Forcing template resolution avoids implicit conversions. An
|
|
||||||
* human-readable identifier can be anything but a plain, old bunch of
|
|
||||||
* characters.<br/>
|
|
||||||
* Example of use:
|
|
||||||
* @code{.cpp}
|
|
||||||
* const auto value = basic_hashed_string<char>::to_value("my.png");
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @tparam N Number of characters of the identifier.
|
|
||||||
* @param str Human-readable identifer.
|
|
||||||
* @return The numeric representation of the string.
|
|
||||||
*/
|
|
||||||
template<std::size_t N>
|
|
||||||
[[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) ENTT_NOEXCEPT {
|
|
||||||
return helper(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns directly the numeric representation of a string.
|
|
||||||
* @param wrapper Helps achieving the purpose by relying on overloading.
|
|
||||||
* @return The numeric representation of the string.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static hash_type value(const_wrapper wrapper) ENTT_NOEXCEPT {
|
|
||||||
return helper(wrapper.str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @brief Constructs an empty hashed string. */
|
|
||||||
constexpr basic_hashed_string() ENTT_NOEXCEPT
|
|
||||||
: str{nullptr}, hash{}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a hashed string from an array of const characters.
|
|
||||||
*
|
|
||||||
* Forcing template resolution avoids implicit conversions. An
|
|
||||||
* human-readable identifier can be anything but a plain, old bunch of
|
|
||||||
* characters.<br/>
|
|
||||||
* Example of use:
|
|
||||||
* @code{.cpp}
|
|
||||||
* basic_hashed_string<char> hs{"my.png"};
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @tparam N Number of characters of the identifier.
|
|
||||||
* @param curr Human-readable identifer.
|
|
||||||
*/
|
|
||||||
template<std::size_t N>
|
|
||||||
constexpr basic_hashed_string(const value_type (&curr)[N]) ENTT_NOEXCEPT
|
|
||||||
: str{curr}, hash{helper(curr)}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Explicit constructor on purpose to avoid constructing a hashed
|
|
||||||
* string directly from a `const value_type *`.
|
|
||||||
* @param wrapper Helps achieving the purpose by relying on overloading.
|
|
||||||
*/
|
|
||||||
explicit constexpr basic_hashed_string(const_wrapper wrapper) ENTT_NOEXCEPT
|
|
||||||
: str{wrapper.str}, hash{helper(wrapper.str)}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the human-readable representation of a hashed string.
|
|
||||||
* @return The string used to initialize the instance.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr const value_type * data() const ENTT_NOEXCEPT {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the numeric representation of a hashed string.
|
|
||||||
* @return The numeric representation of the instance.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr hash_type value() const ENTT_NOEXCEPT {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc data */
|
|
||||||
[[nodiscard]] constexpr operator const value_type *() const ENTT_NOEXCEPT { return data(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the numeric representation of a hashed string.
|
|
||||||
* @return The numeric representation of the instance.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr operator hash_type() const ENTT_NOEXCEPT { return value(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Compares two hashed strings.
|
|
||||||
* @param other Hashed string with which to compare.
|
|
||||||
* @return True if the two hashed strings are identical, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr bool operator==(const basic_hashed_string &other) const ENTT_NOEXCEPT {
|
|
||||||
return hash == other.hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const value_type *str;
|
|
||||||
hash_type hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deduction guide.
|
|
||||||
*
|
|
||||||
* It allows to deduce the character type of the hashed string directly from a
|
|
||||||
* human-readable identifer provided to the constructor.
|
|
||||||
*
|
|
||||||
* @tparam Char Character type.
|
|
||||||
* @tparam N Number of characters of the identifier.
|
|
||||||
* @param str Human-readable identifer.
|
|
||||||
*/
|
|
||||||
template<typename Char, std::size_t N>
|
|
||||||
basic_hashed_string(const Char (&str)[N])
|
|
||||||
-> basic_hashed_string<Char>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Compares two hashed strings.
|
|
||||||
* @tparam Char Character type.
|
|
||||||
* @param lhs A valid hashed string.
|
|
||||||
* @param rhs A valid hashed string.
|
|
||||||
* @return True if the two hashed strings are identical, false otherwise.
|
|
||||||
*/
|
|
||||||
template<typename Char>
|
|
||||||
[[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) ENTT_NOEXCEPT {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Aliases for common character types. */
|
|
||||||
using hashed_string = basic_hashed_string<char>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Aliases for common character types. */
|
|
||||||
using hashed_wstring = basic_hashed_string<wchar_t>;
|
|
||||||
|
|
||||||
|
|
||||||
inline namespace literals {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief User defined literal for hashed strings.
|
|
||||||
* @param str The literal without its suffix.
|
|
||||||
* @return A properly initialized hashed string.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr entt::hashed_string operator"" _hs(const char *str, std::size_t) ENTT_NOEXCEPT {
|
|
||||||
return entt::hashed_string{str};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief User defined literal for hashed wstrings.
|
|
||||||
* @param str The literal without its suffix.
|
|
||||||
* @return A properly initialized hashed wstring.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr entt::hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) ENTT_NOEXCEPT {
|
|
||||||
return entt::hashed_wstring{str};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,64 +0,0 @@
|
|||||||
#ifndef ENTT_CORE_IDENT_HPP
|
|
||||||
#define ENTT_CORE_IDENT_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <utility>
|
|
||||||
#include <type_traits>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
#include "type_traits.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Types identifiers.
|
|
||||||
*
|
|
||||||
* Variable template used to generate identifiers at compile-time for the given
|
|
||||||
* types. Use the `get` member function to know what's the identifier associated
|
|
||||||
* to the specific type.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Identifiers are constant expression and can be used in any context where such
|
|
||||||
* an expression is required. As an example:
|
|
||||||
* @code{.cpp}
|
|
||||||
* using id = entt::identifier<a_type, another_type>;
|
|
||||||
*
|
|
||||||
* switch(a_type_identifier) {
|
|
||||||
* case id::type<a_type>:
|
|
||||||
* // ...
|
|
||||||
* break;
|
|
||||||
* case id::type<another_type>:
|
|
||||||
* // ...
|
|
||||||
* break;
|
|
||||||
* default:
|
|
||||||
* // ...
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @tparam Types List of types for which to generate identifiers.
|
|
||||||
*/
|
|
||||||
template<typename... Types>
|
|
||||||
class identifier {
|
|
||||||
template<typename Type, std::size_t... Index>
|
|
||||||
[[nodiscard]] static constexpr id_type get(std::index_sequence<Index...>) {
|
|
||||||
static_assert(std::disjunction_v<std::is_same<Type, Types>...>, "Invalid type");
|
|
||||||
return (0 + ... + (std::is_same_v<Type, type_list_element_t<Index, type_list<std::decay_t<Types>...>>> ? id_type{Index} : id_type{}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Unsigned integer type. */
|
|
||||||
using identifier_type = id_type;
|
|
||||||
|
|
||||||
/*! @brief Statically generated unique identifier for the given type. */
|
|
||||||
template<typename Type>
|
|
||||||
static constexpr identifier_type type = get<std::decay_t<Type>>(std::index_sequence_for<Types...>{});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,260 +0,0 @@
|
|||||||
#ifndef ENTT_CORE_TYPE_INFO_HPP
|
|
||||||
#define ENTT_CORE_TYPE_INFO_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include <type_traits>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/attribute.h"
|
|
||||||
#include "hashed_string.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cond TURN_OFF_DOXYGEN
|
|
||||||
* Internal details not to be documented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
|
|
||||||
struct ENTT_API type_seq final {
|
|
||||||
[[nodiscard]] static id_type next() ENTT_NOEXCEPT {
|
|
||||||
static ENTT_MAYBE_ATOMIC(id_type) value{};
|
|
||||||
return value++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] constexpr auto stripped_type_name() ENTT_NOEXCEPT {
|
|
||||||
#if defined ENTT_PRETTY_FUNCTION
|
|
||||||
std::string_view pretty_function{ENTT_PRETTY_FUNCTION};
|
|
||||||
auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX)+1);
|
|
||||||
auto value = pretty_function.substr(first, pretty_function.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first);
|
|
||||||
return value;
|
|
||||||
#else
|
|
||||||
return std::string_view{""};
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
|
|
||||||
[[nodiscard]] static constexpr std::string_view type_name(int) ENTT_NOEXCEPT {
|
|
||||||
constexpr auto value = stripped_type_name<Type>();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] static std::string_view type_name(char) ENTT_NOEXCEPT {
|
|
||||||
static const auto value = stripped_type_name<Type>();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')>
|
|
||||||
[[nodiscard]] static constexpr id_type type_hash(int) ENTT_NOEXCEPT {
|
|
||||||
constexpr auto stripped = stripped_type_name<Type>();
|
|
||||||
constexpr auto value = hashed_string::value(stripped.data(), stripped.size());
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] static id_type type_hash(char) ENTT_NOEXCEPT {
|
|
||||||
static const auto value = [](const auto stripped) {
|
|
||||||
return hashed_string::value(stripped.data(), stripped.size());
|
|
||||||
}(stripped_type_name<Type>());
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal details not to be documented.
|
|
||||||
* @endcond
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type sequential identifier.
|
|
||||||
* @tparam Type Type for which to generate a sequential identifier.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename = void>
|
|
||||||
struct ENTT_API type_seq final {
|
|
||||||
/**
|
|
||||||
* @brief Returns the sequential identifier of a given type.
|
|
||||||
* @return The sequential identifier of a given type.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static id_type value() ENTT_NOEXCEPT {
|
|
||||||
static const id_type value = internal::type_seq::next();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc value */
|
|
||||||
[[nodiscard]] constexpr operator id_type() const ENTT_NOEXCEPT { return value(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type hash.
|
|
||||||
* @tparam Type Type for which to generate a hash value.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename = void>
|
|
||||||
struct type_hash final {
|
|
||||||
/**
|
|
||||||
* @brief Returns the numeric representation of a given type.
|
|
||||||
* @return The numeric representation of the given type.
|
|
||||||
*/
|
|
||||||
#if defined ENTT_PRETTY_FUNCTION
|
|
||||||
[[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
|
|
||||||
return internal::type_hash<Type>(0);
|
|
||||||
#else
|
|
||||||
[[nodiscard]] static constexpr id_type value() ENTT_NOEXCEPT {
|
|
||||||
return type_seq<Type>::value();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc value */
|
|
||||||
[[nodiscard]] constexpr operator id_type() const ENTT_NOEXCEPT { return value(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type name.
|
|
||||||
* @tparam Type Type for which to generate a name.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename = void>
|
|
||||||
struct type_name final {
|
|
||||||
/**
|
|
||||||
* @brief Returns the name of a given type.
|
|
||||||
* @return The name of the given type.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static constexpr std::string_view value() ENTT_NOEXCEPT {
|
|
||||||
return internal::type_name<Type>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc value */
|
|
||||||
[[nodiscard]] constexpr operator std::string_view() const ENTT_NOEXCEPT { return value(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Implementation specific information about a type. */
|
|
||||||
class type_info final {
|
|
||||||
template<typename>
|
|
||||||
friend type_info type_id() ENTT_NOEXCEPT;
|
|
||||||
|
|
||||||
type_info(id_type seq_v, id_type hash_v, std::string_view name_v) ENTT_NOEXCEPT
|
|
||||||
: seq_value{seq_v},
|
|
||||||
hash_value{hash_v},
|
|
||||||
name_value{name_v}
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Default constructor. */
|
|
||||||
type_info() ENTT_NOEXCEPT
|
|
||||||
: type_info({}, {}, {})
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*! @brief Default copy constructor. */
|
|
||||||
type_info(const type_info &) ENTT_NOEXCEPT = default;
|
|
||||||
/*! @brief Default move constructor. */
|
|
||||||
type_info(type_info &&) ENTT_NOEXCEPT = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default copy assignment operator.
|
|
||||||
* @return This type info object.
|
|
||||||
*/
|
|
||||||
type_info & operator=(const type_info &) ENTT_NOEXCEPT = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default move assignment operator.
|
|
||||||
* @return This type info object.
|
|
||||||
*/
|
|
||||||
type_info & operator=(type_info &&) ENTT_NOEXCEPT = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a type info object is properly initialized.
|
|
||||||
* @return True if the object is properly initialized, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
|
|
||||||
return name_value.data() != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type sequential identifier.
|
|
||||||
* @return Type sequential identifier.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] id_type seq() const ENTT_NOEXCEPT {
|
|
||||||
return seq_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type hash.
|
|
||||||
* @return Type hash.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] id_type hash() const ENTT_NOEXCEPT {
|
|
||||||
return hash_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type name.
|
|
||||||
* @return Type name.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] std::string_view name() const ENTT_NOEXCEPT {
|
|
||||||
return name_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Compares the contents of two type info objects.
|
|
||||||
* @param other Object with which to compare.
|
|
||||||
* @return False if the two contents differ, true otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool operator==(const type_info &other) const ENTT_NOEXCEPT {
|
|
||||||
return hash_value == other.hash_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
id_type seq_value;
|
|
||||||
id_type hash_value;
|
|
||||||
std::string_view name_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Compares the contents of two type info objects.
|
|
||||||
* @param lhs A type info object.
|
|
||||||
* @param rhs A type info object.
|
|
||||||
* @return True if the two contents differ, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] inline bool operator!=(const type_info &lhs, const type_info &rhs) ENTT_NOEXCEPT {
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the type info object for a given type.
|
|
||||||
* @tparam Type Type for which to generate a type info object.
|
|
||||||
* @return The type info object for the given type.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] type_info type_id() ENTT_NOEXCEPT {
|
|
||||||
return type_info{
|
|
||||||
type_seq<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
|
|
||||||
type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value(),
|
|
||||||
type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_COMPONENT_HPP
|
|
||||||
#define ENTT_ENTITY_COMPONENT_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include "../config/config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Commonly used default traits for all types. */
|
|
||||||
struct basic_component_traits {
|
|
||||||
/*! @brief Pointer stability, default is `std::false_type`. */
|
|
||||||
using in_place_delete = std::false_type;
|
|
||||||
/*! @brief Empty type optimization, default is `ENTT_IGNORE_IF_EMPTY`. */
|
|
||||||
using ignore_if_empty = ENTT_IGNORE_IF_EMPTY;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Common way to access various properties of components.
|
|
||||||
* @tparam Type Type of component.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename = void>
|
|
||||||
struct component_traits: basic_component_traits {
|
|
||||||
static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
147
LiteLoader/Header/third-party/entt/entity/fwd.hpp
vendored
147
LiteLoader/Header/third-party/entt/entity/fwd.hpp
vendored
@ -1,147 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_FWD_HPP
|
|
||||||
#define ENTT_ENTITY_FWD_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "../core/fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Entity, typename = std::allocator<Entity>>
|
|
||||||
class basic_sparse_set;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename, typename Type, typename = std::allocator<Type>>
|
|
||||||
struct basic_storage;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_registry;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename...>
|
|
||||||
struct basic_view;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_runtime_view;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename...>
|
|
||||||
class basic_group;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_observer;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_organizer;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename, typename...>
|
|
||||||
struct basic_handle;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_snapshot;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_snapshot_loader;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename>
|
|
||||||
class basic_continuous_loader;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Default entity identifier. */
|
|
||||||
enum class entity: id_type {};
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using sparse_set = basic_sparse_set<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias declaration for the most common use case.
|
|
||||||
* @tparam Args Other template parameters.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
using storage = basic_storage<entity, Args...>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using registry = basic_registry<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using observer = basic_observer<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using organizer = basic_organizer<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using handle = basic_handle<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using const_handle = basic_handle<const entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias declaration for the most common use case.
|
|
||||||
* @tparam Args Other template parameters.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
using handle_view = basic_handle<entity, Args...>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias declaration for the most common use case.
|
|
||||||
* @tparam Args Other template parameters.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
using const_handle_view = basic_handle<const entity, Args...>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using snapshot = basic_snapshot<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using snapshot_loader = basic_snapshot_loader<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using continuous_loader = basic_continuous_loader<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias declaration for the most common use case.
|
|
||||||
* @tparam Args Other template parameters.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
using view = basic_view<entity, Args...>;
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Alias declaration for the most common use case. */
|
|
||||||
using runtime_view = basic_runtime_view<entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias declaration for the most common use case.
|
|
||||||
* @tparam Args Other template parameters.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
using group = basic_group<entity, Args...>;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
969
LiteLoader/Header/third-party/entt/entity/group.hpp
vendored
969
LiteLoader/Header/third-party/entt/entity/group.hpp
vendored
@ -1,969 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_GROUP_HPP
|
|
||||||
#define ENTT_ENTITY_GROUP_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <tuple>
|
|
||||||
#include <utility>
|
|
||||||
#include <type_traits>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
#include "entity.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
#include "sparse_set.hpp"
|
|
||||||
#include "storage.hpp"
|
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Group.
|
|
||||||
*
|
|
||||||
* Primary template isn't defined on purpose. All the specializations give a
|
|
||||||
* compile-time error, but for a few reasonable cases.
|
|
||||||
*/
|
|
||||||
template<typename...>
|
|
||||||
class basic_group;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Non-owning group.
|
|
||||||
*
|
|
||||||
* A non-owning group returns all entities and only the entities that have at
|
|
||||||
* least the given components. Moreover, it's guaranteed that the entity list
|
|
||||||
* is tightly packed in memory for fast iterations.
|
|
||||||
*
|
|
||||||
* @b Important
|
|
||||||
*
|
|
||||||
* Iterators aren't invalidated if:
|
|
||||||
*
|
|
||||||
* * New instances of the given components are created and assigned to entities.
|
|
||||||
* * The entity currently pointed is modified (as an example, if one of the
|
|
||||||
* given components is removed from the entity to which the iterator points).
|
|
||||||
* * The entity currently pointed is destroyed.
|
|
||||||
*
|
|
||||||
* In all other cases, modifying the pools iterated by the group in any way
|
|
||||||
* invalidates all the iterators and using them results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Groups share references to the underlying data structures of the registry
|
|
||||||
* that generated them. Therefore any change to the entities and to the
|
|
||||||
* components made by means of the registry are immediately reflected by all the
|
|
||||||
* groups.<br/>
|
|
||||||
* Moreover, sorting a non-owning group affects all the instances of the same
|
|
||||||
* group (it means that users don't have to call `sort` on each instance to sort
|
|
||||||
* all of them because they _share_ entities and components).
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Lifetime of a group must not overcome that of the registry that generated it.
|
|
||||||
* In any other case, attempting to use a group results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
* @tparam Exclude Types of components used to filter the group.
|
|
||||||
* @tparam Get Type of components observed by the group.
|
|
||||||
*/
|
|
||||||
template<typename Entity, typename... Exclude, typename... Get>
|
|
||||||
class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>> final {
|
|
||||||
/*! @brief A registry is allowed to create groups. */
|
|
||||||
friend class basic_registry<Entity>;
|
|
||||||
|
|
||||||
using basic_common_type = basic_sparse_set<Entity>;
|
|
||||||
|
|
||||||
template<typename Component>
|
|
||||||
using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
|
|
||||||
|
|
||||||
class iterable final {
|
|
||||||
template<typename It>
|
|
||||||
struct iterable_iterator final {
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
|
|
||||||
using pointer = void;
|
|
||||||
using reference = value_type;
|
|
||||||
using iterator_category = std::input_iterator_tag;
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
iterable_iterator(It from, const std::tuple<storage_type<Get> *...> &args) ENTT_NOEXCEPT
|
|
||||||
: it{from},
|
|
||||||
pools{args}
|
|
||||||
{}
|
|
||||||
|
|
||||||
iterable_iterator & operator++() ENTT_NOEXCEPT {
|
|
||||||
return ++it, *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterable_iterator operator++(int) ENTT_NOEXCEPT {
|
|
||||||
iterable_iterator orig = *this;
|
|
||||||
return ++(*this), orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
|
|
||||||
const auto entt = *it;
|
|
||||||
return std::tuple_cat(std::make_tuple(entt), get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return other.it == it;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
It it;
|
|
||||||
std::tuple<storage_type<Get> *...> pools;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
using iterator = iterable_iterator<typename basic_common_type::iterator>;
|
|
||||||
using reverse_iterator = iterable_iterator<typename basic_common_type::reverse_iterator>;
|
|
||||||
|
|
||||||
iterable(basic_common_type * const ref, const std::tuple<storage_type<Get> *...> &cpools)
|
|
||||||
: handler{ref},
|
|
||||||
pools{cpools}
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
||||||
return handler ? iterator{handler->begin(), pools} : iterator{{}, pools};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
||||||
return handler ? iterator{handler->end(), pools} : iterator{{}, pools};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
||||||
return handler ? reverse_iterator{handler->rbegin(), pools} : reverse_iterator{{}, pools};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
||||||
return handler ? reverse_iterator{handler->rend(), pools} : reverse_iterator{{}, pools};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
basic_common_type * const handler;
|
|
||||||
const std::tuple<storage_type<Get> *...> pools;
|
|
||||||
};
|
|
||||||
|
|
||||||
basic_group(basic_common_type &ref, storage_type<Get> &... gpool) ENTT_NOEXCEPT
|
|
||||||
: handler{&ref},
|
|
||||||
pools{&gpool...}
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Underlying entity identifier. */
|
|
||||||
using entity_type = Entity;
|
|
||||||
/*! @brief Unsigned integer type. */
|
|
||||||
using size_type = std::size_t;
|
|
||||||
/*! @brief Random access iterator type. */
|
|
||||||
using iterator = typename basic_common_type::iterator;
|
|
||||||
/*! @brief Reversed iterator type. */
|
|
||||||
using reverse_iterator = typename basic_common_type::reverse_iterator;
|
|
||||||
/*! @brief Iterable group type. */
|
|
||||||
using iterable_group = iterable;
|
|
||||||
|
|
||||||
/*! @brief Default constructor to use to create empty, invalid groups. */
|
|
||||||
basic_group() ENTT_NOEXCEPT
|
|
||||||
: handler{}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the number of entities that have the given components.
|
|
||||||
* @return Number of entities that have the given components.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type size() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->size() : size_type{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the number of elements that a group has currently
|
|
||||||
* allocated space for.
|
|
||||||
* @return Capacity of the group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->capacity() : size_type{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @brief Requests the removal of unused capacity. */
|
|
||||||
void shrink_to_fit() {
|
|
||||||
if(*this) {
|
|
||||||
handler->shrink_to_fit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks whether a group is empty.
|
|
||||||
* @return True if the group is empty, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool empty() const ENTT_NOEXCEPT {
|
|
||||||
return !*this || handler->empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Direct access to the list of entities.
|
|
||||||
*
|
|
||||||
* The returned pointer is such that range `[data(), data() + size())` is
|
|
||||||
* always a valid range, even if the container is empty.
|
|
||||||
*
|
|
||||||
* @return A pointer to the array of entities.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] auto data() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->data() : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first entity of the group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity of the group. If the
|
|
||||||
* group is empty, the returned iterator will be equal to `end()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity of the group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->begin() : iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator that is past the last entity of the group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the entity following the last entity of
|
|
||||||
* the group. Attempting to dereference the returned iterator results in
|
|
||||||
* undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the entity following the last entity of the
|
|
||||||
* group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->end() : iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first entity of the reversed group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity of the reversed group.
|
|
||||||
* If the group is empty, the returned iterator will be equal to `rend()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity of the reversed group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->rbegin() : reverse_iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator that is past the last entity of the reversed
|
|
||||||
* group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the entity following the last entity of
|
|
||||||
* the reversed group. Attempting to dereference the returned iterator
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the entity following the last entity of the
|
|
||||||
* reversed group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? handler->rend() : reverse_iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the first entity of the group, if any.
|
|
||||||
* @return The first entity of the group if one exists, the null entity
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type front() const {
|
|
||||||
const auto it = begin();
|
|
||||||
return it != end() ? *it : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the last entity of the group, if any.
|
|
||||||
* @return The last entity of the group if one exists, the null entity
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type back() const {
|
|
||||||
const auto it = rbegin();
|
|
||||||
return it != rend() ? *it : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Finds an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return An iterator to the given entity if it's found, past the end
|
|
||||||
* iterator otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator find(const entity_type entt) const {
|
|
||||||
const auto it = *this ? handler->find(entt) : iterator{};
|
|
||||||
return it != end() && *it == entt ? it : end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the identifier that occupies the given position.
|
|
||||||
* @param pos Position of the element to return.
|
|
||||||
* @return The identifier that occupies the given position.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type operator[](const size_type pos) const {
|
|
||||||
return begin()[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a group is properly initialized.
|
|
||||||
* @return True if the group is properly initialized, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
|
|
||||||
return handler != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a group contains an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return True if the group contains the given entity, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool contains(const entity_type entt) const {
|
|
||||||
return *this && handler->contains(entt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the components assigned to the given entity.
|
|
||||||
*
|
|
||||||
* Prefer this function instead of `registry::get` during iterations. It has
|
|
||||||
* far better performance than its counterpart.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to use an invalid component type results in a compilation
|
|
||||||
* error. Attempting to use an entity that doesn't belong to the group
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @tparam Component Types of components to get.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return The components assigned to the entity.
|
|
||||||
*/
|
|
||||||
template<typename... Component>
|
|
||||||
[[nodiscard]] decltype(auto) get(const entity_type entt) const {
|
|
||||||
ENTT_ASSERT(contains(entt), "Group does not contain entity");
|
|
||||||
|
|
||||||
if constexpr(sizeof...(Component) == 0) {
|
|
||||||
return std::tuple_cat(get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
|
|
||||||
} else if constexpr(sizeof...(Component) == 1) {
|
|
||||||
return (std::get<storage_type<Component> *>(pools)->get(entt), ...);
|
|
||||||
} else {
|
|
||||||
return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), entt)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Iterates entities and components and applies the given function
|
|
||||||
* object to them.
|
|
||||||
*
|
|
||||||
* The function object is invoked for each entity. It is provided with the
|
|
||||||
* entity itself and a set of references to non-empty components. The
|
|
||||||
* _constness_ of the components is as requested.<br/>
|
|
||||||
* The signature of the function must be equivalent to one of the following
|
|
||||||
* forms:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* void(const entity_type, Type &...);
|
|
||||||
* void(Type &...);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Empty types aren't explicitly instantiated and therefore they are never
|
|
||||||
* returned during iterations.
|
|
||||||
*
|
|
||||||
* @tparam Func Type of the function object to invoke.
|
|
||||||
* @param func A valid function object.
|
|
||||||
*/
|
|
||||||
template<typename Func>
|
|
||||||
void each(Func func) const {
|
|
||||||
for(const auto entt: *this) {
|
|
||||||
if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
|
|
||||||
std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt)));
|
|
||||||
} else {
|
|
||||||
std::apply(func, get(entt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterable object to use to _visit_ the group.
|
|
||||||
*
|
|
||||||
* The iterable object returns tuples that contain the current entity and a
|
|
||||||
* set of references to its non-empty components. The _constness_ of the
|
|
||||||
* components is as requested.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Empty types aren't explicitly instantiated and therefore they are never
|
|
||||||
* returned during iterations.
|
|
||||||
*
|
|
||||||
* @return An iterable object to use to _visit_ the group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterable_group each() const ENTT_NOEXCEPT {
|
|
||||||
return iterable_group{handler, pools};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sort a group according to the given comparison function.
|
|
||||||
*
|
|
||||||
* Sort the group so that iterating it with a couple of iterators returns
|
|
||||||
* entities and components in the expected order. See `begin` and `end` for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* The comparison function object must return `true` if the first element
|
|
||||||
* is _less_ than the second one, `false` otherwise. The signature of the
|
|
||||||
* comparison function should be equivalent to one of the following:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* bool(std::tuple<Component &...>, std::tuple<Component &...>);
|
|
||||||
* bool(const Component &..., const Component &...);
|
|
||||||
* bool(const Entity, const Entity);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* Where `Component` are such that they are iterated by the group.<br/>
|
|
||||||
* Moreover, the comparison function object shall induce a
|
|
||||||
* _strict weak ordering_ on the values.
|
|
||||||
*
|
|
||||||
* The sort function oject must offer a member function template
|
|
||||||
* `operator()` that accepts three arguments:
|
|
||||||
*
|
|
||||||
* * An iterator to the first element of the range to sort.
|
|
||||||
* * An iterator past the last element of the range to sort.
|
|
||||||
* * A comparison function to use to compare the elements.
|
|
||||||
*
|
|
||||||
* @tparam Component Optional types of components to compare.
|
|
||||||
* @tparam Compare Type of comparison function object.
|
|
||||||
* @tparam Sort Type of sort function object.
|
|
||||||
* @tparam Args Types of arguments to forward to the sort function object.
|
|
||||||
* @param compare A valid comparison function object.
|
|
||||||
* @param algo A valid sort function object.
|
|
||||||
* @param args Arguments to forward to the sort function object, if any.
|
|
||||||
*/
|
|
||||||
template<typename... Component, typename Compare, typename Sort = std_sort, typename... Args>
|
|
||||||
void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
|
|
||||||
if(*this) {
|
|
||||||
if constexpr(sizeof...(Component) == 0) {
|
|
||||||
static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
|
|
||||||
handler->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
|
|
||||||
} else if constexpr(sizeof...(Component) == 1) {
|
|
||||||
handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
|
|
||||||
return compare((std::get<storage_type<Component> *>(pools)->get(lhs), ...), (std::get<storage_type<Component> *>(pools)->get(rhs), ...));
|
|
||||||
}, std::move(algo), std::forward<Args>(args)...);
|
|
||||||
} else {
|
|
||||||
handler->sort([this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
|
|
||||||
return compare(std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(rhs)...));
|
|
||||||
}, std::move(algo), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sort the shared pool of entities according to the given component.
|
|
||||||
*
|
|
||||||
* Non-owning groups of the same type share with the registry a pool of
|
|
||||||
* entities with its own order that doesn't depend on the order of any pool
|
|
||||||
* of components. Users can order the underlying data structure so that it
|
|
||||||
* respects the order of the pool of the given component.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* The shared pool of entities and thus its order is affected by the changes
|
|
||||||
* to each and every pool that it tracks. Therefore changes to those pools
|
|
||||||
* can quickly ruin the order imposed to the pool of entities shared between
|
|
||||||
* the non-owning groups.
|
|
||||||
*
|
|
||||||
* @tparam Component Type of component to use to impose the order.
|
|
||||||
*/
|
|
||||||
template<typename Component>
|
|
||||||
void sort() const {
|
|
||||||
if(*this) {
|
|
||||||
handler->respect(*std::get<storage_type<Component> *>(pools));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
basic_common_type * const handler;
|
|
||||||
const std::tuple<storage_type<Get> *...> pools;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Owning group.
|
|
||||||
*
|
|
||||||
* Owning groups return all entities and only the entities that have at least
|
|
||||||
* the given components. Moreover:
|
|
||||||
*
|
|
||||||
* * It's guaranteed that the entity list is tightly packed in memory for fast
|
|
||||||
* iterations.
|
|
||||||
* * It's guaranteed that the lists of owned components are tightly packed in
|
|
||||||
* memory for even faster iterations and to allow direct access.
|
|
||||||
* * They stay true to the order of the owned components and all instances have
|
|
||||||
* the same order in memory.
|
|
||||||
*
|
|
||||||
* The more types of components are owned by a group, the faster it is to
|
|
||||||
* iterate them.
|
|
||||||
*
|
|
||||||
* @b Important
|
|
||||||
*
|
|
||||||
* Iterators aren't invalidated if:
|
|
||||||
*
|
|
||||||
* * New instances of the given components are created and assigned to entities.
|
|
||||||
* * The entity currently pointed is modified (as an example, if one of the
|
|
||||||
* given components is removed from the entity to which the iterator points).
|
|
||||||
* * The entity currently pointed is destroyed.
|
|
||||||
*
|
|
||||||
* In all other cases, modifying the pools iterated by the group in any way
|
|
||||||
* invalidates all the iterators and using them results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Groups share references to the underlying data structures of the registry
|
|
||||||
* that generated them. Therefore any change to the entities and to the
|
|
||||||
* components made by means of the registry are immediately reflected by all the
|
|
||||||
* groups.
|
|
||||||
* Moreover, sorting an owning group affects all the instance of the same group
|
|
||||||
* (it means that users don't have to call `sort` on each instance to sort all
|
|
||||||
* of them because they share the underlying data structure).
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Lifetime of a group must not overcome that of the registry that generated it.
|
|
||||||
* In any other case, attempting to use a group results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
* @tparam Exclude Types of components used to filter the group.
|
|
||||||
* @tparam Get Types of components observed by the group.
|
|
||||||
* @tparam Owned Types of components owned by the group.
|
|
||||||
*/
|
|
||||||
template<typename Entity, typename... Exclude, typename... Get, typename... Owned>
|
|
||||||
class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> final {
|
|
||||||
/*! @brief A registry is allowed to create groups. */
|
|
||||||
friend class basic_registry<Entity>;
|
|
||||||
|
|
||||||
using basic_common_type = basic_sparse_set<Entity>;
|
|
||||||
|
|
||||||
template<typename Component>
|
|
||||||
using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
|
|
||||||
|
|
||||||
class iterable final {
|
|
||||||
template<typename, typename>
|
|
||||||
struct iterable_iterator;
|
|
||||||
|
|
||||||
template<typename It, typename... OIt>
|
|
||||||
struct iterable_iterator<It, type_list<OIt...>> final {
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_group>().get({})));
|
|
||||||
using pointer = void;
|
|
||||||
using reference = value_type;
|
|
||||||
using iterator_category = std::input_iterator_tag;
|
|
||||||
|
|
||||||
template<typename... Other>
|
|
||||||
iterable_iterator(It from, const std::tuple<Other...> &other, const std::tuple<storage_type<Get> *...> &cpools) ENTT_NOEXCEPT
|
|
||||||
: it{from},
|
|
||||||
owned{std::get<OIt>(other)...},
|
|
||||||
get{cpools}
|
|
||||||
{}
|
|
||||||
|
|
||||||
iterable_iterator & operator++() ENTT_NOEXCEPT {
|
|
||||||
return ++it, (++std::get<OIt>(owned), ...), *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterable_iterator operator++(int) ENTT_NOEXCEPT {
|
|
||||||
iterable_iterator orig = *this;
|
|
||||||
return ++(*this), orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
|
|
||||||
return std::tuple_cat(
|
|
||||||
std::make_tuple(*it),
|
|
||||||
std::forward_as_tuple(*std::get<OIt>(owned)...),
|
|
||||||
get_as_tuple(*std::get<storage_type<Get> *>(get), *it)...
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return other.it == it;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
It it;
|
|
||||||
std::tuple<OIt...> owned;
|
|
||||||
std::tuple<storage_type<Get> *...> get;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
using iterator = iterable_iterator<
|
|
||||||
typename basic_common_type::iterator,
|
|
||||||
type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().end())>>...>
|
|
||||||
>;
|
|
||||||
using reverse_iterator = iterable_iterator<
|
|
||||||
typename basic_common_type::reverse_iterator,
|
|
||||||
type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().rbegin())>>...>
|
|
||||||
>;
|
|
||||||
|
|
||||||
iterable(std::tuple<storage_type<Owned> *..., storage_type<Get> *...> cpools, const std::size_t * const extent)
|
|
||||||
: pools{cpools},
|
|
||||||
length{extent}
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
||||||
return length ? iterator{
|
|
||||||
std::get<0>(pools)->basic_common_type::end() - *length,
|
|
||||||
std::make_tuple((std::get<storage_type<Owned> *>(pools)->end() - *length)...),
|
|
||||||
std::make_tuple(std::get<storage_type<Get> *>(pools)...)
|
|
||||||
} : iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->end()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
||||||
return length ? iterator{
|
|
||||||
std::get<0>(pools)->basic_common_type::end(),
|
|
||||||
std::make_tuple((std::get<storage_type<Owned> *>(pools)->end())...),
|
|
||||||
std::make_tuple(std::get<storage_type<Get> *>(pools)...)
|
|
||||||
} : iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->end()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
||||||
return length ? reverse_iterator{
|
|
||||||
std::get<0>(pools)->basic_common_type::rbegin(),
|
|
||||||
std::make_tuple((std::get<storage_type<Owned> *>(pools)->rbegin())...),
|
|
||||||
std::make_tuple(std::get<storage_type<Get> *>(pools)...)
|
|
||||||
} : reverse_iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->rbegin()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
||||||
return length ? reverse_iterator{
|
|
||||||
std::get<0>(pools)->basic_common_type::rbegin() + *length,
|
|
||||||
std::make_tuple((std::get<storage_type<Owned> *>(pools)->rbegin() + *length)...),
|
|
||||||
std::make_tuple(std::get<storage_type<Get> *>(pools)...)
|
|
||||||
} : reverse_iterator{{}, std::make_tuple(decltype(std::get<storage_type<Owned> *>(pools)->rbegin()){}...), std::make_tuple(std::get<storage_type<Get> *>(pools)...)};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
|
|
||||||
const std::size_t * const length;
|
|
||||||
};
|
|
||||||
|
|
||||||
basic_group(const std::size_t &extent, storage_type<Owned> &... opool, storage_type<Get> &... gpool) ENTT_NOEXCEPT
|
|
||||||
: pools{&opool..., &gpool...},
|
|
||||||
length{&extent}
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Underlying entity identifier. */
|
|
||||||
using entity_type = Entity;
|
|
||||||
/*! @brief Unsigned integer type. */
|
|
||||||
using size_type = std::size_t;
|
|
||||||
/*! @brief Random access iterator type. */
|
|
||||||
using iterator = typename basic_common_type::iterator;
|
|
||||||
/*! @brief Reversed iterator type. */
|
|
||||||
using reverse_iterator = typename basic_common_type::reverse_iterator;
|
|
||||||
/*! @brief Iterable group type. */
|
|
||||||
using iterable_group = iterable;
|
|
||||||
|
|
||||||
/*! @brief Default constructor to use to create empty, invalid groups. */
|
|
||||||
basic_group() ENTT_NOEXCEPT
|
|
||||||
: length{}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the number of entities that have the given components.
|
|
||||||
* @return Number of entities that have the given components.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type size() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? *length : size_type{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks whether a group is empty.
|
|
||||||
* @return True if the group is empty, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool empty() const ENTT_NOEXCEPT {
|
|
||||||
return !*this || !*length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Direct access to the raw representation offered by the storage.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* This function is only available for owned types.
|
|
||||||
*
|
|
||||||
* @tparam Component Type of component in which one is interested.
|
|
||||||
* @return A pointer to the array of components.
|
|
||||||
*/
|
|
||||||
template<typename Component>
|
|
||||||
[[nodiscard]] auto raw() const ENTT_NOEXCEPT {
|
|
||||||
static_assert((std::is_same_v<Component, Owned> || ...), "Non-owned type");
|
|
||||||
auto *cpool = std::get<storage_type<Component> *>(pools);
|
|
||||||
return cpool ? cpool->raw() : decltype(cpool->raw()){};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Direct access to the list of entities.
|
|
||||||
*
|
|
||||||
* The returned pointer is such that range `[data(), data() + size())` is
|
|
||||||
* always a valid range, even if the container is empty.
|
|
||||||
*
|
|
||||||
* @return A pointer to the array of entities.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] auto data() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? std::get<0>(pools)->data() : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first entity of the group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity of the group. If the
|
|
||||||
* group is empty, the returned iterator will be equal to `end()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity of the group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? (std::get<0>(pools)->basic_common_type::end() - *length) : iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator that is past the last entity of the group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the entity following the last entity of
|
|
||||||
* the group. Attempting to dereference the returned iterator results in
|
|
||||||
* undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the entity following the last entity of the
|
|
||||||
* group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? std::get<0>(pools)->basic_common_type::end() : iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first entity of the reversed group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity of the reversed group.
|
|
||||||
* If the group is empty, the returned iterator will be equal to `rend()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity of the reversed group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? std::get<0>(pools)->basic_common_type::rbegin() : reverse_iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator that is past the last entity of the reversed
|
|
||||||
* group.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the entity following the last entity of
|
|
||||||
* the reversed group. Attempting to dereference the returned iterator
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the entity following the last entity of the
|
|
||||||
* reversed group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
||||||
return *this ? (std::get<0>(pools)->basic_common_type::rbegin() + *length) : reverse_iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the first entity of the group, if any.
|
|
||||||
* @return The first entity of the group if one exists, the null entity
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type front() const {
|
|
||||||
const auto it = begin();
|
|
||||||
return it != end() ? *it : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the last entity of the group, if any.
|
|
||||||
* @return The last entity of the group if one exists, the null entity
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type back() const {
|
|
||||||
const auto it = rbegin();
|
|
||||||
return it != rend() ? *it : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Finds an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return An iterator to the given entity if it's found, past the end
|
|
||||||
* iterator otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator find(const entity_type entt) const {
|
|
||||||
const auto it = *this ? std::get<0>(pools)->find(entt) : iterator{};
|
|
||||||
return it != end() && it >= begin() && *it == entt ? it : end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the identifier that occupies the given position.
|
|
||||||
* @param pos Position of the element to return.
|
|
||||||
* @return The identifier that occupies the given position.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type operator[](const size_type pos) const {
|
|
||||||
return begin()[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a group is properly initialized.
|
|
||||||
* @return True if the group is properly initialized, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
|
|
||||||
return length != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a group contains an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return True if the group contains the given entity, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool contains(const entity_type entt) const {
|
|
||||||
return *this && std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < (*length));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the components assigned to the given entity.
|
|
||||||
*
|
|
||||||
* Prefer this function instead of `registry::get` during iterations. It has
|
|
||||||
* far better performance than its counterpart.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to use an invalid component type results in a compilation
|
|
||||||
* error. Attempting to use an entity that doesn't belong to the group
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @tparam Component Types of components to get.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return The components assigned to the entity.
|
|
||||||
*/
|
|
||||||
template<typename... Component>
|
|
||||||
[[nodiscard]] decltype(auto) get(const entity_type entt) const {
|
|
||||||
ENTT_ASSERT(contains(entt), "Group does not contain entity");
|
|
||||||
|
|
||||||
if constexpr(sizeof...(Component) == 0) {
|
|
||||||
return std::tuple_cat(get_as_tuple(*std::get<storage_type<Owned> *>(pools), entt)..., get_as_tuple(*std::get<storage_type<Get> *>(pools), entt)...);
|
|
||||||
} else if constexpr(sizeof...(Component) == 1) {
|
|
||||||
return (std::get<storage_type<Component> *>(pools)->get(entt), ...);
|
|
||||||
} else {
|
|
||||||
return std::tuple_cat(get_as_tuple(*std::get<storage_type<Component> *>(pools), entt)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Iterates entities and components and applies the given function
|
|
||||||
* object to them.
|
|
||||||
*
|
|
||||||
* The function object is invoked for each entity. It is provided with the
|
|
||||||
* entity itself and a set of references to non-empty components. The
|
|
||||||
* _constness_ of the components is as requested.<br/>
|
|
||||||
* The signature of the function must be equivalent to one of the following
|
|
||||||
* forms:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* void(const entity_type, Type &...);
|
|
||||||
* void(Type &...);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Empty types aren't explicitly instantiated and therefore they are never
|
|
||||||
* returned during iterations.
|
|
||||||
*
|
|
||||||
* @tparam Func Type of the function object to invoke.
|
|
||||||
* @param func A valid function object.
|
|
||||||
*/
|
|
||||||
template<typename Func>
|
|
||||||
void each(Func func) const {
|
|
||||||
for(auto args: each()) {
|
|
||||||
if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) {
|
|
||||||
std::apply(func, args);
|
|
||||||
} else {
|
|
||||||
std::apply([&func](auto, auto &&... less) { func(std::forward<decltype(less)>(less)...); }, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterable object to use to _visit_ the group.
|
|
||||||
*
|
|
||||||
* The iterable object returns tuples that contain the current entity and a
|
|
||||||
* set of references to its non-empty components. The _constness_ of the
|
|
||||||
* components is as requested.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Empty types aren't explicitly instantiated and therefore they are never
|
|
||||||
* returned during iterations.
|
|
||||||
*
|
|
||||||
* @return An iterable object to use to _visit_ the group.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterable_group each() const ENTT_NOEXCEPT {
|
|
||||||
return iterable_group{pools, length};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sort a group according to the given comparison function.
|
|
||||||
*
|
|
||||||
* Sort the group so that iterating it with a couple of iterators returns
|
|
||||||
* entities and components in the expected order. See `begin` and `end` for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* The comparison function object must return `true` if the first element
|
|
||||||
* is _less_ than the second one, `false` otherwise. The signature of the
|
|
||||||
* comparison function should be equivalent to one of the following:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* bool(std::tuple<Component &...>, std::tuple<Component &...>);
|
|
||||||
* bool(const Component &, const Component &);
|
|
||||||
* bool(const Entity, const Entity);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* Where `Component` are either owned types or not but still such that they
|
|
||||||
* are iterated by the group.<br/>
|
|
||||||
* Moreover, the comparison function object shall induce a
|
|
||||||
* _strict weak ordering_ on the values.
|
|
||||||
*
|
|
||||||
* The sort function oject must offer a member function template
|
|
||||||
* `operator()` that accepts three arguments:
|
|
||||||
*
|
|
||||||
* * An iterator to the first element of the range to sort.
|
|
||||||
* * An iterator past the last element of the range to sort.
|
|
||||||
* * A comparison function to use to compare the elements.
|
|
||||||
*
|
|
||||||
* @tparam Component Optional types of components to compare.
|
|
||||||
* @tparam Compare Type of comparison function object.
|
|
||||||
* @tparam Sort Type of sort function object.
|
|
||||||
* @tparam Args Types of arguments to forward to the sort function object.
|
|
||||||
* @param compare A valid comparison function object.
|
|
||||||
* @param algo A valid sort function object.
|
|
||||||
* @param args Arguments to forward to the sort function object, if any.
|
|
||||||
*/
|
|
||||||
template<typename... Component, typename Compare, typename Sort = std_sort, typename... Args>
|
|
||||||
void sort(Compare compare, Sort algo = Sort{}, Args &&... args) const {
|
|
||||||
auto *cpool = std::get<0>(pools);
|
|
||||||
|
|
||||||
if constexpr(sizeof...(Component) == 0) {
|
|
||||||
static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
|
|
||||||
cpool->sort_n(*length, std::move(compare), std::move(algo), std::forward<Args>(args)...);
|
|
||||||
} else if constexpr(sizeof...(Component) == 1) {
|
|
||||||
cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
|
|
||||||
return compare((std::get<storage_type<Component> *>(pools)->get(lhs), ...), (std::get<storage_type<Component> *>(pools)->get(rhs), ...));
|
|
||||||
}, std::move(algo), std::forward<Args>(args)...);
|
|
||||||
} else {
|
|
||||||
cpool->sort_n(*length, [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
|
|
||||||
return compare(std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(lhs)...), std::forward_as_tuple(std::get<storage_type<Component> *>(pools)->get(rhs)...));
|
|
||||||
}, std::move(algo), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
[this](auto *head, auto *... other) {
|
|
||||||
for(auto next = *length; next; --next) {
|
|
||||||
const auto pos = next - 1;
|
|
||||||
[[maybe_unused]] const auto entt = head->data()[pos];
|
|
||||||
(other->swap(other->data()[pos], entt), ...);
|
|
||||||
}
|
|
||||||
}(std::get<storage_type<Owned> *>(pools)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::tuple<storage_type<Owned> *..., storage_type<Get> *...> pools;
|
|
||||||
const size_type * const length;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
168
LiteLoader/Header/third-party/entt/entity/helper.hpp
vendored
168
LiteLoader/Header/third-party/entt/entity/helper.hpp
vendored
@ -1,168 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_HELPER_HPP
|
|
||||||
#define ENTT_ENTITY_HELPER_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/fwd.hpp"
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
#include "../signal/delegate.hpp"
|
|
||||||
#include "registry.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Converts a registry to a view.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
struct as_view {
|
|
||||||
/*! @brief Underlying entity identifier. */
|
|
||||||
using entity_type = std::remove_const_t<Entity>;
|
|
||||||
/*! @brief Type of registry to convert. */
|
|
||||||
using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a converter for a given registry.
|
|
||||||
* @param source A valid reference to a registry.
|
|
||||||
*/
|
|
||||||
as_view(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Conversion function from a registry to a view.
|
|
||||||
* @tparam Exclude Types of components used to filter the view.
|
|
||||||
* @tparam Component Type of components used to construct the view.
|
|
||||||
* @return A newly created view.
|
|
||||||
*/
|
|
||||||
template<typename Exclude, typename... Component>
|
|
||||||
operator basic_view<entity_type, Exclude, Component...>() const {
|
|
||||||
return reg.template view<Component...>(Exclude{});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
registry_type ®
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deduction guide.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
as_view(basic_registry<Entity> &) -> as_view<Entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deduction guide.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
as_view(const basic_registry<Entity> &) -> as_view<const Entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Converts a registry to a group.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
struct as_group {
|
|
||||||
/*! @brief Underlying entity identifier. */
|
|
||||||
using entity_type = std::remove_const_t<Entity>;
|
|
||||||
/*! @brief Type of registry to convert. */
|
|
||||||
using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a converter for a given registry.
|
|
||||||
* @param source A valid reference to a registry.
|
|
||||||
*/
|
|
||||||
as_group(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Conversion function from a registry to a group.
|
|
||||||
* @tparam Exclude Types of components used to filter the group.
|
|
||||||
* @tparam Get Types of components observed by the group.
|
|
||||||
* @tparam Owned Types of components owned by the group.
|
|
||||||
* @return A newly created group.
|
|
||||||
*/
|
|
||||||
template<typename Exclude, typename Get, typename... Owned>
|
|
||||||
operator basic_group<entity_type, Exclude, Get, Owned...>() const {
|
|
||||||
if constexpr(std::is_const_v<registry_type>) {
|
|
||||||
return reg.template group_if_exists<Owned...>(Get{}, Exclude{});
|
|
||||||
} else {
|
|
||||||
return reg.template group<Owned...>(Get{}, Exclude{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
registry_type ®
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deduction guide.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
as_group(basic_registry<Entity> &) -> as_group<Entity>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deduction guide.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
as_group(const basic_registry<Entity> &) -> as_group<const Entity>;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Helper to create a listener that directly invokes a member function.
|
|
||||||
* @tparam Member Member function to invoke on a component of the given type.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
* @param reg A registry that contains the given entity and its components.
|
|
||||||
* @param entt Entity from which to get the component.
|
|
||||||
*/
|
|
||||||
template<auto Member, typename Entity = entity>
|
|
||||||
void invoke(basic_registry<Entity> ®, const Entity entt) {
|
|
||||||
static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
|
|
||||||
delegate<void(basic_registry<Entity> &, const Entity)> func;
|
|
||||||
func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
|
|
||||||
func(reg, entt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the entity associated with a given component.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Currently, this function only works correctly with the default pool as it
|
|
||||||
* makes assumptions about how the components are laid out.
|
|
||||||
*
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
* @tparam Component Type of component.
|
|
||||||
* @param reg A registry that contains the given entity and its components.
|
|
||||||
* @param instance A valid component instance.
|
|
||||||
* @return The entity associated with the given component.
|
|
||||||
*/
|
|
||||||
template<typename Entity, typename Component>
|
|
||||||
Entity to_entity(const basic_registry<Entity> ®, const Component &instance) {
|
|
||||||
const auto view = reg.template view<const Component>();
|
|
||||||
const auto *addr = std::addressof(instance);
|
|
||||||
|
|
||||||
for(auto it = view.rbegin(), last = view.rend(); it < last; it += ENTT_PACKED_PAGE) {
|
|
||||||
if(const auto dist = (addr - std::addressof(view.template get<const Component>(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
|
|
||||||
return *(it + dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entt::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_POLY_STORAGE_HPP
|
|
||||||
#define ENTT_ENTITY_POLY_STORAGE_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <tuple>
|
|
||||||
#include "../core/type_info.hpp"
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
#include "../poly/poly.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic poly storage implementation.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
struct Storage: type_list<type_info() const ENTT_NOEXCEPT> {
|
|
||||||
/**
|
|
||||||
* @brief Concept definition.
|
|
||||||
* @tparam Base Opaque base class from which to inherit.
|
|
||||||
*/
|
|
||||||
template<typename Base>
|
|
||||||
struct type: Base {
|
|
||||||
/**
|
|
||||||
* @brief Returns a type info for the contained objects.
|
|
||||||
* @return The type info for the contained objects.
|
|
||||||
*/
|
|
||||||
type_info value_type() const ENTT_NOEXCEPT {
|
|
||||||
return poly_call<0>(*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Concept implementation.
|
|
||||||
* @tparam Type Type for which to generate an implementation.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
using impl = value_list<&type_id<typename Type::value_type>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Defines the poly storage type associate with a given entity type.
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity, typename = void>
|
|
||||||
struct poly_storage_traits {
|
|
||||||
/*! @brief Poly storage type for the given entity type. */
|
|
||||||
using storage_type = poly<Storage<Entity>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
1713
LiteLoader/Header/third-party/entt/entity/registry.hpp
vendored
1713
LiteLoader/Header/third-party/entt/entity/registry.hpp
vendored
File diff suppressed because it is too large
Load Diff
@ -1,245 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
|
|
||||||
#define ENTT_ENTITY_RUNTIME_VIEW_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <type_traits>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "entity.hpp"
|
|
||||||
#include "sparse_set.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Runtime view.
|
|
||||||
*
|
|
||||||
* Runtime views iterate over those entities that have at least all the given
|
|
||||||
* components in their bags. During initialization, a runtime view looks at the
|
|
||||||
* number of entities available for each component and picks up a reference to
|
|
||||||
* the smallest set of candidate entities in order to get a performance boost
|
|
||||||
* when iterate.<br/>
|
|
||||||
* Order of elements during iterations are highly dependent on the order of the
|
|
||||||
* underlying data structures. See sparse_set and its specializations for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* @b Important
|
|
||||||
*
|
|
||||||
* Iterators aren't invalidated if:
|
|
||||||
*
|
|
||||||
* * New instances of the given components are created and assigned to entities.
|
|
||||||
* * The entity currently pointed is modified (as an example, if one of the
|
|
||||||
* given components is removed from the entity to which the iterator points).
|
|
||||||
* * The entity currently pointed is destroyed.
|
|
||||||
*
|
|
||||||
* In all the other cases, modifying the pools of the given components in any
|
|
||||||
* way invalidates all the iterators and using them results in undefined
|
|
||||||
* behavior.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Views share references to the underlying data structures of the registry that
|
|
||||||
* generated them. Therefore any change to the entities and to the components
|
|
||||||
* made by means of the registry are immediately reflected by the views, unless
|
|
||||||
* a pool was missing when the view was built (in this case, the view won't
|
|
||||||
* have a valid reference and won't be updated accordingly).
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Lifetime of a view must not overcome that of the registry that generated it.
|
|
||||||
* In any other case, attempting to use a view results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
*/
|
|
||||||
template<typename Entity>
|
|
||||||
class basic_runtime_view final {
|
|
||||||
using basic_common_type = basic_sparse_set<Entity>;
|
|
||||||
using underlying_iterator = typename basic_common_type::iterator;
|
|
||||||
|
|
||||||
class view_iterator final {
|
|
||||||
[[nodiscard]] bool valid() const {
|
|
||||||
const auto entt = *it;
|
|
||||||
|
|
||||||
return (!stable_storage || (entt != tombstone))
|
|
||||||
&& std::all_of(pools->begin()++, pools->end(), [entt](const auto *curr) { return curr->contains(entt); })
|
|
||||||
&& std::none_of(filter->cbegin(), filter->cend(), [entt](const auto *curr) { return curr && curr->contains(entt); });
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
using difference_type = typename underlying_iterator::difference_type;
|
|
||||||
using value_type = typename underlying_iterator::value_type;
|
|
||||||
using pointer = typename underlying_iterator::pointer;
|
|
||||||
using reference = typename underlying_iterator::reference;
|
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
|
||||||
|
|
||||||
view_iterator() ENTT_NOEXCEPT = default;
|
|
||||||
|
|
||||||
view_iterator(const std::vector<const basic_common_type *> &cpools, const std::vector<const basic_common_type *> &ignore, underlying_iterator curr) ENTT_NOEXCEPT
|
|
||||||
: pools{&cpools},
|
|
||||||
filter{&ignore},
|
|
||||||
it{curr},
|
|
||||||
stable_storage{std::any_of(pools->cbegin(), pools->cend(), [](const basic_common_type *cpool) { return (cpool->policy() == deletion_policy::in_place); })}
|
|
||||||
{
|
|
||||||
if(it != (*pools)[0]->end() && !valid()) {
|
|
||||||
++(*this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view_iterator & operator++() {
|
|
||||||
while(++it != (*pools)[0]->end() && !valid());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
view_iterator operator++(int) {
|
|
||||||
view_iterator orig = *this;
|
|
||||||
return ++(*this), orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
view_iterator & operator--() ENTT_NOEXCEPT {
|
|
||||||
while(--it != (*pools)[0]->begin() && !valid());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
view_iterator operator--(int) ENTT_NOEXCEPT {
|
|
||||||
view_iterator orig = *this;
|
|
||||||
return operator--(), orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(const view_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return other.it == it;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator!=(const view_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] pointer operator->() const {
|
|
||||||
return it.operator->();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reference operator*() const {
|
|
||||||
return *operator->();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::vector<const basic_common_type *> *pools;
|
|
||||||
const std::vector<const basic_common_type *> *filter;
|
|
||||||
underlying_iterator it;
|
|
||||||
bool stable_storage;
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] bool valid() const {
|
|
||||||
return !pools.empty() && pools.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Underlying entity identifier. */
|
|
||||||
using entity_type = Entity;
|
|
||||||
/*! @brief Unsigned integer type. */
|
|
||||||
using size_type = std::size_t;
|
|
||||||
/*! @brief Bidirectional iterator type. */
|
|
||||||
using iterator = view_iterator;
|
|
||||||
|
|
||||||
/*! @brief Default constructor to use to create empty, invalid views. */
|
|
||||||
basic_runtime_view() ENTT_NOEXCEPT
|
|
||||||
: pools{},
|
|
||||||
filter{}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs a runtime view from a set of storage classes.
|
|
||||||
* @param cpools The storage for the types to iterate.
|
|
||||||
* @param epools The storage for the types used to filter the view.
|
|
||||||
*/
|
|
||||||
basic_runtime_view(std::vector<const basic_common_type *> cpools, std::vector<const basic_common_type *> epools) ENTT_NOEXCEPT
|
|
||||||
: pools{std::move(cpools)},
|
|
||||||
filter{std::move(epools)}
|
|
||||||
{
|
|
||||||
// brings the best candidate (if any) on front of the vector
|
|
||||||
std::rotate(pools.begin(), std::min_element(pools.begin(), pools.end(), [](const auto *lhs, const auto *rhs) {
|
|
||||||
return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size());
|
|
||||||
}), pools.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Estimates the number of entities iterated by the view.
|
|
||||||
* @return Estimated number of entities iterated by the view.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type size_hint() const {
|
|
||||||
return valid() ? pools.front()->size() : size_type{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first entity that has the given
|
|
||||||
* components.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity that has the given
|
|
||||||
* components. If the view is empty, the returned iterator will be equal to
|
|
||||||
* `end()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity that has the given components.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator begin() const {
|
|
||||||
return valid() ? iterator{pools, filter, pools[0]->begin()} : iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator that is past the last entity that has the
|
|
||||||
* given components.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the entity following the last entity that
|
|
||||||
* has the given components. Attempting to dereference the returned iterator
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the entity following the last entity that has the
|
|
||||||
* given components.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator end() const {
|
|
||||||
return valid() ? iterator{pools, filter, pools[0]->end()} : iterator{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a view contains an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return True if the view contains the given entity, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool contains(const entity_type entt) const {
|
|
||||||
return valid() && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); })
|
|
||||||
&& std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Iterates entities and applies the given function object to them.
|
|
||||||
*
|
|
||||||
* The function object is invoked for each entity. It is provided only with
|
|
||||||
* the entity itself. To get the components, users can use the registry with
|
|
||||||
* which the view was built.<br/>
|
|
||||||
* The signature of the function should be equivalent to the following:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* void(const entity_type);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @tparam Func Type of the function object to invoke.
|
|
||||||
* @param func A valid function object.
|
|
||||||
*/
|
|
||||||
template<typename Func>
|
|
||||||
void each(Func func) const {
|
|
||||||
for(const auto entity: *this) {
|
|
||||||
func(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<const basic_common_type *> pools;
|
|
||||||
std::vector<const basic_common_type *> filter;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,870 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_SPARSE_SET_HPP
|
|
||||||
#define ENTT_ENTITY_SPARSE_SET_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <iterator>
|
|
||||||
#include <memory>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/algorithm.hpp"
|
|
||||||
#include "../core/fwd.hpp"
|
|
||||||
#include "entity.hpp"
|
|
||||||
#include "fwd.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Sparse set deletion policy. */
|
|
||||||
enum class deletion_policy: std::uint8_t {
|
|
||||||
/*! @brief Swap-and-pop deletion policy. */
|
|
||||||
swap_and_pop = 0u,
|
|
||||||
/*! @brief In-place deletion policy. */
|
|
||||||
in_place = 1u
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic sparse set implementation.
|
|
||||||
*
|
|
||||||
* Sparse set or packed array or whatever is the name users give it.<br/>
|
|
||||||
* Two arrays: an _external_ one and an _internal_ one; a _sparse_ one and a
|
|
||||||
* _packed_ one; one used for direct access through contiguous memory, the other
|
|
||||||
* one used to get the data through an extra level of indirection.<br/>
|
|
||||||
* This is largely used by the registry to offer users the fastest access ever
|
|
||||||
* to the components. Views and groups in general are almost entirely designed
|
|
||||||
* around sparse sets.
|
|
||||||
*
|
|
||||||
* This type of data structure is widely documented in the literature and on the
|
|
||||||
* web. This is nothing more than a customized implementation suitable for the
|
|
||||||
* purpose of the framework.
|
|
||||||
*
|
|
||||||
* @note
|
|
||||||
* Internal data structures arrange elements to maximize performance. There are
|
|
||||||
* no guarantees that entities are returned in the insertion order when iterate
|
|
||||||
* a sparse set. Do not make assumption on the order in any case.
|
|
||||||
*
|
|
||||||
* @tparam Entity A valid entity type (see entt_traits for more details).
|
|
||||||
* @tparam Allocator Type of allocator used to manage memory and elements.
|
|
||||||
*/
|
|
||||||
template<typename Entity, typename Allocator>
|
|
||||||
class basic_sparse_set {
|
|
||||||
static constexpr auto growth_factor = 1.5;
|
|
||||||
static constexpr auto sparse_page = ENTT_SPARSE_PAGE;
|
|
||||||
|
|
||||||
using traits_type = entt_traits<Entity>;
|
|
||||||
|
|
||||||
using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Entity>;
|
|
||||||
using alloc_pointer = typename alloc_traits::pointer;
|
|
||||||
using alloc_const_pointer = typename alloc_traits::const_pointer;
|
|
||||||
|
|
||||||
using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
|
|
||||||
using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
|
|
||||||
|
|
||||||
static_assert(alloc_traits::propagate_on_container_move_assignment::value);
|
|
||||||
static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value);
|
|
||||||
|
|
||||||
struct sparse_set_iterator final {
|
|
||||||
using difference_type = typename traits_type::difference_type;
|
|
||||||
using value_type = Entity;
|
|
||||||
using pointer = const value_type *;
|
|
||||||
using reference = const value_type &;
|
|
||||||
using iterator_category = std::random_access_iterator_tag;
|
|
||||||
|
|
||||||
sparse_set_iterator() ENTT_NOEXCEPT = default;
|
|
||||||
|
|
||||||
sparse_set_iterator(const alloc_const_pointer *ref, const difference_type idx) ENTT_NOEXCEPT
|
|
||||||
: packed{ref},
|
|
||||||
index{idx}
|
|
||||||
{}
|
|
||||||
|
|
||||||
sparse_set_iterator & operator++() ENTT_NOEXCEPT {
|
|
||||||
return --index, *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator operator++(int) ENTT_NOEXCEPT {
|
|
||||||
iterator orig = *this;
|
|
||||||
return ++(*this), orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator & operator--() ENTT_NOEXCEPT {
|
|
||||||
return ++index, *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator operator--(int) ENTT_NOEXCEPT {
|
|
||||||
sparse_set_iterator orig = *this;
|
|
||||||
return operator--(), orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
|
|
||||||
index -= value;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
|
|
||||||
sparse_set_iterator copy = *this;
|
|
||||||
return (copy += value);
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
|
|
||||||
return (*this += -value);
|
|
||||||
}
|
|
||||||
|
|
||||||
sparse_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
|
|
||||||
return (*this + -value);
|
|
||||||
}
|
|
||||||
|
|
||||||
difference_type operator-(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return other.index - index;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reference operator[](const difference_type value) const {
|
|
||||||
const auto pos = size_type(index-value-1u);
|
|
||||||
return (*packed)[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return other.index == index;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator!=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator<(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return index > other.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator>(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return index < other.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator<=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return !(*this > other);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator>=(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
|
|
||||||
return !(*this < other);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] pointer operator->() const {
|
|
||||||
const auto pos = size_type(index-1u);
|
|
||||||
return std::addressof((*packed)[pos]);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] reference operator*() const {
|
|
||||||
return *operator->();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const alloc_const_pointer *packed;
|
|
||||||
difference_type index;
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] static auto page(const Entity entt) ENTT_NOEXCEPT {
|
|
||||||
return static_cast<size_type>(traits_type::to_entity(entt) / sparse_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static auto offset(const Entity entt) ENTT_NOEXCEPT {
|
|
||||||
return static_cast<size_type>(traits_type::to_entity(entt) & (sparse_page - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto assure_page(const std::size_t idx) {
|
|
||||||
if(!(idx < bucket)) {
|
|
||||||
const size_type sz = idx + 1u;
|
|
||||||
const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz);
|
|
||||||
|
|
||||||
std::uninitialized_value_construct(mem + bucket, mem + sz);
|
|
||||||
std::uninitialized_copy(sparse, sparse + bucket, mem);
|
|
||||||
|
|
||||||
std::destroy(sparse, sparse + bucket);
|
|
||||||
bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
|
|
||||||
|
|
||||||
sparse = mem;
|
|
||||||
bucket = sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!sparse[idx]) {
|
|
||||||
sparse[idx] = alloc_traits::allocate(allocator, sparse_page);
|
|
||||||
std::uninitialized_fill(sparse[idx], sparse[idx] + sparse_page, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sparse[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize_packed(const std::size_t req) {
|
|
||||||
ENTT_ASSERT((req != reserved) && !(req < count), "Invalid request");
|
|
||||||
const auto mem = alloc_traits::allocate(allocator, req);
|
|
||||||
|
|
||||||
std::uninitialized_copy(packed, packed + count, mem);
|
|
||||||
std::uninitialized_fill(mem + count, mem + req, tombstone);
|
|
||||||
|
|
||||||
std::destroy(packed, packed + reserved);
|
|
||||||
alloc_traits::deallocate(allocator, packed, reserved);
|
|
||||||
|
|
||||||
packed = mem;
|
|
||||||
reserved = req;
|
|
||||||
}
|
|
||||||
|
|
||||||
void release_memory() {
|
|
||||||
if(packed) {
|
|
||||||
for(size_type pos{}; pos < bucket; ++pos) {
|
|
||||||
if(sparse[pos]) {
|
|
||||||
std::destroy(sparse[pos], sparse[pos] + sparse_page);
|
|
||||||
alloc_traits::deallocate(allocator, sparse[pos], sparse_page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::destroy(packed, packed + reserved);
|
|
||||||
std::destroy(sparse, sparse + bucket);
|
|
||||||
alloc_traits::deallocate(allocator, packed, reserved);
|
|
||||||
bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Swaps two entities in the internal packed array.
|
|
||||||
* @param lhs A valid position of an entity within storage.
|
|
||||||
* @param rhs A valid position of an entity within storage.
|
|
||||||
*/
|
|
||||||
virtual void swap_at([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Moves an entity in the internal packed array.
|
|
||||||
* @param from A valid position of an entity within storage.
|
|
||||||
* @param to A valid position of an entity within storage.
|
|
||||||
*/
|
|
||||||
virtual void move_and_pop([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Attempts to erase an entity from the internal packed array.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
*/
|
|
||||||
virtual void swap_and_pop(const Entity entt, [[maybe_unused]] void *ud) {
|
|
||||||
auto &ref = sparse[page(entt)][offset(entt)];
|
|
||||||
const auto pos = static_cast<size_type>(traits_type::to_entity(ref));
|
|
||||||
ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
|
|
||||||
auto &last = packed[--count];
|
|
||||||
|
|
||||||
packed[pos] = last;
|
|
||||||
sparse[page(last)][offset(last)] = ref;
|
|
||||||
// lazy self-assignment guard
|
|
||||||
ref = null;
|
|
||||||
// unnecessary but it helps to detect nasty bugs
|
|
||||||
ENTT_ASSERT((last = tombstone, true), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Attempts to erase an entity from the internal packed array.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
*/
|
|
||||||
virtual void in_place_pop(const Entity entt, [[maybe_unused]] void *ud) {
|
|
||||||
auto &ref = sparse[page(entt)][offset(entt)];
|
|
||||||
const auto pos = static_cast<size_type>(traits_type::to_entity(ref));
|
|
||||||
ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
|
|
||||||
|
|
||||||
packed[pos] = std::exchange(free_list, traits_type::construct(static_cast<typename traits_type::entity_type>(pos)));
|
|
||||||
// lazy self-assignment guard
|
|
||||||
ref = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*! @brief Allocator type. */
|
|
||||||
using allocator_type = typename alloc_traits::allocator_type;
|
|
||||||
/*! @brief Underlying entity identifier. */
|
|
||||||
using entity_type = Entity;
|
|
||||||
/*! @brief Unsigned integer type. */
|
|
||||||
using size_type = std::size_t;
|
|
||||||
/*! @brief Pointer type to contained entities. */
|
|
||||||
using pointer = alloc_const_pointer;
|
|
||||||
/*! @brief Random access iterator type. */
|
|
||||||
using iterator = sparse_set_iterator;
|
|
||||||
/*! @brief Reverse iterator type. */
|
|
||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs an empty container with the given policy and allocator.
|
|
||||||
* @param pol Type of deletion policy.
|
|
||||||
* @param alloc Allocator to use (possibly default-constructed).
|
|
||||||
*/
|
|
||||||
explicit basic_sparse_set(deletion_policy pol, const allocator_type &alloc = {})
|
|
||||||
: allocator{alloc},
|
|
||||||
bucket_allocator{alloc},
|
|
||||||
sparse{bucket_alloc_traits::allocate(bucket_allocator, 0u)},
|
|
||||||
packed{alloc_traits::allocate(allocator, 0u)},
|
|
||||||
bucket{0u},
|
|
||||||
count{0u},
|
|
||||||
reserved{0u},
|
|
||||||
free_list{tombstone},
|
|
||||||
mode{pol}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructs an empty container with the given allocator.
|
|
||||||
* @param alloc Allocator to use (possibly default-constructed).
|
|
||||||
*/
|
|
||||||
explicit basic_sparse_set(const allocator_type &alloc = {})
|
|
||||||
: basic_sparse_set{deletion_policy::swap_and_pop, alloc}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Move constructor.
|
|
||||||
* @param other The instance to move from.
|
|
||||||
*/
|
|
||||||
basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
|
|
||||||
: allocator{std::move(other.allocator)},
|
|
||||||
bucket_allocator{std::move(other.bucket_allocator)},
|
|
||||||
sparse{std::exchange(other.sparse, bucket_alloc_pointer{})},
|
|
||||||
packed{std::exchange(other.packed, alloc_pointer{})},
|
|
||||||
bucket{std::exchange(other.bucket, 0u)},
|
|
||||||
count{std::exchange(other.count, 0u)},
|
|
||||||
reserved{std::exchange(other.reserved, 0u)},
|
|
||||||
free_list{std::exchange(other.free_list, tombstone)},
|
|
||||||
mode{other.mode}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*! @brief Default destructor. */
|
|
||||||
virtual ~basic_sparse_set() {
|
|
||||||
release_memory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Move assignment operator.
|
|
||||||
* @param other The instance to move from.
|
|
||||||
* @return This sparse set.
|
|
||||||
*/
|
|
||||||
basic_sparse_set & operator=(basic_sparse_set &&other) ENTT_NOEXCEPT {
|
|
||||||
release_memory();
|
|
||||||
|
|
||||||
allocator = std::move(other.allocator);
|
|
||||||
bucket_allocator = std::move(other.bucket_allocator);
|
|
||||||
sparse = std::exchange(other.sparse, bucket_alloc_pointer{});
|
|
||||||
packed = std::exchange(other.packed, alloc_pointer{});
|
|
||||||
bucket = std::exchange(other.bucket, 0u);
|
|
||||||
count = std::exchange(other.count, 0u);
|
|
||||||
reserved = std::exchange(other.reserved, 0u);
|
|
||||||
free_list = std::exchange(other.free_list, tombstone);
|
|
||||||
mode = other.mode;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the deletion policy of a sparse set.
|
|
||||||
* @return The deletion policy of the sparse set.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] deletion_policy policy() const ENTT_NOEXCEPT {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the next slot available for insertion.
|
|
||||||
* @return The next slot available for insertion.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type slot() const ENTT_NOEXCEPT {
|
|
||||||
return free_list == null ? count : static_cast<size_type>(traits_type::to_entity(free_list));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Increases the capacity of a sparse set.
|
|
||||||
*
|
|
||||||
* If the new capacity is greater than the current capacity, new storage is
|
|
||||||
* allocated, otherwise the method does nothing.
|
|
||||||
*
|
|
||||||
* @param cap Desired capacity.
|
|
||||||
*/
|
|
||||||
void reserve(const size_type cap) {
|
|
||||||
if(cap > reserved) {
|
|
||||||
resize_packed(cap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the number of elements that a sparse set has currently
|
|
||||||
* allocated space for.
|
|
||||||
* @return Capacity of the sparse set.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type capacity() const ENTT_NOEXCEPT {
|
|
||||||
return reserved;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @brief Requests the removal of unused capacity. */
|
|
||||||
void shrink_to_fit() {
|
|
||||||
if(count < reserved) {
|
|
||||||
resize_packed(count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the extent of a sparse set.
|
|
||||||
*
|
|
||||||
* The extent of a sparse set is also the size of the internal sparse array.
|
|
||||||
* There is no guarantee that the internal packed array has the same size.
|
|
||||||
* Usually the size of the internal sparse array is equal or greater than
|
|
||||||
* the one of the internal packed array.
|
|
||||||
*
|
|
||||||
* @return Extent of the sparse set.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type extent() const ENTT_NOEXCEPT {
|
|
||||||
return bucket * sparse_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the number of elements in a sparse set.
|
|
||||||
*
|
|
||||||
* The number of elements is also the size of the internal packed array.
|
|
||||||
* There is no guarantee that the internal sparse array has the same size.
|
|
||||||
* Usually the size of the internal sparse array is equal or greater than
|
|
||||||
* the one of the internal packed array.
|
|
||||||
*
|
|
||||||
* @return Number of elements.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type size() const ENTT_NOEXCEPT {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks whether a sparse set is empty.
|
|
||||||
* @return True if the sparse set is empty, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool empty() const ENTT_NOEXCEPT {
|
|
||||||
return (count == size_type{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Direct access to the internal packed array.
|
|
||||||
* @return A pointer to the internal packed array.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] pointer data() const ENTT_NOEXCEPT {
|
|
||||||
return packed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the beginning.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity of the internal packed
|
|
||||||
* array. If the sparse set is empty, the returned iterator will be equal to
|
|
||||||
* `end()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity of the internal packed array.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
|
|
||||||
return iterator{std::addressof(packed), static_cast<typename traits_type::difference_type>(count)};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the end.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the element following the last entity in
|
|
||||||
* the internal packed array. Attempting to dereference the returned
|
|
||||||
* iterator results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the element following the last entity of the
|
|
||||||
* internal packed array.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator end() const ENTT_NOEXCEPT {
|
|
||||||
return iterator{std::addressof(packed), {}};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a reverse iterator to the beginning.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the first entity of the reversed internal
|
|
||||||
* packed array. If the sparse set is empty, the returned iterator will be
|
|
||||||
* equal to `rend()`.
|
|
||||||
*
|
|
||||||
* @return An iterator to the first entity of the reversed internal packed
|
|
||||||
* array.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
|
|
||||||
return std::make_reverse_iterator(end());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a reverse iterator to the end.
|
|
||||||
*
|
|
||||||
* The returned iterator points to the element following the last entity in
|
|
||||||
* the reversed internal packed array. Attempting to dereference the
|
|
||||||
* returned iterator results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @return An iterator to the element following the last entity of the
|
|
||||||
* reversed internal packed array.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
|
|
||||||
return std::make_reverse_iterator(begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Finds an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return An iterator to the given entity if it's found, past the end
|
|
||||||
* iterator otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] iterator find(const entity_type entt) const ENTT_NOEXCEPT {
|
|
||||||
return contains(entt) ? --(end() - index(entt)) : end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if a sparse set contains an entity.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return True if the sparse set contains the entity, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
|
|
||||||
ENTT_ASSERT(entt != tombstone && entt != null, "Invalid entity");
|
|
||||||
const auto curr = page(entt);
|
|
||||||
// testing versions permits to avoid accessing the packed array
|
|
||||||
return (curr < bucket && sparse[curr] && sparse[curr][offset(entt)] != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the position of an entity in a sparse set.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to get the position of an entity that doesn't belong to the
|
|
||||||
* sparse set results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return The position of the entity in the sparse set.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] size_type index(const entity_type entt) const ENTT_NOEXCEPT {
|
|
||||||
ENTT_ASSERT(contains(entt), "Set does not contain entity");
|
|
||||||
return static_cast<size_type>(traits_type::to_entity(sparse[page(entt)][offset(entt)]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the entity at specified location, with bounds checking.
|
|
||||||
* @param pos The position for which to return the entity.
|
|
||||||
* @return The entity at specified location if any, a null entity otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type at(const size_type pos) const ENTT_NOEXCEPT {
|
|
||||||
return pos < count ? packed[pos] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns the entity at specified location, without bounds checking.
|
|
||||||
* @param pos The position for which to return the entity.
|
|
||||||
* @return The entity at specified location.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] entity_type operator[](const size_type pos) const ENTT_NOEXCEPT {
|
|
||||||
ENTT_ASSERT(pos < count, "Position is out of bounds");
|
|
||||||
return packed[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Appends an entity to a sparse set.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to assign an entity that already belongs to the sparse set
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return The slot used for insertion.
|
|
||||||
*/
|
|
||||||
size_type emplace_back(const entity_type entt) {
|
|
||||||
ENTT_ASSERT(!contains(entt), "Set already contains entity");
|
|
||||||
|
|
||||||
if(count == reserved) {
|
|
||||||
const size_type sz = static_cast<size_type>(reserved * growth_factor);
|
|
||||||
resize_packed(sz + !(sz > reserved));
|
|
||||||
}
|
|
||||||
|
|
||||||
assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(count));
|
|
||||||
packed[count] = entt;
|
|
||||||
return count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns an entity to a sparse set.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to assign an entity that already belongs to the sparse set
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @return The slot used for insertion.
|
|
||||||
*/
|
|
||||||
size_type emplace(const entity_type entt) {
|
|
||||||
if(free_list == null) {
|
|
||||||
return emplace_back(entt);
|
|
||||||
} else {
|
|
||||||
ENTT_ASSERT(!contains(entt), "Set already contains entity");
|
|
||||||
const auto pos = static_cast<size_type>(traits_type::to_entity(free_list));
|
|
||||||
assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(pos));
|
|
||||||
free_list = std::exchange(packed[pos], entt);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns one or more entities to a sparse set.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to assign an entity that already belongs to the sparse set
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @tparam It Type of input iterator.
|
|
||||||
* @param first An iterator to the first element of the range of entities.
|
|
||||||
* @param last An iterator past the last element of the range of entities.
|
|
||||||
*/
|
|
||||||
template<typename It>
|
|
||||||
void insert(It first, It last) {
|
|
||||||
reserve(count + std::distance(first, last));
|
|
||||||
|
|
||||||
for(; first != last; ++first) {
|
|
||||||
const auto entt = *first;
|
|
||||||
ENTT_ASSERT(!contains(entt), "Set already contains entity");
|
|
||||||
assure_page(page(entt))[offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(count));
|
|
||||||
packed[count++] = entt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Erases an entity from a sparse set.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to erase an entity that doesn't belong to the sparse set
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
*/
|
|
||||||
void erase(const entity_type entt, void *ud = nullptr) {
|
|
||||||
ENTT_ASSERT(contains(entt), "Set does not contain entity");
|
|
||||||
(mode == deletion_policy::in_place) ? in_place_pop(entt, ud) : swap_and_pop(entt, ud);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Erases entities from a set.
|
|
||||||
*
|
|
||||||
* @sa erase
|
|
||||||
*
|
|
||||||
* @tparam It Type of input iterator.
|
|
||||||
* @param first An iterator to the first element of the range of entities.
|
|
||||||
* @param last An iterator past the last element of the range of entities.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
*/
|
|
||||||
template<typename It>
|
|
||||||
void erase(It first, It last, void *ud = nullptr) {
|
|
||||||
for(; first != last; ++first) {
|
|
||||||
erase(*first, ud);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Removes an entity from a sparse set if it exists.
|
|
||||||
* @param entt A valid entity identifier.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
* @return True if the entity is actually removed, false otherwise.
|
|
||||||
*/
|
|
||||||
bool remove(const entity_type entt, void *ud = nullptr) {
|
|
||||||
return contains(entt) && (erase(entt, ud), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Removes entities from a sparse set if they exist.
|
|
||||||
* @tparam It Type of input iterator.
|
|
||||||
* @param first An iterator to the first element of the range of entities.
|
|
||||||
* @param last An iterator past the last element of the range of entities.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
* @return The number of entities actually removed.
|
|
||||||
*/
|
|
||||||
template<typename It>
|
|
||||||
size_type remove(It first, It last, void *ud = nullptr) {
|
|
||||||
size_type found{};
|
|
||||||
|
|
||||||
for(; first != last; ++first) {
|
|
||||||
found += remove(*first, ud);
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @brief Removes all tombstones from the packed array of a sparse set. */
|
|
||||||
void compact() {
|
|
||||||
size_type next = count;
|
|
||||||
for(; next && packed[next - 1u] == tombstone; --next);
|
|
||||||
|
|
||||||
for(auto *it = &free_list; *it != null && next; it = std::addressof(packed[traits_type::to_entity(*it)])) {
|
|
||||||
if(const size_type pos = traits_type::to_entity(*it); pos < next) {
|
|
||||||
--next;
|
|
||||||
move_and_pop(next, pos);
|
|
||||||
std::swap(packed[next], packed[pos]);
|
|
||||||
sparse[page(packed[pos])][offset(packed[pos])] = traits_type::construct(static_cast<const typename traits_type::entity_type>(pos));
|
|
||||||
*it = traits_type::construct(static_cast<typename traits_type::entity_type>(next));
|
|
||||||
for(; next && packed[next - 1u] == tombstone; --next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_list = tombstone;
|
|
||||||
count = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @copybrief swap_at
|
|
||||||
*
|
|
||||||
* For what it's worth, this function affects both the internal sparse array
|
|
||||||
* and the internal packed array. Users should not care of that anyway.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* Attempting to swap entities that don't belong to the sparse set results
|
|
||||||
* in undefined behavior.
|
|
||||||
*
|
|
||||||
* @param lhs A valid entity identifier.
|
|
||||||
* @param rhs A valid entity identifier.
|
|
||||||
*/
|
|
||||||
void swap(const entity_type lhs, const entity_type rhs) {
|
|
||||||
ENTT_ASSERT(contains(lhs), "Set does not contain entity");
|
|
||||||
ENTT_ASSERT(contains(rhs), "Set does not contain entity");
|
|
||||||
|
|
||||||
auto &entt = sparse[page(lhs)][offset(lhs)];
|
|
||||||
auto &other = sparse[page(rhs)][offset(rhs)];
|
|
||||||
|
|
||||||
const auto from = static_cast<size_type>(traits_type::to_entity(entt));
|
|
||||||
const auto to = static_cast<size_type>(traits_type::to_entity(other));
|
|
||||||
|
|
||||||
// basic no-leak guarantee (with invalid state) if swapping throws
|
|
||||||
swap_at(from, to);
|
|
||||||
std::swap(entt, other);
|
|
||||||
std::swap(packed[from], packed[to]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sort the first count elements according to the given comparison
|
|
||||||
* function.
|
|
||||||
*
|
|
||||||
* The comparison function object must return `true` if the first element
|
|
||||||
* is _less_ than the second one, `false` otherwise. The signature of the
|
|
||||||
* comparison function should be equivalent to the following:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* bool(const Entity, const Entity);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* Moreover, the comparison function object shall induce a
|
|
||||||
* _strict weak ordering_ on the values.
|
|
||||||
*
|
|
||||||
* The sort function object must offer a member function template
|
|
||||||
* `operator()` that accepts three arguments:
|
|
||||||
*
|
|
||||||
* * An iterator to the first element of the range to sort.
|
|
||||||
* * An iterator past the last element of the range to sort.
|
|
||||||
* * A comparison function to use to compare the elements.
|
|
||||||
*
|
|
||||||
* @tparam Compare Type of comparison function object.
|
|
||||||
* @tparam Sort Type of sort function object.
|
|
||||||
* @tparam Args Types of arguments to forward to the sort function object.
|
|
||||||
* @param length Number of elements to sort.
|
|
||||||
* @param compare A valid comparison function object.
|
|
||||||
* @param algo A valid sort function object.
|
|
||||||
* @param args Arguments to forward to the sort function object, if any.
|
|
||||||
*/
|
|
||||||
template<typename Compare, typename Sort = std_sort, typename... Args>
|
|
||||||
void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&... args) {
|
|
||||||
// basic no-leak guarantee (with invalid state) if sorting throws
|
|
||||||
ENTT_ASSERT(!(length > count), "Length exceeds the number of elements");
|
|
||||||
compact();
|
|
||||||
|
|
||||||
algo(std::make_reverse_iterator(packed + length), std::make_reverse_iterator(packed), std::move(compare), std::forward<Args>(args)...);
|
|
||||||
|
|
||||||
for(size_type pos{}; pos < length; ++pos) {
|
|
||||||
auto curr = pos;
|
|
||||||
auto next = index(packed[curr]);
|
|
||||||
|
|
||||||
while(curr != next) {
|
|
||||||
const auto idx = index(packed[next]);
|
|
||||||
const auto entt = packed[curr];
|
|
||||||
|
|
||||||
swap_at(next, idx);
|
|
||||||
sparse[page(entt)][offset(entt)] = traits_type::construct(static_cast<typename traits_type::entity_type>(curr));
|
|
||||||
curr = std::exchange(next, idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sort all elements according to the given comparison function.
|
|
||||||
*
|
|
||||||
* @sa sort_n
|
|
||||||
*
|
|
||||||
* @tparam Compare Type of comparison function object.
|
|
||||||
* @tparam Sort Type of sort function object.
|
|
||||||
* @tparam Args Types of arguments to forward to the sort function object.
|
|
||||||
* @param compare A valid comparison function object.
|
|
||||||
* @param algo A valid sort function object.
|
|
||||||
* @param args Arguments to forward to the sort function object, if any.
|
|
||||||
*/
|
|
||||||
template<typename Compare, typename Sort = std_sort, typename... Args>
|
|
||||||
void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
|
|
||||||
sort_n(count, std::move(compare), std::move(algo), std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sort entities according to their order in another sparse set.
|
|
||||||
*
|
|
||||||
* Entities that are part of both the sparse sets are ordered internally
|
|
||||||
* according to the order they have in `other`. All the other entities goes
|
|
||||||
* to the end of the list and there are no guarantees on their order.<br/>
|
|
||||||
* In other terms, this function can be used to impose the same order on two
|
|
||||||
* sets by using one of them as a master and the other one as a slave.
|
|
||||||
*
|
|
||||||
* Iterating the sparse set with a couple of iterators returns elements in
|
|
||||||
* the expected order after a call to `respect`. See `begin` and `end` for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* @param other The sparse sets that imposes the order of the entities.
|
|
||||||
*/
|
|
||||||
void respect(const basic_sparse_set &other) {
|
|
||||||
compact();
|
|
||||||
|
|
||||||
const auto to = other.end();
|
|
||||||
auto from = other.begin();
|
|
||||||
|
|
||||||
for(size_type pos = count - 1; pos && from != to; ++from) {
|
|
||||||
if(contains(*from)) {
|
|
||||||
if(*from != packed[pos]) {
|
|
||||||
// basic no-leak guarantee (with invalid state) if swapping throws
|
|
||||||
swap(packed[pos], *from);
|
|
||||||
}
|
|
||||||
|
|
||||||
--pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clears a sparse set.
|
|
||||||
* @param ud Optional user data that are forwarded as-is to derived classes.
|
|
||||||
*/
|
|
||||||
void clear(void *ud = nullptr) {
|
|
||||||
for(auto &&entity: *this) {
|
|
||||||
if(entity != tombstone) {
|
|
||||||
in_place_pop(entity, ud);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_list = tombstone;
|
|
||||||
count = 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typename alloc_traits::allocator_type allocator;
|
|
||||||
typename bucket_alloc_traits::allocator_type bucket_allocator;
|
|
||||||
bucket_alloc_pointer sparse;
|
|
||||||
alloc_pointer packed;
|
|
||||||
std::size_t bucket;
|
|
||||||
std::size_t count;
|
|
||||||
std::size_t reserved;
|
|
||||||
entity_type free_list;
|
|
||||||
deletion_policy mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
1045
LiteLoader/Header/third-party/entt/entity/storage.hpp
vendored
1045
LiteLoader/Header/third-party/entt/entity/storage.hpp
vendored
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
|||||||
#ifndef ENTT_ENTITY_UTILITY_HPP
|
|
||||||
#define ENTT_ENTITY_UTILITY_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias for exclusion lists.
|
|
||||||
* @tparam Type List of types.
|
|
||||||
*/
|
|
||||||
template<typename... Type>
|
|
||||||
struct exclude_t: type_list<Type...> {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Variable template for exclusion lists.
|
|
||||||
* @tparam Type List of types.
|
|
||||||
*/
|
|
||||||
template<typename... Type>
|
|
||||||
inline constexpr exclude_t<Type...> exclude{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Alias for lists of observed components.
|
|
||||||
* @tparam Type List of types.
|
|
||||||
*/
|
|
||||||
template<typename... Type>
|
|
||||||
struct get_t: type_list<Type...>{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Variable template for lists of observed components.
|
|
||||||
* @tparam Type List of types.
|
|
||||||
*/
|
|
||||||
template<typename... Type>
|
|
||||||
inline constexpr get_t<Type...> get{};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
1056
LiteLoader/Header/third-party/entt/entity/view.hpp
vendored
1056
LiteLoader/Header/third-party/entt/entity/view.hpp
vendored
File diff suppressed because it is too large
Load Diff
5
LiteLoader/Header/third-party/entt/fwd.hpp
vendored
5
LiteLoader/Header/third-party/entt/fwd.hpp
vendored
@ -1,5 +0,0 @@
|
|||||||
#include "core/fwd.hpp"
|
|
||||||
#include "entity/fwd.hpp"
|
|
||||||
#include "poly/fwd.hpp"
|
|
||||||
#include "resource/fwd.hpp"
|
|
||||||
#include "signal/fwd.hpp"
|
|
@ -1,111 +0,0 @@
|
|||||||
#ifndef ENTT_LOCATOR_LOCATOR_HPP
|
|
||||||
#define ENTT_LOCATOR_LOCATOR_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
#include "../config/config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Service locator, nothing more.
|
|
||||||
*
|
|
||||||
* A service locator can be used to do what it promises: locate services.<br/>
|
|
||||||
* Usually service locators are tightly bound to the services they expose and
|
|
||||||
* thus it's hard to define a general purpose class to do that. This template
|
|
||||||
* based implementation tries to fill the gap and to get rid of the burden of
|
|
||||||
* defining a different specific locator for each application.
|
|
||||||
*
|
|
||||||
* @tparam Service Type of service managed by the locator.
|
|
||||||
*/
|
|
||||||
template<typename Service>
|
|
||||||
struct service_locator {
|
|
||||||
/*! @brief Type of service offered. */
|
|
||||||
using service_type = Service;
|
|
||||||
|
|
||||||
/*! @brief Default constructor, deleted on purpose. */
|
|
||||||
service_locator() = delete;
|
|
||||||
/*! @brief Default destructor, deleted on purpose. */
|
|
||||||
~service_locator() = delete;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tests if a valid service implementation is set.
|
|
||||||
* @return True if the service is set, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool empty() ENTT_NOEXCEPT {
|
|
||||||
return !static_cast<bool>(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a weak pointer to a service implementation, if any.
|
|
||||||
*
|
|
||||||
* Clients of a service shouldn't retain references to it. The recommended
|
|
||||||
* way is to retrieve the service implementation currently set each and
|
|
||||||
* every time the need of using it arises. Otherwise users can incur in
|
|
||||||
* unexpected behaviors.
|
|
||||||
*
|
|
||||||
* @return A reference to the service implementation currently set, if any.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static std::weak_ptr<Service> get() ENTT_NOEXCEPT {
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a weak reference to a service implementation, if any.
|
|
||||||
*
|
|
||||||
* Clients of a service shouldn't retain references to it. The recommended
|
|
||||||
* way is to retrieve the service implementation currently set each and
|
|
||||||
* every time the need of using it arises. Otherwise users can incur in
|
|
||||||
* unexpected behaviors.
|
|
||||||
*
|
|
||||||
* @warning
|
|
||||||
* In case no service implementation has been set, a call to this function
|
|
||||||
* results in undefined behavior.
|
|
||||||
*
|
|
||||||
* @return A reference to the service implementation currently set, if any.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static Service & ref() ENTT_NOEXCEPT {
|
|
||||||
return *service;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets or replaces a service.
|
|
||||||
* @tparam Impl Type of the new service to use.
|
|
||||||
* @tparam Args Types of arguments to use to construct the service.
|
|
||||||
* @param args Parameters to use to construct the service.
|
|
||||||
*/
|
|
||||||
template<typename Impl = Service, typename... Args>
|
|
||||||
static void set(Args &&... args) {
|
|
||||||
service = std::make_shared<Impl>(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sets or replaces a service.
|
|
||||||
* @param ptr Service to use to replace the current one.
|
|
||||||
*/
|
|
||||||
static void set(std::shared_ptr<Service> ptr) {
|
|
||||||
ENTT_ASSERT(static_cast<bool>(ptr), "Null service not allowed");
|
|
||||||
service = std::move(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resets a service.
|
|
||||||
*
|
|
||||||
* The service is no longer valid after a reset.
|
|
||||||
*/
|
|
||||||
static void reset() {
|
|
||||||
service.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline static std::shared_ptr<Service> service = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,406 +0,0 @@
|
|||||||
#ifndef ENTT_META_CONTAINER_HPP
|
|
||||||
#define ENTT_META_CONTAINER_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
#include "type_traits.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Container traits.
|
|
||||||
* @tparam Container Type of the underlying container.
|
|
||||||
* @tparam Trait Traits associated with the underlying container.
|
|
||||||
*/
|
|
||||||
template<typename Container, template<typename> class... Trait>
|
|
||||||
struct meta_container_traits: public Trait<Container>... {
|
|
||||||
/*! @brief Type of container. */
|
|
||||||
using type = Container;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic STL-compatible container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct basic_container {
|
|
||||||
/**
|
|
||||||
* @brief Returns the size of the given container.
|
|
||||||
* @param cont The container for which to return the size.
|
|
||||||
* @return The size of the given container.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::size_type size(const Container &cont) ENTT_NOEXCEPT {
|
|
||||||
return cont.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first element of the given container.
|
|
||||||
* @param cont The container for which to return the iterator.
|
|
||||||
* @return An iterator to the first element of the given container.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::iterator begin(Container &cont) {
|
|
||||||
return cont.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the first element of the given container.
|
|
||||||
* @param cont The container for which to return the iterator.
|
|
||||||
* @return An iterator to the first element of the given container.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::const_iterator cbegin(const Container &cont) {
|
|
||||||
return cont.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator past the last element of the given container.
|
|
||||||
* @param cont The container for which to return the iterator.
|
|
||||||
* @return An iterator past the last element of the given container.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::iterator end(Container &cont) {
|
|
||||||
return cont.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator past the last element of the given container.
|
|
||||||
* @param cont The container for which to return the iterator.
|
|
||||||
* @return An iterator past the last element of the given container.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::const_iterator cend(const Container &cont) {
|
|
||||||
return cont.end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic STL-compatible associative container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct basic_associative_container {
|
|
||||||
/**
|
|
||||||
* @brief Returns an iterator to the element with key equivalent to the
|
|
||||||
* given one, if any.
|
|
||||||
* @param cont The container in which to search for the element.
|
|
||||||
* @param key The key of the element to search.
|
|
||||||
* @return An iterator to the element with the given key, if any.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::iterator find(Container &cont, const typename Container::key_type &key) {
|
|
||||||
return cont.find(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc find */
|
|
||||||
[[nodiscard]] static typename Container::const_iterator cfind(const Container &cont, const typename Container::key_type &key) {
|
|
||||||
return cont.find(key);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic STL-compatible dynamic container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct basic_dynamic_container {
|
|
||||||
/**
|
|
||||||
* @brief Clears the content of the given container.
|
|
||||||
* @param cont The container for which to clear the content.
|
|
||||||
* @return True in case of success, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool clear([[maybe_unused]] Container &cont) {
|
|
||||||
return cont.clear(), true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic STL-compatible dynamic associative container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct basic_dynamic_associative_container {
|
|
||||||
/**
|
|
||||||
* @brief Removes the specified element from the given container.
|
|
||||||
* @param cont The container from which to remove the element.
|
|
||||||
* @param key The element to remove.
|
|
||||||
* @return A bool denoting whether the removal took place.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool erase([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
|
|
||||||
const auto sz = cont.size();
|
|
||||||
return cont.erase(key) != sz;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic STL-compatible sequence container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct basic_sequence_container {
|
|
||||||
/**
|
|
||||||
* @brief Returns a reference to the element at the specified location of
|
|
||||||
* the given container (no bounds checking is performed).
|
|
||||||
* @param cont The container from which to get the element.
|
|
||||||
* @param pos The position of the element to return.
|
|
||||||
* @return A reference to the requested element.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static typename Container::reference get(Container &cont, typename Container::size_type pos) {
|
|
||||||
return cont[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc get */
|
|
||||||
[[nodiscard]] static typename Container::const_reference cget(const Container &cont, typename Container::size_type pos) {
|
|
||||||
return cont[pos];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief STL-compatible dynamic associative key-only container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct dynamic_associative_key_only_container {
|
|
||||||
/**
|
|
||||||
* @brief Inserts an element into the given container.
|
|
||||||
* @param cont The container in which to insert the element.
|
|
||||||
* @param key The element to insert.
|
|
||||||
* @return A bool denoting whether the insertion took place.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
|
|
||||||
return cont.insert(key).second;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief STL-compatible dynamic key-value associative container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct dynamic_associative_key_value_container {
|
|
||||||
/**
|
|
||||||
* @brief Inserts an element (a key/value pair) into the given container.
|
|
||||||
* @param cont The container in which to insert the element.
|
|
||||||
* @param key The key of the element to insert.
|
|
||||||
* @param value The value of the element to insert.
|
|
||||||
* @return A bool denoting whether the insertion took place.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key, [[maybe_unused]] const typename Container::mapped_type &value) {
|
|
||||||
return cont.insert(std::make_pair(key, value)).second;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief STL-compatible dynamic sequence container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct dynamic_sequence_container {
|
|
||||||
/**
|
|
||||||
* @brief Resizes the given container to contain the given number of
|
|
||||||
* elements.
|
|
||||||
* @param cont The container to resize.
|
|
||||||
* @param sz The new size of the container.
|
|
||||||
* @return True in case of success, false otherwise.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool resize([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::size_type sz) {
|
|
||||||
return cont.resize(sz), true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Inserts an element at the specified location of the given
|
|
||||||
* container.
|
|
||||||
* @param cont The container into which to insert the element.
|
|
||||||
* @param it Iterator before which the element will be inserted.
|
|
||||||
* @param value Element value to insert.
|
|
||||||
* @return A pair consisting of an iterator to the inserted element (in case
|
|
||||||
* of success) and a bool denoting whether the insertion took place.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> insert([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it, [[maybe_unused]] const typename Container::value_type &value) {
|
|
||||||
return { cont.insert(it, value), true };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Removes the element at the specified location from the given
|
|
||||||
* container.
|
|
||||||
* @param cont The container from which to remove the element.
|
|
||||||
* @param it Iterator to the element to remove.
|
|
||||||
* @return A pair consisting of an iterator following the last removed
|
|
||||||
* element (in case of success) and a bool denoting whether the insertion
|
|
||||||
* took place.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> erase([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it) {
|
|
||||||
return { cont.erase(it), true };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief STL-compatible fixed sequence container traits
|
|
||||||
* @tparam Container The type of the container.
|
|
||||||
*/
|
|
||||||
template<typename Container>
|
|
||||||
struct fixed_sequence_container {
|
|
||||||
/**
|
|
||||||
* @brief Does nothing.
|
|
||||||
* @return False to indicate failure in all cases.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool resize(const Container &, typename Container::size_type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Does nothing.
|
|
||||||
* @return False to indicate failure in all cases.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static bool clear(const Container &) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Does nothing.
|
|
||||||
* @return A pair consisting of an invalid iterator and a false value to
|
|
||||||
* indicate failure in all cases.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> insert(const Container &, typename Container::const_iterator, const typename Container::value_type &) {
|
|
||||||
return { {}, false };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Does nothing.
|
|
||||||
* @return A pair consisting of an invalid iterator and a false value to
|
|
||||||
* indicate failure in all cases.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static std::pair<typename Container::iterator, bool> erase(const Container &, typename Container::const_iterator) {
|
|
||||||
return { {}, false };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta sequence container traits for `std::vector`s of any type.
|
|
||||||
* @tparam Type The type of elements.
|
|
||||||
* @tparam Args Other arguments.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename... Args>
|
|
||||||
struct meta_sequence_container_traits<std::vector<Type, Args...>>
|
|
||||||
: meta_container_traits<
|
|
||||||
std::vector<Type, Args...>,
|
|
||||||
basic_container,
|
|
||||||
basic_dynamic_container,
|
|
||||||
basic_sequence_container,
|
|
||||||
dynamic_sequence_container
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta sequence container traits for `std::array`s of any type.
|
|
||||||
* @tparam Type The type of elements.
|
|
||||||
* @tparam N The number of elements.
|
|
||||||
*/
|
|
||||||
template<typename Type, auto N>
|
|
||||||
struct meta_sequence_container_traits<std::array<Type, N>>
|
|
||||||
: meta_container_traits<
|
|
||||||
std::array<Type, N>,
|
|
||||||
basic_container,
|
|
||||||
basic_sequence_container,
|
|
||||||
fixed_sequence_container
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta associative container traits for `std::map`s of any type.
|
|
||||||
* @tparam Key The key type of elements.
|
|
||||||
* @tparam Value The value type of elements.
|
|
||||||
* @tparam Args Other arguments.
|
|
||||||
*/
|
|
||||||
template<typename Key, typename Value, typename... Args>
|
|
||||||
struct meta_associative_container_traits<std::map<Key, Value, Args...>>
|
|
||||||
: meta_container_traits<
|
|
||||||
std::map<Key, Value, Args...>,
|
|
||||||
basic_container,
|
|
||||||
basic_associative_container,
|
|
||||||
basic_dynamic_container,
|
|
||||||
basic_dynamic_associative_container,
|
|
||||||
dynamic_associative_key_value_container
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta associative container traits for `std::unordered_map`s of any
|
|
||||||
* type.
|
|
||||||
* @tparam Key The key type of elements.
|
|
||||||
* @tparam Value The value type of elements.
|
|
||||||
* @tparam Args Other arguments.
|
|
||||||
*/
|
|
||||||
template<typename Key, typename Value, typename... Args>
|
|
||||||
struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
|
|
||||||
: meta_container_traits<
|
|
||||||
std::unordered_map<Key, Value, Args...>,
|
|
||||||
basic_container,
|
|
||||||
basic_associative_container,
|
|
||||||
basic_dynamic_container,
|
|
||||||
basic_dynamic_associative_container,
|
|
||||||
dynamic_associative_key_value_container
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta associative container traits for `std::set`s of any type.
|
|
||||||
* @tparam Key The type of elements.
|
|
||||||
* @tparam Args Other arguments.
|
|
||||||
*/
|
|
||||||
template<typename Key, typename... Args>
|
|
||||||
struct meta_associative_container_traits<std::set<Key, Args...>>
|
|
||||||
: meta_container_traits<
|
|
||||||
std::set<Key, Args...>,
|
|
||||||
basic_container,
|
|
||||||
basic_associative_container,
|
|
||||||
basic_dynamic_container,
|
|
||||||
basic_dynamic_associative_container,
|
|
||||||
dynamic_associative_key_only_container
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta associative container traits for `std::unordered_set`s of any
|
|
||||||
* type.
|
|
||||||
* @tparam Key The type of elements.
|
|
||||||
* @tparam Args Other arguments.
|
|
||||||
*/
|
|
||||||
template<typename Key, typename... Args>
|
|
||||||
struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
|
|
||||||
: meta_container_traits<
|
|
||||||
std::unordered_set<Key, Args...>,
|
|
||||||
basic_container,
|
|
||||||
basic_associative_container,
|
|
||||||
basic_dynamic_container,
|
|
||||||
basic_dynamic_associative_container,
|
|
||||||
dynamic_associative_key_only_container
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
68
LiteLoader/Header/third-party/entt/meta/ctx.hpp
vendored
68
LiteLoader/Header/third-party/entt/meta/ctx.hpp
vendored
@ -1,68 +0,0 @@
|
|||||||
#ifndef ENTT_META_CTX_HPP
|
|
||||||
#define ENTT_META_CTX_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include "../core/attribute.h"
|
|
||||||
#include "../config/config.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cond TURN_OFF_DOXYGEN
|
|
||||||
* Internal details not to be documented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_type_node;
|
|
||||||
|
|
||||||
|
|
||||||
struct ENTT_API meta_context {
|
|
||||||
// we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
|
|
||||||
// inline static meta_type_node *local = nullptr;
|
|
||||||
// inline static meta_type_node **global = &local;
|
|
||||||
|
|
||||||
[[nodiscard]] static meta_type_node * & local() ENTT_NOEXCEPT {
|
|
||||||
static meta_type_node *chain = nullptr;
|
|
||||||
return chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static meta_type_node ** & global() ENTT_NOEXCEPT {
|
|
||||||
static meta_type_node **chain = &local();
|
|
||||||
return chain;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal details not to be documented.
|
|
||||||
* @endcond
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Opaque container for a meta context. */
|
|
||||||
struct meta_ctx {
|
|
||||||
/**
|
|
||||||
* @brief Binds the meta system to a given context.
|
|
||||||
* @param other A valid context to which to bind.
|
|
||||||
*/
|
|
||||||
static void bind(meta_ctx other) ENTT_NOEXCEPT {
|
|
||||||
internal::meta_context::global() = other.ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
internal::meta_type_node **ctx{&internal::meta_context::local()};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
597
LiteLoader/Header/third-party/entt/meta/factory.hpp
vendored
597
LiteLoader/Header/third-party/entt/meta/factory.hpp
vendored
@ -1,597 +0,0 @@
|
|||||||
#ifndef ENTT_META_FACTORY_HPP
|
|
||||||
#define ENTT_META_FACTORY_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/fwd.hpp"
|
|
||||||
#include "../core/type_info.hpp"
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
#include "meta.hpp"
|
|
||||||
#include "node.hpp"
|
|
||||||
#include "policy.hpp"
|
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cond TURN_OFF_DOXYGEN
|
|
||||||
* Internal details not to be documented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Node>
|
|
||||||
[[nodiscard]] bool find_if(const Node *candidate, const Node *node) ENTT_NOEXCEPT {
|
|
||||||
return node && (node == candidate || find_if(candidate, node->next));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Id, typename Node>
|
|
||||||
[[nodiscard]] bool find_if_not(const Id id, Node *node, const Node *owner) ENTT_NOEXCEPT {
|
|
||||||
if constexpr(std::is_pointer_v<Id>) {
|
|
||||||
return node && ((*node->id == *id && node != owner) || find_if_not(id, node->next, owner));
|
|
||||||
} else {
|
|
||||||
return node && ((node->id == id && node != owner) || find_if_not(id, node->next, owner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal details not to be documented.
|
|
||||||
* @endcond
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Meta factory to be used for reflection purposes.
|
|
||||||
*
|
|
||||||
* The meta factory is an utility class used to reflect types, data members and
|
|
||||||
* functions of all sorts. This class ensures that the underlying web of types
|
|
||||||
* is built correctly and performs some checks in debug mode to ensure that
|
|
||||||
* there are no subtle errors at runtime.
|
|
||||||
*/
|
|
||||||
template<typename...>
|
|
||||||
struct meta_factory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Extended meta factory to be used for reflection purposes.
|
|
||||||
* @tparam Type Reflected type for which the factory was created.
|
|
||||||
* @tparam Spec Property specialization pack used to disambiguate overloads.
|
|
||||||
*/
|
|
||||||
template<typename Type, typename... Spec>
|
|
||||||
struct meta_factory<Type, Spec...>: public meta_factory<Type> {
|
|
||||||
private:
|
|
||||||
template<std::size_t Step = 0, std::size_t... Index, typename... Property, typename... Other>
|
|
||||||
void unpack(std::index_sequence<Index...>, std::tuple<Property...> property, Other &&... other) {
|
|
||||||
unroll<Step>(choice<3>, std::move(std::get<Index>(property))..., std::forward<Other>(other)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t Step = 0, typename... Property, typename... Other>
|
|
||||||
void unroll(choice_t<3>, std::tuple<Property...> property, Other &&... other) {
|
|
||||||
unpack<Step>(std::index_sequence_for<Property...>{}, std::move(property), std::forward<Other>(other)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t Step = 0, typename... Property, typename... Other>
|
|
||||||
void unroll(choice_t<2>, std::pair<Property...> property, Other &&... other) {
|
|
||||||
assign<Step>(std::move(property.first), std::move(property.second));
|
|
||||||
unroll<Step+1>(choice<3>, std::forward<Other>(other)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t Step = 0, typename Property, typename... Other>
|
|
||||||
std::enable_if_t<!std::is_invocable_v<Property>>
|
|
||||||
unroll(choice_t<1>, Property &&property, Other &&... other) {
|
|
||||||
assign<Step>(std::forward<Property>(property));
|
|
||||||
unroll<Step+1>(choice<3>, std::forward<Other>(other)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t Step = 0, typename Func, typename... Other>
|
|
||||||
void unroll(choice_t<0>, Func &&invocable, Other &&... other) {
|
|
||||||
unroll<Step>(choice<3>, std::forward<Func>(invocable)(), std::forward<Other>(other)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<std::size_t>
|
|
||||||
void unroll(choice_t<0>) {}
|
|
||||||
|
|
||||||
template<std::size_t = 0, typename Key>
|
|
||||||
void assign(Key &&key, meta_any value = {}) {
|
|
||||||
static meta_any property[2u]{};
|
|
||||||
|
|
||||||
static internal::meta_prop_node node{
|
|
||||||
nullptr,
|
|
||||||
property[0u],
|
|
||||||
property[1u]
|
|
||||||
};
|
|
||||||
|
|
||||||
entt::meta_any instance{std::forward<Key>(key)};
|
|
||||||
ENTT_ASSERT(!internal::find_if_not(&instance, *curr, &node), "Duplicate key");
|
|
||||||
property[0u] = std::move(instance);
|
|
||||||
property[1u] = std::move(value);
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, *curr)) {
|
|
||||||
node.next = *curr;
|
|
||||||
*curr = &node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructs an extended factory from a given node.
|
|
||||||
* @param target The underlying node to which to assign the properties.
|
|
||||||
*/
|
|
||||||
meta_factory(internal::meta_prop_node **target) ENTT_NOEXCEPT
|
|
||||||
: curr{target}
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a property to the last meta object created.
|
|
||||||
*
|
|
||||||
* Both the key and the value (if any) must be at least copy constructible.
|
|
||||||
*
|
|
||||||
* @tparam PropertyOrKey Type of the property or property key.
|
|
||||||
* @tparam Value Optional type of the property value.
|
|
||||||
* @param property_or_key Property or property key.
|
|
||||||
* @param value Optional property value.
|
|
||||||
* @return A meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<typename PropertyOrKey, typename... Value>
|
|
||||||
auto prop(PropertyOrKey &&property_or_key, Value &&... value) && {
|
|
||||||
if constexpr(sizeof...(Value) == 0) {
|
|
||||||
unroll(choice<3>, std::forward<PropertyOrKey>(property_or_key));
|
|
||||||
} else {
|
|
||||||
assign(std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type, Spec..., PropertyOrKey, Value...>{curr};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns properties to the last meta object created.
|
|
||||||
*
|
|
||||||
* Both the keys and the values (if any) must be at least copy
|
|
||||||
* constructible.
|
|
||||||
*
|
|
||||||
* @tparam Property Types of the properties.
|
|
||||||
* @param property Properties to assign to the last meta object created.
|
|
||||||
* @return A meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template <typename... Property>
|
|
||||||
auto props(Property... property) && {
|
|
||||||
unroll(choice<3>, std::forward<Property>(property)...);
|
|
||||||
return meta_factory<Type, Spec..., Property...>{curr};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
internal::meta_prop_node **curr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Basic meta factory to be used for reflection purposes.
|
|
||||||
* @tparam Type Reflected type for which the factory was created.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
struct meta_factory<Type> {
|
|
||||||
/**
|
|
||||||
* @brief Makes a meta type _searchable_.
|
|
||||||
* @param id Optional unique identifier.
|
|
||||||
* @return An extended meta factory for the given type.
|
|
||||||
*/
|
|
||||||
auto type(const id_type id = type_hash<Type>::value()) {
|
|
||||||
auto * const node = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
ENTT_ASSERT(!internal::find_if_not(id, *internal::meta_context::global(), node), "Duplicate identifier");
|
|
||||||
node->id = id;
|
|
||||||
|
|
||||||
if(!internal::find_if(node, *internal::meta_context::global())) {
|
|
||||||
node->next = *internal::meta_context::global();
|
|
||||||
*internal::meta_context::global() = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type, Type>{&node->prop};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta base to a meta type.
|
|
||||||
*
|
|
||||||
* A reflected base class must be a real base class of the reflected type.
|
|
||||||
*
|
|
||||||
* @tparam Base Type of the base class to assign to the meta type.
|
|
||||||
* @return A meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<typename Base>
|
|
||||||
auto base() ENTT_NOEXCEPT {
|
|
||||||
static_assert(std::is_base_of_v<Base, Type>, "Invalid base type");
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_base_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
&internal::meta_info<Base>::resolve,
|
|
||||||
[](const void *instance) ENTT_NOEXCEPT -> const void * {
|
|
||||||
return static_cast<const Base *>(static_cast<const Type *>(instance));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->base)) {
|
|
||||||
node.next = type->base;
|
|
||||||
type->base = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta conversion function to a meta type.
|
|
||||||
*
|
|
||||||
* Conversion functions can be either free functions or member
|
|
||||||
* functions.<br/>
|
|
||||||
* In case of free functions, they must accept a const reference to an
|
|
||||||
* instance of the parent type as an argument. In case of member functions,
|
|
||||||
* they should have no arguments at all.
|
|
||||||
*
|
|
||||||
* @tparam Candidate The actual function to use for the conversion.
|
|
||||||
* @return A meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<auto Candidate>
|
|
||||||
std::enable_if_t<std::is_member_function_pointer_v<decltype(Candidate)>, meta_factory<Type>> conv() ENTT_NOEXCEPT {
|
|
||||||
using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_conv_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
&internal::meta_info<conv_type>::resolve,
|
|
||||||
[](const void *instance) -> meta_any {
|
|
||||||
return (static_cast<const Type *>(instance)->*Candidate)();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->conv)) {
|
|
||||||
node.next = type->conv;
|
|
||||||
type->conv = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @copydoc conv */
|
|
||||||
template<auto Candidate>
|
|
||||||
std::enable_if_t<!std::is_member_function_pointer_v<decltype(Candidate)>, meta_factory<Type>> conv() ENTT_NOEXCEPT {
|
|
||||||
using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_conv_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
&internal::meta_info<conv_type>::resolve,
|
|
||||||
[](const void *instance) -> meta_any {
|
|
||||||
return Candidate(*static_cast<const Type *>(instance));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->conv)) {
|
|
||||||
node.next = type->conv;
|
|
||||||
type->conv = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta conversion function to a meta type.
|
|
||||||
*
|
|
||||||
* The given type must be such that an instance of the reflected type can be
|
|
||||||
* converted to it.
|
|
||||||
*
|
|
||||||
* @tparam To Type of the conversion function to assign to the meta type.
|
|
||||||
* @return A meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<typename To>
|
|
||||||
auto conv() ENTT_NOEXCEPT {
|
|
||||||
static_assert(std::is_convertible_v<Type, To>, "Could not convert to the required type");
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_conv_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
&internal::meta_info<To>::resolve,
|
|
||||||
[](const void *instance) -> meta_any {
|
|
||||||
return static_cast<To>(*static_cast<const Type *>(instance));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->conv)) {
|
|
||||||
node.next = type->conv;
|
|
||||||
type->conv = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta constructor to a meta type.
|
|
||||||
*
|
|
||||||
* Both member functions and free function can be assigned to meta types in
|
|
||||||
* the role of constructors. All that is required is that they return an
|
|
||||||
* instance of the underlying type.<br/>
|
|
||||||
* From a client's point of view, nothing changes if a constructor of a meta
|
|
||||||
* type is a built-in one or not.
|
|
||||||
*
|
|
||||||
* @tparam Candidate The actual function to use as a constructor.
|
|
||||||
* @tparam Policy Optional policy (no policy set by default).
|
|
||||||
* @return An extended meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<auto Candidate, typename Policy = as_is_t>
|
|
||||||
auto ctor() ENTT_NOEXCEPT {
|
|
||||||
using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
|
|
||||||
static_assert(std::is_same_v<std::decay_t<typename descriptor::return_type>, Type>, "The function doesn't return an object of the required type");
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_ctor_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
descriptor::args_type::size,
|
|
||||||
[](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
|
|
||||||
return meta_arg(typename descriptor::args_type{}, index);
|
|
||||||
},
|
|
||||||
[](meta_any * const args) {
|
|
||||||
return meta_invoke<Type, Candidate, Policy>({}, args, std::make_index_sequence<descriptor::args_type::size>{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->ctor)) {
|
|
||||||
node.next = type->ctor;
|
|
||||||
type->ctor = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta constructor to a meta type.
|
|
||||||
*
|
|
||||||
* A meta constructor is uniquely identified by the types of its arguments
|
|
||||||
* and is such that there exists an actual constructor of the underlying
|
|
||||||
* type that can be invoked with parameters whose types are those given.
|
|
||||||
*
|
|
||||||
* @tparam Args Types of arguments to use to construct an instance.
|
|
||||||
* @return An extended meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
auto ctor() ENTT_NOEXCEPT {
|
|
||||||
using descriptor = meta_function_helper_t<Type, Type(*)(Args...)>;
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_ctor_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
descriptor::args_type::size,
|
|
||||||
[](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
|
|
||||||
return meta_arg(typename descriptor::args_type{}, index);
|
|
||||||
},
|
|
||||||
[](meta_any * const args) {
|
|
||||||
return meta_construct<Type, Args...>(args, std::make_index_sequence<descriptor::args_type::size>{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->ctor)) {
|
|
||||||
node.next = type->ctor;
|
|
||||||
type->ctor = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type, Type(Args...)>{&node.prop};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta destructor to a meta type.
|
|
||||||
*
|
|
||||||
* Free functions can be assigned to meta types in the role of destructors.
|
|
||||||
* The signature of the function should identical to the following:
|
|
||||||
*
|
|
||||||
* @code{.cpp}
|
|
||||||
* void(Type &);
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* The purpose is to give users the ability to free up resources that
|
|
||||||
* require special treatment before an object is actually destroyed.
|
|
||||||
*
|
|
||||||
* @tparam Func The actual function to use as a destructor.
|
|
||||||
* @return A meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<auto Func>
|
|
||||||
auto dtor() ENTT_NOEXCEPT {
|
|
||||||
static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
type->dtor = [](void *instance) {
|
|
||||||
Func(*static_cast<Type *>(instance));
|
|
||||||
};
|
|
||||||
|
|
||||||
return meta_factory<Type>{};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta data to a meta type.
|
|
||||||
*
|
|
||||||
* Both data members and static and global variables, as well as constants
|
|
||||||
* of any kind, can be assigned to a meta type.<br/>
|
|
||||||
* From a client's point of view, all the variables associated with the
|
|
||||||
* reflected object will appear as if they were part of the type itself.
|
|
||||||
*
|
|
||||||
* @tparam Data The actual variable to attach to the meta type.
|
|
||||||
* @tparam Policy Optional policy (no policy set by default).
|
|
||||||
* @param id Unique identifier.
|
|
||||||
* @return An extended meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<auto Data, typename Policy = as_is_t>
|
|
||||||
auto data(const id_type id) ENTT_NOEXCEPT {
|
|
||||||
if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
|
|
||||||
return data<Data, Data, Policy>(id);
|
|
||||||
} else {
|
|
||||||
using data_type = std::remove_pointer_t<decltype(Data)>;
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_data_node node{
|
|
||||||
{},
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
std::is_same_v<Type, data_type> || std::is_const_v<data_type>,
|
|
||||||
true,
|
|
||||||
&internal::meta_info<data_type>::resolve,
|
|
||||||
&meta_setter<Type, Data>,
|
|
||||||
&meta_getter<Type, Data, Policy>
|
|
||||||
};
|
|
||||||
|
|
||||||
ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier");
|
|
||||||
node.id = id;
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->data)) {
|
|
||||||
node.next = type->data;
|
|
||||||
type->data = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type, std::integral_constant<decltype(Data), Data>>{&node.prop};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta data to a meta type by means of its setter and
|
|
||||||
* getter.
|
|
||||||
*
|
|
||||||
* Setters and getters can be either free functions, member functions or a
|
|
||||||
* mix of them.<br/>
|
|
||||||
* In case of free functions, setters and getters must accept a reference to
|
|
||||||
* an instance of the parent type as their first argument. A setter has then
|
|
||||||
* an extra argument of a type convertible to that of the parameter to
|
|
||||||
* set.<br/>
|
|
||||||
* In case of member functions, getters have no arguments at all, while
|
|
||||||
* setters has an argument of a type convertible to that of the parameter to
|
|
||||||
* set.
|
|
||||||
*
|
|
||||||
* @tparam Setter The actual function to use as a setter.
|
|
||||||
* @tparam Getter The actual function to use as a getter.
|
|
||||||
* @tparam Policy Optional policy (no policy set by default).
|
|
||||||
* @param id Unique identifier.
|
|
||||||
* @return An extended meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<auto Setter, auto Getter, typename Policy = as_is_t>
|
|
||||||
auto data(const id_type id) ENTT_NOEXCEPT {
|
|
||||||
using underlying_type = std::remove_reference_t<std::invoke_result_t<decltype(Getter), Type &>>;
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_data_node node{
|
|
||||||
{},
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>),
|
|
||||||
false,
|
|
||||||
&internal::meta_info<underlying_type>::resolve,
|
|
||||||
&meta_setter<Type, Setter>,
|
|
||||||
&meta_getter<Type, Getter, Policy>
|
|
||||||
};
|
|
||||||
|
|
||||||
ENTT_ASSERT(!internal::find_if_not(id, type->data, &node), "Duplicate identifier");
|
|
||||||
node.id = id;
|
|
||||||
|
|
||||||
if(!internal::find_if(&node, type->data)) {
|
|
||||||
node.next = type->data;
|
|
||||||
type->data = &node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Assigns a meta funcion to a meta type.
|
|
||||||
*
|
|
||||||
* Both member functions and free functions can be assigned to a meta
|
|
||||||
* type.<br/>
|
|
||||||
* From a client's point of view, all the functions associated with the
|
|
||||||
* reflected object will appear as if they were part of the type itself.
|
|
||||||
*
|
|
||||||
* @tparam Candidate The actual function to attach to the meta type.
|
|
||||||
* @tparam Policy Optional policy (no policy set by default).
|
|
||||||
* @param id Unique identifier.
|
|
||||||
* @return An extended meta factory for the parent type.
|
|
||||||
*/
|
|
||||||
template<auto Candidate, typename Policy = as_is_t>
|
|
||||||
auto func(const id_type id) ENTT_NOEXCEPT {
|
|
||||||
using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
|
|
||||||
auto * const type = internal::meta_info<Type>::resolve();
|
|
||||||
|
|
||||||
static internal::meta_func_node node{
|
|
||||||
{},
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
descriptor::args_type::size,
|
|
||||||
descriptor::is_const,
|
|
||||||
descriptor::is_static,
|
|
||||||
&internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename descriptor::return_type>>::resolve,
|
|
||||||
[](const typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
|
|
||||||
return meta_arg(typename descriptor::args_type{}, index);
|
|
||||||
},
|
|
||||||
[](meta_handle instance, meta_any *args) {
|
|
||||||
return meta_invoke<Type, Candidate, Policy>(std::move(instance), args, std::make_index_sequence<descriptor::args_type::size>{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for(auto *it = &type->func; *it; it = &(*it)->next) {
|
|
||||||
if(*it == &node) {
|
|
||||||
*it = node.next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal::meta_func_node **it = &type->func;
|
|
||||||
for(; *it && (*it)->id != id; it = &(*it)->next);
|
|
||||||
for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
|
|
||||||
|
|
||||||
node.id = id;
|
|
||||||
node.next = *it;
|
|
||||||
*it = &node;
|
|
||||||
|
|
||||||
return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Utility function to use for reflection.
|
|
||||||
*
|
|
||||||
* This is the point from which everything starts.<br/>
|
|
||||||
* By invoking this function with a type that is not yet reflected, a meta type
|
|
||||||
* is created to which it will be possible to attach meta objects through a
|
|
||||||
* dedicated factory.
|
|
||||||
*
|
|
||||||
* @tparam Type Type to reflect.
|
|
||||||
* @return A meta factory for the given type.
|
|
||||||
*/
|
|
||||||
template<typename Type>
|
|
||||||
[[nodiscard]] auto meta() ENTT_NOEXCEPT {
|
|
||||||
auto * const node = internal::meta_info<Type>::resolve();
|
|
||||||
// extended meta factory to allow assigning properties to opaque meta types
|
|
||||||
return meta_factory<Type, Type>{&node->prop};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
2226
LiteLoader/Header/third-party/entt/meta/meta.hpp
vendored
2226
LiteLoader/Header/third-party/entt/meta/meta.hpp
vendored
File diff suppressed because it is too large
Load Diff
270
LiteLoader/Header/third-party/entt/meta/node.hpp
vendored
270
LiteLoader/Header/third-party/entt/meta/node.hpp
vendored
@ -1,270 +0,0 @@
|
|||||||
#ifndef ENTT_META_NODE_HPP
|
|
||||||
#define ENTT_META_NODE_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include "../config/config.h"
|
|
||||||
#include "../core/attribute.h"
|
|
||||||
#include "../core/fwd.hpp"
|
|
||||||
#include "../core/type_info.hpp"
|
|
||||||
#include "../core/type_traits.hpp"
|
|
||||||
#include "type_traits.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
class meta_any;
|
|
||||||
class meta_type;
|
|
||||||
struct meta_handle;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @cond TURN_OFF_DOXYGEN
|
|
||||||
* Internal details not to be documented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_type_node;
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_prop_node {
|
|
||||||
meta_prop_node * next;
|
|
||||||
const meta_any &id;
|
|
||||||
meta_any &value;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_base_node {
|
|
||||||
meta_type_node * const parent;
|
|
||||||
meta_base_node * next;
|
|
||||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
|
||||||
const void *(* const cast)(const void *) ENTT_NOEXCEPT;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_conv_node {
|
|
||||||
meta_type_node * const parent;
|
|
||||||
meta_conv_node * next;
|
|
||||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
|
||||||
meta_any(* const conv)(const void *);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_ctor_node {
|
|
||||||
using size_type = std::size_t;
|
|
||||||
meta_type_node * const parent;
|
|
||||||
meta_ctor_node * next;
|
|
||||||
meta_prop_node * prop;
|
|
||||||
const size_type arity;
|
|
||||||
meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
|
|
||||||
meta_any(* const invoke)(meta_any * const);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_data_node {
|
|
||||||
id_type id;
|
|
||||||
meta_type_node * const parent;
|
|
||||||
meta_data_node * next;
|
|
||||||
meta_prop_node * prop;
|
|
||||||
const bool is_const;
|
|
||||||
const bool is_static;
|
|
||||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
|
||||||
bool(* const set)(meta_handle, meta_any);
|
|
||||||
meta_any(* const get)(meta_handle);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_func_node {
|
|
||||||
using size_type = std::size_t;
|
|
||||||
id_type id;
|
|
||||||
meta_type_node * const parent;
|
|
||||||
meta_func_node * next;
|
|
||||||
meta_prop_node * prop;
|
|
||||||
const size_type arity;
|
|
||||||
const bool is_const;
|
|
||||||
const bool is_static;
|
|
||||||
meta_type_node *(* const ret)() ENTT_NOEXCEPT;
|
|
||||||
meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
|
|
||||||
meta_any(* const invoke)(meta_handle, meta_any *);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_template_info {
|
|
||||||
using size_type = std::size_t;
|
|
||||||
const bool is_template_specialization;
|
|
||||||
const size_type arity;
|
|
||||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
|
||||||
meta_type_node *(* const arg)(const size_type) ENTT_NOEXCEPT;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct meta_type_node {
|
|
||||||
using size_type = std::size_t;
|
|
||||||
const type_info info;
|
|
||||||
id_type id;
|
|
||||||
meta_type_node * next;
|
|
||||||
meta_prop_node * prop;
|
|
||||||
const size_type size_of;
|
|
||||||
const bool is_void;
|
|
||||||
const bool is_integral;
|
|
||||||
const bool is_floating_point;
|
|
||||||
const bool is_array;
|
|
||||||
const bool is_enum;
|
|
||||||
const bool is_union;
|
|
||||||
const bool is_class;
|
|
||||||
const bool is_pointer;
|
|
||||||
const bool is_function_pointer;
|
|
||||||
const bool is_member_object_pointer;
|
|
||||||
const bool is_member_function_pointer;
|
|
||||||
const bool is_pointer_like;
|
|
||||||
const bool is_sequence_container;
|
|
||||||
const bool is_associative_container;
|
|
||||||
const meta_template_info template_info;
|
|
||||||
const size_type rank;
|
|
||||||
size_type(* const extent)(const size_type) ENTT_NOEXCEPT ;
|
|
||||||
meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
|
|
||||||
meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
|
|
||||||
meta_ctor_node * const def_ctor;
|
|
||||||
meta_ctor_node *ctor{nullptr};
|
|
||||||
meta_base_node *base{nullptr};
|
|
||||||
meta_conv_node *conv{nullptr};
|
|
||||||
meta_data_node *data{nullptr};
|
|
||||||
meta_func_node *func{nullptr};
|
|
||||||
void(* dtor)(void *){nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<auto Member, typename Op, typename Node>
|
|
||||||
auto meta_visit(const Op &op, const Node *node)
|
|
||||||
-> std::decay_t<decltype(node->*Member)> {
|
|
||||||
for(auto *curr = node->*Member; curr; curr = curr->next) {
|
|
||||||
if(op(curr)) {
|
|
||||||
return curr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr(std::is_same_v<Node, meta_type_node>) {
|
|
||||||
for(auto *curr = node->base; curr; curr = curr->next) {
|
|
||||||
if(auto *ret = meta_visit<Member>(op, curr->type()); ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
meta_type_node * meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
class ENTT_API meta_node {
|
|
||||||
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
|
|
||||||
|
|
||||||
template<std::size_t... Index>
|
|
||||||
[[nodiscard]] static auto extent(const meta_type_node::size_type dim, std::index_sequence<Index...>) ENTT_NOEXCEPT {
|
|
||||||
meta_type_node::size_type ext{};
|
|
||||||
((ext = (dim == Index ? std::extent_v<Type, Index> : ext)), ...);
|
|
||||||
return ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static meta_ctor_node * meta_default_constructor([[maybe_unused]] meta_type_node *type) ENTT_NOEXCEPT {
|
|
||||||
if constexpr(std::is_default_constructible_v<Type>) {
|
|
||||||
static meta_ctor_node node{
|
|
||||||
type,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
0u,
|
|
||||||
nullptr,
|
|
||||||
[](meta_any * const) { return meta_any{std::in_place_type<Type>}; }
|
|
||||||
};
|
|
||||||
|
|
||||||
return &node;
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static meta_template_info meta_template_descriptor() ENTT_NOEXCEPT {
|
|
||||||
if constexpr(is_complete_v<meta_template_traits<Type>>) {
|
|
||||||
return {
|
|
||||||
true,
|
|
||||||
meta_template_traits<Type>::args_type::size,
|
|
||||||
&meta_node<typename meta_template_traits<Type>::class_type>::resolve,
|
|
||||||
[](const std::size_t index) ENTT_NOEXCEPT {
|
|
||||||
return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return { false, 0u, nullptr, nullptr };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
[[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
|
|
||||||
static meta_type_node node{
|
|
||||||
type_id<Type>(),
|
|
||||||
{},
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
size_of_v<Type>,
|
|
||||||
std::is_void_v<Type>,
|
|
||||||
std::is_integral_v<Type>,
|
|
||||||
std::is_floating_point_v<Type>,
|
|
||||||
std::is_array_v<Type>,
|
|
||||||
std::is_enum_v<Type>,
|
|
||||||
std::is_union_v<Type>,
|
|
||||||
std::is_class_v<Type>,
|
|
||||||
std::is_pointer_v<Type>,
|
|
||||||
std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
|
|
||||||
std::is_member_object_pointer_v<Type>,
|
|
||||||
std::is_member_function_pointer_v<Type>,
|
|
||||||
is_meta_pointer_like_v<Type>,
|
|
||||||
is_complete_v<meta_sequence_container_traits<Type>>,
|
|
||||||
is_complete_v<meta_associative_container_traits<Type>>,
|
|
||||||
meta_template_descriptor(),
|
|
||||||
std::rank_v<Type>,
|
|
||||||
[](meta_type_node::size_type dim) ENTT_NOEXCEPT { return extent(dim, std::make_index_sequence<std::rank_v<Type>>{}); },
|
|
||||||
&meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<Type>>>>::resolve,
|
|
||||||
&meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_extent_t<Type>>>>::resolve,
|
|
||||||
meta_default_constructor(&node),
|
|
||||||
meta_default_constructor(&node)
|
|
||||||
};
|
|
||||||
|
|
||||||
return &node;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>> {};
|
|
||||||
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
meta_type_node * meta_arg_node(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
|
|
||||||
meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::meta_info<Args>::resolve()...};
|
|
||||||
return args[index + 1u];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal details not to be documented.
|
|
||||||
* @endcond
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,27 +0,0 @@
|
|||||||
#ifndef ENTT_META_POLICY_HPP
|
|
||||||
#define ENTT_META_POLICY_HPP
|
|
||||||
|
|
||||||
|
|
||||||
namespace entt {
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Empty class type used to request the _as ref_ policy. */
|
|
||||||
struct as_ref_t {};
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Empty class type used to request the _as cref_ policy. */
|
|
||||||
struct as_cref_t {};
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Empty class type used to request the _as-is_ policy. */
|
|
||||||
struct as_is_t {};
|
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Empty class type used to request the _as void_ policy. */
|
|
||||||
struct as_void_t {};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user