├── src ├── cs │ ├── Directory.Build.targets │ ├── production │ │ ├── Directory.Build.props │ │ ├── Directory.Build.targets │ │ ├── Flecs.Core │ │ │ ├── _README_PACKAGE.md │ │ │ ├── IEcsComponent.cs │ │ │ ├── CallbackIterator.cs │ │ │ ├── Component │ │ │ │ ├── CallbackComponentCopy.cs │ │ │ │ ├── CallbackComponentMove.cs │ │ │ │ ├── CallbackComponentConstructor.cs │ │ │ │ ├── CallbackComponentDeconstructor.cs │ │ │ │ ├── IComponent.cs │ │ │ │ ├── ComponentDeconstructorContext.cs │ │ │ │ ├── ComponentConstructorContext.cs │ │ │ │ ├── ComponentCopyContext.cs │ │ │ │ ├── ComponentMoveContext.cs │ │ │ │ └── ComponentHooks.cs │ │ │ ├── ITag.cs │ │ │ ├── Flecs.Core.csproj.DotSettings │ │ │ ├── Pair.cs │ │ │ ├── FlecsException.cs │ │ │ ├── IteratorEvent.cs │ │ │ ├── Table.cs │ │ │ ├── EntityType.cs │ │ │ ├── IdentifiersEnumerable.cs │ │ │ ├── Expressions │ │ │ │ ├── Expression.cs │ │ │ │ └── TermBuilder.cs │ │ │ ├── Properties │ │ │ │ └── AdditionalCodeAnalysisSuppressions.cs │ │ │ ├── Flecs.Core.csproj │ │ │ ├── IdentifiersEnumerator.cs │ │ │ ├── Identifier.cs │ │ │ ├── EntityIterator.cs │ │ │ ├── Iterator.cs │ │ │ ├── CallbacksHelper.cs │ │ │ ├── World.cs │ │ │ └── Entity.cs │ │ ├── Interop.Flecs.Core │ │ │ ├── _README_PACKAGE.md │ │ │ ├── Generated │ │ │ │ └── AssemblyAttributes.gen.cs │ │ │ ├── Interop.Flecs.Core.csproj │ │ │ └── PInvoke.Extensions.cs │ │ ├── Interop.Flecs.runtime.osx │ │ │ ├── _README_PACKAGE.md │ │ │ └── Interop.Flecs.runtime.osx.csproj │ │ ├── Interop.Flecs.runtime.win-x64 │ │ │ ├── _README_PACKAGE.md │ │ │ └── Interop.Flecs.runtime.win-x64.csproj │ │ ├── Interop.Flecs.runtime.linux-x64 │ │ │ ├── _README_PACKAGE.md │ │ │ └── Interop.Flecs.runtime.linux-x64.csproj │ │ ├── Interop.Flecs.Unity │ │ │ ├── Generated │ │ │ │ └── AssemblyAttributes.gen.cs │ │ │ └── Interop.Flecs.Unity.csproj │ │ └── Flecs.Unity │ │ │ └── Flecs.Unity.csproj │ ├── examples │ │ ├── Directory.Build.targets │ │ ├── queries │ │ │ ├── Directory.Build.props │ │ │ ├── Directory.Build.targets │ │ │ └── Flecs.Examples.Queries.OptionalOr │ │ │ │ ├── Flecs.Examples.Queries.OptionalOr.csproj │ │ │ │ └── Program.cs │ │ ├── systems │ │ │ ├── Directory.Build.props │ │ │ ├── Directory.Build.targets │ │ │ └── Flecs.Examples.Systems.CustomPhase │ │ │ │ ├── Flecs.Examples.Systems.CustomPhase.csproj │ │ │ │ └── Program.cs │ │ ├── entities │ │ │ ├── Directory.Build.props │ │ │ ├── Directory.Build.targets │ │ │ ├── Flecs.Examples.Entities.RelationBasic │ │ │ │ ├── Flecs.Examples.Entities.RelationBasic.csproj │ │ │ │ └── Program.cs │ │ │ ├── Flecs.Examples.Entities.RelationComponents │ │ │ │ ├── Flecs.Examples.Entities.RelationComponents.csproj │ │ │ │ └── Program.cs │ │ │ ├── Flecs.Examples.Entities.Basics │ │ │ │ ├── Flecs.Examples.Entities.Basics.csproj │ │ │ │ └── Program.cs │ │ │ ├── Flecs.Examples.Entities.Hooks │ │ │ │ ├── Flecs.Examples.Entities.Hooks.csproj │ │ │ │ └── Program.cs │ │ │ ├── Flecs.Examples.Entities.Prefab │ │ │ │ ├── Flecs.Examples.Entities.Prefab.csproj │ │ │ │ └── Program.cs │ │ │ ├── Flecs.Examples.Entities.Hierarchy │ │ │ │ ├── Flecs.Examples.Entities.Hierarchy.csproj │ │ │ │ └── Program.cs │ │ │ ├── Flecs.Examples.Entities.PrefabSlot │ │ │ │ ├── Flecs.Examples.Entities.PrefabSlot.csproj │ │ │ │ └── Program.cs │ │ │ └── Flecs.Examples.Entities.IterateComponents │ │ │ │ ├── Flecs.Examples.Entities.IterateComponents.csproj │ │ │ │ └── Program.cs │ │ ├── Flecs.Examples.HelloWorld │ │ │ ├── Flecs.Examples.HelloWorld.csproj │ │ │ └── Program.cs │ │ └── Directory.Build.props │ ├── Flecs.sln.DotSettings │ ├── Flecs.sln.DotSettings.user │ ├── .globalconfig │ ├── Directory.Build.props │ ├── StyleCop.json │ └── Flecs.sln └── c │ └── production │ └── flecs │ ├── src │ └── flecs_pinvoke.c │ ├── CMakeLists.txt │ └── include │ ├── flecs_pinvoke.h │ └── pinvoke.h ├── .gitmodules ├── bindgen ├── config-build-c-library.json ├── config-extract-macos.json ├── config-extract-windows.json ├── config-extract-linux.json ├── merge.sh ├── generate.sh ├── config-generate-cs-core.json ├── config-generate-cs-unity.json ├── appsettings.json └── extract.sh ├── .github ├── dependabot.yml └── workflows │ ├── pull-release.yml │ ├── commit.yml │ ├── release.yml │ ├── build.yml │ └── bindgen.yml ├── .gitignore ├── library.sh ├── LICENSE ├── .editorconfig └── README.md /src/cs/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/c/production/flecs/src/flecs_pinvoke.c: -------------------------------------------------------------------------------- 1 | #include "flecs_pinvoke.h" 2 | #include "flecs.h" -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/flecs"] 2 | path = ext/flecs 3 | url = https://github.com/SanderMertens/flecs -------------------------------------------------------------------------------- /src/cs/production/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/queries/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/systems/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/production/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/queries/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/examples/systems/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/_README_PACKAGE.md: -------------------------------------------------------------------------------- 1 | 2 | # flecs_hub.Flecs 3 | 4 | Automatically updated C# bindings for https://github.com/SanderMertens/flecs. -------------------------------------------------------------------------------- /bindgen/config-build-c-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "cMakeDirectoryPath": "../src/c/production/flecs", 3 | "outputDirectoryPath": "../lib", 4 | "deleteBuildFiles": true 5 | } -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.Core/_README_PACKAGE.md: -------------------------------------------------------------------------------- 1 | 2 | # flecs_hub.Interop.Flecs.Core 3 | 4 | Automatically updated C# bindings for https://github.com/SanderMertens/flecs. -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gitsubmodule" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | time: "00:15" # 8:15pm EDT -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.runtime.osx/_README_PACKAGE.md: -------------------------------------------------------------------------------- 1 | 2 | # flecs_hub.Interop.Flecs.runtime.osx 3 | 4 | Automatically updated C# bindings for https://github.com/flecs-hub/flecs-cs. -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.runtime.win-x64/_README_PACKAGE.md: -------------------------------------------------------------------------------- 1 | 2 | # flecs_hub.Interop.Flecs.runtime.win-x64 3 | 4 | Automatically updated C# bindings for https://github.com/flecs-hub/flecs-cs. -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.runtime.linux-x64/_README_PACKAGE.md: -------------------------------------------------------------------------------- 1 | 2 | # flecs_hub.Interop.Flecs.runtime.linux-x64 3 | 4 | Automatically updated C# bindings for https://github.com/flecs-hub/flecs-cs. -------------------------------------------------------------------------------- /bindgen/config-extract-macos.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputFilePath": "../src/c/production/flecs/include/flecs_pinvoke.h", 3 | "userIncludeDirectories": [ 4 | "../ext/flecs/include" 5 | ], 6 | "platforms": { 7 | "aarch64-apple-darwin": {}, 8 | "x86_64-apple-darwin": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /bindgen/config-extract-windows.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputFilePath": "../src/c/production/flecs/include/flecs_pinvoke.h", 3 | "userIncludeDirectories": [ 4 | "../ext/flecs/include" 5 | ], 6 | "platforms": { 7 | "x86_64-pc-windows-msvc": {}, 8 | "aarch64-pc-windows-msvc": {} 9 | } 10 | } -------------------------------------------------------------------------------- /bindgen/config-extract-linux.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputFilePath": "../src/c/production/flecs/include/flecs_pinvoke.h", 3 | "userIncludeDirectories": [ 4 | "../ext/flecs/include" 5 | ], 6 | "platforms": { 7 | "x86_64-unknown-linux-gnu": {}, 8 | "aarch64-unknown-linux-gnu": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/IEcsComponent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public interface IEcsComponent 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/CallbackIterator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public delegate void CallbackIterator(Iterator iterator); 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # JetBrains 2 | .idea/ 3 | 4 | # VisualStudio 5 | .suo 6 | .vs/ 7 | 8 | # C# build artifacts 9 | bin/ 10 | obj/ 11 | /artifacts/ 12 | 13 | # C# packages 14 | /nupkg/ 15 | 16 | # Native libraries 17 | /lib/ 18 | 19 | # C2CS 20 | /bindgen/ast/ 21 | /bindgen/x-ast/ 22 | 23 | # macOS 24 | .DS_store 25 | 26 | # scripts 27 | /build 28 | /ext/scripts 29 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/CallbackComponentCopy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public delegate void CallbackComponentCopy(ref ComponentCopyContext context); 7 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/CallbackComponentMove.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public delegate void CallbackComponentMove(ref ComponentMoveContext context); 7 | -------------------------------------------------------------------------------- /src/cs/examples/queries/Flecs.Examples.Queries.OptionalOr/Flecs.Examples.Queries.OptionalOr.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | true 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/cs/examples/systems/Flecs.Examples.Systems.CustomPhase/Flecs.Examples.Systems.CustomPhase.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | true 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.RelationBasic/Flecs.Examples.Entities.RelationBasic.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | true 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/CallbackComponentConstructor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public delegate void CallbackComponentConstructor(ref ComponentConstructorContext context); 7 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/CallbackComponentDeconstructor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public delegate void CallbackComponentDeconstructor(ref ComponentDeconstructorContext context); 7 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.RelationComponents/Flecs.Examples.Entities.RelationComponents.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | true 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/ITag.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | /// 7 | /// Marker interface for a Flecs tag. 8 | /// 9 | public interface ITag : IEcsComponent 10 | { 11 | } 12 | -------------------------------------------------------------------------------- /src/cs/Flecs.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /src/cs/examples/Flecs.Examples.HelloWorld/Flecs.Examples.HelloWorld.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bindgen/merge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 3 | 4 | if ! [[ -x "$(command -v castffi)" ]]; then 5 | echo "Error: 'castffi' is not installed. Please visit https://github.com/bottlenoselabs/CAstFfi for instructions to install the CAstFfi tool." >&2 6 | exit 1 7 | fi 8 | 9 | castffi merge --inputDirectoryPath "$DIRECTORY/ast" --outputFilePath "$DIRECTORY/x-ast/ast-cross-platform.json" -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Basics/Flecs.Examples.Entities.Basics.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Hooks/Flecs.Examples.Entities.Hooks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Prefab/Flecs.Examples.Entities.Prefab.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/cs/Flecs.sln.DotSettings.user: -------------------------------------------------------------------------------- 1 | 2 | VISIBLE_FILES 3 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Hierarchy/Flecs.Examples.Entities.Hierarchy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.PrefabSlot/Flecs.Examples.Entities.PrefabSlot.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bindgen/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 3 | 4 | if ! [[ -x "$(command -v c2cs)" ]]; then 5 | echo "Error: 'c2cs' is not installed. Please visit https://github.com/bottlenoselabs/C2CS for instructions to install the C2CS tool." >&2 6 | exit 1 7 | fi 8 | 9 | c2cs generate --config "$DIRECTORY/config-generate-cs-core.json" 10 | c2cs generate --config "$DIRECTORY/config-generate-cs-unity.json" -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.IterateComponents/Flecs.Examples.Entities.IterateComponents.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | net7.0 7 | true 8 | true 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/cs/.globalconfig: -------------------------------------------------------------------------------- 1 | # NOTE: Requires .NET 5 SDK (VS2019 16.8 or later) 2 | # https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files#global-analyzerconfig 3 | is_global = true 4 | 5 | dotnet_diagnostic.CA1815.severity = none 6 | 7 | # StyleCop Rules 8 | ## Description: StyleCop code analysis rules for C# projects. 9 | dotnet_diagnostic.SA1401.severity = none 10 | dotnet_diagnostic.SA1600.severity = none 11 | dotnet_diagnostic.SA1649.severity = none -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Flecs.Core.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /bindgen/config-generate-cs-core.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputFilePath": "./x-ast/ast-cross-platform.json", 3 | "outputFileDirectory": "./../src/cs/production/Interop.Flecs.Core/Generated", 4 | "namespaceName": "flecs_hub.Interop.Flecs", 5 | "className": "PInvoke", 6 | "libraryName": "flecs", 7 | "isEnabledGeneratingRuntimeCode": false, 8 | "isEnabledLibraryImport": true, 9 | "isEnabledFunctionPointers": true, 10 | "isEnabledFileScopedNamespace": true 11 | } 12 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/IComponent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | namespace Flecs; 7 | 8 | /// 9 | /// Marker interface for a Flecs component. 10 | /// 11 | public interface IComponent : IEcsComponent 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /bindgen/config-generate-cs-unity.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputFilePath": "./x-ast/ast-cross-platform.json", 3 | "outputFileDirectory": "./../src/cs/production/Interop.Flecs.Unity/Generated", 4 | "namespaceName": "flecs_hub.Interop.Flecs", 5 | "className": "PInvoke", 6 | "libraryName": "flecs", 7 | "isEnabledGeneratingRuntimeCode": false, 8 | "isEnabledLibraryImport": false, 9 | "isEnabledFunctionPointers": false, 10 | "isEnabledFileScopedNamespace": false 11 | } 12 | -------------------------------------------------------------------------------- /bindgen/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "Console": { 4 | "LogLevel": { 5 | "Default": "Warning", 6 | "CAstFfi": "Debug", 7 | "C2CS": "Debug" 8 | }, 9 | "FormatterOptions": { 10 | "ColorBehavior": "Enabled", 11 | "SingleLine": true, 12 | "IncludeScopes": true, 13 | "TimestampFormat": "yyyy-dd-MM HH:mm:ss ", 14 | "UseUtcTimestamp": true 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Pair.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs; 5 | 6 | public readonly struct Pair 7 | { 8 | public readonly Entity First; 9 | public readonly Entity Second; 10 | 11 | internal Pair(Entity first, Entity second) 12 | { 13 | First = first; 14 | Second = second; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /library.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 3 | 4 | if ! [[ -x "$(command -v c2cs)" ]]; then 5 | echo "Error: 'c2cs' is not installed. The C2CS tool is used to generate a C shared library for the purposes of P/Invoke with C#. Please visit https://github.com/bottlenoselabs/C2CS for instructions to install the C2CS tool." >&2 6 | exit 1 7 | fi 8 | 9 | c2cs library --config "$DIRECTORY/bindgen/config-build-c-library.json" 10 | 11 | if [[ -z "$1" ]]; then 12 | read 13 | fi -------------------------------------------------------------------------------- /.github/workflows/pull-release.yml: -------------------------------------------------------------------------------- 1 | name: "Pull request" 2 | 3 | on: 4 | pull_request: 5 | types: [assigned, opened, synchronize, reopened] 6 | paths-ignore: 7 | - '**.md' 8 | 9 | jobs: 10 | 11 | bindgen-job: 12 | uses: "./.github/workflows/bindgen.yml" 13 | 14 | build-job: 15 | needs: [bindgen-job] 16 | if: always() 17 | uses: "./.github/workflows/build.yml" 18 | 19 | commit-job: 20 | needs: [bindgen-job, build-job] 21 | if: github.actor == 'dependabot[bot]' 22 | uses: "./.github/workflows/commit.yml" 23 | -------------------------------------------------------------------------------- /src/c/production/flecs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(flecs C) 4 | set(CMAKE_C_STANDARD 11) 5 | 6 | get_filename_component(FLECS_DIRECTORY_PATH "../../../../ext/flecs" REALPATH BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 7 | file(GLOB_RECURSE SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c;${FLECS_DIRECTORY_PATH}/src/*.c) 8 | 9 | include_directories(flecs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${FLECS_DIRECTORY_PATH}/include) 10 | 11 | add_library(flecs SHARED ${SRC}) 12 | 13 | if (WIN32) 14 | target_link_libraries(flecs wsock32 ws2_32) 15 | endif() -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/FlecsException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | 6 | namespace Flecs; 7 | 8 | public class FlecsException : Exception 9 | { 10 | public FlecsException() 11 | { 12 | } 13 | 14 | public FlecsException(string message) 15 | : base(message) 16 | { 17 | } 18 | 19 | public FlecsException(string message, Exception innerException) 20 | : base(message, innerException) 21 | { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/cs/examples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/IteratorEvent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using JetBrains.Annotations; 5 | using static flecs_hub.Interop.Flecs.PInvoke; 6 | 7 | namespace Flecs; 8 | 9 | [PublicAPI] 10 | public readonly unsafe struct IteratorEvent 11 | { 12 | internal readonly World World; 13 | internal readonly ecs_entity_t Handle; 14 | 15 | internal IteratorEvent(World world, ecs_entity_t handle) 16 | { 17 | World = world; 18 | Handle = handle; 19 | } 20 | 21 | public string Name() 22 | { 23 | var result = ecs_get_name(World.Handle, Handle); 24 | return result.ToString(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/ComponentDeconstructorContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace Flecs; 7 | 8 | public readonly unsafe struct ComponentDeconstructorContext 9 | { 10 | private readonly void* _pointer; 11 | private readonly int _count; 12 | 13 | public ComponentDeconstructorContext(void* pointer, int count) 14 | { 15 | _pointer = pointer; 16 | _count = count; 17 | } 18 | 19 | public ref TComponent Get() 20 | where TComponent : unmanaged, IComponent 21 | { 22 | return ref Unsafe.AsRef(_pointer); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/ComponentConstructorContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace Flecs; 8 | 9 | public readonly unsafe struct ComponentConstructorContext 10 | { 11 | private readonly void* _pointer; 12 | private readonly int _count; 13 | 14 | public ComponentConstructorContext(void* pointer, int count) 15 | { 16 | _pointer = pointer; 17 | _count = count; 18 | } 19 | 20 | public ref TComponent Get() 21 | where TComponent : unmanaged, IComponent 22 | { 23 | return ref Unsafe.AsRef(_pointer); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Table.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | using JetBrains.Annotations; 6 | using static flecs_hub.Interop.Flecs.PInvoke; 7 | 8 | namespace Flecs; 9 | 10 | [PublicAPI] 11 | public readonly unsafe struct Table 12 | { 13 | public readonly ecs_table_t* Handle; 14 | private readonly ecs_world_t* _worldHandle; 15 | 16 | internal Table(ecs_world_t* world, ecs_table_t* handle) 17 | { 18 | _worldHandle = world; 19 | Handle = handle; 20 | } 21 | 22 | public string String() 23 | { 24 | var cString = ecs_table_str(_worldHandle, Handle); 25 | var result = Marshal.PtrToStringAnsi(cString)!; 26 | Marshal.FreeHGlobal(cString); 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/cs/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), .gitignore))/artifacts 7 | 8 | 9 | 10 | 11 | 12 | all 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | 22 | $(MSBuildThisFileDirectory)StyleCop.json 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.Core/Generated/AssemblyAttributes.gen.cs: -------------------------------------------------------------------------------- 1 | // To disable generating this file set `isEnabledGenerateAssemblyAttributes` to `false` in the config file for generating C# code. 2 | // 3 | // This code was generated by the following tool on 2023-09-05 00:24:37 GMT+00:00: 4 | // https://github.com/bottlenoselabs/c2cs (v6.1.3.0) 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. 7 | // 8 | // ReSharper disable All 9 | 10 | #region Template 11 | #nullable enable 12 | #pragma warning disable CS1591 13 | #pragma warning disable CS8981 14 | using bottlenoselabs.C2CS.Runtime; 15 | using System; 16 | using System.Collections.Generic; 17 | using System.Globalization; 18 | using System.Runtime.InteropServices; 19 | using System.Runtime.CompilerServices; 20 | #endregion 21 | 22 | #if NET7_0_OR_GREATER 23 | [assembly: DisableRuntimeMarshalling] 24 | #endif 25 | 26 | [assembly: DefaultDllImportSearchPathsAttribute(DllImportSearchPath.SafeDirectories)] 27 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.Unity/Generated/AssemblyAttributes.gen.cs: -------------------------------------------------------------------------------- 1 | // To disable generating this file set `isEnabledGenerateAssemblyAttributes` to `false` in the config file for generating C# code. 2 | // 3 | // This code was generated by the following tool on 2023-09-05 00:24:52 GMT+00:00: 4 | // https://github.com/bottlenoselabs/c2cs (v6.1.3.0) 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. 7 | // 8 | // ReSharper disable All 9 | 10 | #region Template 11 | #nullable enable 12 | #pragma warning disable CS1591 13 | #pragma warning disable CS8981 14 | using bottlenoselabs.C2CS.Runtime; 15 | using System; 16 | using System.Collections.Generic; 17 | using System.Globalization; 18 | using System.Runtime.InteropServices; 19 | using System.Runtime.CompilerServices; 20 | #endregion 21 | 22 | #if NET7_0_OR_GREATER 23 | [assembly: DisableRuntimeMarshalling] 24 | #endif 25 | 26 | [assembly: DefaultDllImportSearchPathsAttribute(DllImportSearchPath.SafeDirectories)] 27 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/EntityType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | using static flecs_hub.Interop.Flecs.PInvoke; 6 | 7 | namespace Flecs; 8 | 9 | public readonly unsafe struct EntityType 10 | { 11 | private readonly World _world; 12 | private readonly ecs_type_t* _handle; 13 | 14 | internal EntityType(World world, ecs_type_t* handle) 15 | { 16 | _handle = handle; 17 | _world = world; 18 | } 19 | 20 | public IdentifiersEnumerable Identifiers() 21 | { 22 | return new IdentifiersEnumerable(_world, _handle); 23 | } 24 | 25 | public string String() 26 | { 27 | var cString = ecs_type_str(_world.Handle, _handle); 28 | var result = Marshal.PtrToStringAnsi(cString.Pointer)!; 29 | Marshal.FreeHGlobal(cString.Pointer); 30 | return result; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/cs/StyleCop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "indentation": { 5 | "useTabs": false 6 | }, 7 | "documentationRules": { 8 | "companyName": "Flecs Hub (https://github.com/flecs-hub)", 9 | "copyrightText": "Copyright (c) {companyName}. All rights reserved.\nLicensed under the {licenseName} license. See {licenseFile} file in the Git repository root directory for full license information.", 10 | "variables": { 11 | "licenseName": "MIT", 12 | "licenseFile": "LICENSE" 13 | }, 14 | "xmlHeader": false, 15 | "documentInternalElements": false 16 | }, 17 | "orderingRules": { 18 | "usingDirectivesPlacement": "outsideNamespace", 19 | "elementOrder": [ 20 | "kind", 21 | "accessibility", 22 | "constant", 23 | "readonly" 24 | ] 25 | }, 26 | "layoutRules": { 27 | "newlineAtEndOfFile": "require" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Bottlenose Labs Inc. (https://github.com/bottlenoselabs) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/IdentifiersEnumerable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using JetBrains.Annotations; 8 | using static flecs_hub.Interop.Flecs.PInvoke; 9 | 10 | namespace Flecs; 11 | 12 | [PublicAPI] 13 | public readonly unsafe struct IdentifiersEnumerable : IEnumerable 14 | { 15 | private readonly IdentifiersEnumerator _enumerator; 16 | 17 | internal IdentifiersEnumerable(World world, ecs_type_t* type) 18 | { 19 | _enumerator = new IdentifiersEnumerator(world, type); 20 | } 21 | 22 | public IdentifiersEnumerator GetEnumerator() 23 | { 24 | // This method is duck-typed for usage in a `foreach` 25 | return _enumerator; 26 | } 27 | 28 | IEnumerator IEnumerable.GetEnumerator() 29 | { 30 | throw new InvalidOperationException(); 31 | } 32 | 33 | IEnumerator IEnumerable.GetEnumerator() 34 | { 35 | throw new InvalidOperationException(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Expressions/Expression.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Flecs; 11 | 12 | public class Expression 13 | { 14 | private World _world; 15 | 16 | public Expression(World world) 17 | { 18 | _world = world; 19 | } 20 | 21 | public TermBuilder Term() 22 | where T : unmanaged, IEcsComponent 23 | { 24 | var termBuilder = new TermBuilder(_world); 25 | termBuilder.First(); 26 | return termBuilder; 27 | } 28 | 29 | public TermBuilder Term() 30 | where T1 : unmanaged, IEcsComponent 31 | where T2 : unmanaged, IEcsComponent 32 | { 33 | var termBuilder = new TermBuilder(_world); 34 | termBuilder.First(); 35 | termBuilder.Second(); 36 | return termBuilder; 37 | } 38 | 39 | public TermBuilder Term() 40 | { 41 | return new TermBuilder(_world); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/commit.yml: -------------------------------------------------------------------------------- 1 | name: "Commit generated C# code" 2 | 3 | on: 4 | workflow_call: 5 | 6 | permissions: write-all 7 | 8 | jobs: 9 | 10 | commit-job: 11 | name: "Commit generated C# code" 12 | runs-on: ubuntu-latest 13 | if: github.actor == 'dependabot[bot]' 14 | 15 | steps: 16 | - name: "Clone Git repository" 17 | uses: actions/checkout@v2 18 | with: 19 | submodules: 'false' 20 | 21 | - name: "Download changes to commit: .NET 7+" 22 | uses: actions/download-artifact@v3 23 | with: 24 | name: "bindgen-cs-core" 25 | path: "./src/cs/production/Interop.Flecs.Core/Generated" 26 | 27 | - name: "Download changes to commit: Unity" 28 | uses: actions/download-artifact@v3 29 | with: 30 | name: "bindgen-cs-unity" 31 | path: "./src/cs/production/Interop.Flecs.Unity/Generated" 32 | 33 | - name: "Echo download path" 34 | run: echo ${{steps.download.outputs.download-path}} 35 | 36 | - name: "Add + commit + push (if necessary)" 37 | uses: EndBug/add-and-commit@v7 38 | with: 39 | author_name: 'lithiumtoast' 40 | author_email: '519592+lithiumtoast@users.noreply.github.com' 41 | message: "Update C# bindings" 42 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Properties/AdditionalCodeAnalysisSuppressions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | [assembly: SuppressMessage( 7 | "Microsoft.Reliability", 8 | "CA2020:Prevent behavioral change", 9 | MessageId = "Prevent behavioral change caused by built-in operators of IntPtr/UIntPtr", 10 | Justification = "The new changes from .NET 6 to .NET 7 for IntPtr/UIntPtr are acceptable.")] 11 | 12 | [assembly: SuppressMessage( 13 | "Microsoft.Performance", 14 | "CA1815:Override equals and operator equals on value types", 15 | MessageId = "Override equals and operator equals on value types", 16 | Justification = "Any time we are using structs for Interop or are creating structs that wrap Interop structs we most definitely want them to be blittable to which rule this does not apply.")] 17 | 18 | [assembly: SuppressMessage( 19 | "Microsoft.Design", 20 | "CA1040:Avoid empty interfaces", 21 | MessageId = "Avoid empty interfaces", 22 | Justification = "We are using interfaces with generics for compile time markers; this is acceptable according to MSDN.")] 23 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Flecs.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net7.0 6 | true 7 | false 8 | enable 9 | flecs_hub.Flecs 10 | 11 | 12 | 13 | 14 | true 15 | flecs_hub.Flecs 16 | C# API for https://github.com/SanderMertens/flecs 17 | https://github.com/flecs_hub/flecs-cs 18 | MIT 19 | 20 | 21 | 22 | true 23 | / 24 | PreserveNewest 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Is this file the top-most EditorConfig file? 2 | root = true 3 | 4 | # Any and all files 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 4 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | # C# files 13 | [*.cs] 14 | indent_style = space 15 | 16 | # Visual Studio Solution files 17 | [*.sln] 18 | indent_style = tab 19 | 20 | # Visual Studio XML project files 21 | [*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}] 22 | indent_style = tab 23 | indent_size = 2 24 | 25 | # XML configuration files 26 | [*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] 27 | indent_style = tab 28 | indent_size = 2 29 | 30 | # JSON files 31 | [*.{json,json5,webmanifest}] 32 | indent_style = space 33 | indent_size = 2 34 | 35 | # YAML files 36 | [*.{yml,yaml}] 37 | indent_style = space 38 | indent_size = 2 39 | 40 | # Markdown files 41 | [*.md] 42 | indent_style = space 43 | trim_trailing_whitespace = false 44 | indent_size = 4 45 | 46 | # Web files 47 | [*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}] 48 | indent_style = space 49 | indent_size = 2 50 | 51 | # Batch files 52 | [*.{cmd,bat}] 53 | indent_style = tab 54 | end_of_line = crlf 55 | 56 | # Bash files 57 | [*.sh] 58 | indent_style = tab 59 | end_of_line = lf 60 | 61 | # Makefiles 62 | [Makefile] 63 | indent_style = tab -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/ComponentCopyContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace Flecs; 8 | 9 | public readonly unsafe struct ComponentCopyContext 10 | { 11 | private readonly void* _destinationPointer; 12 | private readonly void* _sourcePointer; 13 | private readonly int _count; 14 | 15 | public IntPtr DestinationPointer => (IntPtr)_destinationPointer; 16 | 17 | public IntPtr SourcePointer => (IntPtr)_sourcePointer; 18 | 19 | public ComponentCopyContext(void* destinationPointer, void* sourcePointer, int count) 20 | { 21 | _destinationPointer = destinationPointer; 22 | _sourcePointer = sourcePointer; 23 | _count = count; 24 | } 25 | 26 | public ref TComponent GetDestination() 27 | where TComponent : unmanaged, IComponent 28 | { 29 | return ref Unsafe.AsRef(_destinationPointer); 30 | } 31 | 32 | public ref TComponent GetSource() 33 | where TComponent : unmanaged, IComponent 34 | { 35 | return ref Unsafe.AsRef(_sourcePointer); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/ComponentMoveContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Runtime.CompilerServices; 6 | 7 | namespace Flecs; 8 | 9 | public readonly unsafe struct ComponentMoveContext 10 | { 11 | private readonly void* _destinationPointer; 12 | private readonly void* _sourcePointer; 13 | private readonly int _count; 14 | 15 | public IntPtr DestinationPointer => (IntPtr)_destinationPointer; 16 | 17 | public IntPtr SourcePointer => (IntPtr)_sourcePointer; 18 | 19 | public ComponentMoveContext(void* destinationPointer, void* sourcePointer, int count) 20 | { 21 | _destinationPointer = destinationPointer; 22 | _sourcePointer = sourcePointer; 23 | _count = count; 24 | } 25 | 26 | public ref TComponent GetDestination() 27 | where TComponent : unmanaged, IComponent 28 | { 29 | return ref Unsafe.AsRef(_destinationPointer); 30 | } 31 | 32 | public ref TComponent GetSource() 33 | where TComponent : unmanaged, IComponent 34 | { 35 | return ref Unsafe.AsRef(_sourcePointer); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.Unity/Interop.Flecs.Unity.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netstandard2.1 6 | disable 7 | true 8 | flecs_hub.Interop.Flecs 9 | false 10 | enable 11 | en 12 | false 13 | false 14 | $(NoWarn);CS8981;CA1016 15 | 16 | 17 | 18 | 19 | false 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | %(RecursiveDir)%(Filename)%(Extension) 30 | PreserveNewest 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.Core/Interop.Flecs.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net7.0 6 | enable 7 | true 8 | flecs_hub.Interop.Flecs 9 | false 10 | enable 11 | en 12 | $(NoWarn);CS8981 13 | 14 | 15 | 16 | 17 | true 18 | flecs_hub.Interop.Flecs 19 | C# interop bindings for https://github.com/SanderMertens/flecs 20 | https://github.com/flecs_hub/flecs-cs 21 | MIT 22 | 23 | 24 | 25 | true 26 | / 27 | PreserveNewest 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/IdentifiersEnumerator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using static flecs_hub.Interop.Flecs.PInvoke; 8 | 9 | namespace Flecs; 10 | 11 | public unsafe struct IdentifiersEnumerator : IEnumerator 12 | { 13 | private readonly World _world; 14 | private int _index; 15 | private readonly ecs_type_t* _type; 16 | 17 | public Identifier Current { get; private set; } 18 | 19 | public IdentifiersEnumerator(World world, ecs_type_t* type) 20 | { 21 | _world = world; 22 | _type = type; 23 | _index = 0; 24 | Current = default; 25 | } 26 | 27 | public bool MoveNext() 28 | { 29 | if (_index >= _type->count) 30 | { 31 | return false; 32 | } 33 | 34 | var current = _type->array[_index++]; 35 | Current = new Identifier(_world, current); 36 | return true; 37 | } 38 | 39 | public void Reset() 40 | { 41 | _index = 0; 42 | Current = default; 43 | } 44 | 45 | public void Dispose() 46 | { 47 | } 48 | 49 | object IEnumerator.Current => throw new InvalidOperationException(); 50 | } 51 | -------------------------------------------------------------------------------- /bindgen/extract.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 3 | 4 | function get_host_operating_system() { 5 | local UNAME_STRING="$(uname -a)" 6 | case "${UNAME_STRING}" in 7 | *Microsoft*) local HOST_OS="windows";; 8 | *microsoft*) local HOST_OS="windows";; 9 | Linux*) local HOST_OS="linux";; 10 | Darwin*) local HOST_OS="macos";; 11 | CYGWIN*) local HOST_OS="linux";; 12 | MINGW*) local HOST_OS="windows";; 13 | *Msys) local HOST_OS="windows";; 14 | *) local HOST_OS="UNKNOWN:${UNAME_STRING}" 15 | esac 16 | echo "$HOST_OS" 17 | return 0 18 | } 19 | 20 | OS="$(get_host_operating_system)" 21 | 22 | if [[ "$OS" == "windows" ]]; then 23 | CASTFFI_CONFIG_FILE_PATH="$DIRECTORY/config-extract-windows.json" 24 | elif [[ "$OS" == "macos" ]]; then 25 | CASTFFI_CONFIG_FILE_PATH="$DIRECTORY/config-extract-macos.json" 26 | elif [[ "$OS" == "linux" ]]; then 27 | CASTFFI_CONFIG_FILE_PATH="$DIRECTORY/config-extract-linux.json" 28 | else 29 | echo "Error: Unknown operating system '$OS'" >&2 30 | exit 1 31 | fi 32 | 33 | if ! [[ -x "$(command -v castffi)" ]]; then 34 | echo "Error: 'castffi' is not installed. Please visit https://github.com/bottlenoselabs/CAstFfi for instructions to install the CAstFfi tool." >&2 35 | exit 1 36 | fi 37 | 38 | castffi extract --config "$CASTFFI_CONFIG_FILE_PATH" 39 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Unity/Flecs.Unity.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netstandard2.1 6 | disable 7 | enable 8 | $(DefineConstants);UNITY_5_3_OR_NEWER 9 | $(NoWarn);CA1016 10 | flecs_hub.Flecs 11 | false 12 | false 13 | $(NoWarn);CA1016 14 | 15 | 16 | 17 | 18 | false 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | %(RecursiveDir)%(Filename)%(Extension) 36 | PreserveNewest 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/cs/examples/systems/Flecs.Examples.Systems.CustomPhase/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using static flecs_hub.Interop.Flecs.PInvoke; 5 | 6 | namespace Flecs.Examples.Systems.CustomPhase; 7 | 8 | #pragma warning disable CS0649 9 | 10 | internal static class Program 11 | { 12 | internal struct Position : IComponent 13 | { 14 | public float X; 15 | public float Y; 16 | } 17 | 18 | private static int Main(string[] args) 19 | { 20 | var world = new World(args); 21 | 22 | var physics = world.CreateEntity("physics"); 23 | physics.Add(world.EcsPhase); 24 | physics.DependsOn(world.EcsDependsOn); 25 | 26 | var collision = world.CreateEntity("collision"); 27 | collision.Add(world.EcsPhase); 28 | collision.DependsOn(physics); 29 | 30 | world.RegisterSystem(System1, physics, string.Empty); 31 | world.RegisterSystem(System2, collision, string.Empty); 32 | world.RegisterSystem(System3, EcsOnUpdate, string.Empty); 33 | 34 | world.Progress(0); 35 | 36 | return world.Fini(); 37 | } 38 | 39 | private static void System1(Iterator iterator) 40 | { 41 | Console.WriteLine("Sys1: Physics < OnUpdate"); 42 | } 43 | 44 | private static void System2(Iterator iterator) 45 | { 46 | Console.WriteLine("Sys2: Collision < Physics < OnUpdate"); 47 | } 48 | 49 | private static void System3(Iterator iterator) 50 | { 51 | Console.WriteLine("Sys3 OnUpdate"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Identifier.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | using static flecs_hub.Interop.Flecs.PInvoke; 6 | 7 | namespace Flecs; 8 | 9 | public readonly unsafe struct Identifier 10 | { 11 | internal readonly World World; 12 | internal readonly ecs_id_t Handle; 13 | 14 | internal Identifier(World world, ecs_id_t handle) 15 | { 16 | World = world; 17 | Handle = handle; 18 | } 19 | 20 | public bool IsPair => ecs_id_is_pair(Handle); 21 | 22 | public string String() 23 | { 24 | var cString = ecs_id_str(World.Handle, Handle); 25 | var result = Marshal.PtrToStringAnsi(cString.Pointer)!; 26 | Marshal.FreeHGlobal(cString.Pointer); 27 | return result; 28 | } 29 | 30 | public string RoleString() 31 | { 32 | var id = default(ecs_id_t); 33 | id.Data = Handle.Data & ECS_ID_FLAGS_MASK; 34 | var cString = ecs_id_flag_str(id); 35 | var result = Marshal.PtrToStringAnsi(cString.Pointer)!; 36 | return result; 37 | } 38 | 39 | public Pair AsPair() 40 | { 41 | var first = ecs_pair_first(World.Handle, Handle); 42 | var firstEntity = new Entity(World, first); 43 | var second = ecs_pair_second(World.Handle, Handle); 44 | var secondEntity = new Entity(World, second); 45 | return new Pair(firstEntity, secondEntity); 46 | } 47 | 48 | public Entity AsComponent() 49 | { 50 | var value = Handle.Data & ECS_COMPONENT_MASK; 51 | return new Entity(World, *(ecs_entity_t*)&value); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/EntityIterator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Runtime.CompilerServices; 6 | using JetBrains.Annotations; 7 | using static flecs_hub.Interop.Flecs.PInvoke; 8 | 9 | namespace Flecs; 10 | 11 | [PublicAPI] 12 | public readonly unsafe struct EntityIterator 13 | { 14 | internal readonly ecs_iter_t Handle; 15 | private readonly ecs_world_t* _world; 16 | 17 | public int Count => Handle.count; 18 | 19 | internal EntityIterator(World world, ecs_iter_t it) 20 | { 21 | _world = world.Handle; 22 | Handle = it; 23 | } 24 | 25 | public float DeltaTime() => Handle.delta_time; 26 | 27 | public float DeltaSystemTime() => Handle.delta_system_time; 28 | 29 | public bool HasNext() 30 | { 31 | fixed (EntityIterator* @this = &this) 32 | { 33 | var handlePointer = &@this->Handle; 34 | var result = ecs_term_next(handlePointer); 35 | return result; 36 | } 37 | } 38 | 39 | public Span Field(int index) 40 | { 41 | fixed (EntityIterator* @this = &this) 42 | { 43 | var handlePointer = &@this->Handle; 44 | var structSize = Unsafe.SizeOf(); 45 | var pointer = ecs_field_w_size(handlePointer, (ulong)structSize, index); 46 | return new Span(pointer, Handle.count); 47 | } 48 | } 49 | 50 | public Entity Entity(int index) 51 | { 52 | var world = World.Pointers[(IntPtr)_world]; 53 | var result = new Entity(world, Handle.entities[index]); 54 | return result; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/c/production/flecs/include/flecs_pinvoke.h: -------------------------------------------------------------------------------- 1 | #include "pinvoke.h" 2 | #include "flecs.h" 3 | 4 | // Roles 5 | PINVOKE_API ecs_id_t pinvoke_ECS_PAIR() 6 | { 7 | return ECS_PAIR; 8 | } 9 | 10 | PINVOKE_API ecs_id_t pinvoke_ECS_OVERRIDE() 11 | { 12 | return ECS_OVERRIDE; 13 | } 14 | 15 | // Relationships 16 | PINVOKE_API ecs_entity_t pinvoke_EcsIsA() 17 | { 18 | return EcsIsA; 19 | } 20 | 21 | PINVOKE_API ecs_entity_t pinvoke_EcsDependsOn() 22 | { 23 | return EcsDependsOn; 24 | } 25 | 26 | PINVOKE_API ecs_entity_t pinvoke_EcsChildOf() 27 | { 28 | return EcsChildOf; 29 | } 30 | 31 | PINVOKE_API ecs_entity_t pinvoke_EcsSlotOf() 32 | { 33 | return EcsSlotOf; 34 | } 35 | 36 | // Entity tags 37 | PINVOKE_API ecs_entity_t pinvoke_EcsPrefab() 38 | { 39 | return EcsPrefab; 40 | } 41 | 42 | // System tags 43 | PINVOKE_API ecs_entity_t pinvoke_EcsPreFrame() 44 | { 45 | return EcsPreFrame; 46 | } 47 | 48 | PINVOKE_API ecs_entity_t pinvoke_EcsOnLoad() 49 | { 50 | return EcsOnLoad; 51 | } 52 | 53 | PINVOKE_API ecs_entity_t pinvoke_EcsPostLoad() 54 | { 55 | return EcsPostLoad; 56 | } 57 | 58 | PINVOKE_API ecs_entity_t pinvoke_EcsPreUpdate() 59 | { 60 | return EcsPreUpdate; 61 | } 62 | 63 | PINVOKE_API ecs_entity_t pinvoke_EcsOnUpdate() 64 | { 65 | return EcsOnUpdate; 66 | } 67 | 68 | PINVOKE_API ecs_entity_t pinvoke_EcsOnValidate() 69 | { 70 | return EcsOnValidate; 71 | } 72 | 73 | PINVOKE_API ecs_entity_t pinvoke_EcsPostUpdate() 74 | { 75 | return EcsPostUpdate; 76 | } 77 | 78 | PINVOKE_API ecs_entity_t pinvoke_EcsPreStore() 79 | { 80 | return EcsPreStore; 81 | } 82 | 83 | PINVOKE_API ecs_entity_t pinvoke_EcsOnStore() 84 | { 85 | return EcsOnStore; 86 | } 87 | 88 | PINVOKE_API ecs_entity_t pinvoke_EcsPostFrame() 89 | { 90 | return EcsPostFrame; 91 | } 92 | 93 | PINVOKE_API ecs_entity_t pinvoke_EcsPhase() 94 | { 95 | return EcsPhase; 96 | } -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.runtime.osx/Interop.Flecs.runtime.osx.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netstandard1.0 6 | false 7 | disable 8 | true 9 | 10 | 11 | 12 | 13 | true 14 | flecs_hub.Interop.Flecs.runtime.osx 15 | 16 | macOS x64/arm64 native libraries for the `flecs_hub.Interop.Flecs` package. 17 | 18 | https://github.com/flecs-hub/flecs-cs 19 | MIT 20 | _README_PACKAGE.md 21 | true 22 | true 23 | false 24 | false 25 | 26 | 27 | 28 | true 29 | / 30 | PreserveNewest 31 | 32 | 33 | 34 | 35 | 36 | 37 | %(Filename)%(Extension) 38 | runtimes/osx/native/%(Filename)%(Extension) 39 | true 40 | PreserveNewest 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.runtime.win-x64/Interop.Flecs.runtime.win-x64.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netstandard1.0 6 | false 7 | disable 8 | true 9 | 10 | 11 | 12 | 13 | true 14 | flecs_hub.Interop.Flecs.runtime.win-x64 15 | 16 | Windows x64 native libraries for the `flecs_hub.Interop.Flecs` package. 17 | 18 | https://github.com/flecs-hub/flecs-cs 19 | MIT 20 | _README_PACKAGE.md 21 | true 22 | true 23 | false 24 | false 25 | 26 | 27 | 28 | true 29 | / 30 | PreserveNewest 31 | 32 | 33 | 34 | 35 | 36 | 37 | %(Filename)%(Extension) 38 | runtimes/win-x64/native/%(Filename)%(Extension) 39 | true 40 | PreserveNewest 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.runtime.linux-x64/Interop.Flecs.runtime.linux-x64.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netstandard1.0 6 | false 7 | disable 8 | true 9 | 10 | 11 | 12 | 13 | true 14 | flecs_hub.Interop.Flecs.runtime.linux-x64 15 | 16 | Linux x64 native libraries for the `flecs_hub.Interop.Flecs` package. 17 | 18 | https://github.com/flecs-hub/flecs-cs 19 | MIT 20 | _README_PACKAGE.md 21 | true 22 | true 23 | false 24 | false 25 | 26 | 27 | 28 | true 29 | / 30 | PreserveNewest 31 | 32 | 33 | 34 | 35 | 36 | 37 | %(Filename)%(Extension) 38 | runtimes/linux-x64/native/%(Filename)%(Extension) 39 | true 40 | PreserveNewest 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.PrefabSlot/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs.Examples.Entities.PrefabSlot; 5 | 6 | internal static class Program 7 | { 8 | private static int Main(string[] args) 9 | { 10 | var world = new World(args); 11 | // ecs_world_t* ecs = ecs_init_w_args(argc, argv); 12 | 13 | // Create the same prefab hierarchy as from the hierarchy example, but now with the SlotOf relationship. 14 | 15 | var spaceShipPrefab = world.CreatePrefab("SpaceShip"); 16 | var enginePrefab = world.CreatePrefab("Engine"); 17 | enginePrefab.AddParent(spaceShipPrefab); 18 | enginePrefab.AddSlotOf(spaceShipPrefab); 19 | 20 | var cockpitPrefab = world.CreatePrefab("Cockpit"); 21 | cockpitPrefab.AddParent(spaceShipPrefab); 22 | cockpitPrefab.AddSlotOf(spaceShipPrefab); 23 | 24 | // Add an additional child to the Cockpit prefab to demonstrate how 25 | // slots can be different from the parent. This slot could have been 26 | // added to the Cockpit prefab, but instead we register it on the top 27 | // level SpaceShip prefab. 28 | var pilotSeat = world.CreatePrefab("PilotSeat"); 29 | pilotSeat.AddParent(cockpitPrefab); 30 | pilotSeat.AddSlotOf(spaceShipPrefab); 31 | 32 | // Create a prefab instance. 33 | var shipInstance = world.CreateEntity("SpaceShipInstance"); 34 | shipInstance.IsA(spaceShipPrefab); 35 | 36 | // Get the instantiated entities for the prefab slots 37 | Entity engineInstance = shipInstance.GetTarget(enginePrefab); 38 | Entity cockpitInstance = shipInstance.GetTarget(cockpitPrefab); 39 | Entity pilotSeatInstance = shipInstance.GetTarget(pilotSeat); 40 | 41 | Console.WriteLine($"Instance engine: {engineInstance.FullPathString()}"); 42 | Console.WriteLine($"Instance cockpit: {cockpitInstance.FullPathString()}"); 43 | Console.WriteLine($"Instance pilot seat: {pilotSeatInstance.FullPathString()}"); 44 | 45 | return world.Fini(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Iterator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Runtime.CompilerServices; 6 | using JetBrains.Annotations; 7 | using static flecs_hub.Interop.Flecs.PInvoke; 8 | 9 | namespace Flecs; 10 | 11 | [PublicAPI] 12 | public readonly unsafe struct Iterator 13 | { 14 | internal readonly ecs_iter_t* Handle; 15 | private readonly World _world; 16 | 17 | public int Count => Handle->count; 18 | 19 | internal Iterator(World world, ecs_iter_t* it) 20 | { 21 | _world = world; 22 | Handle = it; 23 | } 24 | 25 | public float DeltaTime() => Handle->delta_time; 26 | 27 | public float DeltaSystemTime() => Handle->delta_system_time; 28 | 29 | public Span Field(int index) 30 | { 31 | var structSize = Unsafe.SizeOf(); 32 | var pointer = ecs_field_w_size(Handle, (ulong)structSize, index); 33 | return new Span(pointer, Handle->count); 34 | } 35 | 36 | public bool FieldIsSet(int index) 37 | { 38 | return ecs_field_is_set(Handle, index); 39 | } 40 | 41 | public bool FieldIs(int index) 42 | where T : unmanaged, IEcsComponent 43 | { 44 | var id = ecs_field_id(Handle, index); 45 | var compId = _world.GetIdentifier(); 46 | return id == compId.Handle; 47 | } 48 | 49 | public Table Table() 50 | { 51 | return new Table(Handle->world, Handle->table); 52 | } 53 | 54 | public Entity Entity(int index) 55 | { 56 | var result = new Entity(_world, Handle->entities[index]); 57 | return result; 58 | } 59 | 60 | public bool HasQueryChanged() 61 | { 62 | return ecs_query_changed(null, Handle); 63 | } 64 | 65 | public void QuerySkip() 66 | { 67 | ecs_query_skip(Handle); 68 | } 69 | 70 | public bool IsSelf(int index) 71 | { 72 | return ecs_field_is_self(Handle, index); 73 | } 74 | 75 | public IteratorEvent Event() 76 | { 77 | var result = new IteratorEvent(_world, Handle->@event); 78 | return result; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Basics/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Flecs.Examples.Entities.Basics; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | public struct Position : IComponent 10 | { 11 | public double X; 12 | public double Y; 13 | } 14 | 15 | public struct Walking : ITag 16 | { 17 | } 18 | 19 | internal static class Program 20 | { 21 | private static int Main(string[] args) 22 | { 23 | var world = new World(args); 24 | 25 | world.RegisterComponent(); 26 | world.RegisterTag(); 27 | 28 | var bob = world.CreateEntity("Bob"); 29 | bob.Set(new Position { X = 10, Y = 20 }); 30 | bob.Add(); 31 | 32 | var position = bob.GetComponent(); 33 | Console.WriteLine("Bob's initial position: {" + position.X + ", " + position.Y + "}"); 34 | 35 | // Print all the components the entity has. This will output: 36 | // Position, Walking, (Identifier,Name) 37 | Console.WriteLine("Bob's type: " + bob.Type().String()); 38 | 39 | bob.Set(new Position { X = 20, Y = 30 }); 40 | 41 | var alice = world.CreateEntity("Alice"); 42 | alice.Set(new Position { X = 10, Y = 20 }); 43 | alice.Add(); 44 | 45 | // Print all the components the entity has. This will output: 46 | // Position, Walking, (Identifier,Name) 47 | Console.WriteLine("Alice's type: " + alice.Type().String()); 48 | 49 | // Remove tag 50 | alice.Remove(); 51 | 52 | // Iterate all entities with Position 53 | var it = world.EntityIterator(); 54 | while (it.HasNext()) 55 | { 56 | var p = it.Field(1); 57 | for (var i = 0; i < it.Count; i++) 58 | { 59 | var entity = it.Entity(i); 60 | var entityName = entity.Name(); 61 | var entityPosition = p[i]; 62 | Console.WriteLine(entityName + ": {" + entityPosition.X + ", " + entityPosition.Y + "}"); 63 | } 64 | } 65 | 66 | return world.Fini(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/cs/examples/Flecs.Examples.HelloWorld/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Flecs.Examples.HelloWorld; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | public struct Position : IComponent 10 | { 11 | public double X; 12 | public double Y; 13 | } 14 | 15 | [StructLayout(LayoutKind.Sequential)] 16 | public struct Velocity : IComponent 17 | { 18 | public double X; 19 | public double Y; 20 | } 21 | 22 | public struct Eats : ITag 23 | { 24 | } 25 | 26 | public struct Apples : ITag 27 | { 28 | } 29 | 30 | public struct Pears : ITag 31 | { 32 | } 33 | 34 | internal static class Program 35 | { 36 | // Move system implementation. System callbacks may be called multiple times, as entities are grouped by which 37 | // components they have, and each group has its own set of component arrays. 38 | private static void Move(Iterator iterator) 39 | { 40 | var p = iterator.Field(1); 41 | var v = iterator.Field(2); 42 | 43 | // Print the set of components for the iterated over entities 44 | var tableString = iterator.Table().String(); 45 | Console.WriteLine("Move entities with table: " + tableString); 46 | 47 | // Iterate entities for the current group 48 | for (var i = 0; i < iterator.Count; i++) 49 | { 50 | ref var position = ref p[i]; 51 | var velocity = v[i]; 52 | 53 | position.X += velocity.X; 54 | position.Y += velocity.Y; 55 | } 56 | } 57 | 58 | private static int Main(string[] args) 59 | { 60 | // Create the world 61 | var world = new World(args); 62 | 63 | world.RegisterComponent(); 64 | world.RegisterComponent(); 65 | world.RegisterTag(); 66 | world.RegisterTag(); 67 | world.RegisterTag(); 68 | 69 | // Register system 70 | world.RegisterSystem(Move); 71 | 72 | // Create an entity with name Bob, add Position and food preference 73 | var bob = world.CreateEntity("Bob"); 74 | bob.Set(new Position { X = 0, Y = 0 }); 75 | bob.Set(new Velocity { X = 2, Y = 2 }); 76 | bob.Add(); 77 | 78 | // Run systems twice. Usually this function is called once per frame 79 | world.Progress(0); 80 | world.Progress(0); 81 | 82 | // See if Bob has moved (he has) 83 | var p = bob.GetComponent(); 84 | Console.WriteLine("Bob's position is {" + p.X + ", " + p.Y + "}"); 85 | 86 | return world.Fini(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flecs-cs 2 | 3 | Archived; see: https://github.com/BeanCheeseBurrito/Flecs.NET 4 | 5 | Automatically updated C# bindings for https://github.com/SanderMertens/flecs with native dynamic link libraries. Includes the lower-level unsafe C# "binding" which is 100% automatically generated. The higher level safe "wrapper" is still being worked on. 6 | 7 | ## How to use 8 | 9 | ### NuGet 10 | 11 | NuGet packages are experimental; please add the NuGet feed `https://www.myget.org/F/bottlenoselabs/api/v3/index.json` to access the NuGet packages. 12 | 13 | Either install `flecs_hub.Flecs` or `flecs_hub.Interop.Flecs` along with one the native library packages for your operating system / hardware. 14 | 15 | |Package name|Description| 16 | |-|-| 17 | |`flecs_hub.Flecs`|High-level, safe, idomatic C# API.| 18 | |`flecs_hub.Interop.Flecs`|Low-level, unsafe, 1-1 C# bindings.| 19 | |`flecs_hub.Interop.Flecs.runtime.win-x64`|Native libraries for Windows x64.| 20 | |`flecs_hub.Interop.Flecs.runtime.osx`|Native libraries for macOS universal (x64 and arm64).| 21 | |`flecs_hub.Interop.Flecs.runtime.linux-x64`|Native libraries for Linux x64.| 22 | 23 | ### From source 24 | 25 | 1. Download and install [.NET 7](https://dotnet.microsoft.com/download). 26 | 2. Fork the repository using GitHub or clone the repository manually with submodules: `git clone --recurse-submodules https://github.com/flecs-hub/flecs-cs`. 27 | 3. Build the native library by running `library.sh`. To execute `.sh` scripts on Windows, use Git Bash which can be installed with Git itself: https://git-scm.com/download/win. The `library.sh` script requires that CMake is installed and in your path and that [`C2CS`](https://github.com/bottlenoselabs/c2cs) is installed. 28 | 4. 29 | - .NET 7+: Add the `src/cs/production/Flecs.Core/Flecs.Core.csproj` C# project to your solution as an existing project and then reference it within your own solution. 30 | - Unity: Build the `src/cs/production/Flecs.Unity/Flecs.Unity.csproj` C# project and create the resulting `Flecs.Unity.dll` with it's dependencies; follow Unity's documentation for using the compiled C# code as a `.dll`: https://docs.unity3d.com/Manual/UsingDLL. 31 | 32 | ## Developers: Documentation 33 | 34 | ### C# Examples 35 | 36 | For examples in C# (.NET Core, not Unity), see [./src/cs/examples](https://github.com/flecs-hub/flecs-cs/tree/main/src/cs/examples), or open up the solution `.sln` file in VisualStudio / Rider. 37 | 38 | ### C Examples 39 | 40 | To learn how to use `flecs` directly, check out the https://github.com/SanderMertens/flecs#documentation. 41 | 42 | ### Binding / wrapper 43 | 44 | For more information on how C# binding / wrapper work, see [`C2CS`](https://github.com/lithiumtoast/c2cs), the tool that generates the binding / wrapper for `flecs` and other C libraries. 45 | 46 | ## License 47 | 48 | `flecs-cs` is licensed under the MIT License (`MIT`) - see the [LICENSE file](LICENSE) for details. 49 | 50 | `flecs` itself is licensed under MIT (`MIT`) - see https://github.com/SanderMertens/flecs/blob/master/LICENSE for more details. 51 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/CallbacksHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Threading; 7 | 8 | namespace Flecs; 9 | 10 | internal static class CallbacksHelper 11 | { 12 | private static SystemCallbackContext[] _systemCallbackContexts = new SystemCallbackContext[64]; 13 | private static int _systemCallbackContextsCount; 14 | 15 | private static ComponentHooksCallbackContext[] _componentHooksCallbackContexts = new ComponentHooksCallbackContext[64]; 16 | private static int _componentHooksCallbackContextsCount; 17 | 18 | public static IntPtr CreateSystemCallbackContext(World world, CallbackIterator callback) 19 | { 20 | var data = new SystemCallbackContext(world, callback); 21 | var count = Interlocked.Increment(ref _systemCallbackContextsCount); 22 | if (count > _systemCallbackContexts.Length) 23 | { 24 | Array.Resize(ref _systemCallbackContexts, count * 2); 25 | } 26 | 27 | _systemCallbackContexts[count - 1] = data; 28 | var result = (IntPtr)count; 29 | return result; 30 | } 31 | 32 | public static void GetSystemCallbackContext(IntPtr pointer, out SystemCallbackContext data) 33 | { 34 | var index = (int)pointer; 35 | data = _systemCallbackContexts[index - 1]; 36 | } 37 | 38 | public static IntPtr CreateComponentHooksCallbackContext(World world, ComponentHooks hooks) 39 | { 40 | var data = new ComponentHooksCallbackContext(world, hooks); 41 | var count = Interlocked.Increment(ref _componentHooksCallbackContextsCount); 42 | if (count > _componentHooksCallbackContexts.Length) 43 | { 44 | Array.Resize(ref _componentHooksCallbackContexts, count * 2); 45 | } 46 | 47 | _componentHooksCallbackContexts[count - 1] = data; 48 | var result = (IntPtr)count; 49 | return result; 50 | } 51 | 52 | public static unsafe ref ComponentHooksCallbackContext GetComponentHooksCallbackContext(void* pointer) 53 | { 54 | var index = (int)pointer; 55 | return ref _componentHooksCallbackContexts[index - 1]; 56 | } 57 | 58 | public readonly struct SystemCallbackContext 59 | { 60 | public readonly World World; 61 | public readonly CallbackIterator Callback; 62 | 63 | public SystemCallbackContext(World world, CallbackIterator callback) 64 | { 65 | World = world; 66 | Callback = callback; 67 | } 68 | } 69 | 70 | public readonly struct ComponentHooksCallbackContext 71 | { 72 | public readonly World World; 73 | public readonly ComponentHooks Hooks; 74 | 75 | public ComponentHooksCallbackContext(World world, ComponentHooks hooks) 76 | { 77 | World = world; 78 | Hooks = hooks; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Release" 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | pre-release: 6 | description: 'Is this a release candidate (pre-release)? (NOTE: candidates get uploaded to MyGet.org instead of NuGet.org)' 7 | required: true 8 | default: 'true' 9 | schedule: 10 | - cron: "0 0 1 * *" # First day of every month 11 | 12 | jobs: 13 | 14 | build-job: 15 | name: "Build" 16 | uses: "./.github/workflows/build.yml" 17 | 18 | release-job: 19 | name: "Release" 20 | needs: [build-job] 21 | runs-on: ubuntu-latest 22 | permissions: 23 | contents: write 24 | steps: 25 | 26 | - name: "Clone Git repository" 27 | uses: actions/checkout@master 28 | with: 29 | submodules: "recursive" 30 | 31 | - name: "Set version" 32 | id: set-version 33 | shell: bash 34 | run: | 35 | IS_PRERELEASE="${{ github.event.inputs.pre-release }}" 36 | if [[ "$IS_PRERELEASE" = "true" ]]; then 37 | VERSION="$(date +'%Y.%m.%d')-rc" 38 | else 39 | VERSION="$(date +'%Y.%m.%d')" 40 | fi 41 | echo "VERSION=$VERSION" 42 | echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" 43 | 44 | - name: "Download native libraries (win-x64)" 45 | uses: actions/download-artifact@v1 46 | with: 47 | name: "native-libraries-win-x64" 48 | path: "./lib" 49 | 50 | - name: "Download native libraries (osx)" 51 | uses: actions/download-artifact@v1 52 | with: 53 | name: "native-libraries-osx" 54 | path: "./lib" 55 | 56 | - name: "Download native libraries (linux-x64)" 57 | uses: actions/download-artifact@v1 58 | with: 59 | name: "native-libraries-linux-x64" 60 | path: "./lib" 61 | 62 | - name: ".NET pack" 63 | run: dotnet pack "./src/cs" --nologo --verbosity minimal --configuration Release -p:Version="${{ steps.set-version.outputs.VERSION }}" -p:RepositoryBranch="${{ github.head_ref || github.ref_name }}" -p:RepositoryCommit="${{ github.sha }}" 64 | 65 | - name: "Upload packages to MyGet" 66 | if: github.event_name == 'workflow_dispatch' && github.event.inputs.pre-release == 'true' 67 | env: 68 | MYGET_ACCESS_TOKEN: ${{ secrets.MYGET_ACCESS_TOKEN }} 69 | run: dotnet nuget push "./nupkg/**/*.nupkg" --source https://www.myget.org/F/bottlenoselabs/api/v3/index.json --skip-duplicate --api-key $MYGET_ACCESS_TOKEN 70 | 71 | - name: "Upload packages to NuGet" 72 | if: github.event_name == 'schedule' || github.event.inputs.pre-release == 'false' 73 | env: 74 | NUGET_ACCESS_TOKEN: ${{ secrets.NUGET_ACCESS_TOKEN }} 75 | run: dotnet nuget push "./nupkg/**/*.nupkg" --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key $NUGET_ACCESS_TOKEN 76 | 77 | - name: "Create tag and GitHub release" 78 | uses: softprops/action-gh-release@v1 79 | if: github.event_name == 'schedule' || github.event.inputs.pre-release == 'false' 80 | with: 81 | generate_release_notes: true 82 | prerelease: "{{ github.event.inputs.pre-release == 'true' }}" 83 | tag_name: "v${{ steps.set-version.outputs.VERSION }}" 84 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Hierarchy/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Flecs.Examples.Entities.Hierarchy; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | public struct Position : IComponent 10 | { 11 | public double X; 12 | public double Y; 13 | } 14 | 15 | public struct Star : ITag 16 | { 17 | } 18 | 19 | public struct Planet : ITag 20 | { 21 | } 22 | 23 | public struct Moon : ITag 24 | { 25 | } 26 | 27 | internal static class Program 28 | { 29 | private static int Main(string[] args) 30 | { 31 | var world = new World(args); 32 | 33 | world.RegisterComponent(); 34 | world.RegisterTag(); 35 | world.RegisterTag(); 36 | world.RegisterTag(); 37 | 38 | // Create a simple hierarchy. 39 | // Hierarchies use ECS relations and the builtin flecs::ChildOf relation to 40 | // create entities as children of other entities. 41 | 42 | var sun = world.CreateEntity("Sun"); 43 | sun.Add(); 44 | sun.Set(new Position { X = 1, Y = 1 }); 45 | 46 | var mercury = world.CreateEntity("Mercury"); 47 | mercury.AddParent(sun); 48 | mercury.Add(); 49 | mercury.Set(new Position { X = 1, Y = 1 }); 50 | 51 | var venus = world.CreateEntity("Venus"); 52 | venus.AddParent(sun); 53 | venus.Add(); 54 | venus.Set(new Position { X = 2, Y = 2 }); 55 | 56 | var earth = world.CreateEntity("Earth"); 57 | earth.AddParent(sun); 58 | earth.Add(); 59 | earth.Set(new Position { X = 3, Y = 3 }); 60 | 61 | var moon = world.CreateEntity("Moon"); 62 | moon.AddParent(earth); 63 | moon.Add(); 64 | moon.Set(new Position { X = 0.1f, Y = 0.1f }); 65 | 66 | // Is the Moon a child of Earth? 67 | Console.WriteLine("Is Moon a child entity of Earth?: " + moon.IsChildOf(earth)); 68 | Console.WriteLine("Is Earth a child entity of Moon?: " + earth.IsChildOf(moon)); 69 | 70 | // Do a depth-first walk of the tree 71 | IterateTree(world, sun, default); 72 | 73 | return world.Fini(); 74 | } 75 | 76 | private static void IterateTree(World world, Entity entity, Position parentPosition) 77 | { 78 | // Print hierarchical name of entity & the entity type 79 | var pathString = entity.FullPathString(); 80 | var typeString = entity.Type().String(); 81 | Console.WriteLine(pathString + " " + typeString); 82 | 83 | // Get entity position 84 | var position = entity.GetComponent(); 85 | 86 | // Calculate actual position 87 | var actualPosition = new Position { X = position.X + parentPosition.X, Y = position.Y + parentPosition.Y }; 88 | Console.WriteLine("{" + actualPosition.X + ", " + actualPosition.Y + "}"); 89 | 90 | // Iterate children recursively 91 | var it = entity.Children(); 92 | while (it.HasNext()) 93 | { 94 | for (var i = 0; i < it.Count; i++) 95 | { 96 | IterateTree(world, it.Entity(i), actualPosition); 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build .NET solution" 2 | 3 | on: 4 | workflow_call: 5 | push: 6 | tags: 7 | - v* 8 | branches: 9 | - main 10 | paths-ignore: 11 | - "**.md" 12 | 13 | jobs: 14 | 15 | native-job: 16 | name: "Build native libraries: ${{ matrix.platform.rid }}" 17 | runs-on: ${{ matrix.platform.os }} 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | platform: 22 | - { name: Windows (x64), os: windows-latest, rid: win-x64 } 23 | - { name: macOS (x64 + arm64), os: macos-latest, rid: osx } 24 | - { name: Linux (x64), os: ubuntu-latest, rid: linux-x64 } 25 | steps: 26 | 27 | - name: "Clone Git repository" 28 | uses: actions/checkout@master 29 | with: 30 | submodules: "recursive" 31 | 32 | - name: "Cache native libraries" 33 | id: cache-libs 34 | uses: actions/cache@v3 35 | with: 36 | path: "./lib" 37 | key: "libs-${{ matrix.platform.rid }}-${{ hashFiles('ext/flecs/**/*') }}-${{ hashFiles('src/c/**/*') }}" 38 | 39 | - name: "Install C2CS" 40 | shell: bash 41 | run: dotnet tool install --global bottlenoselabs.C2CS.Tool 42 | 43 | - name: "Install Linux dependencies" 44 | if: runner.os == 'Linux' && steps.cache-libs.outputs.cache-hit != 'true' 45 | run: sudo apt-get update 46 | 47 | - name: "Build native libraries" 48 | if: steps.cache-libs.outputs.cache-hit != 'true' 49 | shell: bash 50 | run: ./library.sh "auto" 51 | 52 | - name: "Upload native libraries" 53 | uses: actions/upload-artifact@v2 54 | with: 55 | path: "./lib" 56 | name: "native-libraries-${{ matrix.platform.rid }}" 57 | 58 | dotnet-job: 59 | name: "Build .NET solution" 60 | needs: [native-job] 61 | runs-on: ubuntu-latest 62 | steps: 63 | 64 | - name: "Clone Git repository" 65 | uses: actions/checkout@master 66 | 67 | - name: "Download native libraries (win-x64)" 68 | uses: actions/download-artifact@v1 69 | continue-on-error: ${{ github.actor != 'dependabot[bot]' && github.actor != 'lithiumtoast' }} 70 | with: 71 | name: "native-libraries-win-x64" 72 | path: "./lib" 73 | 74 | - name: "Download native libraries (osx)" 75 | uses: actions/download-artifact@v1 76 | continue-on-error: ${{ github.actor != 'dependabot[bot]' && github.actor != 'lithiumtoast' }} 77 | with: 78 | name: "native-libraries-osx" 79 | path: "./lib" 80 | 81 | - name: "Download native libraries (linux-x64)" 82 | uses: actions/download-artifact@v1 83 | continue-on-error: ${{ github.actor != 'dependabot[bot]' && github.actor != 'lithiumtoast' }} 84 | with: 85 | name: "native-libraries-linux-x64" 86 | path: "./lib" 87 | 88 | - name: "Download generated C# code: .NET 7+" 89 | uses: actions/download-artifact@v1 90 | continue-on-error: true 91 | with: 92 | name: "bindgen-cs-core" 93 | path: "./src/cs/production/Interop.Flecs.Core/Generated" 94 | 95 | - name: "Download generated C# code: Unity" 96 | uses: actions/download-artifact@v1 97 | continue-on-error: true 98 | with: 99 | name: "bindgen-cs-unity" 100 | path: "./src/cs/production/Interop.Flecs.Unity/Generated" 101 | 102 | - name: ".NET Build" 103 | run: dotnet build "./src/cs" --nologo --verbosity minimal --configuration Release 104 | 105 | -------------------------------------------------------------------------------- /src/cs/examples/queries/Flecs.Examples.Queries.OptionalOr/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | using static flecs_hub.Interop.Flecs.PInvoke; 6 | 7 | namespace Flecs.Examples.Entities.OptionalOr; 8 | 9 | internal static class Program 10 | { 11 | [StructLayout(LayoutKind.Sequential)] 12 | public struct Position : IComponent 13 | { 14 | public float X; 15 | public float Y; 16 | } 17 | 18 | [StructLayout(LayoutKind.Sequential)] 19 | public struct Velocity : IComponent 20 | { 21 | public float Value; 22 | } 23 | 24 | [StructLayout(LayoutKind.Sequential)] 25 | public struct Speed : IComponent 26 | { 27 | public float Value; 28 | } 29 | 30 | private static int Main(string[] args) 31 | { 32 | var world = new World(args); 33 | world.RegisterComponent(); 34 | world.RegisterComponent(); 35 | world.RegisterComponent(); 36 | 37 | var e1 = world.CreateEntity("e1"); 38 | e1.Set(default(Position)); 39 | e1.Set(default(Velocity)); 40 | var e2 = world.CreateEntity("e2"); 41 | e2.Set(default(Position)); 42 | e2.Set(default(Speed)); 43 | world.RegisterSystem( 44 | MoveOptionalVel, 45 | EcsOnUpdate, 46 | $"{world.GetFlecsTypeName(typeof(Position))}, ?{world.GetFlecsTypeName(typeof(Velocity))}"); 47 | world.RegisterSystem( 48 | MoveOr, 49 | EcsOnUpdate, 50 | $"{world.GetFlecsTypeName(typeof(Position))}, " + $"{world.GetFlecsTypeName(typeof(Velocity))} || {world.GetFlecsTypeName(typeof(Speed))}"); 51 | 52 | world.Progress(0); 53 | 54 | return world.Fini(); 55 | } 56 | 57 | private static void MoveOptionalVel(Iterator iterator) 58 | { 59 | var p = iterator.Field(1); 60 | 61 | if (iterator.FieldIsSet(2)) 62 | { 63 | var v = iterator.Field(2); 64 | for (var i = 0; i < iterator.Count; i++) 65 | { 66 | Console.WriteLine("entity has: pos, vel for"); 67 | Console.WriteLine(iterator.Table().String()); 68 | } 69 | } 70 | else 71 | { 72 | for (var i = 0; i < iterator.Count; i++) 73 | { 74 | Console.WriteLine("entity has: pos, no vel"); 75 | Console.WriteLine(iterator.Table().String()); 76 | } 77 | } 78 | } 79 | 80 | private static void MoveOr(Iterator iterator) 81 | { 82 | var p = iterator.Field(1); 83 | 84 | if (iterator.FieldIs(2)) 85 | { 86 | var v = iterator.Field(2); 87 | for (var i = 0; i < iterator.Count; i++) 88 | { 89 | Console.WriteLine("entity has: pos, vel"); 90 | Console.WriteLine(iterator.Table().String()); 91 | } 92 | } 93 | else if (iterator.FieldIs(2)) 94 | { 95 | for (var i = 0; i < iterator.Count; i++) 96 | { 97 | Console.WriteLine("entity has: pos, speed"); 98 | Console.WriteLine(iterator.Table().String()); 99 | } 100 | } 101 | else 102 | { 103 | // top could be written as else 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/cs/production/Interop.Flecs.Core/PInvoke.Extensions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // ReSharper disable All 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace flecs_hub.Interop.Flecs 7 | { 8 | public static unsafe partial class PInvoke 9 | { 10 | // Roles 11 | public static ecs_id_t ECS_PAIR => pinvoke_ECS_PAIR(); 12 | public static ecs_id_t ECS_OVERRIDE => pinvoke_ECS_OVERRIDE(); 13 | 14 | // Relationships 15 | public static ecs_entity_t EcsIsA => pinvoke_EcsIsA(); 16 | public static ecs_entity_t EcsDependsOn => pinvoke_EcsDependsOn(); 17 | public static ecs_entity_t EcsChildOf => pinvoke_EcsChildOf(); 18 | 19 | public static ecs_entity_t EcsSlotOf => pinvoke_EcsSlotOf(); 20 | 21 | // Entity tags 22 | public static ecs_entity_t EcsPrefab => pinvoke_EcsPrefab(); 23 | 24 | // System tags 25 | public static ecs_entity_t EcsPreFrame => pinvoke_EcsPreFrame(); 26 | public static ecs_entity_t EcsOnLoad => pinvoke_EcsOnLoad(); 27 | public static ecs_entity_t EcsPostLoad => pinvoke_EcsPostLoad(); 28 | public static ecs_entity_t EcsPreUpdate => pinvoke_EcsPreUpdate(); 29 | public static ecs_entity_t EcsOnUpdate => pinvoke_EcsOnUpdate(); 30 | public static ecs_entity_t EcsOnValidate => pinvoke_EcsOnValidate(); 31 | public static ecs_entity_t EcsPostUpdate => pinvoke_EcsPostUpdate(); 32 | public static ecs_entity_t EcsPreStore => pinvoke_EcsPreStore(); 33 | public static ecs_entity_t EcsOnStore => pinvoke_EcsOnStore(); 34 | public static ecs_entity_t EcsPostFrame => pinvoke_EcsPostFrame(); 35 | public static ecs_entity_t EcsPhase => pinvoke_EcsPhase(); 36 | 37 | 38 | public static ulong ecs_pair(ecs_entity_t pred, ecs_entity_t obj) 39 | { 40 | return ECS_PAIR.Data | ecs_entity_t_comb(obj.Data.Data, pred.Data.Data); 41 | } 42 | 43 | public static ulong ecs_childof(ecs_entity_t e) 44 | { 45 | return ecs_pair(EcsChildOf, e); 46 | } 47 | 48 | public static ulong ecs_entity_t_comb(ulong lo, ulong hi) 49 | { 50 | return (hi << 32) + (uint)lo; 51 | } 52 | 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | public static ecs_entity_t ecs_pair_first(ecs_world_t* world, ecs_entity_t entity) 55 | { 56 | var value = ECS_PAIR_FIRST(entity.Data.Data); 57 | return ecs_get_alive(world, *(ecs_entity_t*)&value); 58 | } 59 | 60 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 61 | public static ecs_entity_t ecs_pair_second(ecs_world_t* world, ecs_entity_t entity) 62 | { 63 | var value = ECS_PAIR_SECOND(entity.Data.Data); 64 | return ecs_get_alive(world, *(ecs_entity_t*)&value); 65 | } 66 | 67 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 68 | public static ulong ECS_PAIR_FIRST(ulong entity) 69 | { 70 | var value = entity & ECS_COMPONENT_MASK; 71 | return ecs_entity_t_hi(value); 72 | } 73 | 74 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 75 | public static ulong ECS_PAIR_SECOND(ulong entity) 76 | { 77 | var value = entity; 78 | return ecs_entity_t_lo(value); 79 | } 80 | 81 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 82 | public static uint ecs_entity_t_hi(ulong value) 83 | { 84 | return (uint)(value >> 32); 85 | } 86 | 87 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 88 | public static uint ecs_entity_t_lo(ulong value) 89 | { 90 | return (uint)value; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.RelationBasic/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | namespace Flecs.Examples.Entities.RelationBasic; 5 | 6 | public struct Eats : ITag 7 | { 8 | } 9 | 10 | public struct People : ITag 11 | { 12 | } 13 | 14 | internal static class Program 15 | { 16 | private static int Main(string[] args) 17 | { 18 | var world = new World(args); 19 | world.RegisterTag(); 20 | world.RegisterTag(); 21 | var grows = world.CreateEntity("Grows"); 22 | var apples = world.CreateEntity("Apples"); 23 | var pears = world.CreateEntity("Pears"); 24 | 25 | var bob = world.CreateEntity("Bob"); 26 | bob.AddSecond(apples); 27 | bob.AddSecond(pears); 28 | bob.Add(); 29 | 30 | // Pairs can also be constructed from two entity ids 31 | bob.Add(grows, pears); 32 | 33 | Console.WriteLine("bob has (Grows, Pears) (dynamic): " + bob.Has(grows, pears)); 34 | Console.WriteLine("bob has (Pears, Grows) (dynamic): " + bob.Has(pears, grows)); 35 | 36 | Console.WriteLine("bob has (Eats, Apples) (dynamic): " + bob.Has(apples)); 37 | Console.WriteLine("bob has (Apples, Eats) (dynamic): " + bob.HasSecond(apples)); 38 | 39 | Console.WriteLine("bob has (Eats, People): " + bob.Has()); 40 | Console.WriteLine("bob has (People, Eats): " + bob.Has()); 41 | 42 | Console.WriteLine("\n"); 43 | IterateComponents(bob); 44 | 45 | return world.Fini(); 46 | } 47 | 48 | private static void IterateComponents(Entity entity) 49 | { 50 | // First get the entity's type, which is a vector of (component) ids. 51 | var type = entity.Type(); 52 | 53 | // 1. The easiest way to print the components is the type's string 54 | var typeString = type.String(); 55 | Console.WriteLine("Type: " + typeString); 56 | 57 | // 2. To print individual ids, iterate the type array with ecs_id_str 58 | var i = 0; 59 | foreach (var identifier in type.Identifiers()) 60 | { 61 | var identifierString = identifier.String(); 62 | Console.WriteLine(i + ": " + identifierString); 63 | i++; 64 | } 65 | 66 | Console.WriteLine(); 67 | 68 | // 3. we can also inspect and print the ids in our own way. This is a 69 | // bit more complicated as we need to handle the edge cases of what can be 70 | // encoded in an id, but provides the most flexibility. 71 | i = 0; 72 | foreach (var identifier in type.Identifiers()) 73 | { 74 | Console.Write(i + ": "); 75 | 76 | var roleString = identifier.RoleString(); 77 | if (roleString != "UNKNOWN") 78 | { 79 | Console.Write("Role: " + roleString + ", "); 80 | } 81 | 82 | if (identifier.IsPair) 83 | { 84 | var pair = identifier.AsPair(); 85 | var relationName = pair.First.Name(); 86 | var objectName = pair.Second.Name(); 87 | Console.Write("Relation: " + relationName + ", Object: " + objectName); 88 | } 89 | else 90 | { 91 | var component = identifier.AsComponent(); 92 | var componentName = component.Name(); 93 | Console.Write("Name: " + componentName); 94 | } 95 | 96 | Console.WriteLine(); 97 | i++; 98 | } 99 | 100 | Console.WriteLine(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /.github/workflows/bindgen.yml: -------------------------------------------------------------------------------- 1 | name: "Bindgen" 2 | 3 | on: 4 | workflow_call: 5 | 6 | jobs: 7 | 8 | bindgen-platform-ast-job: 9 | name: "Bindgen AST platform" 10 | runs-on: ${{ matrix.platform.os }} 11 | if: github.actor == 'dependabot[bot]' || github.actor == 'lithiumtoast' || github.actor == 'BlackPhoenix134' 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | platform: 16 | - { name: Windows, os: windows-latest, rid: win } 17 | - { name: macOS, os: macos-latest, rid: osx } 18 | - { name: Linux, os: ubuntu-latest, rid: linux } 19 | 20 | steps: 21 | - name: "Clone Git repository" 22 | uses: actions/checkout@v2 23 | with: 24 | submodules: 'true' 25 | 26 | - name: "Install CAstFfi" 27 | shell: bash 28 | run: dotnet tool install --global bottlenoselabs.CAstFfi.Tool 29 | 30 | - name: "Read C code: Linux dependencies" 31 | if: runner.os == 'Linux' 32 | run: sudo apt-get update && sudo apt-get install gcc-aarch64-linux-gnu 33 | 34 | - name: "Read C code: extract ${{ matrix.platform.rid }}" 35 | shell: bash 36 | run: cd ./bindgen && ./extract.sh 37 | 38 | - name: "Upload C code platform abstract syntax trees" 39 | uses: actions/upload-artifact@v2 40 | with: 41 | name: "ast-${{ matrix.platform.rid }}" 42 | path: "./bindgen/ast" 43 | 44 | bindgen-cross-platform-ast-job: 45 | name: "Bindgen AST cross-platform" 46 | needs: [bindgen-platform-ast-job] 47 | runs-on: ubuntu-latest 48 | 49 | steps: 50 | - name: "Clone Git repository" 51 | uses: actions/checkout@v2 52 | with: 53 | submodules: 'false' 54 | 55 | - name: "Download C code platform abstract syntax trees (win)" 56 | uses: actions/download-artifact@v1 57 | with: 58 | name: "ast-win" 59 | path: "./bindgen/ast" 60 | 61 | - name: "Download C code platform abstract syntax trees (osx)" 62 | uses: actions/download-artifact@v1 63 | with: 64 | name: "ast-osx" 65 | path: "./bindgen/ast" 66 | 67 | - name: "Download C code platform abstract syntax trees (linux)" 68 | uses: actions/download-artifact@v1 69 | with: 70 | name: "ast-linux" 71 | path: "./bindgen/ast" 72 | 73 | - name: "Install CAstFfi" 74 | shell: bash 75 | run: dotnet tool install --global bottlenoselabs.CAstFfi.Tool 76 | 77 | - name: "Generate cross-platform AST" 78 | shell: bash 79 | run: cd ./bindgen && ./merge.sh 80 | 81 | - name: "Upload cross-platform AST" 82 | uses: actions/upload-artifact@v2 83 | with: 84 | name: "ast-cross-platform" 85 | path: "./bindgen/x-ast/ast-cross-platform.json" 86 | 87 | bindgen-cs-job: 88 | name: "Bindgen C#" 89 | needs: [bindgen-cross-platform-ast-job] 90 | runs-on: ubuntu-latest 91 | 92 | steps: 93 | - name: "Clone Git repository" 94 | uses: actions/checkout@v2 95 | with: 96 | submodules: 'false' 97 | 98 | - name: "Download C code cross-platform abstract syntax tree" 99 | uses: actions/download-artifact@v1 100 | with: 101 | name: "ast-cross-platform" 102 | path: "./bindgen/x-ast" 103 | 104 | - name: "Install C2CS" 105 | shell: bash 106 | run: dotnet tool install --global bottlenoselabs.C2CS.Tool 107 | 108 | - name: "Generate C# code" 109 | shell: bash 110 | run: cd ./bindgen && ./generate.sh 111 | 112 | - name: "Upload generated C# code: .NET 7+" 113 | uses: actions/upload-artifact@v2 114 | with: 115 | name: "bindgen-cs-core" 116 | path: "./src/cs/production/Interop.Flecs.Core/Generated" 117 | 118 | - name: "Upload generated C# code: Unity" 119 | uses: actions/upload-artifact@v2 120 | with: 121 | name: "bindgen-cs-unity" 122 | path: "./src/cs/production/Interop.Flecs.Unity/Generated" 123 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.IterateComponents/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Flecs.Examples.Entities.IterateComponents; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | public struct Position : IComponent 10 | { 11 | public double X; 12 | public double Y; 13 | } 14 | 15 | [StructLayout(LayoutKind.Sequential)] 16 | public struct Velocity : IComponent 17 | { 18 | public double X; 19 | public double Y; 20 | } 21 | 22 | public struct Human : ITag 23 | { 24 | } 25 | 26 | public struct Eats : ITag 27 | { 28 | } 29 | 30 | public struct Apples : ITag 31 | { 32 | } 33 | 34 | internal static class Program 35 | { 36 | private static int Main(string[] args) 37 | { 38 | var world = new World(args); 39 | 40 | // Ordinary components 41 | world.RegisterComponent(); 42 | world.RegisterComponent(); 43 | 44 | // A tag 45 | world.RegisterTag(); 46 | 47 | // Two tags used to create a pair 48 | world.RegisterTag(); 49 | world.RegisterTag(); 50 | 51 | // Create an entity which all of the above 52 | var bob = world.CreateEntity("bob"); 53 | 54 | bob.Set(new Position { X = 10, Y = 20 }); 55 | bob.Set(new Velocity { X = 1, Y = 1 }); 56 | bob.Add(); 57 | bob.Add(); 58 | 59 | // Iterate & components of Bob 60 | Console.WriteLine("Bob's components:"); 61 | IterateComponents(bob); 62 | 63 | // We can use the same function to iterate the components of a component 64 | Console.WriteLine("Position's components:"); 65 | IterateComponents(Entity.FromIdentifier(world.GetIdentifier())); 66 | 67 | return world.Fini(); 68 | } 69 | 70 | private static void IterateComponents(Entity entity) 71 | { 72 | // First get the entity's type, which is a vector of (component) ids. 73 | var type = entity.Type(); 74 | 75 | // 1. The easiest way to print the components is the type's string 76 | var typeString = type.String(); 77 | Console.WriteLine("Type: " + typeString); 78 | 79 | // 2. To print individual ids, iterate the type array with ecs_id_str 80 | var i = 0; 81 | foreach (var identifier in type.Identifiers()) 82 | { 83 | var identifierString = identifier.String(); 84 | Console.WriteLine(i + ": " + identifierString); 85 | i++; 86 | } 87 | 88 | Console.WriteLine(); 89 | 90 | // 3. we can also inspect and print the ids in our own way. This is a 91 | // bit more complicated as we need to handle the edge cases of what can be 92 | // encoded in an id, but provides the most flexibility. 93 | i = 0; 94 | foreach (var identifier in type.Identifiers()) 95 | { 96 | Console.Write(i + ": "); 97 | 98 | var idFlagsStr = identifier.RoleString(); 99 | if (idFlagsStr != "UNKNOWN") 100 | { 101 | Console.Write("ID Flags: " + idFlagsStr + ", "); 102 | } 103 | 104 | if (identifier.IsPair) 105 | { 106 | var pair = identifier.AsPair(); 107 | var relationName = pair.First.Name(); 108 | var objectName = pair.Second.Name(); 109 | Console.Write("First: " + relationName + ", Second: " + objectName); 110 | } 111 | else 112 | { 113 | var component = identifier.AsComponent(); 114 | var componentName = component.Name(); 115 | Console.Write("Name: " + componentName); 116 | } 117 | 118 | Console.WriteLine(); 119 | i++; 120 | } 121 | 122 | Console.WriteLine(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Expressions/TermBuilder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Text; 5 | 6 | namespace Flecs; 7 | 8 | public class TermBuilder 9 | { 10 | private string _entity1 = string.Empty; 11 | private string _entity2 = string.Empty; 12 | private string _source = "$This"; 13 | private string _accessModifier = string.Empty; // empty == default == [InOut] 14 | private string _access = ","; 15 | private string _prefix = string.Empty; 16 | 17 | private readonly StringBuilder _stringBuilder; 18 | private readonly World _world; 19 | 20 | public TermBuilder(World world) 21 | { 22 | _world = world; 23 | _stringBuilder = new(); 24 | } 25 | 26 | public TermBuilder First() 27 | where T : unmanaged, IEcsComponent 28 | => First(_world.GetFlecsTypeName()); 29 | 30 | public TermBuilder First(string name) 31 | { 32 | _entity1 = name; 33 | return this; 34 | } 35 | 36 | public TermBuilder Second() 37 | where T : unmanaged, IEcsComponent 38 | => Second(_world.GetFlecsTypeName()); 39 | 40 | public TermBuilder Second(string name) 41 | { 42 | _entity2 = name; 43 | return this; 44 | } 45 | 46 | public TermBuilder Source(string name) 47 | { 48 | _source = name; 49 | return this; 50 | } 51 | 52 | public TermBuilder Or() 53 | { 54 | _access = "||"; 55 | return this; 56 | } 57 | 58 | public TermBuilder Not() 59 | { 60 | _prefix = "!"; 61 | return this; 62 | } 63 | 64 | public TermBuilder Optional() 65 | { 66 | _prefix = "?"; 67 | return this; 68 | } 69 | 70 | public TermBuilder Term() 71 | where T : unmanaged, IEcsComponent 72 | { 73 | FlushToBuilder(); 74 | First(); 75 | return this; 76 | } 77 | 78 | public TermBuilder Term() 79 | where T1 : unmanaged, IEcsComponent 80 | where T2 : unmanaged, IEcsComponent 81 | { 82 | var termBuilder = new TermBuilder(_world); 83 | termBuilder.First(); 84 | termBuilder.Second(); 85 | return termBuilder; 86 | } 87 | 88 | public TermBuilder Term() 89 | { 90 | FlushToBuilder(); 91 | return this; 92 | } 93 | 94 | public TermBuilder In() 95 | { 96 | _accessModifier = "[in]"; 97 | return this; 98 | } 99 | 100 | public TermBuilder Out() 101 | { 102 | _accessModifier = "[out]"; 103 | return this; 104 | } 105 | 106 | public TermBuilder None() 107 | { 108 | _accessModifier = "[none]"; 109 | return this; 110 | } 111 | 112 | public TermBuilder InOut() // default, empty == inout 113 | { 114 | _accessModifier = "[inout]"; 115 | return this; 116 | } 117 | 118 | public string Build() 119 | { 120 | FlushToBuilder(); 121 | return _stringBuilder.ToString(); 122 | } 123 | 124 | private void Reset() 125 | { 126 | _entity1 = string.Empty; 127 | _entity2 = string.Empty; 128 | _source = "$This"; 129 | _accessModifier = string.Empty; 130 | _access = ","; 131 | _prefix = string.Empty; 132 | } 133 | 134 | private void FlushToBuilder() 135 | { 136 | if (_stringBuilder.Length != 0) 137 | { 138 | _stringBuilder.Append(_access).Append(' '); 139 | } 140 | 141 | if (!string.IsNullOrEmpty(_access)) 142 | { 143 | _stringBuilder.Append(_accessModifier).Append(' '); 144 | } 145 | 146 | _stringBuilder.Append(_prefix).Append(_entity1) 147 | .Append('(').Append(_source); 148 | 149 | if (!string.IsNullOrEmpty(_entity2)) 150 | { 151 | _stringBuilder.Append(", ").Append(_entity2); 152 | } 153 | 154 | _stringBuilder.Append(')'); 155 | Reset(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Hooks/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | using bottlenoselabs.C2CS.Runtime; 6 | 7 | namespace Flecs.Examples.Entities.Hooks; 8 | 9 | // Component hooks are callbacks that can be registered for a type that are 10 | // invoked during different parts of the component lifecycle. 11 | 12 | [StructLayout(LayoutKind.Sequential)] 13 | public struct String : IComponent 14 | { 15 | public CString Value; 16 | } 17 | 18 | public struct Tag : ITag 19 | { 20 | } 21 | 22 | internal static class Program 23 | { 24 | private static int Main(string[] args) 25 | { 26 | var world = new World(args); 27 | 28 | var componentHooks = new ComponentHooks 29 | { 30 | // Resource management hooks. These hooks should primarily be used for managing memory used by the component. 31 | Constructor = ComponentHookConstructor, 32 | Deconstructor = ComponentHookDeconstructor, 33 | Copy = ComponentHookCopy, 34 | Move = ComponentHookMove, 35 | // Lifecycle hooks. These hooks should be used for application logic. 36 | OnAdd = HookCallback, 37 | OnSet = HookCallback, 38 | OnRemove = HookCallback 39 | }; 40 | world.RegisterComponent(componentHooks); 41 | world.RegisterTag(); 42 | 43 | var entity = world.CreateEntity("Entity"); 44 | 45 | Console.WriteLine("entity.Add()"); 46 | entity.Add(); 47 | 48 | Console.WriteLine("entity.SetComponent()(\"Hello World\")"); 49 | entity.Set(new String { Value = (CString)"Hello World" }); 50 | 51 | Console.WriteLine("entity.AddTag()"); 52 | // This operation changes the entity's archetype, which invokes a move 53 | entity.Add(); 54 | 55 | Console.WriteLine("entity.Delete()"); 56 | entity.Delete(); 57 | 58 | return world.Fini(); 59 | } 60 | 61 | // The constructor should initialize the component value. 62 | private static void ComponentHookConstructor(ref ComponentConstructorContext context) 63 | { 64 | Console.WriteLine("\tConstructor"); 65 | ref var component = ref context.Get(); 66 | component.Value = default; 67 | } 68 | 69 | // The destructor should free resources. 70 | private static void ComponentHookDeconstructor(ref ComponentDeconstructorContext context) 71 | { 72 | Console.WriteLine("\tDeconstructor"); 73 | ref var component = ref context.Get(); 74 | Marshal.FreeHGlobal(component.Value); 75 | } 76 | 77 | // The copy hook should copy resources from one location to another. 78 | private static void ComponentHookCopy(ref ComponentCopyContext context) 79 | { 80 | Console.WriteLine("\tCopy"); 81 | ref var source = ref context.GetSource(); 82 | ref var destination = ref context.GetDestination(); 83 | var value = source.Value.ToString(); 84 | source.Value = default; 85 | destination.Value = (CString)value; 86 | } 87 | 88 | // The move hook should move resources from one location to another. 89 | private static void ComponentHookMove(ref ComponentMoveContext context) 90 | { 91 | Console.WriteLine("\tMove"); 92 | ref var source = ref context.GetSource(); 93 | ref var destination = ref context.GetDestination(); 94 | destination.Value = source.Value; 95 | source.Value = default; 96 | } 97 | 98 | // This callback is used for the add, remove and set hooks. Note that the 99 | // signature is the same as systems, triggers, observers. 100 | private static void HookCallback(Iterator iterator) 101 | { 102 | for (var i = 0; i < iterator.Count; i++) 103 | { 104 | var eventName = iterator.Event().Name(); 105 | var entityName = iterator.Entity(i).Name(); 106 | Console.WriteLine("\t" + eventName + ": " + entityName); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.Prefab/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Flecs.Examples.Entities.Prefab; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | public struct Attack : IComponent 10 | { 11 | public double Value; 12 | } 13 | 14 | [StructLayout(LayoutKind.Sequential)] 15 | public struct Defense : IComponent 16 | { 17 | public double Value; 18 | } 19 | 20 | [StructLayout(LayoutKind.Sequential)] 21 | public struct FreightCapacity : IComponent 22 | { 23 | public double Value; 24 | } 25 | 26 | [StructLayout(LayoutKind.Sequential)] 27 | public struct ImpulseSpeed : IComponent 28 | { 29 | public double Value; 30 | } 31 | 32 | [StructLayout(LayoutKind.Sequential)] 33 | public struct Position : IComponent 34 | { 35 | public double X; 36 | public double Y; 37 | } 38 | 39 | public struct HasFtl : ITag 40 | { 41 | } 42 | 43 | public struct Amount : IComponent 44 | { 45 | public int Max; 46 | public int Current; 47 | } 48 | 49 | internal static class Program 50 | { 51 | private static int Main(string[] args) 52 | { 53 | var world = new World(args); 54 | 55 | world.RegisterComponent(); 56 | world.RegisterComponent(); 57 | world.RegisterComponent(); 58 | world.RegisterComponent(); 59 | world.RegisterComponent(); 60 | world.RegisterComponent(); 61 | world.RegisterTag(); 62 | 63 | var hull = world.CreateEntity("Hull"); 64 | var shield = world.CreateEntity("Shield"); 65 | 66 | // Create a prefab hierarchy. Prefabs are entities that by default are 67 | // ignored by queries. 68 | var spaceShip = world.CreatePrefab("SpaceShip"); 69 | spaceShip.Set(new ImpulseSpeed { Value = 50 }); 70 | spaceShip.Set(new Defense { Value = 50 }); 71 | // setting as overridable, every ship instance can be damaged individually 72 | spaceShip.SetOverride(hull, new Amount() { Max = 200, Current = 200}); 73 | spaceShip.SetOverride(shield, new Amount() { Max = 200, Current = 200 }); 74 | 75 | // By default components in an inheritance hierarchy are shared between 76 | // entities. The override function ensures that instances have a private 77 | // copy of the component. 78 | spaceShip.SetOverride(new Position { X = 0, Y = 0 }); 79 | 80 | var freighter = world.CreatePrefab("Freighter"); 81 | // This ensures the entity inherits all components from spaceship. 82 | freighter.IsA(spaceShip); 83 | freighter.Set(new FreightCapacity { Value = 100 }); 84 | freighter.Set(new Defense { Value = 50 }); 85 | 86 | var mammothFreighter = world.CreatePrefab("MammothFreighter"); 87 | mammothFreighter.IsA(freighter); 88 | mammothFreighter.Set(new FreightCapacity { Value = 500 }); 89 | mammothFreighter.Set(new Defense { Value = 300 }); 90 | 91 | var frigate = world.CreatePrefab("Frigate"); 92 | // This ensures the entity inherits all components from spaceship. 93 | frigate.IsA(spaceShip); 94 | frigate.Set(new Attack { Value = 100 }); 95 | frigate.Set(new Defense { Value = 75 }); 96 | frigate.Set(new ImpulseSpeed { Value = 125 }); 97 | 98 | // Create an entity from a prefab. 99 | // The instance will have a private copy of the Position component, because 100 | // of the override in the spaceship entity. All other components are shared. 101 | var freighter1 = world.CreateEntity("my_mammoth_freighter1"); 102 | freighter1.IsA(mammothFreighter); 103 | 104 | var freighter2 = world.CreateEntity("my_mammoth_freighter2"); 105 | freighter2.IsA(mammothFreighter); 106 | 107 | // Inspect the type of the entity. This outputs: 108 | // Position,(Identifier,Name),(IsA,MammothFreighter) 109 | var instanceTypeString = freighter1.Type().String(); 110 | Console.WriteLine("Instance type: " + instanceTypeString); 111 | 112 | // Even though the instance doesn't have a private copy of ImpulseSpeed, we 113 | // can still get it using the regular API (outputs 50) 114 | var impulseSpeed = freighter1.GetComponent(); 115 | Console.WriteLine("Impulse speed: " + impulseSpeed.Value); 116 | 117 | ref var freighter1Hull = ref freighter1.GetSecond(hull); 118 | freighter1Hull.Current -= 100; 119 | 120 | Console.WriteLine($"Freigher 1 hull: {freighter1.GetSecond(hull).Current}"); 121 | Console.WriteLine($"Freigher 2 hull: {freighter2.GetSecond(hull).Current}"); 122 | 123 | return world.Fini(); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Component/ComponentHooks.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | using flecs_hub.Interop.Flecs; 6 | using JetBrains.Annotations; 7 | using static flecs_hub.Interop.Flecs.PInvoke; 8 | 9 | namespace Flecs; 10 | 11 | [PublicAPI] 12 | public unsafe struct ComponentHooks 13 | { 14 | public CallbackComponentConstructor? Constructor; 15 | public CallbackComponentDeconstructor? Deconstructor; 16 | public CallbackComponentCopy? Copy; 17 | public CallbackComponentMove? Move; 18 | public CallbackIterator? OnAdd; 19 | public CallbackIterator? OnSet; 20 | public CallbackIterator? OnRemove; 21 | 22 | internal static void Fill(World world, ref ComponentHooks hooks, ecs_type_hooks_t* desc) 23 | { 24 | #if UNITY_5_3_OR_NEWER 25 | desc->ctor.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackConstructor); 26 | desc->dtor.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackDeconstructor); 27 | desc->copy.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackCopy); 28 | desc->move.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackMove); 29 | desc->on_add.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackOnAdd); 30 | desc->on_set.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackOnSet); 31 | desc->on_remove.Data.Pointer = Marshal.GetFunctionPointerForDelegate(CallbackOnRemove); 32 | #else 33 | desc->ctor.Data.Pointer = &CallbackConstructor; 34 | desc->dtor.Data.Pointer = &CallbackDeconstructor; 35 | desc->copy.Data.Pointer = &CallbackCopy; 36 | desc->move.Data.Pointer = &CallbackMove; 37 | desc->on_add.Data.Pointer = &CallbackOnAdd; 38 | desc->on_set.Data.Pointer = &CallbackOnSet; 39 | desc->on_remove.Data.Pointer = &CallbackOnRemove; 40 | #endif 41 | desc->binding_ctx = (void*)CallbacksHelper.CreateComponentHooksCallbackContext(world, hooks); 42 | } 43 | 44 | #if !UNITY_5_3_OR_NEWER 45 | [UnmanagedCallersOnly] 46 | #endif 47 | private static void CallbackConstructor(void* pointer, int count, ecs_type_info_t* typeInfo) 48 | { 49 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(typeInfo->hooks.binding_ctx); 50 | var context = new ComponentConstructorContext(pointer, count); 51 | data.Hooks.Constructor?.Invoke(ref context); 52 | } 53 | 54 | #if !UNITY_5_3_OR_NEWER 55 | [UnmanagedCallersOnly] 56 | #endif 57 | private static void CallbackDeconstructor(void* pointer, int count, ecs_type_info_t* typeInfo) 58 | { 59 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(typeInfo->hooks.binding_ctx); 60 | var context = new ComponentDeconstructorContext(pointer, count); 61 | data.Hooks.Deconstructor?.Invoke(ref context); 62 | } 63 | 64 | #if !UNITY_5_3_OR_NEWER 65 | [UnmanagedCallersOnly] 66 | #endif 67 | private static void CallbackCopy(void* destinationPointer, void* sourcePointer, int count, ecs_type_info_t* typeInfo) 68 | { 69 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(typeInfo->hooks.binding_ctx); 70 | var context = new ComponentCopyContext(destinationPointer, sourcePointer, count); 71 | data.Hooks.Copy?.Invoke(ref context); 72 | } 73 | 74 | #if !UNITY_5_3_OR_NEWER 75 | [UnmanagedCallersOnly] 76 | #endif 77 | private static void CallbackMove(void* destinationPointer, void* sourcePointer, int count, PInvoke.ecs_type_info_t* typeInfo) 78 | { 79 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(typeInfo->hooks.binding_ctx); 80 | var context = new ComponentMoveContext(destinationPointer, sourcePointer, count); 81 | data.Hooks.Move?.Invoke(ref context); 82 | } 83 | 84 | #if !UNITY_5_3_OR_NEWER 85 | [UnmanagedCallersOnly] 86 | #endif 87 | private static void CallbackOnAdd(ecs_iter_t* it) 88 | { 89 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(it->binding_ctx); 90 | var iterator = new Iterator(data.World, it); 91 | data.Hooks.OnAdd?.Invoke(iterator); 92 | } 93 | 94 | #if !UNITY_5_3_OR_NEWER 95 | [UnmanagedCallersOnly] 96 | #endif 97 | private static void CallbackOnSet(ecs_iter_t* it) 98 | { 99 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(it->binding_ctx); 100 | var iterator = new Iterator(data.World, it); 101 | data.Hooks.OnSet?.Invoke(iterator); 102 | } 103 | 104 | #if !UNITY_5_3_OR_NEWER 105 | [UnmanagedCallersOnly] 106 | #endif 107 | private static void CallbackOnRemove(ecs_iter_t* it) 108 | { 109 | ref var data = ref CallbacksHelper.GetComponentHooksCallbackContext(it->binding_ctx); 110 | var iterator = new Iterator(data.World, it); 111 | data.Hooks.OnRemove?.Invoke(iterator); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/c/production/flecs/include/pinvoke.h: -------------------------------------------------------------------------------- 1 | // Provides macros, types, and functions that make P/Invoke with C# easier. 2 | #pragma once 3 | 4 | #if defined(__APPLE__) && __has_include("TargetConditionals.h") 5 | #include 6 | 7 | // CPUs 8 | #define PINVOKE_TARGET_CPU_X64 TARGET_CPU_X86_64 9 | #define PINVOKE_TARGET_CPU_X86 TARGET_CPU_X86 10 | #define PINVOKE_TARGET_CPU_ARM64 TARGET_CPU_ARM64 11 | 12 | // Desktops 13 | #define PINVOKE_TARGET_OS_WINDOWS 0 14 | #define PINVOKE_TARGET_OS_LINUX 0 15 | #define PINVOKE_TARGET_OS_FREEBSD 0 16 | #define PINVOKE_TARGET_OS_MACOS TARGET_OS_OSX 17 | 18 | // Mobiles 19 | #define PINVOKE_TARGET_OS_IOS TARGET_OS_IOS 20 | #define PINVOKE_TARGET_OS_ANDROID 0 21 | 22 | // Browsers 23 | #if defined(__EMSCRIPTEN__) 24 | #define PINVOKE_TARGET_OS_BROWSER 1 25 | #else 26 | #define PINVOKE_TARGET_OS_BROWSER 0 27 | #endif 28 | 29 | // Compiler environments 30 | #define PINVOKE_TARGET_ENV_MSVC 0 31 | #define PINVOKE_TARGET_ENV_GNU 0 32 | #else 33 | 34 | // CPUs 35 | #if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) 36 | #define PINVOKE_TARGET_CPU_X64 1 37 | #else 38 | #define PINVOKE_TARGET_CPU_X64 0 39 | #endif 40 | 41 | #if defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) 42 | #define PINVOKE_TARGET_CPU_X86 1 43 | #else 44 | #define PINVOKE_TARGET_CPU_X86 0 45 | #endif 46 | 47 | #if defined(__aarch64__) || defined(_M_ARM64) 48 | #define PINVOKE_TARGET_CPU_ARM64 1 49 | #else 50 | #define PINVOKE_TARGET_CPU_ARM64 0 51 | #endif 52 | 53 | // Desktops 54 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) 55 | #define PINVOKE_TARGET_OS_WINDOWS 1 56 | #else 57 | #define PINVOKE_TARGET_OS_WINDOWS 0 58 | #endif 59 | 60 | #if defined(__FreeBSD__) 61 | #define PINVOKE_TARGET_OS_FREEBSD 1 62 | #else 63 | #define PINVOKE_TARGET_OS_FREEBSD 0 64 | #endif 65 | 66 | #if defined(__linux__) && !defined(__ANDROID__) 67 | #define PINVOKE_TARGET_OS_LINUX 1 68 | #else 69 | #define PINVOKE_TARGET_OS_LINUX 0 70 | #endif 71 | 72 | #define PINVOKE_TARGET_OS_MACOS 0 73 | 74 | // Mobiles 75 | #define PINVOKE_TARGET_OS_IOS 0 76 | 77 | #if defined(__ANDROID__) 78 | #define PINVOKE_TARGET_OS_ANDROID 1 79 | #else 80 | #define PINVOKE_TARGET_OS_ANDROID 0 81 | #endif 82 | 83 | // Browsers 84 | #if defined(__EMSCRIPTEN__) 85 | #define PINVOKE_TARGET_OS_BROWSER 1 86 | #else 87 | #define PINVOKE_TARGET_OS_BROWSER 0 88 | #endif 89 | 90 | // Compiler environments 91 | #if defined(_MSC_VER) 92 | #define PINVOKE_TARGET_ENV_MSVC 1 93 | #else 94 | #define PINVOKE_TARGET_ENV_MSVC 0 95 | #endif 96 | 97 | #if defined(__GNUC__) 98 | #define PINVOKE_TARGET_ENV_GNU 1 99 | #else 100 | #define PINVOKE_TARGET_ENV_GNU 0 101 | #endif 102 | #endif 103 | 104 | #if PINVOKE_TARGET_OS_WINDOWS && PINVOKE_TARGET_ENV_GNU 105 | #if PINVOKE_TARGET_CPU_X64 106 | #define PINVOKE_TARGET_NAME "x86_64-pc-windows-gnu" 107 | #elif PINVOKE_TARGET_CPU_X86 108 | #define PINVOKE_TARGET_NAME "i686-pc-windows-gnu" 109 | #elif PINVOKE_TARGET_CPU_ARM64 110 | #define PINVOKE_TARGET_NAME "aarch64-pc-windows-gnu" 111 | #else 112 | #error "Unknown computer architecture for Windows (GNU)." 113 | #endif 114 | #elif PINVOKE_TARGET_OS_WINDOWS && PINVOKE_TARGET_ENV_MSVC 115 | #if PINVOKE_TARGET_CPU_X64 116 | #define PINVOKE_TARGET_NAME "x86_64-pc-windows-msvc" 117 | #elif PINVOKE_TARGET_CPU_X86 118 | #define PINVOKE_TARGET_NAME "i686-pc-windows-msvc" 119 | #elif PINVOKE_TARGET_CPU_ARM64 120 | #define PINVOKE_TARGET_NAME "aarch64-pc-windows-msvc" 121 | #else 122 | #error "Unknown computer architecture for Windows (Microsoft Visual C++)." 123 | #endif 124 | #elif PINVOKE_TARGET_OS_LINUX 125 | #if PINVOKE_TARGET_CPU_X64 126 | #define PINVOKE_TARGET_NAME "x86_64-unknown-linux-gnu" 127 | #elif PINVOKE_TARGET_CPU_X86 128 | #define PINVOKE_TARGET_NAME "i686-unknown-linux-gnu" 129 | #elif PINVOKE_TARGET_CPU_ARM64 130 | #define PINVOKE_TARGET_NAME "aarch64-unknown-linux-gnu" 131 | #else 132 | #error "Unknown computer architecture for Linux." 133 | #endif 134 | #elif PINVOKE_TARGET_OS_FREEBSD 135 | #if PINVOKE_TARGET_CPU_X64 136 | #define PINVOKE_TARGET_NAME "x86_64-unknown-freebsd" 137 | #elif PINVOKE_TARGET_CPU_X86 138 | #define PINVOKE_TARGET_NAME "i686-unknown-freebsd" 139 | #elif PINVOKE_TARGET_CPU_ARM64 140 | #define PINVOKE_TARGET_NAME "aarch64-unknown-freebsd" 141 | #else 142 | #error "Unknown computer architecture for FreeBSD." 143 | #endif 144 | #elif PINVOKE_TARGET_OS_MACOS 145 | #if PINVOKE_TARGET_CPU_X64 146 | #define PINVOKE_TARGET_NAME "x86_64-apple-darwin" 147 | #elif PINVOKE_TARGET_CPU_X86 148 | #define PINVOKE_TARGET_NAME "i686-apple-darwin" 149 | #elif PINVOKE_TARGET_CPU_ARM64 150 | #define PINVOKE_TARGET_NAME "aarch64-apple-darwin" 151 | #else 152 | #error "Unknown computer architecture for macOS." 153 | #endif 154 | #elif PINVOKE_TARGET_OS_IOS 155 | #if PINVOKE_TARGET_CPU_X64 156 | #define PINVOKE_TARGET_NAME "x86_64-apple-ios" 157 | #elif PINVOKE_TARGET_CPU_X86 158 | #define PINVOKE_TARGET_NAME "i686-apple-ios" 159 | #elif PINVOKE_TARGET_CPU_ARM64 160 | #define PINVOKE_TARGET_NAME "aarch64-apple-ios" 161 | #else 162 | #error "Unknown computer architecture for iOS." 163 | #endif 164 | #elif PINVOKE_TARGET_OS_ANDROID 165 | #if PINVOKE_TARGET_CPU_X64 166 | #define PINVOKE_TARGET_NAME "x86_64-linux-android" 167 | #elif PINVOKE_TARGET_CPU_X86 168 | #define PINVOKE_TARGET_NAME "i686-linux-android" 169 | #elif PINVOKE_TARGET_CPU_ARM64 170 | #define PINVOKE_TARGET_NAME "aarch64-linux-android" 171 | #else 172 | #error "Unknown computer architecture for Android." 173 | #endif 174 | #elif PINVOKE_TARGET_OS_BROWSER 175 | #error "WebAssembly is currently not supported!" 176 | #else 177 | #define PINVOKE_TARGET_NAME 0 178 | #endif 179 | 180 | #if PINVOKE_TARGET_OS_WINDOWS 181 | #define PINVOKE_API __declspec(dllexport) 182 | #else 183 | #define PINVOKE_API extern 184 | #endif 185 | 186 | #undef PINVOKE_TARGET_NAME 187 | #undef PINVOKE_TARGET_CPU_X64 188 | #undef PINVOKE_TARGET_CPU_X86 189 | #undef PINVOKE_TARGET_CPU_ARM64 190 | #undef PINVOKE_TARGET_OS_WINDOWS 191 | #undef PINVOKE_TARGET_OS_LINUX 192 | #undef PINVOKE_TARGET_OS_FREEBSD 193 | #undef PINVOKE_TARGET_OS_MACOS 194 | #undef PINVOKE_TARGET_OS_IOS 195 | #undef PINVOKE_TARGET_OS_ANDROID 196 | #undef PINVOKE_TARGET_OS_BROWSER 197 | #undef PINVOKE_TARGET_ENV_MSVC 198 | #undef PINVOKE_TARGET_ENV_GNU 199 | -------------------------------------------------------------------------------- /src/cs/examples/entities/Flecs.Examples.Entities.RelationComponents/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Flecs.Examples.Entities.RelationComponents; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | public struct Requires : IComponent 10 | { 11 | public float Amount; 12 | } 13 | 14 | [StructLayout(LayoutKind.Sequential)] 15 | public struct Expires : IComponent 16 | { 17 | public float Timeout; 18 | } 19 | 20 | [StructLayout(LayoutKind.Sequential)] 21 | public struct Position : IComponent 22 | { 23 | public float X; 24 | public float Y; 25 | } 26 | 27 | public struct Gigawatts : ITag 28 | { 29 | } 30 | 31 | public struct MustHave : ITag 32 | { 33 | } 34 | 35 | internal static class Program 36 | { 37 | private static int Main(string[] args) 38 | { 39 | var world = new World(args); 40 | 41 | world.RegisterComponent(); 42 | world.RegisterComponent(); 43 | world.RegisterComponent(); 44 | world.RegisterTag(); 45 | world.RegisterTag(); 46 | 47 | // When one element of a pair is a component and the other element is a tag, 48 | // the pair assumes the type of the component. 49 | var e1 = world.CreateEntity("e1"); 50 | e1.Set(new Requires() { Amount = 1.21f }); 51 | ref var requires1 = ref e1.Get(); 52 | Console.WriteLine($"<{nameof(Requires)}, {nameof(Gigawatts)}> (first is value) {nameof(Requires)}: {requires1.Amount}"); 53 | 54 | // The component can be either the first or second part of a pair: 55 | var e2 = world.CreateEntity("e2"); 56 | e2.Set(new Requires() { Amount = 2.5f }); 57 | ref var requires2 = ref e2.GetSecond(); 58 | Console.WriteLine($"<{nameof(Gigawatts)}, {nameof(Requires)}> (second is value) {nameof(Requires)}: {requires2.Amount}"); 59 | 60 | // Note that and are two 61 | // different pairs, and can be added to an entity at the same time. 62 | 63 | // If both parts of a pair are components, the pair assumes the type of 64 | // the first element:# 65 | // cs binding: GetPairFirstComp <- component value of first 66 | var e3 = world.CreateEntity("e3"); 67 | e3.Set(new Expires() { Timeout = 2.5f }); 68 | ref var expires = ref e3.Get(); 69 | Console.WriteLine($"<{nameof(Expires)}, {nameof(Position)}> (2 comps, first is value) {nameof(Expires)}: {expires.Timeout}"); 70 | 71 | // cs binding: GetPairSecondComp <- component value of second 72 | var e4 = world.CreateEntity("e4"); 73 | e4.Set(new Position() { X = 0.5f, Y = 1f }); 74 | ref var pos = ref e4.GetSecond(); 75 | Console.WriteLine($"<{nameof(Expires)}, {nameof(Position)}> (2 comps, second is value) {nameof(Position)}: {pos.X}/{pos.Y}"); 76 | Console.WriteLine($"has <{nameof(Expires)}, {nameof(Position)}>: {e4.Has()}"); 77 | Console.WriteLine($"has <{nameof(Position)}, {nameof(Expires)}>: {e4.Has()}"); 78 | Console.WriteLine(); 79 | 80 | var eRuntimeTag = world.CreateEntity("RuntimeTag"); 81 | var e5 = world.CreateEntity("e5"); 82 | e5.Set(new Position() { X = 0.5f, Y = 1f }, eRuntimeTag); 83 | e5.Set(eRuntimeTag, new Expires() { Timeout = 0.5f }); 84 | Console.WriteLine($"has ({nameof(Position)}, {nameof(eRuntimeTag)}): {e5.Has(eRuntimeTag)}"); 85 | Console.WriteLine($"has ({nameof(eRuntimeTag)}, {nameof(Position)}): {e5.HasSecond(eRuntimeTag)}"); 86 | 87 | Console.WriteLine($"has ({nameof(Expires)}, {nameof(eRuntimeTag)}): {e5.Has(eRuntimeTag)}"); 88 | Console.WriteLine($"has ({nameof(eRuntimeTag)}, {nameof(Expires)}): {e5.HasSecond(eRuntimeTag)}"); 89 | 90 | ref var e4RuntimePos = ref e5.Get(eRuntimeTag); 91 | ref var e4RuntimeExpires = ref e5.GetSecond(eRuntimeTag); 92 | Console.WriteLine($"({nameof(Position)}, {nameof(eRuntimeTag)}) (2 comps, second is runtime tag) {nameof(Position)}: {e4RuntimePos.X}/{e4RuntimePos.Y}"); 93 | Console.WriteLine($"({nameof(eRuntimeTag)}, {nameof(Expires)}) (2 comps, first is runtime tag) {nameof(Expires)}: {e4RuntimeExpires.Timeout}"); 94 | 95 | Console.WriteLine("\n\nComponents e1"); 96 | IterateComponents(e1); 97 | Console.WriteLine("Components e2"); 98 | IterateComponents(e2); 99 | Console.WriteLine("Components e3"); 100 | IterateComponents(e3); 101 | Console.WriteLine("Components e4"); 102 | IterateComponents(e4); 103 | 104 | return world.Fini(); 105 | } 106 | 107 | private static void IterateComponents(Entity entity) 108 | { 109 | // First get the entity's type, which is a vector of (component) ids. 110 | var type = entity.Type(); 111 | 112 | // 1. The easiest way to print the components is the type's string 113 | var typeString = type.String(); 114 | Console.WriteLine("Type: " + typeString); 115 | 116 | // 2. To print individual ids, iterate the type array with ecs_id_str 117 | var i = 0; 118 | foreach (var identifier in type.Identifiers()) 119 | { 120 | var identifierString = identifier.String(); 121 | Console.WriteLine(i + ": " + identifierString); 122 | i++; 123 | } 124 | 125 | Console.WriteLine(); 126 | 127 | // 3. we can also inspect and print the ids in our own way. This is a 128 | // bit more complicated as we need to handle the edge cases of what can be 129 | // encoded in an id, but provides the most flexibility. 130 | i = 0; 131 | foreach (var identifier in type.Identifiers()) 132 | { 133 | Console.Write(i + ": "); 134 | 135 | var roleString = identifier.RoleString(); 136 | if (roleString != "UNKNOWN") 137 | { 138 | Console.Write("Role: " + roleString + ", "); 139 | } 140 | 141 | if (identifier.IsPair) 142 | { 143 | var pair = identifier.AsPair(); 144 | var relationName = pair.First.Name(); 145 | var objectName = pair.Second.Name(); 146 | Console.Write("Relation: " + relationName + ", Object: " + objectName); 147 | } 148 | else 149 | { 150 | var component = identifier.AsComponent(); 151 | var componentName = component.Name(); 152 | Console.Write("Name: " + componentName); 153 | } 154 | 155 | Console.WriteLine(); 156 | i++; 157 | } 158 | 159 | Console.WriteLine(); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/World.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Runtime.CompilerServices; 8 | using System.Runtime.InteropServices; 9 | using bottlenoselabs.C2CS.Runtime; 10 | using JetBrains.Annotations; 11 | using static flecs_hub.Interop.Flecs.PInvoke; 12 | 13 | namespace Flecs; 14 | 15 | [PublicAPI] 16 | public unsafe class World 17 | { 18 | // Relationships 19 | public Entity EcsIsA => new(this, pinvoke_EcsIsA()); 20 | 21 | public Entity EcsDependsOn => new(this, pinvoke_EcsDependsOn()); 22 | 23 | public Entity EcsChildOf => new(this, pinvoke_EcsChildOf()); 24 | 25 | public Entity EcsSlotOf => new(this, pinvoke_EcsSlotOf()); 26 | 27 | // Entity tags 28 | public Entity EcsPrefab => new(this, pinvoke_EcsPrefab()); 29 | 30 | // System tags 31 | public Entity EcsPreFrame => new(this, pinvoke_EcsPreFrame()); 32 | 33 | public Entity EcsOnLoad => new(this, pinvoke_EcsOnLoad()); 34 | 35 | public Entity EcsPostLoad => new(this, pinvoke_EcsPostLoad()); 36 | 37 | public Entity EcsPreUpdate => new(this, pinvoke_EcsPreUpdate()); 38 | 39 | public Entity EcsOnUpdate => new(this, pinvoke_EcsOnUpdate()); 40 | 41 | public Entity EcsOnValidate => new(this, pinvoke_EcsOnValidate()); 42 | 43 | public Entity EcsPostUpdate => new(this, pinvoke_EcsPostUpdate()); 44 | 45 | public Entity EcsPreStore => new(this, pinvoke_EcsPreStore()); 46 | 47 | public Entity EcsOnStore => new(this, pinvoke_EcsOnStore()); 48 | 49 | public Entity EcsPostFrame => new(this, pinvoke_EcsPostFrame()); 50 | 51 | public Entity EcsPhase => new Entity(this, pinvoke_EcsPhase()); 52 | 53 | internal static Dictionary Pointers = new(); 54 | 55 | internal readonly ecs_world_t* Handle; 56 | // tags = components without data 57 | private Dictionary _componentIdentifiersByType = new(); 58 | 59 | public int ExitCode { get; private set; } 60 | 61 | public World(string[] args) 62 | { 63 | var argv = args.Length == 0 ? default : CStrings.CStringArray(args); 64 | Handle = ecs_init_w_args(args.Length, argv); 65 | Pointers.Add((IntPtr)Handle, this); 66 | 67 | for (var i = 0; i < args.Length; i++) 68 | { 69 | Marshal.FreeHGlobal(argv[i].Pointer); 70 | } 71 | } 72 | 73 | public int Fini() 74 | { 75 | Pointers.Remove((IntPtr)Handle); 76 | var exitCode = ecs_fini(Handle); 77 | return exitCode; 78 | } 79 | 80 | public void RegisterComponent(ComponentHooks? hooks = null) 81 | where TComponent : unmanaged 82 | { 83 | var type = typeof(TComponent); 84 | var componentName = GetFlecsTypeName(type); 85 | var structLayoutAttribute = type.StructLayoutAttribute; 86 | CheckStructLayout(structLayoutAttribute); 87 | var structSize = Unsafe.SizeOf(); 88 | var structAlignment = structLayoutAttribute!.Pack; 89 | if (structAlignment == 0) 90 | { 91 | structAlignment = 1; 92 | } 93 | 94 | ecs_entity_desc_t entityDesc = default; 95 | entityDesc.name = componentName; 96 | entityDesc.symbol = componentName; 97 | ecs_component_desc_t componentDesc = default; 98 | componentDesc.entity = ecs_entity_init(Handle, &entityDesc); 99 | componentDesc.type.size = structSize; 100 | componentDesc.type.alignment = structAlignment; 101 | var id = ecs_component_init(Handle, &componentDesc); 102 | _componentIdentifiersByType[typeof(TComponent)] = id.Data.Data; 103 | SetHooks(hooks, id); 104 | } 105 | 106 | public void RegisterTag() 107 | where TTag : unmanaged, ITag 108 | { 109 | ecs_entity_desc_t desc = default; 110 | var type = typeof(TTag); 111 | var typeName = GetFlecsTypeName(); 112 | desc.name = typeName; 113 | var id = ecs_entity_init(Handle, &desc); 114 | Debug.Assert(id.Data != 0, "ECS_INVALID_PARAMETER"); 115 | _componentIdentifiersByType[type] = id.Data.Data; 116 | } 117 | 118 | public void RegisterSystem( 119 | CallbackIterator callback, Entity phase, string filterExpression, string? name = null) 120 | { 121 | RegisterSystem(callback, phase._handle, filterExpression, name); 122 | } 123 | 124 | public void RegisterSystem( 125 | CallbackIterator callback, ecs_entity_t phase, string filterExpression, string? name = null) 126 | { 127 | ecs_system_desc_t desc = default; 128 | FillSystemDescriptorCommon(ref desc, callback, phase, name); 129 | 130 | desc.query.filter.expr = filterExpression; 131 | ecs_system_init(Handle, &desc); 132 | } 133 | 134 | public void RegisterSystem( 135 | CallbackIterator callback, Entity phase, string? name = null) 136 | { 137 | ecs_system_desc_t desc = default; 138 | FillSystemDescriptorCommon(ref desc, callback, phase._handle, name); 139 | 140 | desc.query.filter.expr = GetFlecsTypeName(); 141 | ecs_system_init(Handle, &desc); 142 | } 143 | 144 | public void RegisterSystem( 145 | CallbackIterator callback, string? name = null) 146 | { 147 | ecs_system_desc_t desc = default; 148 | // desc.query.filter.name = (Runtime.CString)(name ?? callback.Method.Name); 149 | var phase = EcsOnUpdate; 150 | FillSystemDescriptorCommon(ref desc, callback, phase._handle, name); 151 | 152 | var componentName1 = GetFlecsTypeName(); 153 | var componentName2 = GetFlecsTypeName(); 154 | desc.query.filter.expr = componentName1 + ", " + componentName2; 155 | ecs_system_init(Handle, &desc); 156 | } 157 | 158 | public Entity CreateEntity(string name) 159 | { 160 | var desc = default(ecs_entity_desc_t); 161 | desc.name = name; 162 | var entity = ecs_entity_init(Handle, &desc); 163 | var result = new Entity(this, entity); 164 | return result; 165 | } 166 | 167 | public Entity CreatePrefab(string name) 168 | { 169 | var desc = default(ecs_entity_desc_t); 170 | desc.name = name; 171 | desc.add[0] = pinvoke_EcsPrefab(); 172 | 173 | var entity = ecs_entity_init(Handle, &desc); 174 | var result = new Entity(this, entity); 175 | return result; 176 | } 177 | 178 | public EntityIterator EntityIterator() 179 | where TComponent : unmanaged, IComponent 180 | { 181 | var term = default(ecs_term_t); 182 | term.id = _componentIdentifiersByType[typeof(TComponent)]; 183 | var iterator = ecs_term_iter(Handle, &term); 184 | var result = new EntityIterator(this, iterator); 185 | return result; 186 | } 187 | 188 | public bool Progress(float deltaTime) 189 | { 190 | return ecs_progress(Handle, deltaTime); 191 | } 192 | 193 | public string GetFlecsTypeName(Type type) 194 | { 195 | #if !UNITY_5_3_OR_NEWER 196 | #pragma warning disable CA1307 197 | return type.FullName!.Replace("+", "."); 198 | #pragma warning restore CA1307 199 | #else 200 | return type.FullName!.Replace("+", ".", StringComparison.InvariantCulture); 201 | #endif 202 | } 203 | 204 | public string GetFlecsTypeName() 205 | { 206 | return GetFlecsTypeName(typeof(T)); 207 | } 208 | 209 | public Identifier GetIdentifier() 210 | where T : unmanaged, IEcsComponent 211 | { 212 | var type = typeof(T); 213 | var containsKey = _componentIdentifiersByType.TryGetValue(type, out var value); 214 | if (!containsKey) 215 | { 216 | RegisterComponent(); 217 | value = _componentIdentifiersByType[type]; 218 | } 219 | 220 | var id = default(ecs_id_t); 221 | id.Data = value; 222 | return new Identifier(this, id); 223 | } 224 | 225 | private void FillSystemDescriptorCommon( 226 | ref ecs_system_desc_t systemDesc, CallbackIterator callback, ecs_entity_t phase, string? name) 227 | { 228 | ecs_entity_desc_t entityDesc = default; 229 | entityDesc.name = name ?? callback.Method.Name; 230 | entityDesc.add[0] = phase.Data != 0 ? ecs_pair(EcsDependsOn._handle, phase) : default; 231 | entityDesc.add[1] = phase; 232 | systemDesc.entity = ecs_entity_init(Handle, &entityDesc); 233 | #if UNITY_5_3_OR_NEWER 234 | systemDesc.callback.Data.Pointer = Marshal.GetFunctionPointerForDelegate(SystemCallback); 235 | #else 236 | systemDesc.callback.Data.Pointer = &SystemCallback; 237 | #endif 238 | systemDesc.binding_ctx = (void*)CallbacksHelper.CreateSystemCallbackContext(this, callback); 239 | } 240 | 241 | #if !UNITY_5_3_OR_NEWER 242 | [UnmanagedCallersOnly] 243 | #endif 244 | private static void SystemCallback(ecs_iter_t* it) 245 | { 246 | CallbacksHelper.GetSystemCallbackContext((IntPtr)it->binding_ctx, out var data); 247 | 248 | var iterator = new Iterator(data.World, it); 249 | data.Callback(iterator); 250 | } 251 | 252 | private void SetHooks(ComponentHooks? hooksNullable, ecs_entity_t id) 253 | { 254 | if (hooksNullable == null) 255 | { 256 | return; 257 | } 258 | 259 | var hooksDesc = default(ecs_type_hooks_t); 260 | var hooks = hooksNullable.Value; 261 | ComponentHooks.Fill(this, ref hooks, &hooksDesc); 262 | ecs_set_hooks_id(Handle, id, &hooksDesc); 263 | } 264 | 265 | private static void CheckStructLayout(StructLayoutAttribute? structLayoutAttribute) 266 | { 267 | if (structLayoutAttribute == null || structLayoutAttribute.Value == LayoutKind.Auto) 268 | { 269 | throw new FlecsException( 270 | "Component must have a StructLayout attribute with LayoutKind sequential or explicit. This is to ensure that the struct fields are not reorganized by the C# compiler."); 271 | } 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/cs/Flecs.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32210.238 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{9E1476CE-E22E-44FD-ABC4-93625DDBBA99}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Production", "Production", "{39423871-7923-4AFB-A756-35E17FCBA274}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Core", "production\Flecs.Core\Flecs.Core.csproj", "{5EB4443F-134E-43A0-9607-9F3504671E47}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Entities", "Entities", "{3DA02832-2DA5-49CC-929D-6DB290DA28EC}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.HelloWorld", "examples\Flecs.Examples.HelloWorld\Flecs.Examples.HelloWorld.csproj", "{E5E0E0A5-DF34-403B-A2BD-93EFF21C4825}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.Hierarchy", "examples\entities\Flecs.Examples.Entities.Hierarchy\Flecs.Examples.Entities.Hierarchy.csproj", "{603A7B38-8FEF-45A6-8EA7-1AE82D9504C4}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.Basics", "examples\entities\Flecs.Examples.Entities.Basics\Flecs.Examples.Entities.Basics.csproj", "{5B604D6C-EDC7-4D7F-8CF4-D368CAE30A37}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.Hooks", "examples\entities\Flecs.Examples.Entities.Hooks\Flecs.Examples.Entities.Hooks.csproj", "{CA4D5654-1D45-442E-9C18-F93B1F670263}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.IterateComponents", "examples\entities\Flecs.Examples.Entities.IterateComponents\Flecs.Examples.Entities.IterateComponents.csproj", "{449DE999-B69C-43D7-9848-0F4BDE7CCC24}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.Prefab", "examples\entities\Flecs.Examples.Entities.Prefab\Flecs.Examples.Entities.Prefab.csproj", "{D298B204-9318-44F9-9330-A1EFAADCD205}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.RelationComponents", "examples\entities\Flecs.Examples.Entities.RelationComponents\Flecs.Examples.Entities.RelationComponents.csproj", "{63057DDB-7E98-465D-91AE-396037A0B282}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.RelationBasic", "examples\entities\Flecs.Examples.Entities.RelationBasic\Flecs.Examples.Entities.RelationBasic.csproj", "{EC0A2533-C10C-412F-8D98-7B37AB53FA28}" 29 | EndProject 30 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Queries", "Queries", "{04650426-AD83-4E99-B211-3C70309C6FCF}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Queries.OptionalOr", "examples\queries\Flecs.Examples.Queries.OptionalOr\Flecs.Examples.Queries.OptionalOr.csproj", "{4A8057DB-51F1-4BDB-B40C-1EAAD4620234}" 33 | EndProject 34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Entities.PrefabSlot", "examples\entities\Flecs.Examples.Entities.PrefabSlot\Flecs.Examples.Entities.PrefabSlot.csproj", "{B8C4D7B7-45C4-46A8-8C7E-03C36F5949B2}" 35 | EndProject 36 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Systems", "Systems", "{36062DD2-C7DC-4074-B1EC-218636DD4B76}" 37 | EndProject 38 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flecs.Examples.Systems.CustomPhase", "examples\systems\Flecs.Examples.Systems.CustomPhase\Flecs.Examples.Systems.CustomPhase.csproj", "{81CFEB14-4C31-4CEF-BE4B-B281EC42D060}" 39 | EndProject 40 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flecs.Unity", "production\Flecs.Unity\Flecs.Unity.csproj", "{45B80105-C0E9-42E0-9D70-D42B65958262}" 41 | EndProject 42 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Flecs.Core", "production\Interop.Flecs.Core\Interop.Flecs.Core.csproj", "{1C5CE028-B4F3-4D18-9BF5-8785103B6138}" 43 | EndProject 44 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Flecs.Unity", "production\Interop.Flecs.Unity\Interop.Flecs.Unity.csproj", "{26B6B8F0-2CAE-4DFC-9F79-9313682F10BA}" 45 | EndProject 46 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Flecs.runtime.linux-x64", "production\Interop.Flecs.runtime.linux-x64\Interop.Flecs.runtime.linux-x64.csproj", "{B6EA6A81-D9D9-4B20-B897-7A8DED05CB00}" 47 | EndProject 48 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Flecs.runtime.osx", "production\Interop.Flecs.runtime.osx\Interop.Flecs.runtime.osx.csproj", "{BFC9867A-C542-401D-AF76-7094D3D4261A}" 49 | EndProject 50 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.Flecs.runtime.win-x64", "production\Interop.Flecs.runtime.win-x64\Interop.Flecs.runtime.win-x64.csproj", "{F205AFC3-2ED6-4F65-BD63-7077F3CE07C0}" 51 | EndProject 52 | Global 53 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 54 | Debug|Any CPU = Debug|Any CPU 55 | Release|Any CPU = Release|Any CPU 56 | EndGlobalSection 57 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 58 | {5EB4443F-134E-43A0-9607-9F3504671E47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {5EB4443F-134E-43A0-9607-9F3504671E47}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {5EB4443F-134E-43A0-9607-9F3504671E47}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {5EB4443F-134E-43A0-9607-9F3504671E47}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {E5E0E0A5-DF34-403B-A2BD-93EFF21C4825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {E5E0E0A5-DF34-403B-A2BD-93EFF21C4825}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {E5E0E0A5-DF34-403B-A2BD-93EFF21C4825}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {E5E0E0A5-DF34-403B-A2BD-93EFF21C4825}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {603A7B38-8FEF-45A6-8EA7-1AE82D9504C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {603A7B38-8FEF-45A6-8EA7-1AE82D9504C4}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {603A7B38-8FEF-45A6-8EA7-1AE82D9504C4}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {603A7B38-8FEF-45A6-8EA7-1AE82D9504C4}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {5B604D6C-EDC7-4D7F-8CF4-D368CAE30A37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {5B604D6C-EDC7-4D7F-8CF4-D368CAE30A37}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {5B604D6C-EDC7-4D7F-8CF4-D368CAE30A37}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {5B604D6C-EDC7-4D7F-8CF4-D368CAE30A37}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {CA4D5654-1D45-442E-9C18-F93B1F670263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 75 | {CA4D5654-1D45-442E-9C18-F93B1F670263}.Debug|Any CPU.Build.0 = Debug|Any CPU 76 | {CA4D5654-1D45-442E-9C18-F93B1F670263}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {CA4D5654-1D45-442E-9C18-F93B1F670263}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {449DE999-B69C-43D7-9848-0F4BDE7CCC24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {449DE999-B69C-43D7-9848-0F4BDE7CCC24}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {449DE999-B69C-43D7-9848-0F4BDE7CCC24}.Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {449DE999-B69C-43D7-9848-0F4BDE7CCC24}.Release|Any CPU.Build.0 = Release|Any CPU 82 | {D298B204-9318-44F9-9330-A1EFAADCD205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 83 | {D298B204-9318-44F9-9330-A1EFAADCD205}.Debug|Any CPU.Build.0 = Debug|Any CPU 84 | {D298B204-9318-44F9-9330-A1EFAADCD205}.Release|Any CPU.ActiveCfg = Release|Any CPU 85 | {D298B204-9318-44F9-9330-A1EFAADCD205}.Release|Any CPU.Build.0 = Release|Any CPU 86 | {63057DDB-7E98-465D-91AE-396037A0B282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 87 | {63057DDB-7E98-465D-91AE-396037A0B282}.Debug|Any CPU.Build.0 = Debug|Any CPU 88 | {63057DDB-7E98-465D-91AE-396037A0B282}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {63057DDB-7E98-465D-91AE-396037A0B282}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {EC0A2533-C10C-412F-8D98-7B37AB53FA28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 91 | {EC0A2533-C10C-412F-8D98-7B37AB53FA28}.Debug|Any CPU.Build.0 = Debug|Any CPU 92 | {EC0A2533-C10C-412F-8D98-7B37AB53FA28}.Release|Any CPU.ActiveCfg = Release|Any CPU 93 | {EC0A2533-C10C-412F-8D98-7B37AB53FA28}.Release|Any CPU.Build.0 = Release|Any CPU 94 | {4A8057DB-51F1-4BDB-B40C-1EAAD4620234}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 95 | {4A8057DB-51F1-4BDB-B40C-1EAAD4620234}.Debug|Any CPU.Build.0 = Debug|Any CPU 96 | {4A8057DB-51F1-4BDB-B40C-1EAAD4620234}.Release|Any CPU.ActiveCfg = Release|Any CPU 97 | {4A8057DB-51F1-4BDB-B40C-1EAAD4620234}.Release|Any CPU.Build.0 = Release|Any CPU 98 | {B8C4D7B7-45C4-46A8-8C7E-03C36F5949B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 99 | {B8C4D7B7-45C4-46A8-8C7E-03C36F5949B2}.Debug|Any CPU.Build.0 = Debug|Any CPU 100 | {B8C4D7B7-45C4-46A8-8C7E-03C36F5949B2}.Release|Any CPU.ActiveCfg = Release|Any CPU 101 | {B8C4D7B7-45C4-46A8-8C7E-03C36F5949B2}.Release|Any CPU.Build.0 = Release|Any CPU 102 | {81CFEB14-4C31-4CEF-BE4B-B281EC42D060}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 103 | {81CFEB14-4C31-4CEF-BE4B-B281EC42D060}.Debug|Any CPU.Build.0 = Debug|Any CPU 104 | {81CFEB14-4C31-4CEF-BE4B-B281EC42D060}.Release|Any CPU.ActiveCfg = Release|Any CPU 105 | {81CFEB14-4C31-4CEF-BE4B-B281EC42D060}.Release|Any CPU.Build.0 = Release|Any CPU 106 | {45B80105-C0E9-42E0-9D70-D42B65958262}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 107 | {45B80105-C0E9-42E0-9D70-D42B65958262}.Debug|Any CPU.Build.0 = Debug|Any CPU 108 | {45B80105-C0E9-42E0-9D70-D42B65958262}.Release|Any CPU.ActiveCfg = Release|Any CPU 109 | {45B80105-C0E9-42E0-9D70-D42B65958262}.Release|Any CPU.Build.0 = Release|Any CPU 110 | {1C5CE028-B4F3-4D18-9BF5-8785103B6138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 111 | {1C5CE028-B4F3-4D18-9BF5-8785103B6138}.Debug|Any CPU.Build.0 = Debug|Any CPU 112 | {1C5CE028-B4F3-4D18-9BF5-8785103B6138}.Release|Any CPU.ActiveCfg = Release|Any CPU 113 | {1C5CE028-B4F3-4D18-9BF5-8785103B6138}.Release|Any CPU.Build.0 = Release|Any CPU 114 | {26B6B8F0-2CAE-4DFC-9F79-9313682F10BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 115 | {26B6B8F0-2CAE-4DFC-9F79-9313682F10BA}.Debug|Any CPU.Build.0 = Debug|Any CPU 116 | {26B6B8F0-2CAE-4DFC-9F79-9313682F10BA}.Release|Any CPU.ActiveCfg = Release|Any CPU 117 | {26B6B8F0-2CAE-4DFC-9F79-9313682F10BA}.Release|Any CPU.Build.0 = Release|Any CPU 118 | {B6EA6A81-D9D9-4B20-B897-7A8DED05CB00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 119 | {B6EA6A81-D9D9-4B20-B897-7A8DED05CB00}.Debug|Any CPU.Build.0 = Debug|Any CPU 120 | {B6EA6A81-D9D9-4B20-B897-7A8DED05CB00}.Release|Any CPU.ActiveCfg = Release|Any CPU 121 | {B6EA6A81-D9D9-4B20-B897-7A8DED05CB00}.Release|Any CPU.Build.0 = Release|Any CPU 122 | {BFC9867A-C542-401D-AF76-7094D3D4261A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 123 | {BFC9867A-C542-401D-AF76-7094D3D4261A}.Debug|Any CPU.Build.0 = Debug|Any CPU 124 | {BFC9867A-C542-401D-AF76-7094D3D4261A}.Release|Any CPU.ActiveCfg = Release|Any CPU 125 | {BFC9867A-C542-401D-AF76-7094D3D4261A}.Release|Any CPU.Build.0 = Release|Any CPU 126 | {F205AFC3-2ED6-4F65-BD63-7077F3CE07C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 127 | {F205AFC3-2ED6-4F65-BD63-7077F3CE07C0}.Debug|Any CPU.Build.0 = Debug|Any CPU 128 | {F205AFC3-2ED6-4F65-BD63-7077F3CE07C0}.Release|Any CPU.ActiveCfg = Release|Any CPU 129 | {F205AFC3-2ED6-4F65-BD63-7077F3CE07C0}.Release|Any CPU.Build.0 = Release|Any CPU 130 | EndGlobalSection 131 | GlobalSection(SolutionProperties) = preSolution 132 | HideSolutionNode = FALSE 133 | EndGlobalSection 134 | GlobalSection(NestedProjects) = preSolution 135 | {5EB4443F-134E-43A0-9607-9F3504671E47} = {39423871-7923-4AFB-A756-35E17FCBA274} 136 | {3DA02832-2DA5-49CC-929D-6DB290DA28EC} = {9E1476CE-E22E-44FD-ABC4-93625DDBBA99} 137 | {E5E0E0A5-DF34-403B-A2BD-93EFF21C4825} = {9E1476CE-E22E-44FD-ABC4-93625DDBBA99} 138 | {603A7B38-8FEF-45A6-8EA7-1AE82D9504C4} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 139 | {5B604D6C-EDC7-4D7F-8CF4-D368CAE30A37} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 140 | {CA4D5654-1D45-442E-9C18-F93B1F670263} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 141 | {449DE999-B69C-43D7-9848-0F4BDE7CCC24} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 142 | {D298B204-9318-44F9-9330-A1EFAADCD205} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 143 | {63057DDB-7E98-465D-91AE-396037A0B282} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 144 | {EC0A2533-C10C-412F-8D98-7B37AB53FA28} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 145 | {04650426-AD83-4E99-B211-3C70309C6FCF} = {9E1476CE-E22E-44FD-ABC4-93625DDBBA99} 146 | {4A8057DB-51F1-4BDB-B40C-1EAAD4620234} = {04650426-AD83-4E99-B211-3C70309C6FCF} 147 | {B8C4D7B7-45C4-46A8-8C7E-03C36F5949B2} = {3DA02832-2DA5-49CC-929D-6DB290DA28EC} 148 | {36062DD2-C7DC-4074-B1EC-218636DD4B76} = {9E1476CE-E22E-44FD-ABC4-93625DDBBA99} 149 | {81CFEB14-4C31-4CEF-BE4B-B281EC42D060} = {36062DD2-C7DC-4074-B1EC-218636DD4B76} 150 | {45B80105-C0E9-42E0-9D70-D42B65958262} = {39423871-7923-4AFB-A756-35E17FCBA274} 151 | {1C5CE028-B4F3-4D18-9BF5-8785103B6138} = {39423871-7923-4AFB-A756-35E17FCBA274} 152 | {26B6B8F0-2CAE-4DFC-9F79-9313682F10BA} = {39423871-7923-4AFB-A756-35E17FCBA274} 153 | {B6EA6A81-D9D9-4B20-B897-7A8DED05CB00} = {39423871-7923-4AFB-A756-35E17FCBA274} 154 | {BFC9867A-C542-401D-AF76-7094D3D4261A} = {39423871-7923-4AFB-A756-35E17FCBA274} 155 | {F205AFC3-2ED6-4F65-BD63-7077F3CE07C0} = {39423871-7923-4AFB-A756-35E17FCBA274} 156 | EndGlobalSection 157 | GlobalSection(ExtensibilityGlobals) = postSolution 158 | SolutionGuid = {C4B6B4B9-1CB6-414C-BF33-521394D6CD71} 159 | EndGlobalSection 160 | EndGlobal 161 | -------------------------------------------------------------------------------- /src/cs/production/Flecs.Core/Entity.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Flecs Hub (https://github.com/flecs-hub). All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the Git repository root directory for full license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.InteropServices; 6 | using bottlenoselabs.C2CS.Runtime; 7 | using JetBrains.Annotations; 8 | using static flecs_hub.Interop.Flecs.PInvoke; 9 | 10 | namespace Flecs; 11 | 12 | [PublicAPI] 13 | public readonly unsafe struct Entity 14 | { 15 | internal readonly ecs_entity_t _handle; 16 | private readonly World _world; 17 | 18 | internal Entity(World world, ecs_entity_t handle) 19 | { 20 | _world = world; 21 | _handle = handle; 22 | } 23 | 24 | public static Entity FromIdentifier(Identifier identifier) 25 | { 26 | return new Entity(identifier.World, identifier.Handle); 27 | } 28 | 29 | public EntityType Type() 30 | { 31 | var type = ecs_get_type(_world.Handle, _handle); 32 | var result = new EntityType(_world, type); 33 | return result; 34 | } 35 | 36 | public void Add() 37 | where T : unmanaged, IEcsComponent 38 | { 39 | var tagId = _world.GetIdentifier(); 40 | ecs_add_id(_world.Handle, _handle, tagId.Handle); 41 | } 42 | 43 | public void Add(Entity entity) 44 | { 45 | ecs_add_id(_world.Handle, _handle, entity._handle); 46 | } 47 | 48 | public void Remove() 49 | where T : unmanaged, IEcsComponent 50 | { 51 | var tagId = _world.GetIdentifier(); 52 | ecs_remove_id(_world.Handle, _handle, tagId.Handle); 53 | } 54 | 55 | public void Remove(Entity entity) 56 | { 57 | ecs_remove_id(_world.Handle, _handle, entity._handle); 58 | } 59 | 60 | public void Add() 61 | where TTag1 : unmanaged, ITag 62 | where TTag2 : unmanaged, ITag 63 | { 64 | var tagId1 = _world.GetIdentifier(); 65 | var tagId2 = _world.GetIdentifier(); 66 | var id = ecs_pair(tagId1.Handle, tagId2.Handle); 67 | ecs_add_id(_world.Handle, _handle, id); 68 | } 69 | 70 | public void AddOverride() 71 | where TTag1 : unmanaged, ITag 72 | where TTag2 : unmanaged, ITag 73 | { 74 | var tagId1 = _world.GetIdentifier(); 75 | var tagId2 = _world.GetIdentifier(); 76 | var id = ecs_pair(tagId1.Handle, tagId2.Handle); 77 | ecs_override_id(_world.Handle, _handle, id); 78 | } 79 | 80 | public void Add(Entity first, Entity second) 81 | { 82 | var id = ecs_pair(first._handle, second._handle); 83 | ecs_add_id(_world.Handle, _handle, id); 84 | } 85 | 86 | public void AddOverride(Entity first, Entity second) 87 | { 88 | var id = ecs_pair(first._handle, second._handle); 89 | ecs_override_id(_world.Handle, _handle, id); 90 | } 91 | 92 | public void Add(Entity first) 93 | where TTag : unmanaged, ITag 94 | { 95 | var tagId = _world.GetIdentifier(); 96 | var id = ecs_pair(first._handle, tagId.Handle); 97 | ecs_add_id(_world.Handle, _handle, id); 98 | } 99 | 100 | public void AddOverride(Entity first) 101 | where TTag : unmanaged, ITag 102 | { 103 | var tagId = _world.GetIdentifier(); 104 | var id = ecs_pair(first._handle, tagId.Handle); 105 | ecs_override_id(_world.Handle, _handle, id); 106 | } 107 | 108 | public void AddSecond(Entity second) 109 | where TTag : unmanaged, ITag 110 | { 111 | var tagId = _world.GetIdentifier(); 112 | var id = ecs_pair(tagId.Handle, second._handle); 113 | ecs_add_id(_world.Handle, _handle, id); 114 | } 115 | 116 | public void AddSecondOverride(Entity second) 117 | where TTag : unmanaged, ITag 118 | { 119 | var tagId = _world.GetIdentifier(); 120 | var id = ecs_pair(tagId.Handle, second._handle); 121 | ecs_override_id(_world.Handle, _handle, id); 122 | } 123 | 124 | public void Set(TComponent component) // right comp 125 | where TEcsComponent : unmanaged, IEcsComponent 126 | where TComponent : unmanaged, IComponent 127 | { 128 | var ecsCompId = _world.GetIdentifier(); 129 | var compId = _world.GetIdentifier(); 130 | SetPairData(component, ecsCompId, compId); 131 | } 132 | 133 | public void SetOverride(TComponent component) // right comp 134 | where TEcsComponent : unmanaged, IEcsComponent 135 | where TComponent : unmanaged, IComponent 136 | { 137 | var ecsCompId = _world.GetIdentifier(); 138 | var compId = _world.GetIdentifier(); 139 | SetPairDataOverride(component, ecsCompId, compId); 140 | } 141 | 142 | public void Set(TComponent component) // left comp 143 | where TComponent : unmanaged, IComponent 144 | where TEcsComponent : unmanaged, IEcsComponent 145 | { 146 | var compId = _world.GetIdentifier(); 147 | var ecsCompId = _world.GetIdentifier(); 148 | SetPairData(component, compId, ecsCompId); 149 | } 150 | 151 | public void SetOverride(TComponent component) // left comp 152 | where TComponent : unmanaged, IComponent 153 | where TEcsComponent : unmanaged, IEcsComponent 154 | { 155 | var compId = _world.GetIdentifier(); 156 | var ecsCompId = _world.GetIdentifier(); 157 | SetPairData(component, compId, ecsCompId); 158 | } 159 | 160 | public void Set(TComponent first, Entity second) // assume left comp, right is used as tag 161 | where TComponent : unmanaged, IComponent 162 | { 163 | var firstId = _world.GetIdentifier(); 164 | var secondId = new Identifier(_world, second._handle); 165 | SetPairData(first, firstId, secondId); 166 | } 167 | 168 | public void SetOverride(TComponent first, Entity second) // assume left comp, right is used as tag 169 | where TComponent : unmanaged, IComponent 170 | { 171 | var firstId = _world.GetIdentifier(); 172 | var secondId = new Identifier(_world, second._handle); 173 | SetPairDataOverride(first, firstId, secondId); 174 | } 175 | 176 | public void Set(Entity first, TComponent second) // assume left comp, right is used as tag 177 | where TComponent : unmanaged, IComponent 178 | { 179 | var firstId = new Identifier(_world, first._handle); 180 | var secondId = _world.GetIdentifier(); 181 | SetPairData(second, firstId, secondId); 182 | } 183 | 184 | public void SetOverride(Entity first, TComponent second) // assume left comp, right is used as tag 185 | where TComponent : unmanaged, IComponent 186 | { 187 | var firstId = new Identifier(_world, first._handle); 188 | var secondId = _world.GetIdentifier(); 189 | SetPairDataOverride(second, firstId, secondId); 190 | } 191 | 192 | public ref TComponent Get() 193 | where TComponent : unmanaged, IComponent 194 | where TEscComponent : unmanaged, IEcsComponent 195 | { 196 | var compId = _world.GetIdentifier(); 197 | var tagId = _world.GetIdentifier(); 198 | return ref GetPairData(compId, tagId); 199 | } 200 | 201 | public ref TComponent GetSecond() 202 | where TEscComponent : unmanaged, IEcsComponent 203 | where TComponent : unmanaged, IComponent 204 | { 205 | var tagId = _world.GetIdentifier(); 206 | var compId = _world.GetIdentifier(); 207 | return ref GetPairData(tagId, compId); 208 | } 209 | 210 | public ref TComponent Get(Entity second) 211 | where TComponent : unmanaged, IComponent 212 | { 213 | var compId = _world.GetIdentifier(); 214 | return ref GetPairData(compId, new Identifier(_world, second._handle)); 215 | } 216 | 217 | public ref TComponent GetSecond(Entity first) 218 | where TComponent : unmanaged, IComponent 219 | { 220 | var compId = _world.GetIdentifier(); 221 | return ref GetPairData(new Identifier(_world, first._handle), compId); 222 | } 223 | 224 | public Entity GetTarget(Entity relation) 225 | { 226 | var target = ecs_get_target(_world.Handle, _handle, relation._handle, 0); 227 | return new Entity(_world, target); 228 | } 229 | 230 | public void AddParent(Entity entity) 231 | { 232 | var id = ecs_pair(EcsChildOf, entity._handle); 233 | ecs_add_id(_world.Handle, _handle, id); 234 | } 235 | 236 | public void IsA(Entity entity) 237 | { 238 | var id = ecs_pair(EcsIsA, entity._handle); 239 | ecs_add_id(_world.Handle, _handle, id); 240 | } 241 | 242 | public void AddSlotOf(Entity entity) 243 | { 244 | var id = ecs_pair(EcsSlotOf, entity._handle); 245 | ecs_add_id(_world.Handle, _handle, id); 246 | } 247 | 248 | public ref TComponent GetComponent() 249 | where TComponent : unmanaged, IComponent 250 | { 251 | var componentId = _world.GetIdentifier(); 252 | var pointer = ecs_get_id(_world.Handle, _handle, componentId.Handle); 253 | return ref Unsafe.AsRef(pointer); 254 | } 255 | 256 | public void Set(ref TComponent component) 257 | where TComponent : unmanaged, IComponent 258 | { 259 | var componentId = _world.GetIdentifier(); 260 | var structSize = Unsafe.SizeOf(); 261 | var pointer = Unsafe.AsPointer(ref component); 262 | ecs_set_id(_world.Handle, _handle, componentId.Handle, (ulong)structSize, pointer); 263 | } 264 | 265 | public void Set(TComponent component) 266 | where TComponent : unmanaged, IComponent 267 | { 268 | Set(ref component); 269 | } 270 | 271 | public void SetOverride(ref TComponent component) 272 | where TComponent : unmanaged, IComponent 273 | { 274 | var componentId = _world.GetIdentifier(); 275 | var structSize = Unsafe.SizeOf(); 276 | var pointer = Unsafe.AsPointer(ref component); 277 | 278 | var overrideValue = ECS_OVERRIDE.Data; 279 | var identifierValue = overrideValue | componentId.Handle.Data; 280 | ecs_add_id(_world.Handle, _handle, *(ecs_id_t*)&identifierValue); 281 | ecs_set_id(_world.Handle, _handle, componentId.Handle, (ulong)structSize, pointer); 282 | } 283 | 284 | public void SetOverride(TComponent component) 285 | where TComponent : unmanaged, IComponent 286 | { 287 | SetOverride(ref component); 288 | } 289 | 290 | public void Delete() 291 | { 292 | ecs_delete(_world.Handle, _handle); 293 | } 294 | 295 | public string Name() 296 | { 297 | var result = ecs_get_name(_world.Handle, _handle); 298 | return result.ToString(); 299 | } 300 | 301 | public bool Has() 302 | where T : unmanaged, IEcsComponent 303 | { 304 | var compId = _world.GetIdentifier(); 305 | return ecs_has_id(_world.Handle, _handle, compId.Handle); 306 | } 307 | 308 | public bool Has() 309 | where T1 : unmanaged, IEcsComponent 310 | where T2 : unmanaged, IEcsComponent 311 | { 312 | var id1 = _world.GetIdentifier(); 313 | var id2 = _world.GetIdentifier(); 314 | var id = ecs_pair(id1.Handle, id2.Handle); 315 | return ecs_has_id(_world.Handle, _handle, id); 316 | } 317 | 318 | public bool Has(Entity first, Entity second) 319 | { 320 | var id = ecs_pair(first._handle, second._handle); 321 | return ecs_has_id(_world.Handle, _handle, id); 322 | } 323 | 324 | public bool Has(Entity second) 325 | where T : unmanaged, IEcsComponent 326 | { 327 | var compId = _world.GetIdentifier(); 328 | var id = ecs_pair(compId.Handle, second._handle); 329 | return ecs_has_id(_world.Handle, _handle, id); 330 | } 331 | 332 | public bool HasSecond(Entity first) 333 | where T : unmanaged, IEcsComponent 334 | { 335 | var compId = _world.GetIdentifier(); 336 | var id = ecs_pair(first._handle, compId.Handle); 337 | return ecs_has_id(_world.Handle, _handle, id); 338 | } 339 | 340 | public void DependsOn(Entity entity) 341 | { 342 | Add(new Entity(_world, EcsDependsOn), entity); 343 | } 344 | 345 | public bool IsChildOf(Entity entity) 346 | { 347 | var pair = ecs_childof(entity._handle); 348 | var result = ecs_has_id(_world.Handle, _handle, pair); 349 | return result; 350 | } 351 | 352 | public string FullPathString() 353 | { 354 | var cString = ecs_get_path_w_sep(_world.Handle, default, _handle, (CString)".", default); 355 | var result = Marshal.PtrToStringAnsi(cString.Pointer)!; 356 | Marshal.FreeHGlobal(cString.Pointer); 357 | return result; 358 | } 359 | 360 | public EntityIterator Children() 361 | { 362 | var term = default(ecs_term_t); 363 | term.id = ecs_childof(_handle); 364 | var iterator = ecs_term_iter(_world.Handle, &term); 365 | var result = new EntityIterator(_world, iterator); 366 | return result; 367 | } 368 | 369 | private ref TComp GetPairData(Identifier first, Identifier second) 370 | where TComp : unmanaged, IComponent 371 | { 372 | var id = ecs_pair(first.Handle, second.Handle); 373 | var pointer = ecs_get_id(_world.Handle, _handle, id); 374 | return ref Unsafe.AsRef(pointer); 375 | } 376 | 377 | private void SetPairData(TComponent component, Identifier left, Identifier right) 378 | where TComponent : unmanaged, IComponent 379 | { 380 | var id = ecs_pair(left.Handle, right.Handle); 381 | var structSize = Unsafe.SizeOf(); 382 | var pointer = Unsafe.AsPointer(ref component); 383 | ecs_set_id(_world.Handle, _handle, id, (ulong)structSize, pointer); 384 | } 385 | 386 | private void SetPairDataOverride(TComponent component, Identifier left, Identifier right) 387 | where TComponent : unmanaged, IComponent 388 | { 389 | var id = ecs_pair(left.Handle, right.Handle); 390 | var structSize = Unsafe.SizeOf(); 391 | var pointer = Unsafe.AsPointer(ref component); 392 | ecs_override_id(_world.Handle, _handle, id); 393 | ecs_set_id(_world.Handle, _handle, id, (ulong)structSize, pointer); 394 | } 395 | } 396 | --------------------------------------------------------------------------------