diff --git a/src/gaemstone.Bloxel/Components/CoreComponents.cs b/src/gaemstone.Bloxel/Components/CoreComponents.cs index f6bf299..e6cd60d 100644 --- a/src/gaemstone.Bloxel/Components/CoreComponents.cs +++ b/src/gaemstone.Bloxel/Components/CoreComponents.cs @@ -2,17 +2,17 @@ using gaemstone.ECS; namespace gaemstone.Bloxel.Components; -[Public, Module] +[Module] public partial class CoreComponents { - [Component] + [Component, Symbol] public readonly struct Chunk { public ChunkPos Position { get; } public Chunk(ChunkPos pos) => Position = pos; } - [Component] + [Component, Symbol] public class ChunkStoreBlocks : ChunkPaletteStorage { diff --git a/src/gaemstone.Client/Components/InputComponents.cs b/src/gaemstone.Client/Components/InputComponents.cs index fc8d898..6fe27a5 100644 --- a/src/gaemstone.Client/Components/InputComponents.cs +++ b/src/gaemstone.Client/Components/InputComponents.cs @@ -4,33 +4,36 @@ using gaemstone.ECS; namespace gaemstone.Client.Components; -[Public, Module] +[Module] public partial class InputComponents { - [Entity, Path("/Input")] + [Entity, Path("/Input"), Symbol] [Add] public struct Input { } - [Entity, Path("/Input/Mouse")] + [Entity, Path("/Input/Mouse"), Symbol] [Add] public struct Mouse { } - [Entity, Path("/Input/Keyboard")] + [Entity, Path("/Input/Keyboard"), Symbol] [Add] public struct Keyboard { } - [Tag] + [Tag, Symbol] public struct Gamepad { } /// Present on inputs / actions that are currently active. - [Component] public struct Active { public TimeSpan Duration; } + [Component, Symbol] + public struct Active { public TimeSpan Duration; } /// Present on inputs / actions were activated this frame. - [Tag] public struct Activated { } + [Tag, Symbol] + public struct Activated { } /// Present on inputs / actions were deactivated this frame. - [Tag] public struct Deactivated { } + [Tag, Symbol] + public struct Deactivated { } /// @@ -41,7 +44,7 @@ public partial class InputComponents /// This is set if a UI element is focused that captures /// navigational or text input. /// - [Relation, Tag, Exclusive] + [Relation, Tag, Symbol, Exclusive] public struct InputCapturedBy { } /// @@ -52,7 +55,7 @@ public partial class InputComponents /// This could for example include the mouse currently being over /// a UI element, preventing the game from handling mouse input. /// - [Relation, Tag, Exclusive] + [Relation, Tag, Symbol, Exclusive] public struct MouseInputCapturedBy { } /// @@ -62,13 +65,13 @@ public partial class InputComponents /// /// This is set when a camera controller assumes control of the mouse. /// - [Relation, Tag, Exclusive] + [Relation, Tag, Symbol, Exclusive] [With] [With] public struct CursorCapturedBy { } - [Private, Component] + [Component] internal readonly struct RawValue1D { private readonly float _value; @@ -78,7 +81,7 @@ public partial class InputComponents public static implicit operator RawValue1D(float value) => new(value); } - [Private, Component] + [Component] internal readonly struct RawValue2D { private readonly Vector2 _value; diff --git a/src/gaemstone.Client/Components/RenderingComponents.cs b/src/gaemstone.Client/Components/RenderingComponents.cs index d6d47ce..714a352 100644 --- a/src/gaemstone.Client/Components/RenderingComponents.cs +++ b/src/gaemstone.Client/Components/RenderingComponents.cs @@ -5,10 +5,10 @@ using Silk.NET.OpenGL; namespace gaemstone.Client.Components; -[Public, Module] +[Module] public partial class RenderingComponents { - [Component] + [Component, Symbol] public readonly struct MeshHandle { public uint Handle { get; } @@ -19,7 +19,7 @@ public partial class RenderingComponents { Handle = handle; Count = count; IsIndexed = indexed; } } - [Component] + [Component, Symbol] public readonly struct TextureHandle { public TextureTarget Target { get; } @@ -29,7 +29,7 @@ public partial class RenderingComponents => (Target, Handle) = (target, handle); } - [Component] + [Component, Symbol] public readonly struct TextureCoords4 { public Vector2 TopLeft { get; } diff --git a/src/gaemstone.Client/Components/ResourceComponents.cs b/src/gaemstone.Client/Components/ResourceComponents.cs index d875e97..ca73ca1 100644 --- a/src/gaemstone.Client/Components/ResourceComponents.cs +++ b/src/gaemstone.Client/Components/ResourceComponents.cs @@ -2,10 +2,10 @@ using gaemstone.ECS; namespace gaemstone.Client.Components; -[Public, Module] +[Module] public partial class ResourceComponents { - [Tag] + [Tag, Symbol] public struct Resource { } // Entities can have for example Texture as a tag, in which case @@ -14,9 +14,9 @@ public partial class ResourceComponents // Entities can also have a (Texture, $T) pair where $T is a resource, // meaning the entity has that resource assigned as their texture. - [Relation, Tag, IsA] + [Relation, Tag, Symbol, IsA] public struct Texture { } - [Relation, Tag, IsA] + [Relation, Tag, Symbol, IsA] public struct Mesh { } } diff --git a/src/gaemstone.SourceGen/ModuleGenerator.cs b/src/gaemstone.SourceGen/ModuleGenerator.cs index 0a83af3..825500f 100644 --- a/src/gaemstone.SourceGen/ModuleGenerator.cs +++ b/src/gaemstone.SourceGen/ModuleGenerator.cs @@ -150,8 +150,10 @@ public class ModuleGenerator sb.AppendLine("\t\t// Register entities."); foreach (var e in entities) { var @var = $"_{e.Name}_Entity"; - var path = (e.Path ?? e.Name).ToStringLiteral(); + var path = (e.EntityPath ?? e.Name).ToStringLiteral(); sb.AppendLine($"\t\tvar {@var} = world.New({path}, module)"); + if (e.EntitySymbol != null) + sb.AppendLine($"\t\t\t.Symbol({e.EntitySymbol.ToStringLiteral()})"); // Since this is a custom gaemstone tag, we want to add it even for [BuiltIn] modules. if (e.IsRelation) sb.AppendLine("\t\t\t.Add()"); @@ -193,7 +195,7 @@ public class ModuleGenerator sb.AppendLine("\t\t// Register systems / observers."); foreach (var m in methods) { var @var = $"_{m.Name}_Entity"; - var path = (m.Path ?? m.Name).ToStringLiteral(); + var path = (m.EntityPath ?? m.Name).ToStringLiteral(); sb.AppendLine($"\t\tvar {@var} = world.New({path}, module)"); sb.Append("\t\t\t.Build()"); diff --git a/src/gaemstone.SourceGen/RelevantSymbolReceiver.cs b/src/gaemstone.SourceGen/RelevantSymbolReceiver.cs index bca43a3..3d42dfd 100644 --- a/src/gaemstone.SourceGen/RelevantSymbolReceiver.cs +++ b/src/gaemstone.SourceGen/RelevantSymbolReceiver.cs @@ -24,9 +24,8 @@ public class RelevantSymbolReceiver "Observer", // Entity properties that specify additional info / behavior - "Public", - "Private", "Path", + "Symbol", "Add", "BuiltIn", // Valid on [Module] "Expression", // Valid on [System] and [Observer] diff --git a/src/gaemstone.SourceGen/Structure/BaseEntityInfo.cs b/src/gaemstone.SourceGen/Structure/BaseEntityInfo.cs index db4e92e..8c62dab 100644 --- a/src/gaemstone.SourceGen/Structure/BaseEntityInfo.cs +++ b/src/gaemstone.SourceGen/Structure/BaseEntityInfo.cs @@ -9,10 +9,8 @@ public abstract class BaseEntityInfo : BaseInfo { public new TypeEntityInfo? Parent { get => (TypeEntityInfo?)base.Parent; set => base.Parent = value; } - public string? Path { get; } - // TODO: Rename this to something sensible, like [Symbol]. - // public bool IsPublic { get; private set; } - // private bool IsPrivate { get; } + public string? EntityPath { get; } + public string? EntitySymbol { get; } public List EntitiesToAdd { get; } = new(); public List<(INamedTypeSymbol, INamedTypeSymbol)> RelationsToAdd { get; } = new(); @@ -21,10 +19,14 @@ public abstract class BaseEntityInfo : BaseInfo public BaseEntityInfo(ISymbol symbol) : base(symbol) { - Path = Get("Path")?.ConstructorArguments.FirstOrDefault().Value as string; - - // IsPublic = Symbol.HasAttribute("gaemstone.ECS.PublicAttribute"); - // IsPrivate = Symbol.HasAttribute("gaemstone.ECS.PrivateAttribute"); + // TODO: Validate that these only contain valid characters. + EntityPath = Get("Path")?.ConstructorArguments.FirstOrDefault().Value as string; + EntitySymbol = (Get("Symbol") is AttributeData symbolAttr) + // If [Symbol] is present, use the given custom symbol (if given), .. + ? (symbolAttr.ConstructorArguments.FirstOrDefault().Value as string) + ?? EntityPath?.Split('/')[^1] // .. otherwise default to the name in [Path], .. + ?? Name // .. or just use the default: The symbol's name. + : null; } protected override IEnumerable ValidateSelf() @@ -39,10 +41,6 @@ public abstract class BaseEntityInfo : BaseInfo Descriptors.EntityMustBeInModule, Location); } - // var moduleIsPublic = (Parent?.IsPublic == true); - // var inheritsPublic = (this is MethodEntityInfo); // Observers and systems don't inherit [Public] from their module. - // IsPublic = IsPublic || (moduleIsPublic && inheritsPublic && !IsPrivate); - // Add entities and relationships specified using [Add<...>] attributes. foreach (var attr in Symbol.GetAttributes()) { for (var attrType = attr.AttributeClass; attrType != null; attrType = attrType.BaseType) { diff --git a/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs b/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs index 58bdf44..a5c0573 100644 --- a/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs +++ b/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs @@ -29,7 +29,7 @@ public class ModuleEntityInfo : TypeEntityInfo if (!IsPartial) yield return Diagnostic.Create( Descriptors.ModuleMustBePartial, Location); - if (IsBuiltIn && (Path == null)) yield return Diagnostic.Create( + if (IsBuiltIn && (EntityPath == null)) yield return Diagnostic.Create( Descriptors.BuiltInModuleMustHavePath, Location); } diff --git a/src/gaemstone/Components/TransformComponents.cs b/src/gaemstone/Components/TransformComponents.cs index 28970c5..d727408 100644 --- a/src/gaemstone/Components/TransformComponents.cs +++ b/src/gaemstone/Components/TransformComponents.cs @@ -3,10 +3,10 @@ using gaemstone.ECS; namespace gaemstone.Components; -[Public, Module] +[Module] public partial class TransformComponents { - [Component] + [Component, Symbol] public struct GlobalTransform { public Matrix4x4 Value; diff --git a/src/gaemstone/ECS/Module+Attributes.cs b/src/gaemstone/ECS/Module+Attributes.cs index 8241dc0..b0b593e 100644 --- a/src/gaemstone/ECS/Module+Attributes.cs +++ b/src/gaemstone/ECS/Module+Attributes.cs @@ -4,24 +4,20 @@ using static gaemstone.Flecs.Core; namespace gaemstone.ECS; /// -///

-/// Components marked with this attribute are automatically registered with -/// a equal to their . +/// Entities marked with this attribute are automatically registered with a +/// specified in the attribute constructor, +/// defaulting to their if not given. +/// /// Symbols are unique string identifiers used to look up their entities. -///

-///

-/// Modules marked with this attribute apply this property to all their -/// components, except ones marked with . -///

///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method)] -public class PublicAttribute : Attribute { } - -/// -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct - | AttributeTargets.Enum | AttributeTargets.Method)] -public class PrivateAttribute : Attribute { } +public class SymbolAttribute : Attribute +{ + public string? Value { get; } + public SymbolAttribute() { } + public SymbolAttribute(string value) => Value = value; +} // TODO: Should this be renamed from [Add<...>] to something else?