ECS refactor: new ComponentSet, serialization, generators

Major ECS API overhaul: added ComponentSet, refactored ComponentRegistry, and updated all entity/component creation methods. Introduced robust custom serialization infrastructure and per-component source generators for registration and (de)serialization. Updated editor, engine, and test code to use new APIs. Improved code quality, naming, and performance throughout. Removed obsolete code and updated dependencies.
This commit is contained in:
2025-12-20 20:41:40 +09:00
parent 3118021272
commit 00b4e82ded
60 changed files with 1216 additions and 814 deletions

View File

@@ -2,5 +2,6 @@ using Ghost.Core.Attributes;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Ghost.Graphics")]
[assembly: InternalsVisibleTo("Ghost.Engine")]
[assembly: EngineAssembly]

View File

@@ -23,9 +23,9 @@
<PackageReference Include="Misaki.HighPerformance" Version="1.0.2" />
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="1.2.1" />
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.3.2" />
<PackageReference Include="Misaki.HighPerformance.Mathematics" Version="1.2.6" />
<PackageReference Include="System.IO.Hashing" Version="10.0.0" />
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.5" />
<PackageReference Include="Misaki.HighPerformance.Mathematics" Version="1.3.0" />
<PackageReference Include="System.IO.Hashing" Version="10.0.1" />
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.6" />
</ItemGroup>
</Project>

View File

@@ -68,7 +68,7 @@ public readonly struct Identifier<T> : IEquatable<Identifier<T>>
public static Identifier<T> Invalid => new(-1);
public readonly bool IsValid => this != Invalid;
public readonly bool IsNotValid => this == Invalid;
public readonly bool IsInvalid => this == Invalid;
public readonly override int GetHashCode()
{

View File

@@ -11,7 +11,7 @@ public static partial class AssetDatabase
private static void InitializeMetaData()
{
if (_watcher == null)
if (s_watcher == null)
{
throw new InvalidOperationException("AssetDatabase is not initialized. Ensure that Initialize() is called before registering asset importers.");
}
@@ -26,24 +26,24 @@ public static partial class AssetDatabase
}
}
_watcher.Created += OnAssetCreated;
_watcher.Deleted += OnAssetDeleted;
_watcher.Renamed += OnAssetRenamed;
s_watcher.Created += OnAssetCreated;
s_watcher.Deleted += OnAssetDeleted;
s_watcher.Renamed += OnAssetRenamed;
}
private static Result<string> GetMetaFilePath(string assetPath)
private static Result<string, ErrorStatus> GetMetaFilePath(string assetPath)
{
if (Directory.Exists(assetPath))
{
return Result<string>.Failure("Folder does not have meta data");
return ErrorStatus.NotFound;
}
if (Path.GetExtension(assetPath).Equals(".meta", StringComparison.OrdinalIgnoreCase))
{
return Result<string>.Failure("Asset path cannot be a meta file");
return ErrorStatus.InvalidState;
}
return Result<string>.Success(assetPath + ".meta");
return assetPath + ".meta";
}
private static ImporterSettings? GetDefaultSettingsForAsset(string assetPath)
@@ -83,7 +83,7 @@ public static partial class AssetDatabase
var metaFileResult = GetMetaFilePath(assetPath);
if (!metaFileResult.IsSuccess)
{
return Result.Failure(metaFileResult.Message);
return Result.Failure(metaFileResult.Error.ToString());
}
if (File.Exists(metaFileResult.Value))

View File

@@ -1,3 +1,4 @@
using Ghost.Editor.Core.Utilities;
using System.Diagnostics;
using System.Reflection;
@@ -9,8 +10,7 @@ public static partial class AssetDatabase
private static void InitializeAssetHandle()
{
var methods = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
var methods = TypeCache.GetTypes()
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
.Where(m => m.GetCustomAttribute<AssetOpenHandlerAttribute>() != null &&
m.GetParameters().Length == 1 &&

View File

@@ -4,7 +4,7 @@ namespace Ghost.Editor.Core.AssetHandle;
public static partial class AssetDatabase
{
private static FileSystemWatcher? _watcher;
private static FileSystemWatcher? s_watcher;
private static readonly Dictionary<Guid, string> s_assetPathLookup = new();
@@ -22,7 +22,7 @@ public static partial class AssetDatabase
}
AssetsDirectory = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(ProjectService.CurrentProject.Path)!, ProjectService.ASSETS_FOLDER));
_watcher = new FileSystemWatcher
s_watcher = new FileSystemWatcher
{
Path = AssetsDirectory.FullName,
IncludeSubdirectories = true,

View File

@@ -19,12 +19,14 @@ public sealed partial class PropertyField : ContentControl
{ typeof(RangeBase), RangeBase.ValueProperty },
};
private object? sourceObject;
private FieldInfo? propertyInfo;
private Type? _fieldType;
private object? _sourceObject;
internal FieldInfo? _propertyInfo;
internal Type? _fieldType;
private object? _lastValue;
public event Action<PropertyField>? OnValueChanged;
public string Label
{
get => (string)GetValue(LabelProperty);
@@ -59,8 +61,8 @@ public sealed partial class PropertyField : ContentControl
private static TField ConfigureField<TField>(PropertyField propertyField, FieldInfo fieldInfo, object sourceObject, Func<TField> factory)
where TField : FrameworkElement
{
propertyField.sourceObject = sourceObject;
propertyField.propertyInfo = fieldInfo;
propertyField._sourceObject = sourceObject;
propertyField._propertyInfo = fieldInfo;
propertyField._fieldType = typeof(TField);
var field = factory();
@@ -72,6 +74,12 @@ public sealed partial class PropertyField : ContentControl
Path = new PropertyPath(fieldInfo.Name),
Mode = BindingMode.TwoWay,
});
field.RegisterPropertyChangedCallback(dp, (s, e) =>
{
propertyField.OnValueChanged?.Invoke(propertyField);
});
return field;
}
@@ -82,14 +90,10 @@ public sealed partial class PropertyField : ContentControl
Label = label
};
FrameworkElement content;
switch (fieldInfo.FieldType)
FrameworkElement content = fieldInfo.FieldType switch
{
case Type t when t == typeof(string):
content = ConfigureField(propertyField, fieldInfo, sourceObject, () => new TextBox());
break;
case Type t when t == typeof(int) || t == typeof(float) || t == typeof(double):
content = ConfigureField(propertyField, fieldInfo, sourceObject, () => new NumberBox
Type t when t == typeof(string) => ConfigureField(propertyField, fieldInfo, sourceObject, () => new TextBox()),
Type t when t == typeof(int) || t == typeof(float) || t == typeof(double) => ConfigureField(propertyField, fieldInfo, sourceObject, () => new NumberBox
{
SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Hidden,
AcceptsExpression = true,
@@ -97,27 +101,20 @@ public sealed partial class PropertyField : ContentControl
{
FractionDigits = t == typeof(int) ? 0 : 9,
}
});
break;
case Type t when t == typeof(bool):
content = ConfigureField(propertyField, fieldInfo, sourceObject, () => new ToggleSwitch());
break;
case Type t when t == typeof(Enum):
content = ConfigureField(propertyField, fieldInfo, sourceObject, () => new ComboBox
}),
Type t when t == typeof(bool) => ConfigureField(propertyField, fieldInfo, sourceObject, () => new ToggleSwitch()),
Type t when t == typeof(Enum) => ConfigureField(propertyField, fieldInfo, sourceObject, () => new ComboBox
{
ItemsSource = Enum.GetValues(t),
SelectedValuePath = "Value",
});
break;
default:
content = new TextBlock
}),
_ => new TextBlock
{
Text = $"Unsupported type: {fieldInfo.FieldType.Name}",
VerticalAlignment = VerticalAlignment.Center,
Foreground = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Red)
},
};
break;
}
propertyField.Content = content;
return propertyField;
@@ -125,12 +122,12 @@ public sealed partial class PropertyField : ContentControl
public void UpdateValue()
{
if (sourceObject == null || propertyInfo == null || _fieldType == null)
if (_sourceObject == null || _propertyInfo == null || _fieldType == null)
{
return;
}
var currentValue = propertyInfo.GetValue(sourceObject);
var currentValue = _propertyInfo.GetValue(_sourceObject);
if (Equals(currentValue, _lastValue))
{
return;
@@ -139,7 +136,7 @@ public sealed partial class PropertyField : ContentControl
var dp = GetValueProperty(_fieldType);
if (dp != null)
{
SetValue(dp, propertyInfo.GetValue(sourceObject));
SetValue(dp, _propertyInfo.GetValue(_sourceObject));
_lastValue = currentValue;
}
}

View File

@@ -4,10 +4,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Ghost.Editor.Core.Controls.Internal">
<Style TargetType="local:ComponentDataView">
<Style TargetType="local:ComponentView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ComponentDataView">
<ControlTemplate TargetType="local:ComponentView">
<StackPanel Margin="0,0,0,16">
<Border
Padding="8"

View File

@@ -1,15 +1,15 @@
using Ghost.Core;
using Ghost.Editor.Core.Inspector;
using Ghost.Editor.Core.Resources;
using Ghost.Editor.Core.Utilities;
using Ghost.SparseEntities;
using Ghost.Entities;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Ghost.Editor.Core.Controls.Internal;
internal unsafe sealed partial class ComponentDataView : Control
internal sealed unsafe partial class ComponentView : Control
{
private delegate void EditorUpdate();
@@ -18,6 +18,10 @@ internal unsafe sealed partial class ComponentDataView : Control
private readonly World? _world;
private readonly Entity _entity = Entity.Invalid;
private readonly Type? _componentType;
private readonly ComponentInfo _componentInfo;
private object? _managedInstance;
private void* _pComponentData;
private ComponentEditor? _customEditor;
private PropertyField[]? _propertyFields;
@@ -30,11 +34,11 @@ internal unsafe sealed partial class ComponentDataView : Control
}
public static readonly DependencyProperty HeaderTextProperty =
DependencyProperty.Register(nameof(HeaderText), typeof(string), typeof(ComponentDataView), new PropertyMetadata(string.Empty));
DependencyProperty.Register(nameof(HeaderText), typeof(string), typeof(ComponentView), new PropertyMetadata(string.Empty));
internal ComponentDataView()
internal ComponentView()
{
DefaultStyleKey = typeof(ComponentDataView);
DefaultStyleKey = typeof(ComponentView);
Unloaded += (s, e) =>
{
@@ -46,12 +50,14 @@ internal unsafe sealed partial class ComponentDataView : Control
};
}
public ComponentDataView(string header, World world, Entity entity, Type componentType) : this()
public ComponentView(string header, World world, Entity entity, Type componentType) : this()
{
HeaderText = header;
_world = world;
_entity = entity;
_componentType = componentType;
_componentInfo = ComponentRegistry.GetComponentInfo(componentType);
}
protected override void OnApplyTemplate()
@@ -77,7 +83,7 @@ internal unsafe sealed partial class ComponentDataView : Control
private void CustomEditorUpdate()
{
_customEditor!.Update();
_customEditor?.Update();
}
public void ReBuild()
@@ -93,6 +99,14 @@ internal unsafe sealed partial class ComponentDataView : Control
return;
}
if (_propertyFields != null)
{
foreach (var propertyField in _propertyFields)
{
propertyField.OnValueChanged -= OnPropertyValueChanged;
}
}
var componentObject = new ComponentObject(_world, _entity);
var editorType = TypeCache.GetTypes().FirstOrDefault(t =>
typeof(ComponentEditor).IsAssignableFrom(t) &&
@@ -106,18 +120,21 @@ internal unsafe sealed partial class ComponentDataView : Control
}
else
{
var fields = _componentType.GetFields(StaticResource.componentPropertyBindingFlags);
var fields = _componentType.GetFields(StaticResource.ComponentPropertyBindingFlags);
_propertyFields = new PropertyField[fields.Length];
_pComponentData = _world.EntityManager.GetComponent(_entity, _componentInfo.id);
_managedInstance = Marshal.PtrToStructure((nint)_pComponentData, _componentType);
if (_managedInstance == null)
{
return;
}
for (var i = 0; i < fields.Length; i++)
{
var field = fields[i];
if (!_world.ComponentStorage.TryGetPool(TypeHandle.Get(_componentType), out var pool))
{
continue;
}
var component = pool.Get(_entity);
var propertyField = PropertyField.Create(field.Name, field, component);
var propertyField = PropertyField.Create(field.Name, field, _managedInstance);
propertyField.OnValueChanged += OnPropertyValueChanged;
_propertyFields[i] = propertyField;
_contentContainer.Children.Add(propertyField);
@@ -126,19 +143,15 @@ internal unsafe sealed partial class ComponentDataView : Control
_editorUpdate = _customEditor == null ? ReflectionUpdate : CustomEditorUpdate;
_editorUpdate();
_world.ComponentChanged += OnComponentChanged;
}
private void OnComponentChanged(World world, Entity entity, Type type)
private void OnPropertyValueChanged(PropertyField field)
{
if (world != _world
|| entity != _entity
|| type != _componentType)
if (_managedInstance == null || _pComponentData == null)
{
return;
}
_editorUpdate?.Invoke();
Marshal.StructureToPtr(_managedInstance, (nint)_pComponentData, false);
}
}

View File

@@ -41,8 +41,4 @@
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Folder Include="Data\" />
</ItemGroup>
</Project>

View File

