├── Source └── ArchECSStride │ ├── ArchECSStride.Windows │ ├── Resources │ │ └── Icon.ico │ ├── ArchECSStrideApp.cs │ ├── ArchECSStride.Windows.sdpkg │ └── ArchECSStride.Windows.csproj │ ├── ArchECSStride │ ├── Resources │ │ └── skybox_texture_hdr.dds │ ├── Assets │ │ ├── Skybox.sdsky │ │ ├── Skybox texture.sdtex │ │ ├── Materials │ │ │ ├── Leaves.sdmat │ │ │ ├── Trunk.sdmat │ │ │ └── Grass.sdmat │ │ ├── Sphere.sdpromodel │ │ ├── Cube.sdpromodel │ │ ├── Ground.sdpromodel │ │ ├── Models │ │ │ └── Tree.sdm3d │ │ ├── Ground Material.sdmat │ │ ├── Sphere Material.sdmat │ │ ├── GameSettings.sdgamesettings │ │ ├── CubePrefab.sdprefab │ │ ├── GraphicsCompositor.sdgfxcomp │ │ └── MainScene.sdscene │ ├── Code │ │ ├── CustomGame.cs │ │ ├── GamePlay │ │ │ └── Data │ │ │ │ ├── ResourceType.cs │ │ │ │ └── AgentJobType.cs │ │ ├── Arch │ │ │ └── Components │ │ │ │ ├── ArchAgent.cs │ │ │ │ ├── ArchRotation.cs │ │ │ │ ├── ArchVelocity.cs │ │ │ │ ├── ArchTest.cs │ │ │ │ ├── ArchPosition.cs │ │ │ │ └── ArchPathfinder.cs │ │ ├── NPC │ │ │ ├── Components │ │ │ │ └── ArchNPCAgent.cs │ │ │ └── Systems │ │ │ │ └── NPCAgentSystem.cs │ │ ├── Resources │ │ │ └── Components │ │ │ │ └── Resource.cs │ │ ├── InitializeInstanceMesh.cs │ │ ├── Systems │ │ │ ├── SpawnPrefabSystem.cs │ │ │ ├── TestSystem.cs │ │ │ ├── MoveEntitySystem.cs │ │ │ ├── UpdateStridePositionsSystem.cs │ │ │ └── PathfindingSystem.cs │ │ └── Extensions │ │ │ └── EntityExtensions.cs │ ├── ArchECSStride.sdpkg │ ├── ArchECSStride.csproj │ ├── GameProfiler.cs │ └── BasicCameraController.cs │ ├── .gitignore │ ├── Doprez.Stride.Arch │ ├── Module.cs │ ├── ArchGameExtensions.cs │ ├── Components │ │ └── ArchStrideId.cs │ ├── ArchComponent.cs │ ├── Configurations │ │ └── ArchSettings.cs │ ├── Services │ │ └── StrideEntityManager.cs │ ├── Doprez.Stride.Arch.csproj │ ├── ArchSystem.cs │ ├── Systems │ │ └── DefaultEntityRegisterSystem.cs │ └── ArchProcessor.cs │ └── ArchECSStride.sln ├── LICENSE ├── .circleci └── config.yml ├── README.md └── .gitignore /Source/ArchECSStride/ArchECSStride.Windows/Resources/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doprez/stride-arch-ecs/HEAD/Source/ArchECSStride/ArchECSStride.Windows/Resources/Icon.ico -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Resources/skybox_texture_hdr.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Doprez/stride-arch-ecs/HEAD/Source/ArchECSStride/ArchECSStride/Resources/skybox_texture_hdr.dds -------------------------------------------------------------------------------- /Source/ArchECSStride/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.user 3 | *.lock 4 | *.lock.json 5 | .vs/ 6 | _ReSharper* 7 | *.suo 8 | *.VC.db 9 | *.vshost.exe 10 | *.manifest 11 | *.sdf 12 | [Bb]in/ 13 | obj/ 14 | Cache/ 15 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Skybox.sdsky: -------------------------------------------------------------------------------- 1 | !SkyboxAsset 2 | Id: 916ddf54-9e2e-4091-a3ba-c84b4ca0a160 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | CubeMap: 9afb3f25-f91f-41c5-b5c8-ede65dc63b3e:Skybox texture 6 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/CustomGame.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Engine; 3 | 4 | namespace ArchECSStride.Code; 5 | public class CustomGame : Game 6 | { 7 | protected override void BeginRun() 8 | { 9 | this.AddArch(Services); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/GamePlay/Data/ResourceType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ArchECSStride.Code.GamePlay.Data; 8 | public enum ResourceType 9 | { 10 | Wood, 11 | Stone 12 | } 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Skybox texture.sdtex: -------------------------------------------------------------------------------- 1 | !Texture 2 | Id: 9afb3f25-f91f-41c5-b5c8-ede65dc63b3e 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Source: !file ../Resources/skybox_texture_hdr.dds 6 | Type: !ColorTextureType 7 | UseSRgbSampling: false 8 | ColorKeyColor: {R: 255, G: 0, B: 255, A: 255} 9 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/GamePlay/Data/AgentJobType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ArchECSStride.Code.GamePlay.Data; 8 | public enum AgentJobType 9 | { 10 | WoodCutter, 11 | Miner, 12 | Builder, 13 | StoneCutter 14 | } 15 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride.Windows/ArchECSStrideApp.cs: -------------------------------------------------------------------------------- 1 | using ArchECSStride.Code; 2 | 3 | namespace ArchECSStride 4 | { 5 | class ArchECSStrideApp 6 | { 7 | static void Main(string[] args) 8 | { 9 | using (var game = new CustomGame()) 10 | { 11 | game.Run(); 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/Module.cs: -------------------------------------------------------------------------------- 1 | using Stride.Core; 2 | using Stride.Core.Reflection; 3 | using System.Reflection; 4 | 5 | namespace Doprez.Stride.Arch; 6 | internal class Module 7 | { 8 | [ModuleInitializer] 9 | public static void Initialize() 10 | { 11 | AssemblyRegistry.Register(typeof(Module).GetTypeInfo().Assembly, AssemblyCommonCategories.Assets); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/ArchGameExtensions.cs: -------------------------------------------------------------------------------- 1 | using Stride.Core; 2 | using Stride.Engine; 3 | 4 | namespace Doprez.Stride.Arch; 5 | public static class ArchGameExtensions 6 | { 7 | public static void AddArch(this Game game, IServiceRegistry services) 8 | { 9 | var scene = services.GetService().SceneInstance; 10 | scene.Processors.Add(new ArchProcessor()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Arch/Components/ArchAgent.cs: -------------------------------------------------------------------------------- 1 | using ArchECSStride.Code.GamePlay.Data; 2 | using Doprez.Stride.Arch; 3 | using Stride.Core; 4 | 5 | namespace ArchECSStride.Code.Arch.Components; 6 | public class ArchAgent : ArchComponent 7 | { 8 | [DataMemberIgnore] 9 | public override object ComponentValue { get; set; } 10 | } 11 | 12 | public struct Agent 13 | { 14 | public AgentJobType CurrentJob; 15 | } -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride.Windows/ArchECSStride.Windows.sdpkg: -------------------------------------------------------------------------------- 1 | !Package 2 | SerializedVersion: {Assets: 3.1.0.0} 3 | Meta: 4 | Name: ArchECSStride.Windows 5 | Version: 1.0.0 6 | Authors: [] 7 | Owners: [] 8 | Dependencies: null 9 | AssetFolders: 10 | - Path: !dir Assets 11 | ResourceFolders: 12 | - !dir Resources 13 | OutputGroupDirectories: {} 14 | ExplicitFolders: [] 15 | Bundles: [] 16 | TemplateFolders: [] 17 | RootAssets: [] 18 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/ArchECSStride.sdpkg: -------------------------------------------------------------------------------- 1 | !Package 2 | SerializedVersion: {Assets: 3.1.0.0} 3 | Meta: 4 | Name: ArchECSStride 5 | Version: 1.0.0 6 | Authors: [] 7 | Owners: [] 8 | Dependencies: null 9 | AssetFolders: 10 | - Path: !dir Assets 11 | - Path: !dir Effects 12 | ResourceFolders: 13 | - !dir Resources 14 | OutputGroupDirectories: {} 15 | ExplicitFolders: [] 16 | Bundles: [] 17 | TemplateFolders: [] 18 | RootAssets: [] 19 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Materials/Leaves.sdmat: -------------------------------------------------------------------------------- 1 | !MaterialAsset 2 | Id: b0afea36-8e25-4096-b26a-ccf956f78fe5 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Attributes: 6 | Diffuse: !MaterialDiffuseMapFeature 7 | DiffuseMap: !ComputeColor 8 | Value: {R: 0.10312499, G: 0.375, B: 0.0, A: 1.0} 9 | DiffuseModel: !MaterialDiffuseLambertModelFeature {} 10 | Overrides: 11 | UVScale: {X: 1.0, Y: 1.0} 12 | Layers: {} 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Materials/Trunk.sdmat: -------------------------------------------------------------------------------- 1 | !MaterialAsset 2 | Id: e6245846-537b-4b1a-957b-6a1d8715e7d4 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Attributes: 6 | Diffuse: !MaterialDiffuseMapFeature 7 | DiffuseMap: !ComputeColor 8 | Value: {R: 0.28125, G: 0.18984376, B: 0.0, A: 1.0} 9 | DiffuseModel: !MaterialDiffuseLambertModelFeature {} 10 | Overrides: 11 | UVScale: {X: 1.0, Y: 1.0} 12 | Layers: {} 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Materials/Grass.sdmat: -------------------------------------------------------------------------------- 1 | !MaterialAsset 2 | Id: 9ca3427a-0cf2-4e19-a441-62cc07113a23 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Attributes: 6 | Diffuse: !MaterialDiffuseMapFeature 7 | DiffuseMap: !ComputeColor 8 | Value: {R: 0.027500004, G: 0.125, B: 0.003124997, A: 1.0} 9 | DiffuseModel: !MaterialDiffuseLambertModelFeature {} 10 | Overrides: 11 | UVScale: {X: 1.0, Y: 1.0} 12 | Layers: {} 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/NPC/Components/ArchNPCAgent.cs: -------------------------------------------------------------------------------- 1 | using ArchECSStride.Code.Arch; 2 | using Doprez.Stride.Arch; 3 | using Stride.Core; 4 | 5 | namespace ArchECSStride.Code.NPC.Components; 6 | public class ArchNPCAgent : ArchComponent 7 | { 8 | [DataMemberIgnore] 9 | public override object ComponentValue { get; set; } = new NPCAgent(); 10 | } 11 | 12 | public struct NPCAgent 13 | { 14 | public ushort CurrentJobId; 15 | public ushort CurrentStateIndex; 16 | } 17 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Sphere.sdpromodel: -------------------------------------------------------------------------------- 1 | !ProceduralModelAsset 2 | Id: 520ca7ca-3463-4346-bce8-b3d84ace5f50 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Type: !SphereProceduralModel 6 | Tessellation: 30 7 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 8 | UvScale: {X: 1.0, Y: 1.0} 9 | LocalOffset: {X: 0.0, Y: 0.0, Z: 0.0} 10 | NumberOfTextureCoordinates: 10 11 | MaterialInstance: 12 | Material: 704cd52a-397b-4451-87d4-9f504e3eabca:Sphere Material 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Cube.sdpromodel: -------------------------------------------------------------------------------- 1 | !ProceduralModelAsset 2 | Id: fa39d881-d536-4e8a-866f-0f9991c5b065 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Type: !CubeProceduralModel 6 | Size: {X: 1.0, Y: 1.0, Z: 1.0} 7 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 8 | UvScale: {X: 1.0, Y: 1.0} 9 | LocalOffset: {X: 0.0, Y: 0.0, Z: 0.0} 10 | NumberOfTextureCoordinates: 10 11 | MaterialInstance: 12 | Material: 704cd52a-397b-4451-87d4-9f504e3eabca:Sphere Material 13 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Ground.sdpromodel: -------------------------------------------------------------------------------- 1 | !ProceduralModelAsset 2 | Id: 56894502-5bbc-4870-8f4a-9bfad3c09d7b 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Type: !PlaneProceduralModel 6 | Size: {X: 10.0, Y: 10.0} 7 | Tessellation: {X: 1, Y: 1} 8 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 9 | UvScale: {X: 1.0, Y: 1.0} 10 | LocalOffset: {X: 0.0, Y: 0.0, Z: 0.0} 11 | NumberOfTextureCoordinates: 10 12 | MaterialInstance: 13 | Material: d8597848-032c-4e1a-879d-ca652ff06eb8:Ground Material 14 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/Components/ArchStrideId.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using System; 4 | 5 | namespace Doprez.Stride.Arch.Components; 6 | /// 7 | /// Gets added automatically if another ArchComponent exists on the same entity. 8 | /// 9 | public class ArchStrideId : ArchComponent 10 | { 11 | [DataMemberIgnore] 12 | public override object ComponentValue { get; set; } = new StrideId(); 13 | } 14 | 15 | public struct StrideId 16 | { 17 | public Guid Id; 18 | } 19 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Resources/Components/Resource.cs: -------------------------------------------------------------------------------- 1 | using ArchECSStride.Code.GamePlay.Data; 2 | using Doprez.Stride.Arch; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ArchECSStride.Code.Resources.Components; 10 | public class ArchResource : ArchComponent 11 | { 12 | public int Amount { get; set; } 13 | public override object ComponentValue { get; set; } = new Resource(); 14 | } 15 | 16 | public struct Resource 17 | { 18 | public ResourceType ResourceType; 19 | public int Amount; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Arch/Components/ArchRotation.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using Stride.Core.Mathematics; 4 | using Stride.Engine; 5 | 6 | namespace ArchECSStride.Code.Arch.Components; 7 | [DataContract(nameof(ArchRotation))] 8 | [ComponentCategory("Arch Components")] 9 | public class ArchRotation : ArchComponent 10 | { 11 | [DataMemberIgnore] 12 | public override object ComponentValue { get; set; } = new Rotation(); 13 | 14 | public override void SetData() 15 | { 16 | ComponentValue = new Rotation(); 17 | } 18 | } 19 | 20 | public struct Rotation 21 | { 22 | public Quaternion CurrentRotation; 23 | } 24 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/NPC/Systems/NPCAgentSystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using ArchECSStride.Code.NPC.Components; 3 | using Doprez.Stride.Arch; 4 | using Stride.Games; 5 | 6 | namespace ArchECSStride.Code.NPC.Systems; 7 | public class NPCAgentSystem : ArchSystem 8 | { 9 | private QueryDescription _queryDescription; 10 | 11 | public override void Start() 12 | { 13 | _queryDescription = new QueryDescription(). 14 | WithAny(); 15 | } 16 | 17 | public override void Update(in GameTime state) 18 | { 19 | World.Query(in _queryDescription, (ref NPCAgent agent) => 20 | { 21 | agent.CurrentJobId = 0; 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Arch/Components/ArchVelocity.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using Stride.Engine; 4 | 5 | namespace ArchECSStride.Code.Arch.Components; 6 | [DataContract(nameof(ArchVelocity))] 7 | [ComponentCategory("Arch Components")] 8 | public class ArchVelocity : ArchComponent 9 | { 10 | public override object ComponentValue { get; set; } = new Velocity(); 11 | 12 | public override void SetData() 13 | { 14 | ComponentValue = new Velocity() 15 | { 16 | X = 0.5f, 17 | Y = 0.5f, 18 | Z = 0.5f 19 | }; 20 | } 21 | } 22 | 23 | public struct Velocity 24 | { 25 | public float X; 26 | public float Y; 27 | public float Z; 28 | } -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Arch/Components/ArchTest.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using Stride.Engine; 4 | 5 | namespace ArchECSStride.Code.Arch.Components; 6 | [DataContract(nameof(ArchTest))] 7 | [ComponentCategory("Arch Components")] 8 | public class ArchTest : ArchComponent 9 | { 10 | public TestComponent StartComponent { get; set; } = new(); 11 | 12 | [DataMemberIgnore] 13 | public override object ComponentValue { get; set; } = new TestComponent(); 14 | 15 | public override void SetData() 16 | { 17 | ComponentValue = StartComponent; 18 | } 19 | } 20 | 21 | [DataContract] 22 | public struct TestComponent 23 | { 24 | public int Number; 25 | public string Text; 26 | } 27 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/ArchComponent.cs: -------------------------------------------------------------------------------- 1 | using Stride.Core; 2 | using Stride.Engine; 3 | 4 | namespace Doprez.Stride.Arch; 5 | /// 6 | /// This is only to provide a way to mark a component as an ArchComponent and serialize it in the Editor. 7 | /// 8 | [DataContract(Inherited = true)] 9 | [ComponentCategory("Arch Components")] 10 | public abstract class ArchComponent : EntityComponent 11 | { 12 | /// 13 | /// Component to add to the Arch entity 14 | /// 15 | [DataMemberIgnore] 16 | public abstract object ComponentValue { get; set; } 17 | 18 | /// 19 | /// Sets data After Strides Entity is created and before it is registered with Arch ECS. 20 | /// 21 | public virtual void SetData() 22 | { 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride.Windows/ArchECSStride.Windows.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0-windows 4 | win-x64 5 | Resources\Icon.ico 6 | WinExe 7 | ArchECSStride 8 | ..\Bin\Windows\$(Configuration)\ 9 | false 10 | 11 | true 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/Configurations/ArchSettings.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using Stride.Data; 4 | using System.Collections.Generic; 5 | 6 | namespace Doprez.Stride.Arch.Configurations; 7 | /// 8 | /// A central place to add Systems to the Arch ECS. 9 | /// 10 | [DataContract] 11 | [Display("Arch Config")] 12 | public class ArchSettings : Configuration 13 | { 14 | public bool AddDefaultRegisterSystem { get; set; } = true; 15 | /// 16 | /// These systems will run sequentially. 17 | /// 18 | public List Systems { get; set; } = new(); 19 | /// 20 | /// These systems with run in parallel with eachother AFTER Systems. 21 | /// 22 | public List ParallelSystems { get; set; } = new(); 23 | } 24 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/InitializeInstanceMesh.cs: -------------------------------------------------------------------------------- 1 | using Stride.Engine; 2 | using System.Linq; 3 | 4 | namespace ArchECSStride.Code; 5 | /// 6 | /// Searches for a instanced component and assigns the value to this Entity. 7 | /// 8 | public class InitializeInstanceMesh : StartupScript 9 | { 10 | public InstanceComponent InstanceComponent { get; set; } 11 | public string InstancedModelName { get; set; } = "InstancedMesh"; 12 | 13 | public override void Start() 14 | { 15 | AddInstanceModel(); 16 | } 17 | 18 | private void AddInstanceModel() 19 | { 20 | var scene = SceneSystem.SceneInstance.RootScene; 21 | var instancingComponent = scene.Entities.Where(x => x.Name == InstancedModelName).FirstOrDefault().Get(); 22 | 23 | InstanceComponent.Master = instancingComponent; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/ArchECSStride.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Models/Tree.sdm3d: -------------------------------------------------------------------------------- 1 | !Model 2 | Id: f95727a0-119f-483a-a9c0-4982e475c438 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Source: !file ../../Resources/Models/Tree.obj 6 | Skeleton: null 7 | PivotPosition: {X: 0.0, Y: 0.0, Z: 0.0} 8 | Materials: 9 | a6cc4976c3466ac00c7f2f2f7be24baf: 10 | Name: DefaultMaterial 11 | MaterialInstance: 12 | Material: null 13 | 1ceb1b6db96b78da69a451eb44e542c9: 14 | Name: Trunk 15 | MaterialInstance: 16 | Material: e6245846-537b-4b1a-957b-6a1d8715e7d4:Materials/Trunk 17 | 9918fd474a85dc614cc37b3edfcc608b: 18 | Name: Leaves 19 | MaterialInstance: 20 | Material: b0afea36-8e25-4096-b26a-ccf956f78fe5:Materials/Leaves 21 | DeduplicateMaterials: false 22 | Modifiers: {} 23 | ~SourceHashes: 24 | 380c674c292ff0174c8129404e939300~../../Resources/Models/Tree.obj: b62071259fe3a31785c0b1284069d115 25 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Arch/Components/ArchPosition.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using Stride.Core.Mathematics; 4 | using Stride.Engine; 5 | 6 | namespace ArchECSStride.Code.Arch.Components; 7 | [DataContract(nameof(ArchPosition))] 8 | [ComponentCategory("Arch Components")] 9 | public class ArchPosition : ArchComponent 10 | { 11 | public bool UseStridePosition { get; set; } = true; 12 | public Position StartPosition { get; set; } 13 | 14 | [DataMemberIgnore] 15 | public override object ComponentValue { get; set; } = new Position(); 16 | 17 | public override void SetData() 18 | { 19 | if (UseStridePosition) 20 | { 21 | var position = new Position() 22 | { 23 | CurrentPosition = Entity.Get().Position 24 | }; 25 | ComponentValue = position; 26 | } 27 | else 28 | { 29 | ComponentValue = StartPosition; 30 | } 31 | } 32 | } 33 | 34 | [DataContract] 35 | public struct Position 36 | { 37 | public Vector3 CurrentPosition; 38 | } 39 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Systems/SpawnPrefabSystem.cs: -------------------------------------------------------------------------------- 1 | using ArchECSStride.Code.Arch; 2 | using Doprez.Stride.Arch; 3 | using Stride.Core; 4 | using Stride.Core.Serialization; 5 | using Stride.Core.Serialization.Contents; 6 | using Stride.Engine; 7 | 8 | namespace ArchECSStride.Code.Systems; 9 | /// 10 | /// A simple system to spawn prefabs on startup. 11 | /// 12 | [DataContract(nameof(SpawnPrefabSystem))] 13 | public class SpawnPrefabSystem : ArchSystem 14 | { 15 | public UrlReference PrefabToSpawn { get; set; } 16 | public int AmountOfPrefabs { get; set; } = 100; 17 | 18 | private ContentManager _contentManager; 19 | 20 | public override void Start() 21 | { 22 | _contentManager = Services.GetService(); 23 | var prefab = _contentManager.Load(PrefabToSpawn.Url); 24 | 25 | for (int i = 0; i < AmountOfPrefabs; i++) 26 | { 27 | var entity = prefab.Instantiate(); 28 | SceneSystem.SceneInstance.RootScene.Entities.Add(entity[0]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/Services/StrideEntityManager.cs: -------------------------------------------------------------------------------- 1 | using Stride.Engine; 2 | 3 | namespace Doprez.Stride.Arch.Services; 4 | public class StrideEntityManager 5 | { 6 | public Dictionary Entities { get; private set; } = new(); 7 | 8 | /// 9 | /// Returns the index of the added entity. 10 | /// 11 | /// 12 | /// 13 | public Guid AddEntity(Entity entity) 14 | { 15 | var newId = Guid.NewGuid(); 16 | Entities.Add(newId, entity); 17 | return newId; 18 | } 19 | 20 | public void RemoveEntity(Guid id) 21 | { 22 | // Need to make sure this does not shift items in the array 23 | Entities.Remove(id); 24 | } 25 | 26 | public Guid GetEntityId(Entity entity) 27 | { 28 | foreach (var item in Entities) 29 | { 30 | if (item.Value == entity) return item.Key; 31 | } 32 | 33 | return Guid.Empty; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Ground Material.sdmat: -------------------------------------------------------------------------------- 1 | !MaterialAsset 2 | Id: d8597848-032c-4e1a-879d-ca652ff06eb8 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Attributes: 6 | MicroSurface: !MaterialGlossinessMapFeature 7 | GlossinessMap: !ComputeFloat 8 | Value: 0.1 9 | Diffuse: !MaterialDiffuseMapFeature 10 | DiffuseMap: !ComputeColor 11 | Value: {R: 0.14117648, G: 0.14117648, B: 0.14117648, A: 1.0} 12 | DiffuseModel: !MaterialDiffuseLambertModelFeature {} 13 | Specular: !MaterialMetalnessMapFeature 14 | MetalnessMap: !ComputeFloat 15 | Value: 0.0 16 | SpecularModel: !MaterialSpecularMicrofacetModelFeature 17 | Fresnel: !MaterialSpecularMicrofacetFresnelSchlick {} 18 | Visibility: !MaterialSpecularMicrofacetVisibilitySmithSchlickGGX {} 19 | NormalDistribution: !MaterialSpecularMicrofacetNormalDistributionGGX {} 20 | Environment: !MaterialSpecularMicrofacetEnvironmentGGXLUT {} 21 | Overrides: 22 | UVScale: {X: 1.0, Y: 1.0} 23 | Layers: {} 24 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/Sphere Material.sdmat: -------------------------------------------------------------------------------- 1 | !MaterialAsset 2 | Id: 704cd52a-397b-4451-87d4-9f504e3eabca 3 | SerializedVersion: {Stride: 2.0.0.0} 4 | Tags: [] 5 | Attributes: 6 | MicroSurface: !MaterialGlossinessMapFeature 7 | GlossinessMap: !ComputeFloat 8 | Value: 0.65 9 | Diffuse: !MaterialDiffuseMapFeature 10 | DiffuseMap: !ComputeColor 11 | Value: {R: 0.54901963, G: 0.54901963, B: 0.54901963, A: 1.0} 12 | DiffuseModel: !MaterialDiffuseLambertModelFeature {} 13 | Specular: !MaterialMetalnessMapFeature 14 | MetalnessMap: !ComputeFloat 15 | Value: 1.0 16 | SpecularModel: !MaterialSpecularMicrofacetModelFeature 17 | Fresnel: !MaterialSpecularMicrofacetFresnelSchlick {} 18 | Visibility: !MaterialSpecularMicrofacetVisibilitySmithSchlickGGX {} 19 | NormalDistribution: !MaterialSpecularMicrofacetNormalDistributionGGX {} 20 | Environment: !MaterialSpecularMicrofacetEnvironmentGGXLUT {} 21 | Overrides: 22 | UVScale: {X: 1.0, Y: 1.0} 23 | Layers: {} 24 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Extensions/EntityExtensions.cs: -------------------------------------------------------------------------------- 1 | using Stride.Engine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Stride.Engine; 9 | public static class EntityExtensions 10 | { 11 | /// 12 | /// Gets all components of type T 13 | /// 14 | /// 15 | /// 16 | /// 17 | public static IEnumerable GetComponents(this Entity entity) 18 | { 19 | foreach (var entityComponent in entity) 20 | { 21 | if (entityComponent is T t) 22 | yield return t; 23 | } 24 | } 25 | 26 | /// 27 | /// Allows finding components of any type. 28 | /// 29 | /// 30 | /// 31 | /// 32 | public static T GetComponent(this Entity entity) 33 | { 34 | foreach (var entityComponent in entity) 35 | { 36 | if (entityComponent is T t) 37 | return t; 38 | } 39 | 40 | return default; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Doprez 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. 22 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Arch/Components/ArchPathfinder.cs: -------------------------------------------------------------------------------- 1 | using Doprez.Stride.Arch; 2 | using Stride.Core; 3 | using Stride.Core.Mathematics; 4 | using Stride.Engine; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace ArchECSStride.Code.Arch.Components; 12 | [DataContract(nameof(ArchPathfinder))] 13 | [ComponentCategory("Arch Components")] 14 | public class ArchPathfinder : ArchComponent 15 | { 16 | 17 | [DataMemberIgnore] 18 | public override object ComponentValue { get; set; } = new Pathfinder(); 19 | 20 | public override void SetData() 21 | { 22 | ComponentValue = new Pathfinder(); 23 | } 24 | } 25 | 26 | public struct Pathfinder 27 | { 28 | public Vector3 Target; 29 | public bool SetNewPath; 30 | // I think this ruins the benefit of a struct but I dont have an alternative atm. 31 | public List Path = new(); 32 | public bool ShouldMove; 33 | public float Speed = 5; 34 | 35 | public Pathfinder() 36 | { 37 | SetNewPath = false; 38 | Target = Vector3.Zero; 39 | ShouldMove = false; 40 | } 41 | } -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Systems/TestSystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using Doprez.Stride.Arch; 3 | using Doprez.Stride.Arch.Components; 4 | using Stride.Core; 5 | using Stride.Core.Mathematics; 6 | using Stride.Games; 7 | using Stride.Profiling; 8 | 9 | namespace ArchECSStride.Code.Systems; 10 | /// 11 | /// So far this test class turned into basic logging of entity count and FPS. 12 | /// 13 | [DataContract(nameof(TestSystem))] 14 | public class TestSystem : ArchSystem 15 | { 16 | private DebugTextSystem _debugText; 17 | private QueryDescription _queryDescription; 18 | private IGame _game; 19 | 20 | public override void Start() 21 | { 22 | _debugText = Services.GetService(); 23 | _game = Services.GetSafeServiceAs(); 24 | 25 | _queryDescription = new QueryDescription(). 26 | WithAny(); 27 | } 28 | 29 | public override void Update(in GameTime state) 30 | { 31 | var result = World.CountEntities(in _queryDescription); 32 | 33 | _debugText.Print($"Entities: {result} \nFPS: {_game.UpdateTime.FramePerSecond} \nUpdate Time: {state.TimePerFrame.TotalMilliseconds}", new Int2(50, 50)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Systems/MoveEntitySystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using ArchECSStride.Code.Arch.Components; 3 | using Doprez.Stride.Arch; 4 | using Stride.Core; 5 | using Stride.Core.Mathematics; 6 | using Stride.Games; 7 | using System; 8 | 9 | namespace ArchECSStride.Code.Systems; 10 | /// 11 | /// Randomly moves entities in both the Arch world and the Stride scene. 12 | /// 13 | [DataContract(nameof(MoveEntitySystem))] 14 | public class MoveEntitySystem : ArchSystem 15 | { 16 | private QueryDescription _queryDescription; 17 | private Random _random = new(); 18 | 19 | public override void Start() 20 | { 21 | _queryDescription = new QueryDescription(). 22 | WithAny(); 23 | } 24 | 25 | public override void Update(in GameTime state) 26 | { 27 | World.Query(in _queryDescription, (ref Pathfinder pathfinder, ref Position position) => 28 | { 29 | if (Vector3.Distance(pathfinder.Target, position.CurrentPosition) <= 2 || pathfinder.Path.Count == 0) 30 | { 31 | pathfinder.Target.Z = _random.Next(-100, 100); 32 | pathfinder.Target.X = _random.Next(-100, 100); 33 | pathfinder.SetNewPath = true; 34 | pathfinder.ShouldMove = true; 35 | } 36 | else 37 | { 38 | pathfinder.SetNewPath = false; 39 | } 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/Doprez.Stride.Arch.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | README.md 8 | ..\..\..\LICENSE 9 | 1.0.0.1 10 | LICENSE 11 | Doprez.Stride.Arch 12 | A package of helper classes for using Arch ECS in Stride3D 13 | Stride3d;Game Engine;Stride;Arch;ECS;Arch ECS; 14 | https://github.com/Doprez/stride-arch-ecs 15 | 16 | 17 | 18 | 19 | True 20 | \ 21 | 22 | 23 | True 24 | \ 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Use the latest 2.1 version of CircleCI pipeline process engine. 2 | # See: https://circleci.com/docs/2.0/configuration-reference 3 | version: 2.1 4 | 5 | # Define a job to be invoked later in a workflow. 6 | # See: https://circleci.com/docs/2.0/configuration-reference/#jobs 7 | jobs: 8 | dotnet-commands: 9 | # Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. 10 | # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor 11 | docker: 12 | - image: mcr.microsoft.com/dotnet/sdk:8.0 13 | steps: 14 | - checkout 15 | - run: 16 | name: Restore 17 | command: dotnet restore .\\Source\\ArchECSStride\\Doprez.Stride.Arch\\Doprez.Stride.Arch.csproj 18 | - run: 19 | name: Build 20 | command: dotnet build .\\Source\\ArchECSStride\\Doprez.Stride.Arch\\Doprez.Stride.Arch.csproj 21 | - run: 22 | name: Package 23 | command: dotnet pack .\\Source\\ArchECSStride\\Doprez.Stride.Arch\\Doprez.Stride.Arch.csproj -o ./App 24 | - run: 25 | name: Publish 26 | command: cd App && ls && dotnet nuget push Doprez.Stride.*.nupkg --api-key $NUGET_KEY --source https://api.nuget.org/v3/index.json 27 | 28 | # Invoke jobs via workflows 29 | # See: https://circleci.com/docs/2.0/configuration-reference/#workflows 30 | workflows: 31 | run-jobs-workflow: 32 | jobs: 33 | - dotnet-commands: 34 | filters: 35 | branches: 36 | only: 37 | - release -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/ArchSystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using Stride.Core; 3 | using Stride.Engine; 4 | using Stride.Games; 5 | 6 | namespace Doprez.Stride.Arch; 7 | /// 8 | /// This is the base class for all Systems in the Arch ECS. Can be added throught the GameSettings asset. 9 | /// 10 | [DataContract] 11 | public abstract class ArchSystem 12 | { 13 | 14 | /// 15 | /// The for which this system works and must access. 16 | /// 17 | [DataMemberIgnore] 18 | public World World { get; private set; } 19 | /// 20 | /// Gives systems direct access to registered Services in Stride. 21 | /// 22 | [DataMemberIgnore] 23 | public IServiceRegistry Services { get; private set; } 24 | [DataMemberIgnore] 25 | public SceneSystem SceneSystem { get; private set; } 26 | 27 | /// 28 | /// Constructor parameters must be empty for Stride to be able to serialize them, this is a work around. 29 | /// 30 | /// 31 | /// 32 | public void InitializeSystem(World world, IServiceRegistry services, SceneSystem sceneSystem) 33 | { 34 | World = world; 35 | Services = services; 36 | SceneSystem = sceneSystem; 37 | } 38 | 39 | /// 40 | /// Called after all Systems have been initialized. 41 | /// 42 | public virtual void Start() { } 43 | 44 | /// 45 | /// Should be called within the update loop to update this system and execute its logic. 46 | /// 47 | /// A external state being passed to this method to be used. 48 | public virtual void Update(in GameTime state) { } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34031.279 5 | MinimumVisualStudioVersion = 16.0.0.0 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchECSStride.Windows", "ArchECSStride.Windows\ArchECSStride.Windows.csproj", "{6590A0C0-5F7E-4965-B453-A3C1487036A5}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchECSStride", "ArchECSStride\ArchECSStride.csproj", "{DC01CC0A-B8B2-4501-A8B2-F0165E978C0D}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Doprez.Stride.Arch", "Doprez.Stride.Arch\Doprez.Stride.Arch.csproj", "{B174721B-80B9-47CE-B661-3E448742F643}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {6590A0C0-5F7E-4965-B453-A3C1487036A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {6590A0C0-5F7E-4965-B453-A3C1487036A5}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {6590A0C0-5F7E-4965-B453-A3C1487036A5}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {6590A0C0-5F7E-4965-B453-A3C1487036A5}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {DC01CC0A-B8B2-4501-A8B2-F0165E978C0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {DC01CC0A-B8B2-4501-A8B2-F0165E978C0D}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {DC01CC0A-B8B2-4501-A8B2-F0165E978C0D}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {DC01CC0A-B8B2-4501-A8B2-F0165E978C0D}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {B174721B-80B9-47CE-B661-3E448742F643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {B174721B-80B9-47CE-B661-3E448742F643}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {B174721B-80B9-47CE-B661-3E448742F643}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {B174721B-80B9-47CE-B661-3E448742F643}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {46D4B5D8-7186-4C50-BAF4-3DC46D38C0FF} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Systems/UpdateStridePositionsSystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using ArchECSStride.Code.Arch; 3 | using ArchECSStride.Code.Arch.Components; 4 | using Doprez.Stride.Arch; 5 | using Doprez.Stride.Arch.Components; 6 | using Doprez.Stride.Arch.Services; 7 | using Stride.Core; 8 | using Stride.Core.Threading; 9 | using Stride.Games; 10 | using System; 11 | using System.Runtime.CompilerServices; 12 | 13 | namespace ArchECSStride.Code.Systems; 14 | /// 15 | /// Syncs Arch world positions to Strides Positions. 16 | /// 17 | [DataContract(nameof(UpdateStridePositionsSystem))] 18 | public class UpdateStridePositionsSystem : ArchSystem 19 | { 20 | private StrideEntityManager _entityManager; 21 | private QueryDescription _queryDescription; 22 | 23 | public override void Start() 24 | { 25 | _entityManager = Services.GetService(); 26 | 27 | _queryDescription = new QueryDescription(). 28 | WithAny(); 29 | } 30 | 31 | public override void Update(in GameTime state) 32 | { 33 | World.Query(in _queryDescription, (ref StrideId strideId, ref Position position, ref Rotation rotation) => 34 | { 35 | _entityManager.Entities[strideId.Id].Transform.Position = position.CurrentPosition; 36 | _entityManager.Entities[strideId.Id].Transform.Rotation = rotation.CurrentRotation; 37 | }); 38 | 39 | //var testQuery = World.Query(in _queryDescription); 40 | // this works but is slower due to needing to use chunk.GetFirst AND 41 | // the chunk size being limited to 166 Entities per chunk. 42 | //foreach(var chunk in testQuery.GetChunkIterator()) 43 | //{ 44 | // Dispatcher.For(0, chunk.Entities.Length, j => 45 | // { 46 | // var reference = chunk.GetFirst(); 47 | // 48 | // ref var strideId = ref Unsafe.Add(ref reference.t0, j); 49 | // ref var position = ref Unsafe.Add(ref reference.t1, j); 50 | // ref var rotation = ref Unsafe.Add(ref reference.t2, j); 51 | // 52 | // // strideId is not initialized on startup 53 | // if (strideId.Id == Guid.Empty) return; 54 | // _entityManager.Entities[strideId.Id].Transform.Position = position.CurrentPosition; 55 | // _entityManager.Entities[strideId.Id].Transform.Rotation = rotation.CurrentRotation; 56 | // }); 57 | //} 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/GameSettings.sdgamesettings: -------------------------------------------------------------------------------- 1 | !GameSettingsAsset 2 | Id: 468c7d27-722c-4f98-949d-77f59a7653f0 3 | SerializedVersion: {Stride: 3.1.0.1} 4 | Tags: [] 5 | DefaultScene: 7499ad3b-a805-4fba-a68b-816d8f34fb0a:MainScene 6 | GraphicsCompositor: 72aeddc1-0a25-4778-9aef-dc2cdf48f7eb:GraphicsCompositor 7 | Defaults: 8 | - !Stride.Audio.AudioEngineSettings,Stride.Audio 9 | HrtfSupport: false 10 | - !Stride.Assets.EditorSettings,Stride.Assets 11 | RenderingMode: HDR 12 | - !Stride.Graphics.RenderingSettings,Stride.Graphics 13 | DefaultBackBufferWidth: 1280 14 | DefaultBackBufferHeight: 720 15 | AdaptBackBufferToScreen: false 16 | DefaultGraphicsProfile: Level_11_0 17 | ColorSpace: Linear 18 | DisplayOrientation: LandscapeRight 19 | - !Stride.Streaming.StreamingSettings,Stride.Rendering 20 | ManagerUpdatesInterval: 0:00:00:00.0330000 21 | ResourceLiveTimeout: 0:00:00:08.0000000 22 | - !Stride.Assets.Textures.TextureSettings,Stride.Assets 23 | TextureQuality: Fast 24 | - !Stride.Navigation.NavigationSettings,Stride.Navigation 25 | EnableDynamicNavigationMesh: true 26 | IncludedCollisionGroups: StaticFilter 27 | BuildSettings: 28 | CellHeight: 0.2 29 | CellSize: 0.3 30 | TileSize: 32 31 | MinRegionArea: 2 32 | RegionMergeArea: 20 33 | MaxEdgeLen: 12.0 34 | MaxEdgeError: 1.3 35 | DetailSamplingDistance: 6.0 36 | MaxDetailSamplingError: 1.0 37 | Groups: 38 | - Id: c2a2522c-db2c-4d56-b3b7-3aecaacd69af 39 | Name: Human 40 | AgentSettings: 41 | Height: 1.0 42 | MaxClimb: 0.25 43 | MaxSlope: {Radians: 0.7853982} 44 | Radius: 0.5 45 | - !Doprez.Stride.Arch.Configurations.ArchSettings,Doprez.Stride.Arch 46 | AddDefaultRegisterSystem: true 47 | Systems: 48 | - !SpawnPrefabSystem 49 | PrefabToSpawn: 959d605f-86f3-4b2a-9b23-2f73827ed793:CubePrefab 50 | AmountOfPrefabs: 20000 51 | - !UpdateStridePositionsSystem {} 52 | - !MoveEntitySystem {} 53 | - !PathfindingSystem {} 54 | ParallelSystems: [] 55 | Overrides: [] 56 | PlatformFilters: 57 | - PowerVR SGX 54[0-9] 58 | - Adreno \(TM\) 2[0-9][0-9] 59 | - Adreno (TM) 320 60 | - Adreno (TM) 330 61 | - Adreno \(TM\) 4[0-9][0-9] 62 | - NVIDIA Tegra 63 | - Intel(R) HD Graphics 64 | - ^Mali\-4 65 | - ^Mali\-T6 66 | - ^Mali\-T7 67 | SplashScreenTexture: d26edb11-10bd-403c-b3c2-9c7fcccf25e5:StrideDefaultSplashScreen 68 | SplashScreenColor: {R: 0, G: 0, B: 0, A: 255} 69 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/CubePrefab.sdprefab: -------------------------------------------------------------------------------- 1 | !PrefabAsset 2 | Id: 959d605f-86f3-4b2a-9b23-2f73827ed793 3 | SerializedVersion: {Stride: 3.1.0.1} 4 | Tags: [] 5 | Hierarchy: 6 | RootParts: 7 | - ref!! 8f866237-62cc-442a-a8f0-db61b40bbeb0 8 | Parts: 9 | - Entity: 10 | Id: 66a8b642-665d-4275-95e9-2e75eb62c62e 11 | Name: Model 12 | Components: 13 | 44f3171db58af19268a82685c86c32f5: !TransformComponent 14 | Id: c92f2328-8232-4782-abfb-791710993cb2 15 | Position: {X: 0.0, Y: 0.0, Z: 0.0} 16 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 17 | Scale: {X: 0.5, Y: 1.5, Z: 0.5} 18 | Children: {} 19 | 5d0230f756858c8d1494106acb82b18c: !ArchECSStride.Code.InitializeInstanceMesh,ArchECSStride 20 | Id: df682724-3e9d-40c9-9988-143330653b47 21 | InstanceComponent: ref!! 9d29f026-ecdb-4988-832d-7fd7592ddfb9 22 | InstancedModelName: InstancedMesh 23 | db01affb43ced9c5e2f26681e3709082: !InstanceComponent 24 | Id: 9d29f026-ecdb-4988-832d-7fd7592ddfb9 25 | Master: null 26 | - Entity: 27 | Id: 8f866237-62cc-442a-a8f0-db61b40bbeb0 28 | Name: Cube 29 | Components: 30 | e6e08d57d7e41e39d45a3395949668ca: !TransformComponent 31 | Id: 35ec7929-3048-4db4-9a7a-8cfd752865e9 32 | Position: {X: 0.0, Y: 0.5, Z: 0.0} 33 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 34 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 35 | Children: 36 | dcd7b6b383456adb16b4842bb731fef9: ref!! c92f2328-8232-4782-abfb-791710993cb2 37 | ced613a7872156e2a011a0c09bd9a974: !ArchPosition 38 | Id: 45e5ab48-6183-48d5-a92b-10eb399c7515 39 | UseStridePosition: true 40 | StartPosition: 41 | CurrentPosition: {X: 0.0, Y: 0.0, Z: 0.0} 42 | 6d913b7d4eb3808de72a6d4b9f2e2c05: !ArchRotation 43 | Id: e1fced99-2ddb-4773-8170-d2b536f61648 44 | 618ba3cd639bde89e91dfbf8d1eae3e0: !ArchVelocity 45 | Id: 8e63cfb1-8243-44a0-bf2b-356f93757648 46 | ComponentValue: !ArchECSStride.Code.Arch.Components.Velocity,ArchECSStride 47 | X: 0.0 48 | Y: 0.0 49 | Z: 0.0 50 | d92a3b021d0dc38cd7a19a1cb72d8e2a: !ArchPathfinder 51 | Id: fb8339a1-fa08-436b-b0d1-7a41ca776419 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # stride-arch-ecs 2 | An example in [Stride](https://github.com/stride3d/stride) using [Arch ECS](https://github.com/genaray/Arch). 3 | 4 | [![CircleCI](https://dl.circleci.com/status-badge/img/gh/Doprez/stride-arch-ecs/tree/release.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/Doprez/stride-arch-ecs/tree/release) 5 | 6 | # Features 7 | ## Ease of use 8 | Systems can be added through the GameSettings class in the Stride editor for easy management. 9 | ![image](https://github.com/Doprez/stride-arch-ecs/assets/73259914/4840313e-42b5-499e-9ba2-06cb18d77953) 10 | 11 | all that you need to do is inherit from the SystemBase class and add it to the list. 12 | 13 | ### Add Arch components in Strides Editor! 14 | ![image](https://github.com/Doprez/stride-arch-ecs/assets/73259914/03796e5c-4e38-4ff5-8fde-cc2fd813dcfd) 15 | 16 | each component attached will create an Entity in the Arch world, with the correct components to be able to be queried later in any systems. 17 | Example: 18 | - System: 19 | ``` 20 | namespace ArchECSStride.Code.Systems; 21 | [DataContract(nameof(TestSystem))] 22 | public class TestSystem : SystemBase 23 | { 24 | private DebugTextSystem _debugText; 25 | private QueryDescription _queryDescription; 26 | 27 | public override void Start() 28 | { 29 | _debugText = Services.GetService(); 30 | 31 | _queryDescription = new QueryDescription(). 32 | WithAny(); 33 | } 34 | 35 | public override void Update(in GameTime state) 36 | { 37 | var result = World.CountEntities(in _queryDescription); 38 | 39 | _debugText.Print($"TestSystem: {result}", new Int2(50, 50)); 40 | } 41 | } 42 | ``` 43 | - Components: 44 | ``` 45 | [DataContract(nameof(ArchPosition))] 46 | [ComponentCategory("Arch Components")] 47 | public class ArchPosition : ArchComponent 48 | { 49 | public bool UseStridePosition { get; set; } = true; 50 | public Vector3 StartPosition { get; set; } 51 | 52 | [DataMemberIgnore] 53 | public override object ComponentValue { get; set; } = new Vector3(); 54 | 55 | public override void SetData() 56 | { 57 | if (UseStridePosition) 58 | { 59 | ComponentValue = Entity.Transform.Position; 60 | } 61 | else 62 | { 63 | ComponentValue = StartPosition; 64 | } 65 | } 66 | } 67 | ``` 68 | ``` 69 | [DataContract(nameof(ArchTest))] 70 | [ComponentCategory("Arch Components")] 71 | public class ArchTest : ArchComponent 72 | { 73 | [DataMemberIgnore] 74 | public override object ComponentValue { get; set; } = new TestComponent(); 75 | } 76 | public struct TestComponent 77 | { 78 | public int Number; 79 | public string Text; 80 | } 81 | ``` 82 | 83 | 84 | ## Easy access 85 | When inheriting from SystemBase and registered in settings each System has access to both the Arch World and Strides Service registry. 86 | 87 | # Future goals 88 | - ~Allow EntityComponents to create Arch Entities with Arch Components (Partially done. I would like to have editable values in editor as well)~ Done! 89 | - Have an easy way to modify Stride entities with a quick access array reference.(Mostly done. I need a way to verify removing entities wont cause issues.) 90 | - Multithreading 91 | - create a basic game/demo example 92 | 93 | # Example 94 | Below is an example of 50,000 entities randomly changing positions at a capped 144FPS. 95 | ![image](https://github.com/Doprez/stride-arch-ecs/assets/73259914/3932095e-d6ef-4733-8b2d-2f626f8dcf7b) 96 | 97 | The only Stride performance improvement used are instanced meshes since meshes are my current big limitation. 98 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/Systems/DefaultEntityRegisterSystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core.Utils; 2 | using StrideEntity = Stride.Engine.Entity; 3 | using ArchEntity = Arch.Core.Entity; 4 | using Arch.Core.Extensions; 5 | using Stride.Engine; 6 | using Doprez.Stride.Arch.Components; 7 | using Doprez.Stride.Arch.Services; 8 | using Arch.Core; 9 | 10 | namespace Doprez.Stride.Arch.Systems; 11 | /// 12 | /// A system that registers Stride entities with Arch ECS when they are created at runtime. 13 | /// 14 | public class DefaultEntityRegisterSystem : ArchSystem 15 | { 16 | private StrideEntityManager _strideEntityManager; 17 | private QueryDescription _query; 18 | 19 | public override void Start() 20 | { 21 | _strideEntityManager = Services.GetService(); 22 | 23 | _query = new QueryDescription().WithAny(); 24 | 25 | SceneSystem.SceneInstance.EntityAdded += SceneInstance_EntityAdded; 26 | SceneSystem.SceneInstance.EntityRemoved += SceneInstance_EntityRemoved; 27 | } 28 | 29 | // TODO This doesnt work and would be very slow even if it did. 30 | private void SceneInstance_EntityRemoved(object sender, StrideEntity e) 31 | { 32 | if (e.Get() == null) return; 33 | 34 | var id = _strideEntityManager.GetEntityId(e); 35 | 36 | ArchEntity entityToDestroy = new(); 37 | bool found = false; 38 | World.Query(in _query, (ref ArchEntity entity, ref StrideId strideId) => 39 | { 40 | if (strideId.Id == id) 41 | { 42 | entityToDestroy = entity; 43 | found = true; 44 | } 45 | }); 46 | 47 | // Remove from Arch ECS 48 | //if(found) 49 | // World.Destroy(entityToDestroy); 50 | // Unregister from Entity Manager 51 | _strideEntityManager.RemoveEntity(id); 52 | } 53 | 54 | private void SceneInstance_EntityAdded(object sender, StrideEntity e) 55 | { 56 | if (e.Get() == null) return; 57 | 58 | //register to Entity Manager 59 | ArchStrideId id = new(); 60 | StrideId strideId = new() 61 | { 62 | Id = _strideEntityManager.AddEntity(e) 63 | }; 64 | id.ComponentValue = strideId; 65 | e.Add(id); 66 | 67 | 68 | List archComponents = new(); 69 | var components = e.GetAll(); 70 | foreach (var component in components) 71 | { 72 | component.SetData(); 73 | archComponents.Add(component.ComponentValue); 74 | } 75 | CreateFromArray(archComponents.ToArray()); 76 | } 77 | 78 | public ArchEntity CreateFromArray(object[] components) 79 | { 80 | ComponentType[] types = GetComponentTypesForArchetype(components); 81 | ArchEntity entity = World.Create(types); 82 | SetFromArray(entity, components); 83 | return entity; 84 | } 85 | 86 | public void SetFromArray(ArchEntity entity, object[] components) 87 | { 88 | entity.SetRange(components); 89 | } 90 | 91 | private ComponentType[] GetComponentTypesForArchetype(object[] components) 92 | { 93 | ComponentType[] types = new ComponentType[components.Length]; 94 | for (int i = 0; i < components.Length; i++) 95 | { 96 | ComponentType type; 97 | if (!ComponentRegistry.TryGet(components[i].GetType(), out type)) 98 | { 99 | type = ComponentRegistry.Add(components[i].GetType()); 100 | } 101 | types[i] = type; 102 | } 103 | return types; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Code/Systems/PathfindingSystem.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using ArchECSStride.Code.Arch.Components; 3 | using Doprez.Stride.Arch; 4 | using Doprez.Stride.Arch.Services; 5 | using Stride.Core; 6 | using Stride.Core.Mathematics; 7 | using Stride.Engine; 8 | using Stride.Engine.Design; 9 | using Stride.Games; 10 | using Stride.Navigation; 11 | using System; 12 | using System.Linq; 13 | 14 | namespace ArchECSStride.Code.Systems; 15 | 16 | /// 17 | /// Requires a NavigationComponent Entity within the Stride scene. 18 | /// 19 | [DataContract(nameof(PathfindingSystem))] 20 | public class PathfindingSystem : ArchSystem 21 | { 22 | 23 | private StrideEntityManager _entityManager; 24 | private QueryDescription _queryDescription; 25 | private IGame _game; 26 | private SceneSystem _sceneSystem; 27 | private NavigationComponent _navigationComponent; 28 | private GameSettings _gameSettings; 29 | 30 | public override void Start() 31 | { 32 | _entityManager = Services.GetService(); 33 | _game = Services.GetSafeServiceAs(); 34 | _sceneSystem = Services.GetSafeServiceAs(); 35 | _gameSettings = Services.GetService()?.Settings; 36 | 37 | var navSettings = _gameSettings.Configurations.Get(); 38 | 39 | _queryDescription = new QueryDescription(). 40 | WithAny(); 41 | 42 | SetupNavigationComponent(); 43 | } 44 | 45 | public override void Update(in GameTime state) 46 | { 47 | var deltaTime = (float)state.Elapsed.TotalSeconds; 48 | 49 | World.Query(in _queryDescription, (ref Pathfinder pathfinder, ref Position position, ref Rotation rotation) => 50 | { 51 | if(pathfinder.SetNewPath) 52 | { 53 | SetNewPath(ref pathfinder, ref position, ref _navigationComponent); 54 | } 55 | if(pathfinder.ShouldMove) 56 | { 57 | Move(ref pathfinder, ref position, ref deltaTime); 58 | Rotate(ref pathfinder, ref position, ref rotation); 59 | } 60 | }); 61 | } 62 | 63 | private void SetupNavigationComponent() 64 | { 65 | var navComponent =_sceneSystem.SceneInstance.RootScene.Entities.FirstOrDefault(x => x.Name == "ProcessorComponents") 66 | .Get(); 67 | 68 | _navigationComponent = navComponent; 69 | } 70 | 71 | private static void SetNewPath(ref Pathfinder pathfinder, ref Position position, ref NavigationComponent navigationComponent) 72 | { 73 | navigationComponent.TryFindPath(position.CurrentPosition, pathfinder.Target, pathfinder.Path); 74 | } 75 | 76 | private static void Move(ref Pathfinder pathfinder, ref Position position, ref float deltaTime) 77 | { 78 | if (pathfinder.Path.Count == 0) 79 | { 80 | pathfinder.SetNewPath = true; 81 | return; 82 | } 83 | 84 | var nextWaypointPosition = pathfinder.Path[0]; 85 | var distanceToWaypoint = Vector3.Distance(position.CurrentPosition, nextWaypointPosition); 86 | 87 | // When the distance between the character and the next waypoint is large enough, move closer to the waypoint 88 | if (distanceToWaypoint > 0.1) 89 | { 90 | var direction = nextWaypointPosition - position.CurrentPosition; 91 | direction.Normalize(); 92 | direction *= pathfinder.Speed * deltaTime; 93 | 94 | position.CurrentPosition += direction; 95 | } 96 | else 97 | { 98 | if (pathfinder.Path.Count > 0) 99 | { 100 | // need to test if storing the index in Pathfinder would be faster than this. 101 | pathfinder.Path.RemoveAt(0); 102 | } 103 | } 104 | } 105 | 106 | public static void Rotate(ref Pathfinder pathfinder, ref Position position, ref Rotation rotation) 107 | { 108 | if (pathfinder.Path.Count == 0) 109 | { 110 | return; 111 | } 112 | 113 | float angle = (float)Math.Atan2(pathfinder.Target.Z - position.CurrentPosition.Z, 114 | pathfinder.Target.X - position.CurrentPosition.X); 115 | 116 | rotation.CurrentRotation = Quaternion.RotationY(-angle); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Source/ArchECSStride/Doprez.Stride.Arch/ArchProcessor.cs: -------------------------------------------------------------------------------- 1 | using Arch.Core; 2 | using Arch.Core.Extensions; 3 | using Arch.Core.Utils; 4 | using Doprez.Stride.Arch.Components; 5 | using Doprez.Stride.Arch.Configurations; 6 | using Doprez.Stride.Arch.Services; 7 | using Doprez.Stride.Arch.Systems; 8 | using Stride.Core.Threading; 9 | using Stride.Engine; 10 | using Stride.Engine.Design; 11 | using Stride.Games; 12 | using System.Collections.Generic; 13 | using ArchEntity = Arch.Core.Entity; 14 | using StrideEntity = Stride.Engine.Entity; 15 | 16 | namespace Doprez.Stride.Arch; 17 | /// 18 | /// The main processor for Arch ECS. That gets added when its registered in the class. 19 | /// 20 | public class ArchProcessor : EntityProcessor 21 | { 22 | private World _world; 23 | private ArchSettings _archSettings; 24 | private StrideEntityManager _strideEntityManager = new(); 25 | private GameSettings _gameSettings; 26 | private SceneSystem _sceneSystem; 27 | 28 | public ArchProcessor() 29 | { 30 | Order = 50000; 31 | } 32 | 33 | protected override void OnSystemAdd() 34 | { 35 | // get base Stride systems 36 | _gameSettings = Services.GetService().Settings; 37 | _sceneSystem = Services.GetService(); 38 | 39 | _world = World.Create(); 40 | _archSettings = _gameSettings.Configurations.Get(); 41 | 42 | // Register the world as a service so that it can be accessed by Stride systems. 43 | Services.AddService(_world); 44 | // This service will be used to quickly access Entities from Stride with the stored id in Arch Entities 45 | Services.AddService(_strideEntityManager); 46 | 47 | if (_archSettings.AddDefaultRegisterSystem) 48 | { 49 | var registerSystem = new DefaultEntityRegisterSystem(); 50 | _archSettings.Systems.Add(registerSystem); 51 | registerSystem.InitializeSystem(_world, Services, _sceneSystem); 52 | registerSystem.Start(); 53 | } 54 | 55 | // EntityRegisterSystem is run before this, causing some issues. 56 | // Register entities at startup 57 | foreach (var entity in _sceneSystem.SceneInstance.RootScene.Entities) 58 | { 59 | RegisterEntity(entity); 60 | } 61 | 62 | // Since I want to register settings through Stride the constructors can't have parameters. 63 | // So I have to initialize them here. 64 | foreach (var archSystem in _archSettings.Systems) 65 | { 66 | archSystem.InitializeSystem(_world, Services, _sceneSystem); 67 | } 68 | 69 | foreach (var archSystem in _archSettings.Systems) 70 | { 71 | archSystem.Start(); 72 | } 73 | } 74 | 75 | public override void Update(GameTime time) 76 | { 77 | for (int i = 0; i < _archSettings.Systems.Count; i++) 78 | { 79 | _archSettings.Systems[i].Update(in time); 80 | } 81 | 82 | Dispatcher.For(0, _archSettings.ParallelSystems.Count, i => 83 | { 84 | _archSettings.ParallelSystems[i].Update(in time); 85 | }); 86 | } 87 | 88 | private void RegisterEntity(StrideEntity entity) 89 | { 90 | if (entity.Get() == null) return; 91 | 92 | //register to Entity Manager 93 | ArchStrideId id = new(); 94 | StrideId strideId = new() 95 | { 96 | Id = _strideEntityManager.AddEntity(entity) 97 | }; 98 | id.ComponentValue = strideId; 99 | entity.Add(id); 100 | 101 | List archComponents = new(); 102 | var components = entity.GetAll(); 103 | 104 | foreach (var component in components) 105 | { 106 | component.SetData(); 107 | archComponents.Add(component.ComponentValue); 108 | } 109 | CreateFromArray(archComponents.ToArray()); 110 | } 111 | 112 | public ArchEntity CreateFromArray(object[] components) 113 | { 114 | ComponentType[] types = GetComponentTypesForArchetype(components); 115 | ArchEntity entity = _world.Create(types); 116 | SetFromArray(entity, components); 117 | return entity; 118 | } 119 | 120 | public void SetFromArray(ArchEntity entity, object[] components) 121 | { 122 | entity.SetRange(components); 123 | } 124 | 125 | private ComponentType[] GetComponentTypesForArchetype(object[] components) 126 | { 127 | ComponentType[] types = new ComponentType[components.Length]; 128 | for (int i = 0; i < components.Length; i++) 129 | { 130 | ComponentType type; 131 | if (!ComponentRegistry.TryGet(components[i].GetType(), out type)) 132 | { 133 | type = ComponentRegistry.Add(components[i].GetType()); 134 | } 135 | types[i] = type; 136 | } 137 | return types; 138 | } 139 | 140 | protected override void OnSystemRemove() 141 | { 142 | World.Destroy(_world); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/GameProfiler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Stride.Core.Mathematics; 4 | using Stride.Core.Diagnostics; 5 | using Stride.Input; 6 | using Stride.Engine; 7 | using Stride.Profiling; 8 | using Stride.Core; 9 | 10 | namespace ArchECSStride 11 | { 12 | public class GameProfiler : AsyncScript 13 | { 14 | /// 15 | /// Enables or disable the game profiling 16 | /// 17 | public bool Enabled; 18 | 19 | /// 20 | /// The color of the text displayed during profiling 21 | /// 22 | [Display(4, "Text color")] 23 | public Color TextColor { get; set; } = Color.LightGreen; 24 | 25 | /// 26 | /// The time between two refreshes of the profiling information in milliseconds. 27 | /// 28 | [Display(2, "Refresh interval (ms)")] 29 | public double RefreshTime { get; set; } = 500; 30 | 31 | /// 32 | /// Gets or set the sorting mode of the profiling entries 33 | /// 34 | [Display(1, "Sort by")] 35 | public GameProfilingSorting SortingMode { get; set; } = GameProfilingSorting.ByTime; 36 | 37 | /// 38 | /// Gets or sets the type of the profiling to display: CPU or GPU 39 | /// 40 | [Display(0, "Filter")] 41 | public GameProfilingResults FilteringMode { get; set; } = GameProfilingResults.Fps; 42 | 43 | /// 44 | /// Gets or sets the current profiling result page to display. 45 | /// 46 | [Display(3, "Display page")] 47 | public uint ResultPage { get; set; } = 1; 48 | 49 | public override async Task Execute() 50 | { 51 | if (Enabled) 52 | GameProfiler.EnableProfiling(); 53 | 54 | while (Game.IsRunning) 55 | { 56 | GameProfiler.TextColor = TextColor; 57 | GameProfiler.RefreshTime = RefreshTime; 58 | GameProfiler.SortingMode = SortingMode; 59 | GameProfiler.FilteringMode = FilteringMode; 60 | GameProfiler.CurrentResultPage = ResultPage; 61 | ResultPage = GameProfiler.CurrentResultPage; 62 | 63 | if (Input.IsKeyDown(Keys.LeftShift) && Input.IsKeyDown(Keys.LeftCtrl) && Input.IsKeyReleased(Keys.P)) 64 | { 65 | if (Enabled) 66 | { 67 | GameProfiler.DisableProfiling(); 68 | Enabled = false; 69 | } 70 | else 71 | { 72 | GameProfiler.EnableProfiling(); 73 | Enabled = true; 74 | } 75 | } 76 | 77 | if (Enabled) 78 | { 79 | // Toggle the filtering mode 80 | if (Input.IsKeyPressed(Keys.F1)) 81 | { 82 | FilteringMode = (GameProfilingResults)(((int)FilteringMode + 1) % Enum.GetValues(typeof(GameProfilingResults)).Length); 83 | } 84 | // Toggle the sorting mode 85 | if (Input.IsKeyPressed(Keys.F2)) 86 | { 87 | SortingMode = (GameProfilingSorting)(((int)SortingMode + 1) % Enum.GetValues(typeof(GameProfilingSorting)).Length); 88 | } 89 | 90 | // Update the result page 91 | if (Input.IsKeyPressed(Keys.F3)) 92 | { 93 | ResultPage = Math.Max(1, --ResultPage); 94 | } 95 | else if (Input.IsKeyPressed(Keys.F4)) 96 | { 97 | ++ResultPage; 98 | } 99 | if (Input.IsKeyPressed(Keys.D1)) 100 | { 101 | ResultPage = 1; 102 | } 103 | else if (Input.IsKeyPressed(Keys.D2)) 104 | { 105 | ResultPage = 2; 106 | } 107 | else if (Input.IsKeyPressed(Keys.D3)) 108 | { 109 | ResultPage = 3; 110 | } 111 | else if (Input.IsKeyPressed(Keys.D4)) 112 | { 113 | ResultPage = 4; 114 | } 115 | else if (Input.IsKeyPressed(Keys.D5)) 116 | { 117 | ResultPage = 5; 118 | } 119 | 120 | // Update the refreshing speed 121 | if (Input.IsKeyPressed(Keys.Subtract) || Input.IsKeyPressed(Keys.OemMinus)) 122 | { 123 | RefreshTime = Math.Min(RefreshTime * 2, 10000); 124 | } 125 | else if (Input.IsKeyPressed(Keys.Add) || Input.IsKeyPressed(Keys.OemPlus)) 126 | { 127 | RefreshTime = Math.Max(RefreshTime / 2, 100); 128 | } 129 | } 130 | 131 | await Script.NextFrame(); 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/BasicCameraController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Stride.Core; 3 | using Stride.Core.Mathematics; 4 | using Stride.Engine; 5 | using Stride.Input; 6 | 7 | namespace ArchECSStride 8 | { 9 | /// 10 | /// A script that allows to move and rotate an entity through keyboard, mouse and touch input to provide basic camera navigation. 11 | /// 12 | /// 13 | /// The entity can be moved using W, A, S, D, Q and E, arrow keys, a gamepad's left stick or dragging/scaling using multi-touch. 14 | /// Rotation is achieved using the Numpad, the mouse while holding the right mouse button, a gamepad's right stick, or dragging using single-touch. 15 | /// 16 | public class BasicCameraController : SyncScript 17 | { 18 | private const float MaximumPitch = MathUtil.PiOverTwo * 0.99f; 19 | 20 | private Vector3 upVector; 21 | private Vector3 translation; 22 | private float yaw; 23 | private float pitch; 24 | 25 | public bool Gamepad { get; set; } = false; 26 | 27 | public Vector3 KeyboardMovementSpeed { get; set; } = new Vector3(5.0f); 28 | 29 | public Vector3 TouchMovementSpeed { get; set; } = new Vector3(0.7f, 0.7f, 0.3f); 30 | 31 | public float SpeedFactor { get; set; } = 5.0f; 32 | 33 | public Vector2 KeyboardRotationSpeed { get; set; } = new Vector2(3.0f); 34 | 35 | public Vector2 MouseRotationSpeed { get; set; } = new Vector2(1.0f, 1.0f); 36 | 37 | public Vector2 TouchRotationSpeed { get; set; } = new Vector2(1.0f, 0.7f); 38 | 39 | public override void Start() 40 | { 41 | base.Start(); 42 | 43 | // Default up-direction 44 | upVector = Vector3.UnitY; 45 | 46 | // Configure touch input 47 | if (!Platform.IsWindowsDesktop) 48 | { 49 | Input.Gestures.Add(new GestureConfigDrag()); 50 | Input.Gestures.Add(new GestureConfigComposite()); 51 | } 52 | } 53 | 54 | public override void Update() 55 | { 56 | ProcessInput(); 57 | UpdateTransform(); 58 | } 59 | 60 | private void ProcessInput() 61 | { 62 | float deltaTime = (float)Game.UpdateTime.Elapsed.TotalSeconds; 63 | translation = Vector3.Zero; 64 | yaw = 0f; 65 | pitch = 0f; 66 | 67 | // Keyboard and Gamepad based movement 68 | { 69 | // Our base speed is: one unit per second: 70 | // deltaTime contains the duration of the previous frame, let's say that in this update 71 | // or frame it is equal to 1/60, that means that the previous update ran 1/60 of a second ago 72 | // and the next will, in most cases, run in around 1/60 of a second from now. Knowing that, 73 | // we can move 1/60 of a unit on this frame so that in around 60 frames(1 second) 74 | // we will have travelled one whole unit in a second. 75 | // If you don't use deltaTime your speed will be dependant on the amount of frames rendered 76 | // on screen which often are inconsistent, meaning that if the player has performance issues, 77 | // this entity will move around slower. 78 | float speed = 1f * deltaTime; 79 | 80 | Vector3 dir = Vector3.Zero; 81 | 82 | if (Gamepad && Input.HasGamePad) 83 | { 84 | GamePadState padState = Input.DefaultGamePad.State; 85 | // LeftThumb can be positive or negative on both axis (pushed to the right or to the left) 86 | dir.Z += padState.LeftThumb.Y; 87 | dir.X += padState.LeftThumb.X; 88 | 89 | // Triggers are always positive, in this case using one to increase and the other to decrease 90 | dir.Y -= padState.LeftTrigger; 91 | dir.Y += padState.RightTrigger; 92 | 93 | // Increase speed when pressing A, LeftShoulder or RightShoulder 94 | // Here:does the enum flag 'Buttons' has one of the flag ('A','LeftShoulder' or 'RightShoulder') set 95 | if ((padState.Buttons & (GamePadButton.A | GamePadButton.LeftShoulder | GamePadButton.RightShoulder)) != 0) 96 | { 97 | speed *= SpeedFactor; 98 | } 99 | } 100 | 101 | if (Input.HasKeyboard) 102 | { 103 | // Move with keyboard 104 | // Forward/Backward 105 | if (Input.IsKeyDown(Keys.W) || Input.IsKeyDown(Keys.Up)) 106 | { 107 | dir.Z += 1; 108 | } 109 | if (Input.IsKeyDown(Keys.S) || Input.IsKeyDown(Keys.Down)) 110 | { 111 | dir.Z -= 1; 112 | } 113 | 114 | // Left/Right 115 | if (Input.IsKeyDown(Keys.A) || Input.IsKeyDown(Keys.Left)) 116 | { 117 | dir.X -= 1; 118 | } 119 | if (Input.IsKeyDown(Keys.D) || Input.IsKeyDown(Keys.Right)) 120 | { 121 | dir.X += 1; 122 | } 123 | 124 | // Down/Up 125 | if (Input.IsKeyDown(Keys.Q)) 126 | { 127 | dir.Y -= 1; 128 | } 129 | if (Input.IsKeyDown(Keys.E)) 130 | { 131 | dir.Y += 1; 132 | } 133 | 134 | // Increase speed when pressing shift 135 | if (Input.IsKeyDown(Keys.LeftShift) || Input.IsKeyDown(Keys.RightShift)) 136 | { 137 | speed *= SpeedFactor; 138 | } 139 | 140 | // If the player pushes down two or more buttons, the direction and ultimately the base speed 141 | // will be greater than one (vector(1, 1) is farther away from zero than vector(0, 1)), 142 | // normalizing the vector ensures that whichever direction the player chooses, that direction 143 | // will always be at most one unit in length. 144 | // We're keeping dir as is if isn't longer than one to retain sub unit movement: 145 | // a stick not entirely pushed forward should make the entity move slower. 146 | if (dir.Length() > 1f) 147 | { 148 | dir = Vector3.Normalize(dir); 149 | } 150 | } 151 | 152 | // Finally, push all of that to the translation variable which will be used within UpdateTransform() 153 | translation += dir * KeyboardMovementSpeed * speed; 154 | } 155 | 156 | // Keyboard and Gamepad based Rotation 157 | { 158 | // See Keyboard & Gamepad translation's deltaTime usage 159 | float speed = 1f * deltaTime; 160 | Vector2 rotation = Vector2.Zero; 161 | if (Gamepad && Input.HasGamePad) 162 | { 163 | GamePadState padState = Input.DefaultGamePad.State; 164 | rotation.X += padState.RightThumb.Y; 165 | rotation.Y += -padState.RightThumb.X; 166 | } 167 | 168 | if (Input.HasKeyboard) 169 | { 170 | if (Input.IsKeyDown(Keys.NumPad2)) 171 | { 172 | rotation.X += 1; 173 | } 174 | if (Input.IsKeyDown(Keys.NumPad8)) 175 | { 176 | rotation.X -= 1; 177 | } 178 | 179 | if (Input.IsKeyDown(Keys.NumPad4)) 180 | { 181 | rotation.Y += 1; 182 | } 183 | if (Input.IsKeyDown(Keys.NumPad6)) 184 | { 185 | rotation.Y -= 1; 186 | } 187 | 188 | // See Keyboard & Gamepad translation's Normalize() usage 189 | if (rotation.Length() > 1f) 190 | { 191 | rotation = Vector2.Normalize(rotation); 192 | } 193 | } 194 | 195 | // Modulate by speed 196 | rotation *= KeyboardRotationSpeed * speed; 197 | 198 | // Finally, push all of that to pitch & yaw which are going to be used within UpdateTransform() 199 | pitch += rotation.X; 200 | yaw += rotation.Y; 201 | } 202 | 203 | // Mouse movement and gestures 204 | { 205 | // This type of input should not use delta time at all, they already are frame-rate independent. 206 | // Lets say that you are going to move your finger/mouse for one second over 40 units, it doesn't matter 207 | // the amount of frames occuring within that time frame, each frame will receive the right amount of delta: 208 | // a quarter of a second -> 10 units, half a second -> 20 units, one second -> your 40 units. 209 | 210 | if (Input.HasMouse) 211 | { 212 | // Rotate with mouse 213 | if (Input.IsMouseButtonDown(MouseButton.Right)) 214 | { 215 | Input.LockMousePosition(); 216 | Game.IsMouseVisible = false; 217 | 218 | yaw -= Input.MouseDelta.X * MouseRotationSpeed.X; 219 | pitch -= Input.MouseDelta.Y * MouseRotationSpeed.Y; 220 | } 221 | else 222 | { 223 | Input.UnlockMousePosition(); 224 | Game.IsMouseVisible = true; 225 | } 226 | } 227 | 228 | // Handle gestures 229 | foreach (var gestureEvent in Input.GestureEvents) 230 | { 231 | switch (gestureEvent.Type) 232 | { 233 | // Rotate by dragging 234 | case GestureType.Drag: 235 | var drag = (GestureEventDrag)gestureEvent; 236 | var dragDistance = drag.DeltaTranslation; 237 | yaw = -dragDistance.X * TouchRotationSpeed.X; 238 | pitch = -dragDistance.Y * TouchRotationSpeed.Y; 239 | break; 240 | 241 | // Move along z-axis by scaling and in xy-plane by multi-touch dragging 242 | case GestureType.Composite: 243 | var composite = (GestureEventComposite)gestureEvent; 244 | translation.X = -composite.DeltaTranslation.X * TouchMovementSpeed.X; 245 | translation.Y = -composite.DeltaTranslation.Y * TouchMovementSpeed.Y; 246 | translation.Z = MathF.Log(composite.DeltaScale + 1) * TouchMovementSpeed.Z; 247 | break; 248 | } 249 | } 250 | } 251 | } 252 | 253 | private void UpdateTransform() 254 | { 255 | // Get the local coordinate system 256 | var rotation = Matrix.RotationQuaternion(Entity.Transform.Rotation); 257 | 258 | // Enforce the global up-vector by adjusting the local x-axis 259 | var right = Vector3.Cross(rotation.Forward, upVector); 260 | var up = Vector3.Cross(right, rotation.Forward); 261 | 262 | // Stabilize 263 | right.Normalize(); 264 | up.Normalize(); 265 | 266 | // Adjust pitch. Prevent it from exceeding up and down facing. Stabilize edge cases. 267 | var currentPitch = MathUtil.PiOverTwo - MathF.Acos(Vector3.Dot(rotation.Forward, upVector)); 268 | pitch = MathUtil.Clamp(currentPitch + pitch, -MaximumPitch, MaximumPitch) - currentPitch; 269 | 270 | Vector3 finalTranslation = translation; 271 | finalTranslation.Z = -finalTranslation.Z; 272 | finalTranslation = Vector3.TransformCoordinate(finalTranslation, rotation); 273 | 274 | // Move in local coordinates 275 | Entity.Transform.Position += finalTranslation; 276 | 277 | // Yaw around global up-vector, pitch and roll in local space 278 | Entity.Transform.Rotation *= Quaternion.RotationAxis(right, pitch) * Quaternion.RotationAxis(upVector, yaw); 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/GraphicsCompositor.sdgfxcomp: -------------------------------------------------------------------------------- 1 | !GraphicsCompositorAsset 2 | Id: 72aeddc1-0a25-4778-9aef-dc2cdf48f7eb 3 | SerializedVersion: {Stride: 3.1.0.1} 4 | Tags: [] 5 | Archetype: 823a81bf-bac0-4552-9267-aeed499c40df:DefaultGraphicsCompositorLevel10 6 | Cameras: 7 | de2e75c3b2b23e54162686363f3f138e: 8 | Id: f73b8d44-fccf-401c-af72-9be32dda6db0 9 | Name: Main 10 | RenderStages: 11 | 47116750c1a5d449b4ad3625f71439b3: 12 | Id: db2b1453-0697-4a32-afaa-0770eab41b65 13 | Name: Opaque 14 | EffectSlotName: Main 15 | SortMode: !SortModeStateChange {} 16 | 9105a30fee026d4893472b6aee83d035: 17 | Id: ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 18 | Name: Transparent 19 | EffectSlotName: Main 20 | SortMode: !BackToFrontSortMode {} 21 | 554e52c061404d4684dd7c4c70f70e0e: 22 | Id: dce7d47c-a993-426f-94d0-e093376198dc 23 | Name: ShadowMapCaster 24 | EffectSlotName: ShadowMapCaster 25 | SortMode: !FrontToBackSortMode {} 26 | 5a50638f5c514dc490c8c4f57cc88b57: 27 | Id: 15c87d14-e5da-4ba9-a6a2-024f71771c49 28 | Name: ShadowMapCasterParaboloid 29 | EffectSlotName: ShadowMapCasterParaboloid 30 | SortMode: !FrontToBackSortMode {} 31 | bc1a77d2ab254a6e920f86cff65cd75e: 32 | Id: 1c40c9da-1ffc-4ac4-80ce-27688a2055e6 33 | Name: ShadowMapCasterCubeMap 34 | EffectSlotName: ShadowMapCasterCubeMap 35 | SortMode: !FrontToBackSortMode {} 36 | 33d9d311a1a65601da9ef56775477f95: 37 | Id: 98ec74be-714f-4e83-9ad4-5514b483665e 38 | Name: GBuffer 39 | EffectSlotName: GBuffer 40 | SortMode: !FrontToBackSortMode {} 41 | RenderFeatures: 42 | d8fb80b0e7995140a46bca8dc36ee8a2: !Stride.Rendering.MeshRenderFeature,Stride.Rendering 43 | RenderStageSelectors: 44 | 44cf4a95ef82544e9ce3c6507d5569a9: !Stride.Rendering.MeshTransparentRenderStageSelector,Stride.Rendering 45 | OpaqueRenderStage: ref!! db2b1453-0697-4a32-afaa-0770eab41b65 46 | TransparentRenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 47 | EffectName: StrideForwardShadingEffect 48 | 6f7224048750e7260ea87c444f74b32c: !Stride.Rendering.Shadows.ShadowMapRenderStageSelector,Stride.Rendering 49 | ShadowMapRenderStage: ref!! dce7d47c-a993-426f-94d0-e093376198dc 50 | EffectName: StrideForwardShadingEffect.ShadowMapCaster 51 | b60663d7cb46417a94341a39c3bc1a12: !Stride.Rendering.Shadows.ShadowMapRenderStageSelector,Stride.Rendering 52 | ShadowMapRenderStage: ref!! 15c87d14-e5da-4ba9-a6a2-024f71771c49 53 | EffectName: StrideForwardShadingEffect.ShadowMapCasterParaboloid 54 | f5533b1249b942df8a8aba311cd79532: !Stride.Rendering.Shadows.ShadowMapRenderStageSelector,Stride.Rendering 55 | ShadowMapRenderStage: ref!! 1c40c9da-1ffc-4ac4-80ce-27688a2055e6 56 | EffectName: StrideForwardShadingEffect.ShadowMapCasterCubeMap 57 | 106341b76db9fcda6a033dad16aa708b: !Stride.Rendering.MeshTransparentRenderStageSelector,Stride.Rendering 58 | OpaqueRenderStage: ref!! 98ec74be-714f-4e83-9ad4-5514b483665e 59 | EffectName: StrideForwardShadingEffect.ShadowMapCaster 60 | PipelineProcessors: 61 | d70f5aee0616e4ab25081ceaf643290c: !Stride.Rendering.MeshPipelineProcessor,Stride.Rendering 62 | TransparentRenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 63 | 26c899b17f88c21ab13bf60a7220ccd1: !Stride.Rendering.ShadowMeshPipelineProcessor,Stride.Rendering 64 | ShadowMapRenderStage: ref!! dce7d47c-a993-426f-94d0-e093376198dc 65 | ff51170a7d1a4761b73ef6a5c9f0cba2: !Stride.Rendering.ShadowMeshPipelineProcessor,Stride.Rendering 66 | ShadowMapRenderStage: ref!! 15c87d14-e5da-4ba9-a6a2-024f71771c49 67 | DepthClipping: true 68 | ae4336b0a9514e8488e8e0ccbcef25f4: !Stride.Rendering.ShadowMeshPipelineProcessor,Stride.Rendering 69 | ShadowMapRenderStage: ref!! 1c40c9da-1ffc-4ac4-80ce-27688a2055e6 70 | DepthClipping: true 71 | RenderFeatures: 72 | 86b959cbdf51a1438d4973177c77c627: !Stride.Rendering.TransformRenderFeature,Stride.Rendering {} 73 | 8e0351fee9883922648a11016224b195: !Stride.Rendering.SkinningRenderFeature,Stride.Rendering {} 74 | f5a2017030ba4b28784e804807ce7628: !Stride.Rendering.Materials.MaterialRenderFeature,Stride.Rendering {} 75 | 83fea7526ebe4893a5bad953d0502bfd: !Stride.Rendering.Shadows.ShadowCasterRenderFeature,Stride.Rendering {} 76 | 65743b4380f4cc43b2b4bdc23cd0c07c: !Stride.Rendering.Lights.ForwardLightingRenderFeature,Stride.Rendering 77 | LightRenderers: 78 | 7ac2775468f53c4399b2f3f6357c85c9: !Stride.Rendering.Lights.LightAmbientRenderer,Stride.Rendering {} 79 | 7b68f9cd17404a4ba9e5f7df72e3b48d: !Stride.Rendering.Lights.LightDirectionalGroupRenderer,Stride.Rendering {} 80 | 411fdcfb9fc388449a0443173dfa3f27: !Stride.Rendering.Lights.LightSkyboxRenderer,Stride.Rendering {} 81 | facdcd5b543cf1c6bdf2138aab6cc473: !Stride.Rendering.Lights.LightClusteredPointSpotGroupRenderer,Stride.Rendering {} 82 | 79582329a9cf466e960f8920f579de9b: !Stride.Rendering.Lights.LightPointGroupRenderer,Stride.Rendering {} 83 | cf0c6bd4198b4cc4aaaab5b54870bdfd: !Stride.Rendering.Lights.LightSpotGroupRenderer,Stride.Rendering {} 84 | 451af18f3f5c4187cf3fe5f33feb46b1: !Stride.Rendering.LightProbes.LightProbeRenderer,Stride.Rendering {} 85 | ShadowMapRenderer: !Stride.Rendering.Shadows.ShadowMapRenderer,Stride.Rendering 86 | Renderers: 87 | 7c3d3d4c86834c3551bacde2527b3836: !Stride.Rendering.Shadows.LightDirectionalShadowMapRenderer,Stride.Rendering 88 | ShadowCasterRenderStage: ref!! dce7d47c-a993-426f-94d0-e093376198dc 89 | 1c204b09435636256a3fcfd6f9ddb347: !Stride.Rendering.Shadows.LightSpotShadowMapRenderer,Stride.Rendering 90 | ShadowCasterRenderStage: ref!! dce7d47c-a993-426f-94d0-e093376198dc 91 | 7c8c69ce27034b4c8bbcab0bcdfe954b: !Stride.Rendering.Shadows.LightPointShadowMapRendererParaboloid,Stride.Rendering 92 | ShadowCasterRenderStage: ref!! 15c87d14-e5da-4ba9-a6a2-024f71771c49 93 | d59ef45dd99e49d3af3887763d153aa7: !Stride.Rendering.Shadows.LightPointShadowMapRendererCubeMap,Stride.Rendering 94 | ShadowCasterRenderStage: ref!! 1c40c9da-1ffc-4ac4-80ce-27688a2055e6 95 | 42be209952db58294c9f06c58809b8ca: !Stride.Rendering.InstancingRenderFeature,Stride.Rendering {} 96 | 28e9bf54a5adbe063f59fb17acb2723e: !Stride.Rendering.Sprites.SpriteRenderFeature,Stride.Rendering 97 | RenderStageSelectors: 98 | d74665cff080638a2439c4422e542d85: !Stride.Rendering.Sprites.SpriteTransparentRenderStageSelector,Stride.Rendering 99 | OpaqueRenderStage: ref!! db2b1453-0697-4a32-afaa-0770eab41b65 100 | TransparentRenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 101 | EffectName: Test 102 | 60780391e205770513fdd53e07279a01: !Stride.Rendering.Background.BackgroundRenderFeature,Stride.Rendering 103 | RenderStageSelectors: 104 | 11c8b8ccb522e3cd1dd6688016062a6d: !Stride.Rendering.SimpleGroupToRenderStageSelector,Stride.Rendering 105 | RenderStage: ref!! db2b1453-0697-4a32-afaa-0770eab41b65 106 | EffectName: Test 107 | 93933ad00d0c357d4915ad462cbfd04c: !Stride.Rendering.UI.UIRenderFeature,Stride.UI 108 | RenderStageSelectors: 109 | 14a071694411235038a102ac3794bb4d: !Stride.Rendering.SimpleGroupToRenderStageSelector,Stride.Rendering 110 | RenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 111 | EffectName: Test 112 | 9013eab3ea0ef6c98bf133b86c173d45: !Stride.Particles.Rendering.ParticleEmitterRenderFeature,Stride.Particles 113 | RenderStageSelectors: 114 | af1bd241305893ef8ff7952184e1cb0b: !Stride.Particles.Rendering.ParticleEmitterTransparentRenderStageSelector,Stride.Particles 115 | OpaqueRenderStage: ref!! db2b1453-0697-4a32-afaa-0770eab41b65 116 | TransparentRenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 117 | EffectName: null 118 | PipelineProcessors: {} 119 | SharedRenderers: 120 | 60459475d3a3adaf2d1ba5d99913ca75: !Stride.Rendering.Compositing.ForwardRenderer,Stride.Engine 121 | Id: 9cf59b7b-b108-4fe1-950a-eed8738ecf02 122 | Clear: 123 | Id: 4bc4b2ca-027e-4e4a-94cb-2912709bef5f 124 | Color: {R: 0.40491876, G: 0.41189542, B: 0.43775, A: 1.0} 125 | LightProbes: true 126 | OpaqueRenderStage: ref!! db2b1453-0697-4a32-afaa-0770eab41b65 127 | TransparentRenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 128 | ShadowMapRenderStages: 129 | fc4d1e0de5c2b0bbc27bcf96e9a848fd: ref!! dce7d47c-a993-426f-94d0-e093376198dc 130 | 87ff1d9cdd52418daf76385176a0e316: ref!! 15c87d14-e5da-4ba9-a6a2-024f71771c49 131 | 5e059d4cc2db4ee8a1f28a40f4ac3ae8: ref!! 1c40c9da-1ffc-4ac4-80ce-27688a2055e6 132 | GBufferRenderStage: ref!! 98ec74be-714f-4e83-9ad4-5514b483665e 133 | PostEffects: !PostProcessingEffects ref!! 252245cd-42ed-4bae-bbc9-6f1a2339ca9c 134 | LightShafts: null 135 | VRSettings: 136 | Enabled: false 137 | RequiredApis: {} 138 | Overlays: {} 139 | SubsurfaceScatteringBlurEffect: null 140 | MSAALevel: None 141 | MSAAResolver: {} 142 | d5b2e71c088247e21556decdce138d96: !Stride.Rendering.Compositing.ForwardRenderer,Stride.Engine 143 | Id: df158967-ea2c-4a67-80b8-c6ff4f70bbc5 144 | Clear: 145 | Id: 66a42307-1985-4316-871a-768449238c11 146 | Color: {R: 0.40491876, G: 0.41189542, B: 0.43775, A: 1.0} 147 | LightProbes: true 148 | OpaqueRenderStage: ref!! db2b1453-0697-4a32-afaa-0770eab41b65 149 | TransparentRenderStage: ref!! ce0bdde3-ef90-483f-a5c8-b39cb3dc2f6f 150 | ShadowMapRenderStages: 151 | 2323a99a8a983e182f318e55604659b0: ref!! dce7d47c-a993-426f-94d0-e093376198dc 152 | 61b557b74893400898c007d5ece5e87f: ref!! 15c87d14-e5da-4ba9-a6a2-024f71771c49 153 | 5c382f66ee524c498d26d9aaf19fc9c3: ref!! 1c40c9da-1ffc-4ac4-80ce-27688a2055e6 154 | GBufferRenderStage: ref!! 98ec74be-714f-4e83-9ad4-5514b483665e 155 | PostEffects: null 156 | LightShafts: null 157 | VRSettings: 158 | Enabled: false 159 | RequiredApis: {} 160 | Overlays: {} 161 | SubsurfaceScatteringBlurEffect: null 162 | MSAALevel: None 163 | MSAAResolver: {} 164 | 34ecb9b2633eacfc439ba8744fe05102: !PostProcessingEffects 165 | Id: 252245cd-42ed-4bae-bbc9-6f1a2339ca9c 166 | Outline: 167 | Enabled: false 168 | NormalWeight: 2.0 169 | DepthWeight: 0.2 170 | NormalNearCutoff: 0.1 171 | Fog: 172 | Enabled: false 173 | Density: 0.1 174 | Color: {R: 1.0, G: 1.0, B: 1.0} 175 | FogStart: 10.0 176 | SkipBackground: false 177 | AmbientOcclusion: 178 | Enabled: false 179 | LocalReflections: 180 | Enabled: false 181 | ResolvePassResolution: Full 182 | DepthResolution: Half 183 | DepthOfField: 184 | Enabled: false 185 | DOFAreas: {X: 0.5, Y: 6.0, Z: 50.0, W: 200.0} 186 | BrightFilter: 187 | Color: {R: 1.0, G: 1.0, B: 1.0} 188 | Bloom: 189 | Enabled*: true 190 | Distortion: {X: 1.0, Y: 1.0} 191 | Afterimage: 192 | Enabled: false 193 | LightStreak: 194 | Enabled*: false 195 | Attenuation: 0.7 196 | LensFlare: 197 | Enabled*: false 198 | ColorTransforms: 199 | Transforms: 200 | 1e06f805f8b2e949a06c30d45fe413ef: !ToneMap 201 | Operator: !ToneMapHejl2Operator {} 202 | c57351444609d14ea258b3f511ec8a74: !FilmGrain 203 | Enabled: false 204 | e86e22e9a5d65545b8b55fca26e0afee: !Vignetting 205 | Enabled: false 206 | Color: {R: 0.0, G: 0.0, B: 0.0} 207 | Antialiasing: !FXAAEffect {} 208 | ee80a20a9bd99f2d70711114e15fe7ca: !Stride.Rendering.Compositing.DebugRenderer,Stride.Rendering 209 | Id: e1e9aa6f-c6ee-4b3e-84c1-151f69d79c03 210 | DebugRenderStages: {} 211 | Game: !Stride.Rendering.Compositing.SceneCameraRenderer,Stride.Engine 212 | Id: 76fe87cf-f574-4ad6-85b8-e9a9586be0e2 213 | Camera: ref!! f73b8d44-fccf-401c-af72-9be32dda6db0 214 | Child: !Stride.Rendering.Compositing.SceneRendererCollection,Stride.Rendering 215 | Id: 82568e46-92e7-421a-8dca-114a74e0cd69 216 | Children: 217 | d39c5ddbf8b7d5ca02bafb6496b1cc3c: !Stride.Rendering.Compositing.ForwardRenderer,Stride.Engine ref!! 9cf59b7b-b108-4fe1-950a-eed8738ecf02 218 | 01d338078e9b21121ead0868932613dd: !Stride.Rendering.Compositing.DebugRenderer,Stride.Rendering ref!! e1e9aa6f-c6ee-4b3e-84c1-151f69d79c03 219 | RenderMask: All 220 | SingleView: !Stride.Rendering.Compositing.ForwardRenderer,Stride.Engine ref!! df158967-ea2c-4a67-80b8-c6ff4f70bbc5 221 | Editor: !Stride.Rendering.Compositing.ForwardRenderer,Stride.Engine ref!! 9cf59b7b-b108-4fe1-950a-eed8738ecf02 222 | BlockPositions: {} 223 | -------------------------------------------------------------------------------- /Source/ArchECSStride/ArchECSStride/Assets/MainScene.sdscene: -------------------------------------------------------------------------------- 1 | !SceneAsset 2 | Id: 7499ad3b-a805-4fba-a68b-816d8f34fb0a 3 | SerializedVersion: {Stride: 3.1.0.1} 4 | Tags: [] 5 | ChildrenIds: [] 6 | Offset: {X: 0.0, Y: 0.0, Z: 0.0} 7 | Hierarchy: 8 | RootParts: 9 | - ref!! 703e78c2-50b6-46cd-a488-4cb36623baf3 10 | - ref!! 6d2135c4-1c58-4870-b0a6-6194b508a1dd 11 | - ref!! 72238e5d-4efb-4559-8148-777d586fdd51 12 | - ref!! 5076c41b-6bdc-4500-bc46-59bca93f458f 13 | - ref!! 994790fe-3b0b-43ab-8339-55b620c728e7 14 | - ref!! e248bedd-1576-4543-b0d2-ce46cb7220c5 15 | - ref!! 549f8c1b-8534-4701-bf98-6aae06237866 16 | - ref!! 0ede60e3-63c0-4772-a94d-8ca018f77c4f 17 | - ref!! ca8f80ba-812d-4a07-b527-90ed384f961d 18 | - ref!! b5b0f298-5859-4565-9160-931e1a40bf62 19 | - ref!! 3603c345-3543-428e-94b3-c9979b18b5d5 20 | - ref!! 56432019-634c-4640-8b60-e8c358303ffb 21 | - ref!! 3d7a8876-1cc9-480e-946a-ac97788e282d 22 | - ref!! 13033b01-40ec-4c52-af25-cc383e1da08d 23 | - ref!! c3ad6845-21c1-4e06-ab5d-0b246cc10754 24 | - ref!! 3ccd5ba5-f466-4823-bace-002bf38a428a 25 | Parts: 26 | - Folder: NavBoxes 27 | Entity: 28 | Id: 0ede60e3-63c0-4772-a94d-8ca018f77c4f 29 | Name: NavBox 30 | Components: 31 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 32 | Id: c7a3e9a4-cd11-4b27-89c5-3178a34a1941 33 | Position: {X: -200.0, Y: 0.0, Z: 0.0} 34 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 35 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 36 | Children: {} 37 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 38 | Id: 387a0115-58b6-4527-8046-fa3a1b503f5e 39 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 40 | - Folder: NavBoxes 41 | Entity: 42 | Id: 13033b01-40ec-4c52-af25-cc383e1da08d 43 | Name: NavBox 44 | Components: 45 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 46 | Id: 1e36f8ce-18b5-478c-a136-76d4905302ed 47 | Position: {X: 0.0, Y: 0.0, Z: -200.0} 48 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 49 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 50 | Children: {} 51 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 52 | Id: 519ebbd7-9a76-4b00-bb64-5fd20631ff20 53 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 54 | - Folder: NavBoxes 55 | Entity: 56 | Id: 3603c345-3543-428e-94b3-c9979b18b5d5 57 | Name: NavBox 58 | Components: 59 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 60 | Id: 9935264f-e82a-4ffe-ac6b-9366fb6ae31e 61 | Position: {X: 0.0, Y: 0.0, Z: 200.0} 62 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 63 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 64 | Children: {} 65 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 66 | Id: de5d1a7b-06b9-44cd-a12c-c1fe0639d237 67 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 68 | - Entity: 69 | Id: 3ccd5ba5-f466-4823-bace-002bf38a428a 70 | Name: Tree 71 | Components: 72 | 191aaaaf9f18277a4f902b8e7e875ff8: !TransformComponent 73 | Id: 2c3e34c2-973c-431a-953d-71b5984dd90c 74 | Position: {X: 0.0, Y: 0.0, Z: 0.0} 75 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 76 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 77 | Children: {} 78 | 6b2586ea4e852c6ec328b7f66f2b91d0: !ModelComponent 79 | Id: 9585073d-bb6e-4b10-861e-c884b8a0444c 80 | Model: f95727a0-119f-483a-a9c0-4982e475c438:Models/Tree 81 | Materials: {} 82 | - Folder: NavBoxes 83 | Entity: 84 | Id: 3d7a8876-1cc9-480e-946a-ac97788e282d 85 | Name: NavBox 86 | Components: 87 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 88 | Id: 688745b9-25d0-4234-be91-59a661af4b1d 89 | Position: {X: -200.0, Y: 0.0, Z: -200.0} 90 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 91 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 92 | Children: {} 93 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 94 | Id: b85d03c1-c1c1-49d9-aa45-83e68724c716 95 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 96 | - Entity: 97 | Id: 5076c41b-6bdc-4500-bc46-59bca93f458f 98 | Name: Ground 99 | Components: 100 | 2d90da7be78004cf6f2d3643e6e9160f: !TransformComponent 101 | Id: df15f39b-41b8-47b8-aeaa-54c926eb4e59 102 | Position: {X: 0.0, Y: 0.0, Z: 0.0} 103 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 104 | Scale: {X: 1000.0, Y: 1.0, Z: 1000.0} 105 | Children: {} 106 | cf52defb7087fa879cc2b484c8017287: !ModelComponent 107 | Id: 601b8225-6d8d-4766-b155-f9aa9cb32f9b 108 | Model: 56894502-5bbc-4870-8f4a-9bfad3c09d7b:Ground 109 | Materials: 110 | 6c870e5277fabe33fca7ccbd267218c5~0: 9ca3427a-0cf2-4e19-a441-62cc07113a23:Materials/Grass 111 | 63e503e5b1bb62d3911b6a993caf990c: !StaticColliderComponent 112 | Id: 5f560676-10e4-4d4a-b08d-b8e36036b97d 113 | CollisionGroup: StaticFilter 114 | CanSleep: false 115 | Restitution: 0.0 116 | Friction: 0.5 117 | RollingFriction: 0.0 118 | CcdMotionThreshold: 0.0 119 | CcdSweptSphereRadius: 0.0 120 | IsTrigger: false 121 | AlwaysUpdateNaviMeshCache: false 122 | ColliderShapes: 123 | 4adbd5466db759986589a7e369d78847: !BoxColliderShapeDesc 124 | Is2D: false 125 | Size: {X: 10.0, Y: 0.1, Z: 10.0} 126 | LocalOffset: {X: 0.0, Y: -0.05, Z: 0.0} 127 | LocalRotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 128 | - Folder: NavBoxes 129 | Entity: 130 | Id: 549f8c1b-8534-4701-bf98-6aae06237866 131 | Name: NavBox 132 | Components: 133 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 134 | Id: 1ffd0af3-fbbb-41d1-8098-7ca3db597bf7 135 | Position: {X: 0.0, Y: 0.0, Z: 0.0} 136 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 137 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 138 | Children: {} 139 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 140 | Id: ffce9ae5-4316-4d99-8441-893e69ba8390 141 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 142 | - Folder: NavBoxes 143 | Entity: 144 | Id: 56432019-634c-4640-8b60-e8c358303ffb 145 | Name: NavBox 146 | Components: 147 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 148 | Id: bafbc73f-d8db-441c-8b6e-4a7f6953d69d 149 | Position: {X: -200.0, Y: 0.0, Z: 200.0} 150 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 151 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 152 | Children: {} 153 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 154 | Id: 0697ca33-4aab-4047-b685-3e64bbd7dab1 155 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 156 | - Entity: 157 | Id: 6d2135c4-1c58-4870-b0a6-6194b508a1dd 158 | Name: Directional light 159 | Components: 160 | 740fab5ed962a5a1db07237a45a95fcf: !TransformComponent 161 | Id: 82bfbf42-734f-47c4-a051-fe80c5535ea1 162 | Position: {X: 0.0, Y: 2.0, Z: 0.0} 163 | Rotation: {X: 1.131334E-08, Y: -0.9659258, Z: -0.25881904, W: -4.222196E-08} 164 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 165 | Children: {} 166 | 1420ab2cdff8cc56007b6a5126006163: !LightComponent 167 | Id: 6612848d-1568-4852-ae0a-5591ffa1c2a0 168 | Type: !LightDirectional 169 | Color: !ColorRgbProvider 170 | Value: {R: 1.0, G: 1.0, B: 1.0} 171 | Shadow: !LightDirectionalShadowMap 172 | Enabled: true 173 | Filter: !LightShadowMapFilterTypePcf 174 | FilterSize: Filter5x5 175 | Size: Large 176 | DepthRange: {} 177 | PartitionMode: !LightDirectionalShadowMap.PartitionLogarithmic {} 178 | ComputeTransmittance: false 179 | BiasParameters: {} 180 | Intensity: 20.0 181 | - Entity: 182 | Id: 703e78c2-50b6-46cd-a488-4cb36623baf3 183 | Name: Camera 184 | Components: 185 | ea1d28a98ae0524a1157dfdff3046dd8: !TransformComponent 186 | Id: 0ea50b24-50f8-4325-ab6b-fd17af46245f 187 | Position: {X: 2.6, Y: 0.6, Z: -1.0} 188 | Rotation: {X: 0.0, Y: 0.82903755, Z: 0.0, W: 0.5591929} 189 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 190 | Children: {} 191 | 63f64ed24f8fb6c32b7b6ffcf4b0d6cc: !CameraComponent 192 | Id: f4ecd710-7165-447d-8adc-4ea531d95aeb 193 | Name: null 194 | Projection: Perspective 195 | Slot: f73b8d44-fccf-401c-af72-9be32dda6db0 196 | 0be25e0628cb591db247dfae2513c7b7: !ArchECSStride.BasicCameraController,ArchECSStride 197 | Id: 3b9644bc-23ad-4c76-954e-8334d0e0800f 198 | Gamepad: false 199 | KeyboardMovementSpeed: {X: 5.0, Y: 5.0, Z: 5.0} 200 | TouchMovementSpeed: {X: 0.7, Y: 0.7, Z: 0.3} 201 | SpeedFactor: 5.0 202 | KeyboardRotationSpeed: {X: 3.0, Y: 3.0} 203 | MouseRotationSpeed: {X: 1.0, Y: 1.0} 204 | TouchRotationSpeed: {X: 1.0, Y: 0.7} 205 | 2cf50df9a5fc88c8ee99f86b38b1e54d: !ArchECSStride.GameProfiler,ArchECSStride 206 | Id: d62065de-3575-42b8-816e-118743bf717a 207 | Enabled: true 208 | TextColor: {R: 144, G: 238, B: 144, A: 255} 209 | RefreshTime: 500.0 210 | SortingMode: ByTime 211 | FilteringMode: Fps 212 | ResultPage: 1 213 | - Entity: 214 | Id: 72238e5d-4efb-4559-8148-777d586fdd51 215 | Name: Skybox 216 | Components: 217 | b7bb4681fc0ff312b5993f8431c1f424: !TransformComponent 218 | Id: fcf2da08-8c1d-4a8f-a73b-02d70b8bacfd 219 | Position: {X: 0.0, Y: 2.0, Z: -2.0} 220 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 221 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 222 | Children: {} 223 | 13c08b14812d68e10aadc04ba605295d: !BackgroundComponent 224 | Id: 63ff8475-7f91-4361-9c92-3e638bfcbaeb 225 | Texture: 9afb3f25-f91f-41c5-b5c8-ede65dc63b3e:Skybox texture 226 | 86941a84c45584e5c4972912cbec5048: !LightComponent 227 | Id: 0770ce3b-326e-4fbb-ba8e-53f97b6f3f46 228 | Type: !LightSkybox 229 | Skybox: 916ddf54-9e2e-4091-a3ba-c84b4ca0a160:Skybox 230 | - Entity: 231 | Id: 994790fe-3b0b-43ab-8339-55b620c728e7 232 | Name: InstancedMesh 233 | Components: 234 | 541849f42e3825b1952d83aa2cb97e48: !TransformComponent 235 | Id: 16a1b00f-f850-40fb-883d-768e76ec31ca 236 | Position: {X: 12.170552, Y: 0.0, Z: 11.60779} 237 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 238 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 239 | Children: {} 240 | 20f0b328f8396bcb6415dfd858f6c9c1: !ModelComponent 241 | Id: a3be3089-1378-4377-b51a-57160ca25109 242 | Model: fa39d881-d536-4e8a-866f-0f9991c5b065:Cube 243 | Materials: {} 244 | e9de1eec71f3fe43f1bc557b9bba5e30: !InstancingComponent 245 | Id: 2d00fd80-9ca8-4ab1-a823-c0137dd2edbf 246 | Type: !InstancingEntityTransform {} 247 | - Folder: NavBoxes 248 | Entity: 249 | Id: b5b0f298-5859-4565-9160-931e1a40bf62 250 | Name: NavBox 251 | Components: 252 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 253 | Id: 04091088-6ca0-4fbb-9b3f-d070c2cdbeca 254 | Position: {X: 200.0, Y: 0.0, Z: 200.0} 255 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 256 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 257 | Children: {} 258 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 259 | Id: a073cb10-0fea-448b-9b62-d1bb1875ea6f 260 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 261 | - Folder: NavBoxes 262 | Entity: 263 | Id: c3ad6845-21c1-4e06-ab5d-0b246cc10754 264 | Name: NavBox 265 | Components: 266 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 267 | Id: 4e68aebe-9a6e-40e3-91a2-eae82f386c1a 268 | Position: {X: 200.0, Y: 0.0, Z: -200.0} 269 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 270 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 271 | Children: {} 272 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 273 | Id: a2292884-a264-4c6f-a94e-828273d34dc0 274 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 275 | - Folder: NavBoxes 276 | Entity: 277 | Id: ca8f80ba-812d-4a07-b527-90ed384f961d 278 | Name: NavBox 279 | Components: 280 | 396dcd272170b5237528fff3cf0bb174: !TransformComponent 281 | Id: c5ffc176-9b84-47df-98d6-5f8cbde422aa 282 | Position: {X: 200.0, Y: 0.0, Z: 0.0} 283 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 284 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 285 | Children: {} 286 | a857e23b603ca533a778088f383e7be7: !Stride.Navigation.NavigationBoundingBoxComponent,Stride.Navigation 287 | Id: 03ca75a0-b38f-40b2-9f8e-8a8298b1bb80 288 | Size: {X: 100.0, Y: 10.0, Z: 100.0} 289 | - Entity: 290 | Id: e248bedd-1576-4543-b0d2-ce46cb7220c5 291 | Name: ProcessorComponents 292 | Components: 293 | e54bbaf934cf466cb7e0e86b032971ef: !TransformComponent 294 | Id: 5744ee96-a01a-4911-873e-531d03fcaa85 295 | Position: {X: 0.0, Y: 0.0, Z: 0.0} 296 | Rotation: {X: 0.0, Y: 0.0, Z: 0.0, W: 1.0} 297 | Scale: {X: 1.0, Y: 1.0, Z: 1.0} 298 | Children: {} 299 | 1b4f149407e733e51b59f2467437fdf7: !NavigationComponent 300 | Id: ab09349f-53c6-4ade-b4bd-1dea8ebca8a6 301 | NavigationMesh: null 302 | GroupId: c2a2522c-db2c-4d56-b3b7-3aecaacd69af 303 | --------------------------------------------------------------------------------