Re-add [Symbol] attribute

wip/source-generators
copygirl 12 months ago
parent 64f7ece2a7
commit 357e8b4bfa
  1. 6
      src/gaemstone.Bloxel/Components/CoreComponents.cs
  2. 29
      src/gaemstone.Client/Components/InputComponents.cs
  3. 8
      src/gaemstone.Client/Components/RenderingComponents.cs
  4. 8
      src/gaemstone.Client/Components/ResourceComponents.cs
  5. 6
      src/gaemstone.SourceGen/ModuleGenerator.cs
  6. 3
      src/gaemstone.SourceGen/RelevantSymbolReceiver.cs
  7. 22
      src/gaemstone.SourceGen/Structure/BaseEntityInfo.cs
  8. 2
      src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs
  9. 4
      src/gaemstone/Components/TransformComponents.cs
  10. 24
      src/gaemstone/ECS/Module+Attributes.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<Entity>
{

@ -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<Input>]
public struct Input { }
[Entity, Path("/Input/Mouse")]
[Entity, Path("/Input/Mouse"), Symbol]
[Add<Mouse>]
public struct Mouse { }
[Entity, Path("/Input/Keyboard")]
[Entity, Path("/Input/Keyboard"), Symbol]
[Add<Keyboard>]
public struct Keyboard { }
[Tag]
[Tag, Symbol]
public struct Gamepad { }
/// <summary> Present on inputs / actions that are currently active. </summary>
[Component] public struct Active { public TimeSpan Duration; }
[Component, Symbol]
public struct Active { public TimeSpan Duration; }
/// <summary> Present on inputs / actions were activated this frame. </summary>
[Tag] public struct Activated { }
[Tag, Symbol]
public struct Activated { }
/// <summary> Present on inputs / actions were deactivated this frame. </summary>
[Tag] public struct Deactivated { }
[Tag, Symbol]
public struct Deactivated { }
/// <summary>
@ -41,7 +44,7 @@ public partial class InputComponents
/// This is set if a UI element is focused that captures
/// navigational or text input.
/// </remarks>
[Relation, Tag, Exclusive]
[Relation, Tag, Symbol, Exclusive]
public struct InputCapturedBy { }
/// <summary>
@ -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.
/// </remarks>
[Relation, Tag, Exclusive]
[Relation, Tag, Symbol, Exclusive]
public struct MouseInputCapturedBy { }
/// <summary>
@ -62,13 +65,13 @@ public partial class InputComponents
/// <remarks>
/// This is set when a camera controller assumes control of the mouse.
/// </remarks>
[Relation, Tag, Exclusive]
[Relation, Tag, Symbol, Exclusive]
[With<InputCapturedBy>]
[With<MouseInputCapturedBy>]
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;

@ -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; }

@ -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<Resource>]
[Relation, Tag, Symbol, IsA<Resource>]
public struct Texture { }
[Relation, Tag, IsA<Resource>]
[Relation, Tag, Symbol, IsA<Resource>]
public struct Mesh { }
}

@ -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<gaemstone.Doc.Relation>()");
@ -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()");

@ -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]

@ -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<INamedTypeSymbol> 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<Diagnostic> 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) {

@ -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);
}

@ -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;

@ -4,24 +4,20 @@ using static gaemstone.Flecs.Core;
namespace gaemstone.ECS;
/// <summary>
/// <p>
/// Components marked with this attribute are automatically registered with
/// a <see cref="EntityRef.Symbol"/> equal to their <see cref="EntityRef.Name"/>.
/// Entities marked with this attribute are automatically registered with a
/// <see cref="EntityRef.Symbol"/> specified in the attribute constructor,
/// defaulting to their <see cref="EntityRef.Name"/> if not given.
///
/// Symbols are unique string identifiers used to look up their entities.
/// </p>
/// <p>
/// Modules marked with this attribute apply this property to all their
/// components, except ones marked with <see cref="PrivateAttribute"/>.
/// </p>
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
| AttributeTargets.Enum | AttributeTargets.Method)]
public class PublicAttribute : Attribute { }
/// <seealso cref="PublicAttribute"/>
[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?

Loading…
Cancel
Save