@@ -1,10 +1,8 @@
using Ghost.SparseEntities;
using Ghost.SparseEntities.Components;
using Ghost.SparseEntities.Query;
using Ghost.Entities;
namespace Ghost.Editor.Core.Inspector;
public unsafe readonly struct ComponentObject
public readonly struct ComponentObject
{
private readonly World _world;
private readonly Entity _entity;
@@ -15,15 +13,15 @@ public unsafe readonly struct ComponentObject
_entity = entity;
}
public CompRef<T> GetData<T>()
where T : unmanaged, IComponentData
public ref T GetData<T>()
where T : unmanaged, IComponent
{
return _world.EntityManager.GetComponent<T>(_entity);
return ref _world.EntityManager.GetComponent<T>(_entity);
}
public void SetData<T>(in T data)
where T : unmanaged, IComponentData
where T : unmanaged, IComponent
{
_world.EntityManager.SetComponent(_entity, in data);
_world.EntityManager.SetComponent(_entity, data);
}
}

View File

@@ -4,5 +4,5 @@ namespace Ghost.Editor.Core.Resources;
internal static class StaticResource
{
public static readonly BindingFlags componentPropertyBindingFlags = BindingFlags.Public | BindingFlags.Instance;
public static readonly BindingFlags ComponentPropertyBindingFlags = BindingFlags.Public | BindingFlags.Instance;
}

View File

@@ -15,15 +15,15 @@ public enum OpenWorldMode
public static class EditorWorldManager
{
// TODO: Use guid keys instead of string paths for better performance and uniqueness
private static readonly Dictionary<string, WorldNode> _loadedWorlds = new();
public static IEnumerable<WorldNode> LoadedWorlds => _loadedWorlds.Values;
private static readonly Dictionary<string, WorldNode> s_loadedWorlds = new();
public static IEnumerable<WorldNode> LoadedWorlds => s_loadedWorlds.Values;
public static event Action<WorldNode>? OnWorldLoaded;
public static event Action<WorldNode>? OnWorldUnloaded;
public static async Task LoadWorld(string worldPath)
{
if (_loadedWorlds.ContainsKey(worldPath)
if (s_loadedWorlds.ContainsKey(worldPath)
|| !File.Exists(worldPath)
|| Path.GetExtension(worldPath) != FileExtensions.SCENE_FILE_EXTENSION)
{
@@ -33,18 +33,18 @@ public static class EditorWorldManager
var progressService = EditorApplication.GetService<IProgressService>();
progressService.ShowIndeterminateProgress("Loading world...");
foreach (var world in _loadedWorlds)
foreach (var world in s_loadedWorlds)
{
world.Value.Unload();
OnWorldUnloaded?.Invoke(world.Value);
}
await using var readStream = new FileStream(worldPath, FileMode.Open, FileAccess.Read, FileShare.Read);
var deserializedScene = await JsonSerializer.DeserializeAsync<WorldNode>(readStream, Engine.Resources.StaticResource.defaultSerializerOptions) ?? throw new Exception("Deserialization failed.");
var deserializedScene = await JsonSerializer.DeserializeAsync<WorldNode>(readStream, Engine.Resources.EngineResource.defaultSerializerOptions) ?? throw new Exception("Deserialization failed.");
_loadedWorlds.Clear();
s_loadedWorlds.Clear();
_loadedWorlds[worldPath] = deserializedScene;
s_loadedWorlds[worldPath] = deserializedScene;
await deserializedScene.LoadAsync();
progressService.HideProgress();

View File

@@ -2,7 +2,7 @@ using Ghost.Editor.Core.Controls.Internal;
using Ghost.Editor.Core.Inspector;
using Ghost.Editor.Core.Resources;
using Ghost.Engine.Editor;
using Ghost.SparseEntities;
using Ghost.Entities;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -76,31 +76,46 @@ public partial class EntityNode : IInspectable
}
}
public UIElement? InspectorContent
public unsafe UIElement? InspectorContent
{
get
{
var r = Owner.World.EntityManager.GetEntityLocation(Entity);
if (!r)
{
return null;
}
var root = new StackPanel()
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Top
};
foreach (var (typeHandle, componentPtr) in Owner.World.EntityManager.GetComponentsUnsafe(Entity))
var location = r.Value;
ref var archetype = ref Owner.World.GetArchetypeReference(location.archetypeID);
var it = archetype._signature.GetIterator();
while (it.Next(out var typeID))
{
if (componentPtr == IntPtr.Zero)
var pComponent = archetype.GetComponentData(location.chunkIndex, location.rowIndex, typeID);
if (pComponent == null)
{
continue;
}
var type = typeHandle.ToType();
if (type == null || type.GetCustomAttribute<HideEditorAttribute>() != null)
if (!ComponentRegistry.s_runtimeIDToType.TryGetValue(typeID, out var t))
{
continue;
}
var dataView = new ComponentDataView(type.Name, Owner.World, Entity, type);
root.Children.Add(dataView);
if (t.GetCustomAttribute<HideEditorAttribute>() != null)
{
continue;
}
var componentView = new ComponentView(t.Name, Owner.World, Entity, t);
root.Children.Add(componentView);
}
return root;

View File

@@ -1,5 +1,5 @@
using Ghost.Engine.Components;
using Ghost.SparseEntities;
using Ghost.Entities;
namespace Ghost.Editor.Core.SceneGraph;
@@ -37,23 +37,23 @@ public class SceneGraphHelpers
{
// 1) If the child already has a parent, detach it first
var childHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(childNode.Entity);
if (childHierarchy.ValueRO.parent != Entity.Invalid)
if (childHierarchy.parent != Entity.Invalid)
{
DetachFromParent(scene, childNode);
}
// 2) Link child to new parent
childHierarchy.ValueRW.parent = parentNode.Entity;
childHierarchy.parent = parentNode.Entity;
// 3) Insert child at the head of parent's child list
var parentHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(parentNode.Entity);
childHierarchy.ValueRW.nextSibling = parentHierarchy.ValueRO.firstChild;
parentHierarchy.ValueRW.firstChild = childNode.Entity;
childHierarchy.nextSibling = parentHierarchy.firstChild;
parentHierarchy.firstChild = childNode.Entity;
// 4) Write back
scene.World.EntityManager.SetComponent(parentNode.Entity, in parentHierarchy.ValueRO);
scene.World.EntityManager.SetComponent(childNode.Entity, in childHierarchy.ValueRO);
scene.World.EntityManager.SetComponent(parentNode.Entity, parentHierarchy);
scene.World.EntityManager.SetComponent(childNode.Entity, childHierarchy);
// 5) Update children list in parent node
parentNode.AddChild(childNode);
@@ -67,7 +67,7 @@ public class SceneGraphHelpers
public static void DetachFromParent(WorldNode scene, EntityNode node)
{
var hierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(node.Entity);
var parent = hierarchy.ValueRO.parent;
var parent = hierarchy.parent;
if (parent == Entity.Invalid)
{
return; // already root
@@ -76,35 +76,35 @@ public class SceneGraphHelpers
var parentHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(parent);
// If entity is the first child, simply move head
if (parentHierarchy.ValueRO.firstChild == node.Entity)
if (parentHierarchy.firstChild == node.Entity)
{
parentHierarchy.ValueRW.firstChild = hierarchy.ValueRO.nextSibling;
parentHierarchy.firstChild = hierarchy.nextSibling;
}
else
{
// Otherwise, find the previous sibling in the linked list
var prevSibling = parentHierarchy.ValueRO.firstChild;
var prevSibling = parentHierarchy.firstChild;
while (prevSibling != Entity.Invalid)
{
var prevHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(prevSibling);
if (prevHierarchy.ValueRW.nextSibling == node.Entity)
if (prevHierarchy.nextSibling == node.Entity)
{
prevHierarchy.ValueRW.nextSibling = hierarchy.ValueRO.nextSibling;
scene.World.EntityManager.SetComponent(prevSibling, in prevHierarchy.ValueRO);
prevHierarchy.nextSibling = hierarchy.nextSibling;
scene.World.EntityManager.SetComponent(prevSibling, prevHierarchy);
break;
}
prevSibling = prevHierarchy.ValueRO.nextSibling;
prevSibling = prevHierarchy.nextSibling;
}
}
// Clear child's references
hierarchy.ValueRW.parent = Entity.Invalid;
hierarchy.ValueRW.nextSibling = Entity.Invalid;
hierarchy.parent = Entity.Invalid;
hierarchy.nextSibling = Entity.Invalid;
// Write back
scene.World.EntityManager.SetComponent(parent, in parentHierarchy.ValueRO);
scene.World.EntityManager.SetComponent(node.Entity, in hierarchy.ValueRO);
scene.World.EntityManager.SetComponent(parent, parentHierarchy);
scene.World.EntityManager.SetComponent(node.Entity, hierarchy);
// Remove from parent's children list
scene.EntityNodeLookup[parent].RemoveChild(node);

View File

@@ -3,14 +3,14 @@ using Ghost.Editor.Core.Inspector;
using Ghost.Editor.Core.Resources;
using Ghost.Editor.Core.Serializer;
using Ghost.Engine.Components;
using Ghost.SparseEntities;
using Ghost.Engine.IO;
using Ghost.Entities;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Text.Json.Serialization;
namespace Ghost.Editor.Core.SceneGraph;
[JsonConverter(typeof(WorldNodeSerializer))]
[CustomSerializer(typeof(WorldNodeSerializer))]
public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
{
private World _world;
@@ -27,11 +27,6 @@ public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
Name = name;
}
internal WorldNode()
{
_world = World.Create();
}
private void UpdateLookup(Entity key, EntityNode value)
{
_entityNodeLookup[key] = value;
@@ -85,13 +80,13 @@ public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
}
var hc = _world.EntityManager.GetComponent<Hierarchy>(entity);
var child = hc.ValueRO.firstChild;
var child = hc.firstChild;
while (child != Entity.Invalid)
{
node.AddChild(BuildNodeRecursive(child));
var childHC = _world.EntityManager.GetComponent<Hierarchy>(child);
child = childHC.ValueRO.nextSibling;
child = childHC.nextSibling;
}
return node;
@@ -99,14 +94,18 @@ public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
private void BuildGraph()
{
foreach (var (entity, hierarchy) in _world.Query<Hierarchy>())
var queryID = new QueryBuilder()
.WithAll<Hierarchy>()
.Build(_world);
_world.GetEntityQueryReference(queryID).ForEach<Hierarchy>((entity, ref hierarchy) =>
{
if (hierarchy.ValueRO.parent == Entity.Invalid)
if (hierarchy.parent == Entity.Invalid)
{
var node = BuildNodeRecursive(entity);
AddChild(node);
}
}
});
}
public Task LoadAsync()
@@ -116,7 +115,6 @@ public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
public void Unload()
{
_world.Dispose();
_world = null!;
Children?.Clear();

View File

@@ -1,13 +1,13 @@
using Ghost.Editor.Core.SceneGraph;
using Ghost.Engine;
using Ghost.Engine.IO;
using Ghost.Engine.Utilities;
using Ghost.SparseEntities;
using Ghost.SparseEntities.Components;
using Ghost.Entities;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Ghost.Editor.Core.Serializer;
internal class WorldNodeSerializer : JsonConverter<WorldNode>
internal class WorldNodeSerializer : CustomSerializer<WorldNode>
{
private static class Property
{
@@ -25,112 +25,124 @@ internal class WorldNodeSerializer : JsonConverter<WorldNode>
return typeToConvert == typeof(WorldNode) || typeToConvert.IsSubclassOf(typeof(WorldNode));
}
public override WorldNode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var element = JsonDocument.ParseValue(ref reader).RootElement;
var name = element.GetProperty(Property.NAME).GetString() ?? "New World";
var world = World.Create();
var result = new WorldNode(world, name);
foreach (var entityElement in element.GetProperty(Property.ENTITIES).EnumerateArray())
{
var entityName = entityElement.GetProperty(Property.NAME).GetString() ?? "New Entity";
var entityID = entityElement.GetProperty(Property.ID).GetInt32();
var entity = new Entity(entityID, 0);
var node = new EntityNode(result, entity, entityName);
world.EntityManager.AddEntityInternal(entity);
result.EntityNodeLookup[entity] = node;
}
foreach (var componentElement in element.GetProperty(Property.COMPONENTS).EnumerateObject())
{
var typeName = componentElement.Name;
var type = Type.GetType(typeName) ?? throw new Exception($"Type {typeName} not found.");
foreach (var dataElement in componentElement.Value.EnumerateArray())
{
var entityID = dataElement.GetProperty(Property.ENTITY_ID).GetInt32();
var entity = new Entity(entityID, 0);
var dataProperty = dataElement.GetProperty(Property.DATA);
var component = JsonSerializer.Deserialize(dataProperty.GetRawText(), type, options);
if (component is IComponentData data)
{
world.EntityManager.AddComponent(entity, data, type);
}
}
}
foreach (var systemElement in element.GetProperty(Property.SYSTEMS).EnumerateArray())
{
var typeString = systemElement.GetString();
if (string.IsNullOrEmpty(typeString))
{
continue;
}
var systemType = Type.GetType(typeString);
if (systemType == null)
{
continue;
}
world.SystemStorage.AddSystem(systemType);
}
return result;
}
public override void Write(Utf8JsonWriter writer, WorldNode value, JsonSerializerOptions options)
public unsafe override void SerializeJson(Utf8JsonWriter writer, WorldNode value, JsonSerializerOptions options)
{
writer.WriteObject(() =>
{
writer.WriteString(Property.NAME, value.Name);
writer.WriteArray(Property.ENTITIES, value.World.EntityManager.Entities, entity =>
{
if (!entity.IsValid)
{
return;
}
writer.WriteObject(() =>
{
writer.WriteString(Property.NAME, value.EntityNodeLookup[entity].Name);
writer.WriteNumber(Property.ID, entity.ID);
});
});
writer.WriteStartArray(Property.ENTITIES);
writer.WriteObject(Property.COMPONENTS, () =>
for (var i = 0; i < value.World.ArchetypeCount; i++)
{
for (var i = 0; i < value.World.ComponentStorage.ComponentPools.Count; i++)
ref var archetype = ref value.World.GetArchetypeReference(i);
for (var j = 0; j < archetype.ChunkCount; j++)
{
var pool = value.World.ComponentStorage.ComponentPools[i];
if (pool == null)
ref var chunk = ref archetype.GetChunkReference(j);
for (var k = 0; k < chunk._count; k++)
{
foreach (var layout in archetype._layouts)
{
var type = ComponentRegistry.s_runtimeIDToType[layout.componentID];
var size = ComponentRegistry.GetComponentInfo(layout.componentID).size;
if (type.AssemblyQualifiedName == null)
{
continue;
}
var type = value.World.ComponentStorage.GetComponentPoolType(i).GetType();
var typeName = type.AssemblyQualifiedName ?? type.Name;
writer.WriteStartObject(type.AssemblyQualifiedName);
writer.WriteArray(typeName, pool.Enumerate(), data =>
var pComponentData = chunk.GetUnsafePtr() + layout.offset + (k * size);
ComponentSerializerRegistry.SerializeJson(layout.componentID, writer, pComponentData, options);
}
}
}
}
writer.WriteEndArray();
writer.WriteArray(Property.SYSTEMS, value.World.SystemManager.Systems, system =>
{
writer.WriteObject(() =>
var name = system.GetType().AssemblyQualifiedName;
if (name == null)
{
writer.WriteNumber(Property.ENTITY_ID, data.entity.ID);
writer.WritePropertyName(Property.DATA);
JsonSerializer.Serialize(writer, data.component, type, options);
return;
}
writer.WriteStringValue(name);
});
});
}
});
writer.WriteArray(Property.SYSTEMS, value.World.SystemStorage.Systems, systemType =>
public override WorldNode? DeserializeJson(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
writer.WriteStringValue(systemType.AssemblyQualifiedName ?? systemType.Name);
});
});
throw new NotImplementedException();
//var element = JsonDocument.ParseValue(ref reader).RootElement;
//var name = element.GetProperty(Property.NAME).GetString() ?? "New World";
//var world = World.Create(EngineCore.JobScheduler);
//var result = new WorldNode(world, name);
//foreach (var entityElement in element.GetProperty(Property.ENTITIES).EnumerateArray())
//{
// var entityName = entityElement.GetProperty(Property.NAME).GetString() ?? "New Entity";
// var entityID = entityElement.GetProperty(Property.ID).GetInt32();
// var entity = new Entity(entityID, 0);
// var node = new EntityNode(result, entity, entityName);
// world.EntityManager.AddEntityInternal(entity);
// result.EntityNodeLookup[entity] = node;
//}
//foreach (var componentElement in element.GetProperty(Property.COMPONENTS).EnumerateObject())
//{
// var typeName = componentElement.Name;
// var type = Type.GetType(typeName) ?? throw new Exception($"Type {typeName} not found.");
// foreach (var dataElement in componentElement.Value.EnumerateArray())
// {
// var entityID = dataElement.GetProperty(Property.ENTITY_ID).GetInt32();
// var entity = new Entity(entityID, 0);
// var dataProperty = dataElement.GetProperty(Property.DATA);
// var component = JsonSerializer.Deserialize(dataProperty.GetRawText(), type, options);
// if (component is IComponent data)
// {
// world.EntityManager.AddComponent(entity, data, type);
// }
// }
//}
//foreach (var systemElement in element.GetProperty(Property.SYSTEMS).EnumerateArray())
//{
// var typeString = systemElement.GetString();
// if (string.IsNullOrEmpty(typeString))
// {
// continue;
// }
// var systemType = Type.GetType(typeString);
// if (systemType == null)
// {
// continue;
// }
// world.SystemStorage.AddSystem(systemType);
//}
//return result;
}
public override void SerializeBinary(BinaryWriter writer, WorldNode value)
{
throw new NotImplementedException();
}
public override WorldNode? DeserializeBinary(BinaryReader reader)
{
throw new NotImplementedException();
}
}

View File

@@ -5,7 +5,7 @@ namespace Ghost.Editor.Core.Utilities;
public static class TypeCache
{
private static readonly TypeInfo[] _types;
private static readonly TypeInfo[] s_types;
static TypeCache()
{
@@ -26,11 +26,11 @@ public static class TypeCache
}
}
_types = loadableTypes.Select(t => t.GetTypeInfo()).ToArray();
s_types = loadableTypes.Select(t => t.GetTypeInfo()).ToArray();
}
public static Type[] GetTypes()
{
return _types;
return s_types;
}
}

View File

@@ -36,7 +36,7 @@ internal class EditorState : IAppState
ProjectService.CurrentProject = metadataInfo;
_engineCore = App.GetService<EngineCore>();
_engineCore.Start(new Engine.Models.LaunchArgument());
_engineCore.Init(new Engine.Models.LaunchArgument());
CompositionTarget.Rendering += OnRendering;
_window = App.GetService<EngineEditorWindow>();

View File

@@ -8,49 +8,7 @@
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<!--<ItemGroup>
<Content Remove="Assets\icon-256.png" />
<Content Remove="Assets\Icon.altform-lightunplated_targetsize-16.png" />
<Content Remove="Assets\Icon.altform-lightunplated_targetsize-24.png" />
<Content Remove="Assets\Icon.altform-lightunplated_targetsize-256.png" />
<Content Remove="Assets\Icon.altform-lightunplated_targetsize-32.png" />
<Content Remove="Assets\Icon.altform-lightunplated_targetsize-48.png" />
<Content Remove="Assets\Icon.altform-unplated_targetsize-16.png" />
<Content Remove="Assets\Icon.altform-unplated_targetsize-24.png" />
<Content Remove="Assets\Icon.altform-unplated_targetsize-256.png" />
<Content Remove="Assets\Icon.altform-unplated_targetsize-32.png" />
<Content Remove="Assets\Icon.altform-unplated_targetsize-48.png" />
</ItemGroup>
<ItemGroup>
<None Remove="Assets\Icon.scale-100.png" />
<None Remove="Assets\Icon.scale-125.png" />
<None Remove="Assets\Icon.scale-150.png" />
<None Remove="Assets\Icon.scale-200.png" />
<None Remove="Assets\Icon.scale-400.png" />
<None Remove="Assets\Icon.targetsize-16.png" />
<None Remove="Assets\Icon.targetsize-16_altform-unplated.png" />
<None Remove="Assets\Icon.targetsize-24.png" />
<None Remove="Assets\Icon.targetsize-24_altform-lightunplated.png" />
<None Remove="Assets\Icon.targetsize-256.png" />
<None Remove="Assets\Icon.targetsize-256_altform-unplated.png" />
<None Remove="Assets\Icon.targetsize-32.png" />
<None Remove="Assets\Icon.targetsize-32_altform-lightunplated.png" />
<None Remove="Assets\Icon.targetsize-48.png" />
<None Remove="Assets\Icon.targetsize-48_altform-unplated.png" />
<None Remove="View\Pages\EngineEditor\ConsolePage.xaml" />
<None Remove="View\Pages\EngineEditor\HierarchyPage.xaml" />
<None Remove="View\Pages\EngineEditor\InspectorPage.xaml" />
<None Remove="View\Pages\EngineEditor\ProjectPage.xaml" />
<None Remove="View\Pages\EngineEditor\ScenePage.xaml" />
<None Remove="View\Pages\Landing\CreateProjectPage.xaml" />
<None Remove="View\Pages\Landing\OpenProjectPage.xaml" />
<None Remove="View\Windows\EngineEditorWindow.xaml" />
</ItemGroup>
<ItemGroup>
<Page Remove="App.xaml" />
</ItemGroup>-->
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
@@ -75,7 +33,7 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.TabbedCommandBar" Version="8.2.250402" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.1" />
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.7175" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.8.251106002" />
@@ -83,6 +41,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ghost.Editor.Core\Ghost.Editor.Core.csproj" />
<ProjectReference Include="..\Ghost.Entities\Ghost.Entities.csproj" />
</ItemGroup>
<ItemGroup>
<Page Update="View\Pages\Landing\CreateProjectPage.xaml">

View File

@@ -72,7 +72,7 @@ internal partial class CreateProjectViewModel(INotificationService notificationS
return;
}
var result = await projectService.CreateProjectAsync(ProjectName, ProjectLocation, EngineData.s_engineVersion, SelectedTemplate.Value.directory);
var result = await projectService.CreateProjectAsync(ProjectName, ProjectLocation, EngineData.EngineVersion, SelectedTemplate.Value.directory);
if (result.IsFailure)
{
notificationService.ShowNotification(result.Message, MessageType.Error);

View File

@@ -7,7 +7,7 @@ namespace Ghost.Editor.ViewModels.Windows;
internal partial class EngineEditorViewModel : ObservableRecipient
{
public string engineVersionDescriptor = $"{EngineData.ENGINE_NAME} - {EngineData.s_engineVersion}";
public string engineVersionDescriptor = $"{EngineData.ENGINE_NAME} - {EngineData.EngineVersion}";
public ProjectMetadataInfo CurrentProject => ProjectService.CurrentProject;
}

View File

@@ -2,5 +2,6 @@ using Ghost.Core.Attributes;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Ghost.Editor")]
[assembly: InternalsVisibleTo("Ghost.Editor.Core")]
[assembly: EngineAssembly]

View File

@@ -1,13 +1,12 @@
using Ghost.Engine.Editor;
using Ghost.SparseEntities;
using Ghost.SparseEntities.Components;
using Ghost.Entities;
using System.Runtime.CompilerServices;
namespace Ghost.Engine.Components;
[SkipLocalsInit]
[HideEditor]
public struct Hierarchy : IComponentData
public struct Hierarchy : IComponent
{
public Entity parent;
public Entity firstChild;

View File

@@ -1,21 +1,11 @@
using Ghost.Engine.Utilities;
using Ghost.SparseEntities.Components;
using System.Numerics;
using Ghost.Entities;
using Misaki.HighPerformance.Mathematics;
using System.Runtime.CompilerServices;
namespace Ghost.Engine.Components;
[SkipLocalsInit]
public struct LocalToWorld : IComponentData
public struct LocalToWorld : IComponent
{
public Matrix4x4 matrix;
public static LocalToWorld Identity
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new()
{
matrix = MatrixUtility.CreateTRS(Vector3.Zero, Quaternion.Identity, Vector3.One)
};
}
public float4x4 matrix;
}

View File

@@ -1,28 +1,55 @@
using Ghost.Core;
using Ghost.Engine.Models;
using Ghost.Entities;
using Misaki.HighPerformance.Jobs;
namespace Ghost.Engine;
internal class EngineCore
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
internal class EngineEntryAttribute : Attribute
{
public void Start(LaunchArgument args)
}
internal partial class EngineCoreImpl : IDisposable
{
internal readonly JobScheduler _jobScheduler;
internal EngineCoreImpl()
{
ActivationHandler.Handle(args);
//GraphicsPipeline.Initialize();
//GraphicsPipeline.Start();
Logger.LogInfo("Engine started successfully.");
_jobScheduler = new JobScheduler(Environment.ProcessorCount - 2); // We -2 here, one for main thread, one for render thread
}
public void IncrementCPUFenceValue()
internal void IncrementCPUFenceValue()
{
//GraphicsPipeline.SignalCPUReady();
}
public void ShutDown()
public void Dispose()
{
//GraphicsPipeline.SignalCPUReady();
//GraphicsPipeline.Shutdown();
_jobScheduler.Dispose();
JobScheduler.ReleaseTempAllocator();
}
}
[EngineEntry]
public static partial class EngineCore
{
internal static readonly EngineCoreImpl s_impl;
public static JobScheduler JobScheduler => s_impl._jobScheduler;
static EngineCore()
{
s_impl = new EngineCoreImpl();
ComponentRegistry.GetOrRegisterComponent<ManagedEntityRef>();
RegisterIComponentTypes();
}
internal static void Init()
{
}
internal static void Dispose()
{
s_impl.Dispose();
}
}

View File

@@ -16,9 +16,10 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ghost.SparseEntities\Ghost.SparseEntities.csproj" />
<ProjectReference Include="..\Ghost.Core\Ghost.Core.csproj" />
<ProjectReference Include="..\Ghost.Entities\Ghost.Entities.csproj" />
<ProjectReference Include="..\Ghost.Generator\Ghost.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\Ghost.Graphics\Ghost.Graphics.csproj" />
<!--<ProjectReference Include="..\Ghost.Generator\Ghost.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />-->
</ItemGroup>
</Project>

View File

@@ -0,0 +1,32 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Ghost.Engine.IO;
public class CustomSerializerAttribute : JsonConverterAttribute
{
public CustomSerializerAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type serializerType)
: base(serializerType)
{
}
}
public abstract class CustomSerializer<T> : JsonConverter<T>
{
public sealed override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DeserializeJson(ref reader, options);
}
public sealed override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
SerializeJson(writer, value, options);
}
public abstract void SerializeJson(Utf8JsonWriter writer, T value, JsonSerializerOptions options);
public abstract T? DeserializeJson(ref Utf8JsonReader reader, JsonSerializerOptions options);
public abstract void SerializeBinary(BinaryWriter writer, T value);
public abstract T? DeserializeBinary(BinaryReader reader);
}

View File

@@ -0,0 +1,52 @@
using Ghost.Core;
using Ghost.Entities;
using System.Text.Json;
namespace Ghost.Engine.IO;
public static unsafe class ComponentSerializerRegistry
{
public delegate void BinaryWriteDelegate(BinaryWriter writer, void* ptr);
public delegate void JsonWriteDelegate(Utf8JsonWriter writer, void* ptr, JsonSerializerOptions options);
private static BinaryWriteDelegate[] s_binWriters = new BinaryWriteDelegate[64];
private static JsonWriteDelegate[] s_jsonWriters = new JsonWriteDelegate[64];
public static void Register(int typeID, BinaryWriteDelegate binWriter, JsonWriteDelegate jsonWriter)
{
if (typeID < 0)
{
throw new Exception($"Type ID cannot be negative: {typeID}");
}
if (typeID >= s_binWriters.Length)
{
Array.Resize(ref s_binWriters, typeID + 16);
Array.Resize(ref s_jsonWriters, typeID + 16);
}
s_binWriters[typeID] = binWriter;
s_jsonWriters[typeID] = jsonWriter;
}
public static void SerializeBinary(Identifier<IComponent> typeID, BinaryWriter writer, void* ptr)
{
if (s_binWriters[typeID] == null)
{
throw new Exception($"No serializer for ID {typeID}");
}
s_binWriters[typeID](writer, ptr);
}
public static void SerializeJson(Identifier<IComponent> typeID, Utf8JsonWriter writer, void* ptr, JsonSerializerOptions options)
{
if (s_jsonWriters[typeID] == null)
{
// TODO: Fallback to reflection?
return;
}
s_jsonWriters[typeID](writer, ptr, options);
}
}

View File

@@ -4,5 +4,5 @@ internal class EngineData
{
public const string ENGINE_NAME = "Ghost Engine";
public readonly static Version s_engineVersion = new(0, 1, 0);
public readonly static Version EngineVersion = new(0, 1, 0);
}

View File

@@ -2,7 +2,7 @@ using System.Text.Json;
namespace Ghost.Engine.Resources;
public static class StaticResource
public static class EngineResource
{
public static readonly JsonSerializerOptions defaultSerializerOptions = new()
{

View File

@@ -1,57 +0,0 @@
using Ghost.SparseEntities;
namespace Ghost.Engine.Services;
internal static class PlayerLoopService
{
private static bool _isRunning = false;
// TODO: Implement the actual time system
public static float fixedDeltaTime = 0.02f;
public static void Start()
{
if (_isRunning)
{
return;
}
for (var i = 0; i < World.WorldCount; i++)
{
var world = World.GetWorld(i);
foreach (var script in world.QueryScript())
{
script.Start();
}
}
}
public static void Update()
{
for (var i = 0; i < World.WorldCount; i++)
{
var world = World.GetWorld(i);
world.SystemStorage.UpdateSystems();
foreach (var script in world.QueryScript())
{
script.Update();
}
}
}
public static void Shutdown()
{
for (var i = 0; i < World.WorldCount; i++)
{
var world = World.GetWorld(i);
foreach (var script in world.QueryScript())
{
script.OnDestroy();
}
}
_isRunning = false;
}
}

View File

@@ -1,5 +1,6 @@
using Ghost.Test.Core;
using Misaki.HighPerformance.Jobs;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.Mathematics;
namespace Ghost.Entities.Test;
@@ -40,7 +41,11 @@ public partial class EntityQueryTest : ITest
public void Run()
{
var entities = (Span<Entity>)stackalloc Entity[1000];
_world.EntityManager.CreateEntities(entities, ComponentTypeID<Transform>.value);
using var scope = AllocationManager.CreateStackScope();
using var set = new ComponentSet(scope.AllocationHandle, ComponentTypeID<Transform>.Value);
_world.EntityManager.CreateEntities(entities, set);
var queryID = new QueryBuilder().WithAllRW<Transform>().Build(_world);
ref var query = ref _world.GetEntityQueryReference(queryID);

View File

@@ -5,6 +5,8 @@
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>True</PublishAot>
<PublishTrimmed>True</PublishTrimmed>
</PropertyGroup>
<ItemGroup>

View File

@@ -74,7 +74,7 @@ internal unsafe sealed class ChunkDebugView
var it = archetype._signature.GetIterator();
while (it.Next(out var index))
{
var type = ComponentRegister.s_runtimeIDToType[index];
var type = ComponentRegistry.s_runtimeIDToType[index];
if (type == null)
{
continue;
@@ -238,7 +238,7 @@ internal unsafe struct Archetype : IDisposable
for (var i = 0; i < componentIds.Length; i++)
{
_signature.SetBit(componentIds[i]);
components[i] = ComponentRegister.GetComponentInfo(componentIds[i]);
components[i] = ComponentRegistry.GetComponentInfo(componentIds[i]);
}
// Calculate total size per entity to get an initial capacity estimate
@@ -394,7 +394,7 @@ internal unsafe struct Archetype : IDisposable
ref var chunk = ref _chunks[chunkIndex];
var chunkBase = chunk.GetUnsafePtr();
var size = ComponentRegister.GetComponentInfo(componentID).size;
var size = ComponentRegistry.GetComponentInfo(componentID).size;
var dst = chunkBase + offset + (size * rowIndex);
MemoryUtility.MemCpy(dst, pComponent, (nuint)size);
@@ -418,7 +418,7 @@ internal unsafe struct Archetype : IDisposable
var chunk = _chunks[chunkIndex];
var chunkBase = chunk.GetUnsafePtr();
var size = ComponentRegister.GetComponentInfo(componentID).size;
var size = ComponentRegistry.GetComponentInfo(componentID).size;
return chunkBase + offset + (size * rowIndex);
}

View File

@@ -1,4 +1,5 @@
using Ghost.Core;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.CompilerServices;
@@ -16,26 +17,88 @@ public interface IEnableableComponent : IComponent
internal struct ComponentInfo
{
// public string stableName; // Do we actually need this?
public int id;
public Identifier<IComponent> id;
public int size;
public int alignment;
public bool isEnableable;
}
/// <summary>
/// Represents an immutable set of component identifiers used to define a group of components within an entity or system.
/// </summary>
public struct ComponentSet : IDisposable, IEquatable<ComponentSet>
{
private UnsafeArray<Identifier<IComponent>> _components;
private int _hashCode;
public readonly ReadOnlySpan<Identifier<IComponent>> Components => _components.AsSpan();
public ComponentSet(AllocationHandle allocationHandle, params ReadOnlySpan<Identifier<IComponent>> components)
{
_components = new UnsafeArray<Identifier<IComponent>>(components.Length, allocationHandle);
components.CopyTo(_components.AsSpan());
_hashCode = -1;
}
public ComponentSet(Allocator allocator, params ReadOnlySpan<Identifier<IComponent>> components)
: this(AllocationManager.GetAllocationHandle(allocator), components)
{
}
public readonly bool Equals(ComponentSet other)
{
return _hashCode == other._hashCode;
}
public override int GetHashCode()
{
if (_hashCode == -1)
{
_hashCode = ComponentRegistry.GetHashCode(_components.AsSpan());
}
return _hashCode;
}
public override bool Equals(object? obj)
{
return obj is ComponentSet set && Equals(set);
}
public static bool operator ==(ComponentSet left, ComponentSet right)
{
return left.Equals(right);
}
public static bool operator !=(ComponentSet left, ComponentSet right)
{
return !(left == right);
}
public void Dispose()
{
_components.Dispose();
}
}
/// <summary>
/// Provides a unique identifier for the specified unmanaged component type.
/// </summary>
/// <typeparam name="T">The component type for which to obtain an identifier. Must be unmanaged and implement <see cref="IComponent"/>.</typeparam>
public static class ComponentTypeID<T>
where T : unmanaged, IComponent
{
public static readonly Identifier<IComponent> value = ComponentRegister.GetOrRegisterComponent<T>();
public static readonly Identifier<IComponent> Value = ComponentRegistry.GetOrRegisterComponent<T>();
}
internal static class ComponentRegister
internal static class ComponentRegistry
{
private static readonly List<ComponentInfo> s_registeredComponents = new();
private static readonly Dictionary<IntPtr, int> s_typeHandleToID = new();
private static readonly Dictionary<string, int> s_nameToRuntimeID = new();
#if DEBUG || GHOST_EDITOR
internal static readonly Dictionary<int, Type> s_runtimeIDToType = new();
#endif
public static unsafe Identifier<IComponent> GetOrRegisterComponent<T>()
where T : unmanaged, IComponent
@@ -66,9 +129,7 @@ internal static class ComponentRegister
s_typeHandleToID[typeHandle] = newID;
s_nameToRuntimeID[stableName] = newID;
#if DEBUG || GHOST_EDITOR
s_runtimeIDToType[newID.value] = typeof(T);
#endif
return newID;
}
@@ -98,7 +159,21 @@ internal static class ComponentRegister
}
}
// TODO: A ComponentSet structure to cache the hashcode for better performance.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ComponentInfo GetComponentInfo(Type type)
{
lock (s_registeredComponents)
{
var typeId = GetComponentID(type);
if (typeId.IsInvalid)
{
throw new KeyNotFoundException($"Component type {type.FullName} is not registered.");
}
return s_registeredComponents[typeId];
}
}
public static int GetHashCode(params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
{
var largestID = 0;

View File

@@ -108,12 +108,12 @@ public unsafe class EntityCommandBuffer : IDisposable
Write(count);
}
public void CreateEntity(int count, params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
public void CreateEntity(int count, ComponentSet set)
{
WriteHeader(ECBOpCode.CreateEntityWithComponents);
Write(count);
Write(componentTypeIDs.Length);
WriteSpan(componentTypeIDs);
Write(set.Components.Length);
WriteSpan(set.Components);
}
public void DestroyEntity(Entity entity)
@@ -127,7 +127,7 @@ public unsafe class EntityCommandBuffer : IDisposable
{
WriteHeader(ECBOpCode.AddComponent);
Write(entity);
Write(ComponentTypeID<T>.value);
Write(ComponentTypeID<T>.Value);
Write(component);
}
@@ -136,7 +136,7 @@ public unsafe class EntityCommandBuffer : IDisposable
{
WriteHeader(ECBOpCode.RemoveComponent);
Write(entity);
Write(ComponentTypeID<T>.value);
Write(ComponentTypeID<T>.Value);
}
public void SetComponent<T>(Entity entity, T component)
@@ -144,7 +144,7 @@ public unsafe class EntityCommandBuffer : IDisposable
{
WriteHeader(ECBOpCode.SetComponent);
Write(entity);
Write(ComponentTypeID<T>.value);
Write(ComponentTypeID<T>.Value);
Write(component);
}
@@ -157,6 +157,8 @@ public unsafe class EntityCommandBuffer : IDisposable
{
var op = Read<ECBOpCode>(ref cursor);
using var scope = AllocationManager.CreateStackScope();
switch (op)
{
case ECBOpCode.CreateEntity:
@@ -168,7 +170,8 @@ public unsafe class EntityCommandBuffer : IDisposable
var entityCount = Read<int>(ref cursor);
var compCount = Read<int>(ref cursor);
var compTypeIDs = ReadSpan<Identifier<IComponent>>(ref cursor, compCount);
_entityManager.CreateEntities(entityCount, compTypeIDs);
var set = new ComponentSet(scope.AllocationHandle, compTypeIDs);
_entityManager.CreateEntities(entityCount, set);
break;
case ECBOpCode.DestroyEntity:
@@ -179,7 +182,7 @@ public unsafe class EntityCommandBuffer : IDisposable
case ECBOpCode.AddComponent:
var entityToAdd = Read<Entity>(ref cursor);
var addCompTypeID = Read<Identifier<IComponent>>(ref cursor);
var pAddCompData = ReadBuffer(ref cursor, ComponentRegister.GetComponentInfo(addCompTypeID).size);
var pAddCompData = ReadBuffer(ref cursor, ComponentRegistry.GetComponentInfo(addCompTypeID).size);
_entityManager.AddComponent(entityToAdd, addCompTypeID, pAddCompData);
break;
@@ -192,7 +195,7 @@ public unsafe class EntityCommandBuffer : IDisposable
case ECBOpCode.SetComponent:
var entityToSet = Read<Entity>(ref cursor);
var setCompTypeID = Read<Identifier<IComponent>>(ref cursor);
var pSetCompData = ReadBuffer(ref cursor, ComponentRegister.GetComponentInfo(setCompTypeID).size);
var pSetCompData = ReadBuffer(ref cursor, ComponentRegistry.GetComponentInfo(setCompTypeID).size);
_entityManager.SetComponent(entityToSet, setCompTypeID, pSetCompData);
break;
}

View File

@@ -110,7 +110,7 @@ public partial class EntityManager
var location = _entityLocations.GetElementAt(entity.ID, entity.Generation);
ref var archetype = ref _world.GetArchetypeReference(location.archetypeID);
var pManagedEntityRef = (ManagedEntityRef*)archetype.GetComponentData(location.chunkIndex, location.rowIndex, ComponentTypeID<ManagedEntityRef>.value);
var pManagedEntityRef = (ManagedEntityRef*)archetype.GetComponentData(location.chunkIndex, location.rowIndex, ComponentTypeID<ManagedEntityRef>.Value);
if (pManagedEntityRef == null)
{
throw new InvalidOperationException($"Entity {entity} does not have ManagedEntityRef component.");

View File

@@ -7,18 +7,8 @@ using System.Diagnostics;
namespace Ghost.Entities;
/// <summary>
/// A manager for creating, destroying, and managing entities and their components.
/// </summary>
/// <remarks>
/// All methods in this class are not thread-safe and all of them will cause structural changes if not mentioned otherwise.
/// Use <see cref="EntityCommandBuffer"/> to defer structural changes to a safe point.
/// Use <see cref="World.GetThreadLocalEntityCommandBuffer(int)"/> to get a thread-local command buffer for multithreaded scenarios.
/// </remarks>
public unsafe partial class EntityManager : IDisposable
internal struct EntityLocation : IComparable<EntityLocation>
{
private struct EntityLocation : IComparable<EntityLocation>
{
public int archetypeID;
public int chunkIndex;
public int rowIndex;
@@ -39,12 +29,24 @@ public unsafe partial class EntityManager : IDisposable
return rowIndex.CompareTo(other.rowIndex);
}
}
}
/// <summary>
/// A manager for creating, destroying, and managing entities and their components.
/// </summary>
/// <remarks>
/// All methods in this class are not thread-safe and all of them will cause structural changes if not mentioned otherwise.
/// Use <see cref="EntityCommandBuffer"/> to defer structural changes to a safe point.
/// Use <see cref="World.GetThreadLocalEntityCommandBuffer(int)"/> to get a thread-local command buffer for multithreaded scenarios.
/// </remarks>
public unsafe partial class EntityManager : IDisposable
{
private readonly World _world;
private UnsafeSlotMap<EntityLocation> _entityLocations;
private bool _disposed;
public World World => _world;
internal EntityManager(World world, int initialCapacity)
{
_world = world;
@@ -73,6 +75,16 @@ public unsafe partial class EntityManager : IDisposable
return ErrorStatus.None;
}
internal Result<EntityLocation, ErrorStatus> GetEntityLocation(Entity entity)
{
if (_entityLocations.TryGetElementAt(entity.ID, entity.Generation, out var location))
{
return location;
}
return ErrorStatus.NotFound;
}
/// <summary>
/// Create an entity with no components.
/// </summary>
@@ -88,12 +100,12 @@ public unsafe partial class EntityManager : IDisposable
/// <summary>
/// Create an entity with specified components.
/// </summary>
/// <param name="componentTypeIDs">The component type IDs to add to the entity.</param>
/// <param name="set">A set of component type IDs to add to the entities.</param>
/// <returns>The created entity.</returns>
public Entity CreateEntity(params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
public Entity CreateEntity(ComponentSet set)
{
var entities = (Span<Entity>)stackalloc Entity[1];
CreateEntities(entities, componentTypeIDs);
CreateEntities(entities, set);
return entities[0];
}
@@ -150,16 +162,15 @@ public unsafe partial class EntityManager : IDisposable
/// Create multiple entities with specified components.
/// </summary>
/// <param name="allocator">The allocator to use for the returned array.</param>
/// <param name="componentTypeIDs">The component type IDs to add to the entities. </param>
/// <param name="set">A set of component type IDs to add to the entities.</param>
/// <returns>An array of the created entities.</returns>
public void CreateEntities(Span<Entity> entities, params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
public void CreateEntities(Span<Entity> entities, ComponentSet set)
{
var signatureHash = ComponentRegister.GetHashCode(componentTypeIDs);
var arcID = _world.GetArchetypeIDBySignatureHash(signatureHash);
var arcID = _world.GetArchetypeIDBySignatureHash(set.GetHashCode());
if (arcID.IsNotValid)
if (arcID.IsInvalid)
{
arcID = _world.CreateArchetype(componentTypeIDs, signatureHash);
arcID = _world.CreateArchetype(set.Components, set.GetHashCode());
}
ref var archetype = ref _world.GetArchetypeReference(arcID);
@@ -186,15 +197,15 @@ public unsafe partial class EntityManager : IDisposable
/// Create multiple entities with specified components.
/// </summary>
/// <param name="count">The number of entities to create.</param>
/// <param name="componentTypeIDs">The component type IDs to add to the entities. </param>
public void CreateEntities(int count, params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
/// <param name="set">A set of component type IDs to add to the entities.</param>
public void CreateEntities(int count, ComponentSet set)
{
var signatureHash = ComponentRegister.GetHashCode(componentTypeIDs);
var arcID = _world.GetArchetypeIDBySignatureHash(signatureHash);
var hash = set.GetHashCode();
var arcID = _world.GetArchetypeIDBySignatureHash(hash);
if (arcID.IsNotValid)
if (arcID.IsInvalid)
{
arcID = _world.CreateArchetype(componentTypeIDs, signatureHash);
arcID = _world.CreateArchetype(set.Components, hash);
}
ref var archetype = ref _world.GetArchetypeReference(arcID);
@@ -217,7 +228,7 @@ public unsafe partial class EntityManager : IDisposable
private void DestoryManagedEntityIfExists(ref readonly Archetype archetype, EntityLocation location)
{
var pManagedRef = archetype.GetComponentData(location.chunkIndex, location.rowIndex, ComponentTypeID<ManagedEntityRef>.value);
var pManagedRef = archetype.GetComponentData(location.chunkIndex, location.rowIndex, ComponentTypeID<ManagedEntityRef>.Value);
if (pManagedRef != null)
{
DestroyManagedEntity(((ManagedEntityRef*)pManagedRef)->entity);
@@ -260,7 +271,7 @@ public unsafe partial class EntityManager : IDisposable
{
void RemoveManagedEntity(ReadOnlySpan<int> rowIndicesCache, ref readonly Archetype archetype, int chunkIndex)
{
for (int j = 0; j < rowIndicesCache.Length; j++)
for (var j = 0; j < rowIndicesCache.Length; j++)
{
var rowIndex = rowIndicesCache[j];
var location = new EntityLocation
@@ -285,7 +296,7 @@ public unsafe partial class EntityManager : IDisposable
// 1. GATHER
// Resolve all entities to their locations
for (int i = 0; i < entities.Length; i++)
for (var i = 0; i < entities.Length; i++)
{
var entity = entities[i];
if (_entityLocations.TryGetElementAt(entity.ID, entity.Generation, out var location))
@@ -309,12 +320,12 @@ public unsafe partial class EntityManager : IDisposable
var prevArchetypeID = firstLoc.archetypeID;
var prevChunkIndex = firstLoc.chunkIndex;
for (int i = 0; i < batchDestroy.Count; i++)
for (var i = 0; i < batchDestroy.Count; i++)
{
var loc = batchDestroy[i];
// Check if we have crossed a boundary (Different Chunk OR Different Archetype)
bool isNewBatch = (loc.chunkIndex != prevChunkIndex) || (loc.archetypeID != prevArchetypeID);
var isNewBatch = (loc.chunkIndex != prevChunkIndex) || (loc.archetypeID != prevArchetypeID);
if (isNewBatch)
{
@@ -348,7 +359,7 @@ public unsafe partial class EntityManager : IDisposable
}
// 5. Remove from Entity Locations
for (int i = 0; i < entities.Length; i++)
for (var i = 0; i < entities.Length; i++)
{
var entity = entities[i];
_entityLocations.Remove(entity.ID, entity.Generation);
@@ -379,7 +390,7 @@ public unsafe partial class EntityManager : IDisposable
}
// Check if singleton already exists
var signatureHash = ComponentRegister.GetHashCode(componentID);
var signatureHash = ComponentRegistry.GetHashCode(componentID);
var arcID = _world.GetArchetypeIDBySignatureHash(signatureHash);
if (arcID.IsValid)
@@ -415,7 +426,7 @@ public unsafe partial class EntityManager : IDisposable
public ErrorStatus CreateSingleton<T>(T component = default)
where T : unmanaged, IComponent
{
return CreateSingleton(ComponentTypeID<T>.value, &component);
return CreateSingleton(ComponentTypeID<T>.Value, &component);
}
/// <summary>
@@ -425,10 +436,10 @@ public unsafe partial class EntityManager : IDisposable
/// <returns>Pointer to the component data, or null if not found.</returns>
public void* GetSingleton(Identifier<IComponent> componentID)
{
var signatureHash = ComponentRegister.GetHashCode(componentID);
var signatureHash = ComponentRegistry.GetHashCode(componentID);
var arcID = _world.GetArchetypeIDBySignatureHash(signatureHash);
if (arcID.IsNotValid)
if (arcID.IsInvalid)
{
return null;
}
@@ -454,7 +465,7 @@ public unsafe partial class EntityManager : IDisposable
public ref T GetSingleton<T>()
where T : unmanaged, IComponent
{
var ptr = GetSingleton(ComponentTypeID<T>.value);
var ptr = GetSingleton(ComponentTypeID<T>.Value);
return ref *(T*)ptr; // This will return null ref if ptr is null.
}
@@ -508,7 +519,7 @@ public unsafe partial class EntityManager : IDisposable
}
var newArcID = oldArchetype.GetEdgeAdd(componentID);
if (newArcID.IsNotValid)
if (newArcID.IsInvalid)
{
var largestComponentID = Math.Max(oldSignature.Count, componentID);
var length = UnsafeBitSet.RequiredLength(largestComponentID + 1);
@@ -532,7 +543,7 @@ public unsafe partial class EntityManager : IDisposable
// Find or create new archetype
var newSignatureHash = newSignature.GetHashCode();
newArcID = _world.GetArchetypeIDBySignatureHash(newSignatureHash);
if (newArcID.IsNotValid)
if (newArcID.IsInvalid)
{
// Create new archetype
Span<Identifier<IComponent>> componentTypeIDs = stackalloc Identifier<IComponent>[compCount];
@@ -584,7 +595,7 @@ public unsafe partial class EntityManager : IDisposable
public ErrorStatus AddComponent<T>(Entity entity, T component = default)
where T : unmanaged, IComponent
{
return AddComponent(entity, ComponentTypeID<T>.value, &component);
return AddComponent(entity, ComponentTypeID<T>.Value, &component);
}
/// <summary>
@@ -607,7 +618,7 @@ public unsafe partial class EntityManager : IDisposable
var oldSignature = oldArchetype._signature;
var newArcID = oldArchetype.GetEdgeRemove(componentID);
if (newArcID.IsNotValid)
if (newArcID.IsInvalid)
{
var largestComponentID = Math.Max(oldSignature.Count, componentID);
var length = UnsafeBitSet.RequiredLength(largestComponentID + 1);
@@ -631,7 +642,7 @@ public unsafe partial class EntityManager : IDisposable
// Find or create new archetype
var newSignatureHash = newSignature.GetHashCode();
newArcID = _world.GetArchetypeIDBySignatureHash(newSignatureHash);
if (newArcID.IsNotValid)
if (newArcID.IsInvalid)
{
// Create new archetype
Span<Identifier<IComponent>> componentTypeIDs = stackalloc Identifier<IComponent>[compCount];
@@ -664,7 +675,7 @@ public unsafe partial class EntityManager : IDisposable
return r;
}
var pManagedRef = oldArchetype.GetComponentData(location.chunkIndex, location.rowIndex, ComponentTypeID<ManagedEntityRef>.value);
var pManagedRef = oldArchetype.GetComponentData(location.chunkIndex, location.rowIndex, ComponentTypeID<ManagedEntityRef>.Value);
if (pManagedRef != null)
{
DestroyManagedEntity(((ManagedEntityRef*)pManagedRef)->entity);
@@ -687,7 +698,7 @@ public unsafe partial class EntityManager : IDisposable
public ErrorStatus RemoveComponent<T>(Entity entity)
where T : unmanaged, IComponent
{
return RemoveComponent(entity, ComponentTypeID<T>.value);
return RemoveComponent(entity, ComponentTypeID<T>.Value);
}
/// <summary>
@@ -719,7 +730,7 @@ public unsafe partial class EntityManager : IDisposable
public ErrorStatus SetComponent<T>(Entity entity, T component)
where T : unmanaged, IComponent
{
return SetComponent(entity, ComponentTypeID<T>.value, &component);
return SetComponent(entity, ComponentTypeID<T>.Value, &component);
}
/// <summary>
@@ -748,7 +759,7 @@ public unsafe partial class EntityManager : IDisposable
public ref T GetComponent<T>(Entity entity)
where T : unmanaged, IComponent
{
var ptr = GetComponent(entity, ComponentTypeID<T>.value);
var ptr = GetComponent(entity, ComponentTypeID<T>.Value);
return ref *(T*)ptr; // This will return null ref if ptr is null.
}
@@ -778,7 +789,7 @@ public unsafe partial class EntityManager : IDisposable
public bool HasComponent<T>(Entity entity)
where T : unmanaged, IComponent
{
return HasComponent(entity, ComponentTypeID<T>.value);
return HasComponent(entity, ComponentTypeID<T>.Value);
}
/// <summary>
@@ -834,7 +845,7 @@ public unsafe partial class EntityManager : IDisposable
public ErrorStatus SetEnabled<T>(Entity entity, bool enabled)
where T : unmanaged, IEnableableComponent
{
return SetEnabled(entity, ComponentTypeID<T>.value, enabled);
return SetEnabled(entity, ComponentTypeID<T>.Value, enabled);
}
public void Dispose()

View File

@@ -17,10 +17,6 @@
<IsTrimmable>True</IsTrimmable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Templates\ForEach.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Templates\EntityQuery.ForEach.gen.cs">
<DesignTime>True</DesignTime>

View File

@@ -24,7 +24,7 @@ public readonly struct Managed<T> : IComponent, IManagedWrapper
public static class ManagedComponemtnID<T>
where T : IManagedComponent
{
public static readonly Identifier<IManagedComponent> value = ManagedComponentRegister.GetOrRegisterComponent<T>();
public static readonly Identifier<IManagedComponent> value = ManagedComponentRegistry.GetOrRegisterComponent<T>();
}
internal struct ManagedComponentInfo
@@ -33,7 +33,7 @@ internal struct ManagedComponentInfo
public bool isScriptComponent;
}
internal static class ManagedComponentRegister
internal static class ManagedComponentRegistry
{
private static readonly List<ManagedComponentInfo> s_registeredComponents = new();
private static readonly Dictionary<IntPtr, int> s_typeHandleToID = new();

View File

@@ -145,7 +145,7 @@ public readonly unsafe ref struct ChunkView
public readonly bool HasChanged<T>(int version)
where T : unmanaged, IComponent
{
var layout = GetLayout(ComponentTypeID<T>.value);
var layout = GetLayout(ComponentTypeID<T>.Value);
return version < _pVersion[layout.versionIndex];
}
@@ -180,7 +180,7 @@ public readonly unsafe ref struct ChunkView
public readonly int GetComponentVersion<T>()
where T : unmanaged, IComponent
{
return _pVersion[ComponentTypeID<T>.value];
return _pVersion[ComponentTypeID<T>.Value];
}
/// <summary>
@@ -204,7 +204,7 @@ public readonly unsafe ref struct ChunkView
public ReadOnlySpan<T> GetComponentData<T>()
where T : unmanaged, IComponent
{
var layout = GetLayout(ComponentTypeID<T>.value);
var layout = GetLayout(ComponentTypeID<T>.Value);
var pComponentData = _pChunkData + layout.offset;
return new ReadOnlySpan<T>(pComponentData, _entityCount);
}
@@ -219,7 +219,7 @@ public readonly unsafe ref struct ChunkView
public Span<T> GetComponentDataRW<T>()
where T : unmanaged, IComponent
{
var compId = ComponentTypeID<T>.value;
var compId = ComponentTypeID<T>.Value;
var layout = GetLayout(compId);
_pVersion[layout.versionIndex] = _currentVersion;
@@ -239,7 +239,7 @@ public readonly unsafe ref struct ChunkView
public SpanBitSet GetEnableBits<T>()
where T : unmanaged, IEnableableComponent
{
var layout = _layouts[ComponentTypeID<T>.value];
var layout = _layouts[ComponentTypeID<T>.Value];
var maskBase = _pChunkData + layout.enableBitsOffset;
return new SpanBitSet(new Span<uint>(maskBase, (_entityCount + 31) / 32));
}
@@ -255,7 +255,7 @@ public readonly unsafe ref struct ChunkView
public bool IsComponentEnabled<T>(int index)
where T : unmanaged, IEnableableComponent
{
var layout = GetLayout(ComponentTypeID<T>.value);
var layout = GetLayout(ComponentTypeID<T>.Value);
var pMask = _pChunkData + layout.enableBitsOffset;
return EntityQuery.CheckBit(pMask, index);
}
@@ -545,7 +545,7 @@ public ref partial struct QueryBuilder
foreach (var id in _none)
{
if (ComponentRegister.GetComponentInfo(id).isEnableable)
if (ComponentRegistry.GetComponentInfo(id).isEnableable)
{
mask.rejectIfEnabled.SetBit(id); // Filter: Must Not be Enabled (Can be Absent or Disabled)
}

View File

@@ -61,12 +61,12 @@ public abstract class SystemBase : ISystem
_requiredQueries.Add(queryID.value);
}
public void Initialize(ref readonly SystemAPI systemAPI)
void ISystem.Initialize(ref readonly SystemAPI systemAPI)
{
OnInitialize(in systemAPI);
}
public void Update(ref readonly SystemAPI systemAPI)
void ISystem.Update(ref readonly SystemAPI systemAPI)
{
if (ShouldUpdate())
{
@@ -87,7 +87,7 @@ public abstract class SystemBase : ISystem
}
}
public void Cleanup(ref readonly SystemAPI systemAPI)
void ISystem.Cleanup(ref readonly SystemAPI systemAPI)
{
OnCleanup(in systemAPI);
}
@@ -352,6 +352,8 @@ public class SystemManager
private readonly List<ISystem> _systems = [];
internal IReadOnlyList<ISystem> Systems => _systems;
internal SystemManager(World world)
{
_world = world;

View File

@@ -35,7 +35,7 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
@@ -224,11 +224,11 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
@@ -425,15 +425,15 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
@@ -636,19 +636,19 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
@@ -857,23 +857,23 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
@@ -1088,27 +1088,27 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_compTypeIDs[5] = ComponentTypeID<T5>.Value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
@@ -1329,31 +1329,31 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_compTypeIDs[5] = ComponentTypeID<T5>.Value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_compTypeIDs[6] = ComponentTypeID<T6>.value;
_compTypeIDs[6] = ComponentTypeID<T6>.Value;
_offsets[6] = 0;
_compBasePtrs[6] = 0;
@@ -1580,35 +1580,35 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_compTypeIDs[5] = ComponentTypeID<T5>.Value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_compTypeIDs[6] = ComponentTypeID<T6>.value;
_compTypeIDs[6] = ComponentTypeID<T6>.Value;
_offsets[6] = 0;
_compBasePtrs[6] = 0;
_compTypeIDs[7] = ComponentTypeID<T7>.value;
_compTypeIDs[7] = ComponentTypeID<T7>.Value;
_offsets[7] = 0;
_compBasePtrs[7] = 0;

View File

@@ -71,7 +71,7 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
<# for (var j = 0; j < i; j++) { #>
_compTypeIDs[<#= j #>] = ComponentTypeID<T<#= j #>>.value;
_compTypeIDs[<#= j #>] = ComponentTypeID<T<#= j #>>.Value;
_offsets[<#= j #>] = 0;
_compBasePtrs[<#= j #>] = 0;

View File

@@ -55,7 +55,7 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
@@ -253,11 +253,11 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
@@ -461,15 +461,15 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
@@ -679,19 +679,19 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
@@ -907,23 +907,23 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
@@ -1145,27 +1145,27 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_compTypeIDs[5] = ComponentTypeID<T5>.Value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
@@ -1393,31 +1393,31 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_compTypeIDs[5] = ComponentTypeID<T5>.Value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_compTypeIDs[6] = ComponentTypeID<T6>.value;
_compTypeIDs[6] = ComponentTypeID<T6>.Value;
_offsets[6] = 0;
_compBasePtrs[6] = 0;
@@ -1651,35 +1651,35 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_compTypeIDs[0] = ComponentTypeID<T0>.Value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_compTypeIDs[1] = ComponentTypeID<T1>.Value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_compTypeIDs[2] = ComponentTypeID<T2>.Value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_compTypeIDs[3] = ComponentTypeID<T3>.Value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_compTypeIDs[4] = ComponentTypeID<T4>.Value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_compTypeIDs[5] = ComponentTypeID<T5>.Value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_compTypeIDs[6] = ComponentTypeID<T6>.value;
_compTypeIDs[6] = ComponentTypeID<T6>.Value;
_offsets[6] = 0;
_compBasePtrs[6] = 0;
_compTypeIDs[7] = ComponentTypeID<T7>.value;
_compTypeIDs[7] = ComponentTypeID<T7>.Value;
_offsets[7] = 0;
_compBasePtrs[7] = 0;

View File

@@ -75,7 +75,7 @@ public unsafe partial struct EntityQuery
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
<# for (var j = 0; j < i; j++) { #>
_compTypeIDs[<#= j #>] = ComponentTypeID<T<#= j #>>.value;
_compTypeIDs[<#= j #>] = ComponentTypeID<T<#= j #>>.Value;
_offsets[<#= j #>] = 0;
_compBasePtrs[<#= j #>] = 0;

View File

@@ -1,3 +1,4 @@
namespace Ghost.Entities;
public unsafe partial struct EntityQuery
@@ -8,7 +9,7 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -93,8 +94,8 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -182,9 +183,9 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -275,10 +276,10 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -372,11 +373,11 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -473,12 +474,12 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp5TypeID = ComponentTypeID<T5>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var comp5TypeID = ComponentTypeID<T5>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -578,13 +579,13 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp5TypeID = ComponentTypeID<T5>.value;
var comp6TypeID = ComponentTypeID<T6>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var comp5TypeID = ComponentTypeID<T5>.Value;
var comp6TypeID = ComponentTypeID<T6>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -687,14 +688,14 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp5TypeID = ComponentTypeID<T5>.value;
var comp6TypeID = ComponentTypeID<T6>.value;
var comp7TypeID = ComponentTypeID<T7>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var comp5TypeID = ComponentTypeID<T5>.Value;
var comp6TypeID = ComponentTypeID<T6>.Value;
var comp7TypeID = ComponentTypeID<T7>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -792,7 +793,7 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -878,8 +879,8 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -968,9 +969,9 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -1062,10 +1063,10 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -1160,11 +1161,11 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -1262,12 +1263,12 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp5TypeID = ComponentTypeID<T5>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var comp5TypeID = ComponentTypeID<T5>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -1368,13 +1369,13 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp5TypeID = ComponentTypeID<T5>.value;
var comp6TypeID = ComponentTypeID<T6>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var comp5TypeID = ComponentTypeID<T5>.Value;
var comp6TypeID = ComponentTypeID<T6>.Value;
var compTypeIDs = stackalloc int[]
{
@@ -1478,14 +1479,14 @@ public unsafe partial struct EntityQuery
var world = World.GetWorldUncheck(_worldID);
var globalVersion = world.Version;
var comp0TypeID = ComponentTypeID<T0>.value;
var comp1TypeID = ComponentTypeID<T1>.value;
var comp2TypeID = ComponentTypeID<T2>.value;
var comp3TypeID = ComponentTypeID<T3>.value;
var comp4TypeID = ComponentTypeID<T4>.value;
var comp5TypeID = ComponentTypeID<T5>.value;
var comp6TypeID = ComponentTypeID<T6>.value;
var comp7TypeID = ComponentTypeID<T7>.value;
var comp0TypeID = ComponentTypeID<T0>.Value;
var comp1TypeID = ComponentTypeID<T1>.Value;
var comp2TypeID = ComponentTypeID<T2>.Value;
var comp3TypeID = ComponentTypeID<T3>.Value;
var comp4TypeID = ComponentTypeID<T4>.Value;
var comp5TypeID = ComponentTypeID<T5>.Value;
var comp6TypeID = ComponentTypeID<T6>.Value;
var comp7TypeID = ComponentTypeID<T7>.Value;
var compTypeIDs = stackalloc int[]
{

View File

@@ -26,7 +26,7 @@ public unsafe partial struct EntityQuery
var globalVersion = world.Version;
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
var comp<#= localIndex #>TypeID = ComponentTypeID<T<#= localIndex #>>.value;
var comp<#= localIndex #>TypeID = ComponentTypeID<T<#= localIndex #>>.Value;
<# } #>
var compTypeIDs = stackalloc int[]

View File

@@ -1118,7 +1118,7 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -1154,7 +1154,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -1255,9 +1255,9 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -1301,7 +1301,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -1419,11 +1419,11 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
var layout2 = arch.GetLayout(ComponentTypeID<T2>.value)
var layout2 = arch.GetLayout(ComponentTypeID<T2>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -1475,7 +1475,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -1610,13 +1610,13 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
var layout2 = arch.GetLayout(ComponentTypeID<T2>.value)
var layout2 = arch.GetLayout(ComponentTypeID<T2>.Value)
.GetValueOrThrow();
var layout3 = arch.GetLayout(ComponentTypeID<T3>.value)
var layout3 = arch.GetLayout(ComponentTypeID<T3>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -1676,7 +1676,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -1828,15 +1828,15 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
var layout2 = arch.GetLayout(ComponentTypeID<T2>.value)
var layout2 = arch.GetLayout(ComponentTypeID<T2>.Value)
.GetValueOrThrow();
var layout3 = arch.GetLayout(ComponentTypeID<T3>.value)
var layout3 = arch.GetLayout(ComponentTypeID<T3>.Value)
.GetValueOrThrow();
var layout4 = arch.GetLayout(ComponentTypeID<T4>.value)
var layout4 = arch.GetLayout(ComponentTypeID<T4>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -1904,7 +1904,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -2073,17 +2073,17 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
var layout2 = arch.GetLayout(ComponentTypeID<T2>.value)
var layout2 = arch.GetLayout(ComponentTypeID<T2>.Value)
.GetValueOrThrow();
var layout3 = arch.GetLayout(ComponentTypeID<T3>.value)
var layout3 = arch.GetLayout(ComponentTypeID<T3>.Value)
.GetValueOrThrow();
var layout4 = arch.GetLayout(ComponentTypeID<T4>.value)
var layout4 = arch.GetLayout(ComponentTypeID<T4>.Value)
.GetValueOrThrow();
var layout5 = arch.GetLayout(ComponentTypeID<T5>.value)
var layout5 = arch.GetLayout(ComponentTypeID<T5>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -2159,7 +2159,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -2345,19 +2345,19 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
var layout2 = arch.GetLayout(ComponentTypeID<T2>.value)
var layout2 = arch.GetLayout(ComponentTypeID<T2>.Value)
.GetValueOrThrow();
var layout3 = arch.GetLayout(ComponentTypeID<T3>.value)
var layout3 = arch.GetLayout(ComponentTypeID<T3>.Value)
.GetValueOrThrow();
var layout4 = arch.GetLayout(ComponentTypeID<T4>.value)
var layout4 = arch.GetLayout(ComponentTypeID<T4>.Value)
.GetValueOrThrow();
var layout5 = arch.GetLayout(ComponentTypeID<T5>.value)
var layout5 = arch.GetLayout(ComponentTypeID<T5>.Value)
.GetValueOrThrow();
var layout6 = arch.GetLayout(ComponentTypeID<T6>.value)
var layout6 = arch.GetLayout(ComponentTypeID<T6>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -2441,7 +2441,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
@@ -2644,21 +2644,21 @@ public unsafe partial struct EntityQuery
}
// Get offsets ONCE per archetype
var layout0 = arch.GetLayout(ComponentTypeID<T0>.value)
var layout0 = arch.GetLayout(ComponentTypeID<T0>.Value)
.GetValueOrThrow();
var layout1 = arch.GetLayout(ComponentTypeID<T1>.value)
var layout1 = arch.GetLayout(ComponentTypeID<T1>.Value)
.GetValueOrThrow();
var layout2 = arch.GetLayout(ComponentTypeID<T2>.value)
var layout2 = arch.GetLayout(ComponentTypeID<T2>.Value)
.GetValueOrThrow();
var layout3 = arch.GetLayout(ComponentTypeID<T3>.value)
var layout3 = arch.GetLayout(ComponentTypeID<T3>.Value)
.GetValueOrThrow();
var layout4 = arch.GetLayout(ComponentTypeID<T4>.value)
var layout4 = arch.GetLayout(ComponentTypeID<T4>.Value)
.GetValueOrThrow();
var layout5 = arch.GetLayout(ComponentTypeID<T5>.value)
var layout5 = arch.GetLayout(ComponentTypeID<T5>.Value)
.GetValueOrThrow();
var layout6 = arch.GetLayout(ComponentTypeID<T6>.value)
var layout6 = arch.GetLayout(ComponentTypeID<T6>.Value)
.GetValueOrThrow();
var layout7 = arch.GetLayout(ComponentTypeID<T7>.value)
var layout7 = arch.GetLayout(ComponentTypeID<T7>.Value)
.GetValueOrThrow();
// Add all chunks from this archetype
@@ -2750,7 +2750,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))

View File

@@ -151,7 +151,7 @@ public unsafe partial struct EntityQuery
// Get offsets ONCE per archetype
<# for (var j = 0; j < i; j++){ #>
var layout<#= j #> = arch.GetLayout(ComponentTypeID<T<#= j #>>.value)
var layout<#= j #> = arch.GetLayout(ComponentTypeID<T<#= j #>>.Value)
.GetValueOrThrow();
<# } #>
@@ -192,7 +192,7 @@ public unsafe partial struct EntityQuery
version = world.Version,
};
runner.componentIDs[0] = ComponentTypeID<T0>.value;
runner.componentIDs[0] = ComponentTypeID<T0>.Value;
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))

View File

@@ -13,7 +13,7 @@ public ref partial struct QueryBuilder
public QueryBuilder WithAll<T0>()
where T0 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.value);
_all.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -26,8 +26,8 @@ public ref partial struct QueryBuilder
public QueryBuilder WithAllRW<T0>()
where T0 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.value);
_rw.Add(ComponentTypeID<T0>.value);
_all.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -40,7 +40,7 @@ public ref partial struct QueryBuilder
public QueryBuilder WithAny<T0>()
where T0 : unmanaged, IComponent
{
_any.Add(ComponentTypeID<T0>.value);
_any.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -53,7 +53,7 @@ public ref partial struct QueryBuilder
public QueryBuilder WithAbsent<T0>()
where T0 : unmanaged, IComponent
{
_absent.Add(ComponentTypeID<T0>.value);
_absent.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -66,7 +66,7 @@ public ref partial struct QueryBuilder
public QueryBuilder WithNone<T0>()
where T0 : unmanaged, IComponent
{
_none.Add(ComponentTypeID<T0>.value);
_none.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -79,7 +79,7 @@ public ref partial struct QueryBuilder
public QueryBuilder WithDisabled<T0>()
where T0 : unmanaged, IEnableableComponent
{
_disabled.Add(ComponentTypeID<T0>.value);
_disabled.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -92,7 +92,7 @@ public ref partial struct QueryBuilder
public QueryBuilder WithPresent<T0>()
where T0 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.value);
_present.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -105,8 +105,8 @@ public ref partial struct QueryBuilder
public QueryBuilder WithPresentRW<T0>()
where T0 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.value);
_rw.Add(ComponentTypeID<T0>.value);
_present.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
return this;
}
@@ -120,8 +120,8 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.value);
_all.Add(ComponentTypeID<T1>.value);
_all.Add(ComponentTypeID<T0>.Value);
_all.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -135,10 +135,10 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.value);
_rw.Add(ComponentTypeID<T0>.value);
_all.Add(ComponentTypeID<T1>.value);
_rw.Add(ComponentTypeID<T1>.value);
_all.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
_all.Add(ComponentTypeID<T1>.Value);
_rw.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -152,8 +152,8 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_any.Add(ComponentTypeID<T0>.value);
_any.Add(ComponentTypeID<T1>.value);
_any.Add(ComponentTypeID<T0>.Value);
_any.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -167,8 +167,8 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_absent.Add(ComponentTypeID<T0>.value);
_absent.Add(ComponentTypeID<T1>.value);
_absent.Add(ComponentTypeID<T0>.Value);
_absent.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -182,8 +182,8 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_none.Add(ComponentTypeID<T0>.value);
_none.Add(ComponentTypeID<T1>.value);
_none.Add(ComponentTypeID<T0>.Value);
_none.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -197,8 +197,8 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IEnableableComponent
where T1 : unmanaged, IEnableableComponent
{
_disabled.Add(ComponentTypeID<T0>.value);
_disabled.Add(ComponentTypeID<T1>.value);
_disabled.Add(ComponentTypeID<T0>.Value);
_disabled.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -212,8 +212,8 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.value);
_present.Add(ComponentTypeID<T1>.value);
_present.Add(ComponentTypeID<T0>.Value);
_present.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -227,10 +227,10 @@ public ref partial struct QueryBuilder
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.value);
_rw.Add(ComponentTypeID<T0>.value);
_present.Add(ComponentTypeID<T1>.value);
_rw.Add(ComponentTypeID<T1>.value);
_present.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
_present.Add(ComponentTypeID<T1>.Value);
_rw.Add(ComponentTypeID<T1>.Value);
return this;
}
@@ -245,9 +245,9 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.value);
_all.Add(ComponentTypeID<T1>.value);
_all.Add(ComponentTypeID<T2>.value);
_all.Add(ComponentTypeID<T0>.Value);
_all.Add(ComponentTypeID<T1>.Value);
_all.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -262,12 +262,12 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.value);
_rw.Add(ComponentTypeID<T0>.value);
_all.Add(ComponentTypeID<T1>.value);
_rw.Add(ComponentTypeID<T1>.value);
_all.Add(ComponentTypeID<T2>.value);
_rw.Add(ComponentTypeID<T2>.value);
_all.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
_all.Add(ComponentTypeID<T1>.Value);
_rw.Add(ComponentTypeID<T1>.Value);
_all.Add(ComponentTypeID<T2>.Value);
_rw.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -282,9 +282,9 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_any.Add(ComponentTypeID<T0>.value);
_any.Add(ComponentTypeID<T1>.value);
_any.Add(ComponentTypeID<T2>.value);
_any.Add(ComponentTypeID<T0>.Value);
_any.Add(ComponentTypeID<T1>.Value);
_any.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -299,9 +299,9 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_absent.Add(ComponentTypeID<T0>.value);
_absent.Add(ComponentTypeID<T1>.value);
_absent.Add(ComponentTypeID<T2>.value);
_absent.Add(ComponentTypeID<T0>.Value);
_absent.Add(ComponentTypeID<T1>.Value);
_absent.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -316,9 +316,9 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_none.Add(ComponentTypeID<T0>.value);
_none.Add(ComponentTypeID<T1>.value);
_none.Add(ComponentTypeID<T2>.value);
_none.Add(ComponentTypeID<T0>.Value);
_none.Add(ComponentTypeID<T1>.Value);
_none.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -333,9 +333,9 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IEnableableComponent
where T2 : unmanaged, IEnableableComponent
{
_disabled.Add(ComponentTypeID<T0>.value);
_disabled.Add(ComponentTypeID<T1>.value);
_disabled.Add(ComponentTypeID<T2>.value);
_disabled.Add(ComponentTypeID<T0>.Value);
_disabled.Add(ComponentTypeID<T1>.Value);
_disabled.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -350,9 +350,9 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.value);
_present.Add(ComponentTypeID<T1>.value);
_present.Add(ComponentTypeID<T2>.value);
_present.Add(ComponentTypeID<T0>.Value);
_present.Add(ComponentTypeID<T1>.Value);
_present.Add(ComponentTypeID<T2>.Value);
return this;
}
@@ -367,12 +367,12 @@ public ref partial struct QueryBuilder
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.value);
_rw.Add(ComponentTypeID<T0>.value);
_present.Add(ComponentTypeID<T1>.value);
_rw.Add(ComponentTypeID<T1>.value);
_present.Add(ComponentTypeID<T2>.value);
_rw.Add(ComponentTypeID<T2>.value);
_present.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
_present.Add(ComponentTypeID<T1>.Value);
_rw.Add(ComponentTypeID<T1>.Value);
_present.Add(ComponentTypeID<T2>.Value);
_rw.Add(ComponentTypeID<T2>.Value);
return this;
}

View File

@@ -25,7 +25,7 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_all.Add(ComponentTypeID<T<#= j #>>.value);
_all.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -40,8 +40,8 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_all.Add(ComponentTypeID<T<#= j #>>.value);
_rw.Add(ComponentTypeID<T<#= j #>>.value);
_all.Add(ComponentTypeID<T<#= j #>>.Value);
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -56,7 +56,7 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_any.Add(ComponentTypeID<T<#= j #>>.value);
_any.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -71,7 +71,7 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_absent.Add(ComponentTypeID<T<#= j #>>.value);
_absent.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -86,7 +86,7 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_none.Add(ComponentTypeID<T<#= j #>>.value);
_none.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -101,7 +101,7 @@ public ref partial struct QueryBuilder
<#= enableRestrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_disabled.Add(ComponentTypeID<T<#= j #>>.value);
_disabled.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -116,7 +116,7 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_present.Add(ComponentTypeID<T<#= j #>>.value);
_present.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
@@ -131,8 +131,8 @@ public ref partial struct QueryBuilder
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_present.Add(ComponentTypeID<T<#= j #>>.value);
_rw.Add(ComponentTypeID<T<#= j #>>.value);
_present.Add(ComponentTypeID<T<#= j #>>.Value);
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;

View File

@@ -0,0 +1,138 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading;
namespace Ghost.Generator
{
[Generator]
public class ComponentRegistrationGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// 1. Pipeline: Find all structs implementing IComponent
var componentCandidates = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: (s, _) => s is StructDeclarationSyntax,
transform: GetComponentSymbol)
.Where(symbol => symbol != null)
.Collect();
// 2. Pipeline: Find the ONE class with [EngineEntry]
var engineEntryClass = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: (s, _) => s is ClassDeclarationSyntax,
transform: GetEngineEntrySymbol)
.Where(symbol => symbol != null)
.Collect(); // Returns ImmutableArray<INamedTypeSymbol>
// 3. COMBINE: Pair the list of components with the list of entry classes
// The result 'source' in the callback will be a tuple: (ImmutableArray<Info>, ImmutableArray<Entry>)
var combinedProvider = componentCandidates.Combine(engineEntryClass);
// 4. Output: Generate the source using both pieces of data at once
context.RegisterSourceOutput(combinedProvider, GenerateRegistrationCode);
}
// Extraction Logic for Components
private static INamedTypeSymbol GetComponentSymbol(GeneratorSyntaxContext ctx, CancellationToken _)
{
var structSyntax = (StructDeclarationSyntax)ctx.Node;
if (!(ctx.SemanticModel.GetDeclaredSymbol(structSyntax) is INamedTypeSymbol symbol))
{
return null;
}
var iComponentSymbol = ctx.SemanticModel.Compilation.GetTypeByMetadataName("Ghost.Entities.IComponent");
if (iComponentSymbol == null)
{
return null;
}
foreach (var iface in symbol.AllInterfaces)
{
if (SymbolEqualityComparer.Default.Equals(iface, iComponentSymbol))
{
return symbol;
}
}
return null;
}
// Extraction Logic for Engine Entry
private static INamedTypeSymbol GetEngineEntrySymbol(GeneratorSyntaxContext ctx, CancellationToken _)
{
var classSyntax = (ClassDeclarationSyntax)ctx.Node;
if (!(ctx.SemanticModel.GetDeclaredSymbol(classSyntax) is INamedTypeSymbol symbol))
{
return null;
}
// Check attributes
foreach (var attribute in symbol.GetAttributes())
{
if (attribute.AttributeClass?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::Ghost.Engine.EngineEntryAttribute")
{
return symbol;
}
}
return null;
}
// The Generation Logic (Stateless)
private static void GenerateRegistrationCode(
SourceProductionContext context,
(ImmutableArray<INamedTypeSymbol> Components, ImmutableArray<INamedTypeSymbol> Entries) source)
{
var components = source.Components;
var entries = source.Entries;
// 1. Validation: Ensure we found exactly one [EngineEntry] class
if (entries.IsDefaultOrEmpty)
{
return;
}
// Pick the first one (if multiple exist, you might want to report a diagnostic error)
var targetClass = entries[0];
if (components.IsDefaultOrEmpty)
{
return;
}
// 2. Extract Namespace and Class Name directly from the symbol found in the pipeline
var targetNamespace = targetClass.ContainingNamespace.ToDisplayString();
var targetClassName = targetClass.Name;
var sb = new StringBuilder();
sb.Append($@"
namespace {targetNamespace}
{{
public partial class {targetClassName}
{{
private static void RegisterIComponentTypes()
{{");
foreach (var symbol in components.Distinct(SymbolEqualityComparer.Default))
{
if (symbol is null) continue;
sb.Append($@"
global::Ghost.Entities.ComponentRegistry.GetOrRegisterComponent<{symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>();");
}
sb.Append(@"
}
}
}");
context.AddSource($"{targetClassName}.ComponentReg.gen.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
}
}
}

View File

@@ -1,6 +1,5 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
@@ -10,67 +9,200 @@ namespace Ghost.Generator
[Generator]
public class ComponentSerializationGenerator : IIncrementalGenerator
{
private void GenerateJsonContext(SourceProductionContext context, ImmutableArray<INamedTypeSymbol> symbols)
private string GetJsonWriteCall(ITypeSymbol type, string fieldName)
{
if (symbols.IsDefaultOrEmpty)
// 1. PRIMITIVES (Fastest)
switch (type.SpecialType)
{
return;
case SpecialType.System_Byte:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_Decimal:
case SpecialType.System_UInt64:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_IntPtr:
case SpecialType.System_UIntPtr:
return $@"writer.WriteNumber(""{fieldName}"", value.{fieldName});";
case SpecialType.System_Boolean:
return $@"writer.WriteBoolean(""{fieldName}"", value.{fieldName});";
case SpecialType.System_Char:
return $@"writer.WriteString(""{fieldName}"", [value.{fieldName}]);";
}
var sb = new StringBuilder();
sb.Append(@"
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
namespace Ghost.Engine.Components.Serialization
{
[JsonSourceGenerationOptions(WriteIndented = true, IncludeFields = true)]");
foreach (var symbol in symbols.Distinct(SymbolEqualityComparer.Default))
// TODO: Add well-known types like float3, Vector3, etc.
#if false
// 2. KNOWN MATH TYPES (Optimized Arrays)
// Checking by name is simple and effective for standard math libs
if (type.Name == "float3" || type.Name == "Vector3")
{
if (symbol is null)
{
continue;
return $@"writer.WritePropertyName(""{fieldName}"");
writer.WriteStartArray();
writer.WriteNumberValue(value.{fieldName}.x);
writer.WriteNumberValue(value.{fieldName}.y);
writer.WriteNumberValue(value.{fieldName}.z);
writer.WriteEndArray();";
}
#endif
// 3. FALLBACK: System.Text.Json (Reflection)
// If we don't know what it is, let the standard serializer handle it.
// This handles float4x4, List<T>, and other nested structs automatically.
return $@"writer.WritePropertyName(""{fieldName}""); global::System.Text.Json.JsonSerializer.Serialize(writer, value.{fieldName}, options);";
}
var fqtn = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
sb.Append($@"
[JsonSerializable(typeof({fqtn}))]");
}
sb.Append(@"
public partial class ComponentJsonContext : JsonSerializerContext
private string GetJsonReadCall(ITypeSymbol type)
{
private static readonly Dictionary<Type, JsonTypeInfo> _typeLookup = new()
{");
foreach (var symbol in symbols.Distinct(SymbolEqualityComparer.Default))
switch (type.SpecialType)
{
if (symbol is null)
case SpecialType.System_Byte: return "reader.GetByte()";
case SpecialType.System_SByte: return "reader.GetSByte()";
case SpecialType.System_Int16: return "reader.GetInt16()";
case SpecialType.System_Int32: return "reader.GetInt32()";
case SpecialType.System_Int64: return "reader.GetInt64()";
case SpecialType.System_Single: return "reader.GetSingle()";
case SpecialType.System_Double: return "reader.GetDouble()";
case SpecialType.System_Decimal: return "reader.GetDecimal()";
case SpecialType.System_UInt16: return "reader.GetUInt16()";
case SpecialType.System_UInt32: return "reader.GetUInt32()";
case SpecialType.System_UInt64: return "reader.GetUInt64()";
case SpecialType.System_IntPtr: return "reader.GetInt64()"; // Note: IntPtr size varies by platform
case SpecialType.System_UIntPtr: return "reader.GetUInt64()"; // Note: UIntPtr size varies by platform
case SpecialType.System_Boolean: return "reader.GetBoolean()";
case SpecialType.System_Char: return "reader.GetString()[0]";
}
#if false
// For custom math types, you'd need to generate code to read the array back
if (type.Name == "float3") return "new float3(reader.GetSingle(), reader.GetSingle(), reader.GetSingle())"; // Simplified
#endif
return $"global::System.Text.Json.JsonSerializer.Deserialize<{type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>(ref reader, options)";
}
private void GenerateJsonSerializer(SourceProductionContext context, ImmutableArray<INamedTypeSymbol> symbols)
{
continue;
var sbWrites = new StringBuilder();
var sbReads = new StringBuilder();
foreach (var symbol in symbols)
{
var namespaceName = symbol.ContainingNamespace.ToDisplayString();
var structName = symbol.Name;
var fullTypeName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
// 1. Build Field Logic (Same as before)
sbWrites.Clear();
sbReads.Clear();
var fields = symbol.GetMembers()
.OfType<IFieldSymbol>()
.Where(f => !f.IsStatic && f.DeclaredAccessibility == Accessibility.Public);
foreach (var field in fields)
{
// Note: GetJsonWriteCall returns a string ending with ";"
var writeCall = GetJsonWriteCall(field.Type, field.Name);
if (writeCall != null)
{
sbWrites.Append(" "); // Indentation
sbWrites.AppendLine(writeCall);
}
var fqtn = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
sb.Append($@"
{{ typeof({fqtn}), ComponentJsonContext.{symbol.Name} }},");
var readCall = GetJsonReadCall(field.Type);
if (readCall != null)
{
// Note the double quotes ""{field.Name}"" for the case string
sbReads.Append(" "); // Indentation
sbReads.AppendLine($@"case ""{field.Name}"": result.{field.Name} = {readCall}; break;");
}
}
sb.Append(@"
};
// 2. The Main Template using $@
// Watch the double braces {{ }} and double quotes "" ""
var sourceCode = $@"// <auto-generated/>
/// <summary>
/// Tries to retrieve the generated JsonTypeInfo for a given component type.
/// </summary>
public static bool TryGetTypeInfo(Type componentType, out JsonTypeInfo jsonTypeInfo) =>
_typeLookup.TryGetValue(componentType, out jsonTypeInfo);
namespace {namespaceName}
{{
public unsafe static class {structName}_Serializer
{{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void Init()
{{
var id = Ghost.Entities.ComponentTypeID<{fullTypeName}>.Value;
Ghost.Engine.IO.ComponentSerializerRegistry.Register(id, SerializeBinaryUnsafe, SerializeJsonUnsafe);
}}
// ---------------------------------------------------------
// BINARY (Fast Path)
// ---------------------------------------------------------
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static unsafe void SerializeBinaryUnsafe(global::System.IO.BinaryWriter writer, void* value)
{{
writer.Write(new global::System.ReadOnlySpan<byte>(value, sizeof({fullTypeName})));
}}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static void SerializeBinary(this global::System.IO.BinaryWriter writer, ref {fullTypeName} value)
{{
unsafe {{ writer.Write(new global::System.ReadOnlySpan<byte>(global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref value), sizeof({fullTypeName}))); }}
}}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static void DeserializeBinary(this global::System.IO.BinaryReader reader, ref {fullTypeName} value)
{{
unsafe {{ reader.Read(new global::System.Span<byte>(global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref value), sizeof({fullTypeName}))); }}
}}
// ---------------------------------------------------------
// JSON WRITE
// ---------------------------------------------------------
public static unsafe void SerializeJsonUnsafe(System.Text.Json.Utf8JsonWriter writer, void* ptr, System.Text.Json.JsonSerializerOptions? options)
{{
SerializeJson(writer, ref *( {fullTypeName}*)ptr, options);
}}
public static void SerializeJson(this global::System.Text.Json.Utf8JsonWriter writer, ref {fullTypeName} value, global::System.Text.Json.JsonSerializerOptions? options)
{{
writer.WriteStartObject();
{sbWrites}
writer.WriteEndObject();
}}
// ---------------------------------------------------------
// JSON READ
// ---------------------------------------------------------
public static {fullTypeName} DeserializeJson(ref global::System.Text.Json.Utf8JsonReader reader, global::System.Text.Json.JsonSerializerOptions? options)
{{
var result = default({fullTypeName});
if (reader.TokenType != global::System.Text.Json.JsonTokenType.StartObject) throw new global::System.Text.Json.JsonException();
while (reader.Read())
{{
if (reader.TokenType == global::System.Text.Json.JsonTokenType.EndObject) return result;
if (reader.TokenType != global::System.Text.Json.JsonTokenType.PropertyName) throw new global::System.Text.Json.JsonException();
var propName = reader.GetString();
reader.Read();
switch (propName)
{{
{sbReads}
default: reader.Skip(); break;
}}
}}
return result;
}}
}}
}}";
context.AddSource($"{structName}.Serializer.gen.cs", sourceCode);
}
}");
context.AddSource("ComponentJsonContext.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
}
public void Initialize(IncrementalGeneratorInitializationContext context)
@@ -88,16 +220,16 @@ namespace Ghost.Engine.Components.Serialization
}
var compilation = ctx.SemanticModel.Compilation;
var iComponentDataSymbol = compilation.GetTypeByMetadataName("Ghost.Entities.Components.IComponentData");
var iComponentSymbol = compilation.GetTypeByMetadataName("Ghost.Entities.IComponent");
if (iComponentDataSymbol == null)
if (iComponentSymbol == null)
{
return null;
}
foreach (var iface in symbol.AllInterfaces)
{
if (SymbolEqualityComparer.Default.Equals(iface, iComponentDataSymbol))
if (SymbolEqualityComparer.Default.Equals(iface, iComponentSymbol))
{
return symbol;
}
@@ -108,7 +240,7 @@ namespace Ghost.Engine.Components.Serialization
.Where(symbol => symbol != null)
.Collect();
context.RegisterSourceOutput(componentCandidates, GenerateJsonContext);
context.RegisterSourceOutput(componentCandidates, GenerateJsonSerializer);
}
}
}

View File

@@ -5,6 +5,12 @@
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Shader\**" />
<EmbeddedResource Remove="Shader\**" />
<None Remove="Shader\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="4.14.0">
<PrivateAssets>all</PrivateAssets>
@@ -13,8 +19,4 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Shader\" />
</ItemGroup>
</Project>

View File

@@ -53,7 +53,6 @@
<PackageReference Include="MSTest.TestFramework" Version="4.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ghost.Editor.Core\Ghost.Editor.Core.csproj" />
<ProjectReference Include="..\Ghost.Engine\Ghost.Engine.csproj" />
<ProjectReference Include="..\Ghost.Test.Core\Ghost.Test.Core.csproj" />
</ItemGroup>

View File

@@ -1,9 +1,9 @@
using Ghost.Graphics.RHI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.Mathematics;
using System.Text.Json;
namespace Ghost.Graphics.Test.Windows;
@@ -57,6 +57,8 @@ public sealed partial class GraphicsTestWindow : Window
Target = SwapChainTarget.FromCompositionSurface(Panel)
});
_renderer.SetSwapChain(_swapChain);
_renderSystem.Start();
CompositionTarget.Rendering += OnRendering;

View File

@@ -74,7 +74,7 @@ internal class RenderSystem : IRenderSystem
public readonly AutoResetEvent cpuReadyEvent;
public readonly AutoResetEvent gpuReadyEvent;
public FrameResource(ICommandBuffer cmd)
public FrameResource()
{
cpuReadyEvent = new AutoResetEvent(false);
gpuReadyEvent = new AutoResetEvent(true);