Repository navigation
Astra 3.0.0
Astra ECS v3.0 - Resources, Runtime Reflection & Editor Integration
Major Release Highlights
Astra 3.0 introduces a singleton resource system for global state and a comprehensive runtime reflection system providing EnTT meta-style introspection, field enumeration, attribute decoration, and full ECS integration. This release enables editor tooling, runtime component inspection, and JSON schema generation.
New Capabilities
- Resource system for singleton/global components with SBO optimization
- Runtime type introspection with zero overhead when unused
- Field enumeration with get/set accessors and attribute metadata
- Entity inspection API for editor and debugging tools
New Features
Resource System (NEW)
Singleton resources for global state that exists outside the entity-component model:
// Add global resources
registry.AddResource<Time>(Time{ 0.0f, 0.016f });
registry.AddResource<InputState>();
registry.AddResource<RenderSettings>(width, height, vsync);
// Access resources
Time* time = registry.GetResource<Time>();
time->deltaTime = 0.016f;
// Check existence
if (registry.HasResource<InputState>()) { ... }
// Remove resources
registry.RemoveResource<RenderSettings>();Storage Architecture
- Sparse-dense pattern for O(1) access by ComponentID
- Small Buffer Optimization - Resources ≤64 bytes stored inline (no heap allocation)
- Swap-and-pop removal maintains cache locality
- Automatic registration with ComponentRegistry
Type-Erased Operations
For command buffers and deferred execution:
// Set resource by ID (for CommandBuffer)
resourceStorage.SetByID(componentId, dataPtr, dataSize);
// Remove by ID
resourceStorage.RemoveByID(componentId);
// Get by ID
void* data = resourceStorage.GetByID(componentId);Memory Efficiency
struct ResourceSlot {
union Storage {
alignas(64) std::byte inlineData[64]; // SBO: no allocation
void* heapPtr; // Large resources
};
// ... metadata
};
// Memory usage tracking
size_t bytes = resourceStorage.GetMemoryUsage();Runtime Reflection System (NEW)
TypeMeta - Complete Type Metadata
const TypeMeta* meta = GetMeta<Transform>();
// Introspect fields
meta->ForEachField([](const FieldInfo& field) {
std::cout << field.name << " : " << field.typeName << "\n";
});
// Dynamic field access
meta->SetFieldValue(&transform, "x", 100.0f);
float x = meta->GetFieldValue<float>(&transform, "x").value();FieldInfo - Field Descriptors with Accessors
- Type-erased
Get<T>()andSet<T>()methods - Offset, size, alignment metadata
- Compile-time type trait detection (isConst, isPointer, isTrivial)
- Attribute query support
Attribute System
Decorator metadata for fields and types:
ASTRA_REFLECT_TYPE(Transform)
ASTRA_REFLECT_FIELD(Transform, x)
ASTRA_REFLECT_ATTR(Range, -1000.0, 1000.0)
ASTRA_REFLECT_ATTR(DisplayName, "X Position")
ASTRA_REFLECT_ATTR(Tooltip, "Horizontal position in world space")
ASTRA_REFLECT_FIELD(Transform, y)
ASTRA_REFLECT_FIELD(Transform, z);Built-in attributes:
Range- Min/max/step constraintsDisplayName- UI label overrideTooltip- Help textCategory- Property groupingHidden- Exclude from inspectionReadOnly- Prevent modificationSerializable- Control persistence
Enum Reflection
ASTRA_REFLECT_ENUM(DamageType)
ASTRA_REFLECT_ENUM_VALUE(DamageType, Physical)
ASTRA_REFLECT_ENUM_VALUE_NAMED(DamageType, Fire, "Fire Damage")
ASTRA_REFLECT_ENUM_FLAGS(); // Mark as bitmask
// Runtime conversion
auto name = enumInfo->ToString(DamageType::Fire); // "Fire Damage"
auto value = enumInfo->FromString("Physical"); // DamageType::PhysicalContainer Traits Detection
Automatic detection of container types:
std::vector,std::array,std::spanstd::map,std::unordered_mapstd::set,std::unordered_set- Custom containers via trait specialization
ECS-Reflection Integration (NEW)
ComponentDescriptor ↔ TypeMeta Linking
Components registered with the ECS are automatically linked to their reflection metadata:
// ComponentDescriptor now includes:
const TypeMeta* meta; // Auto-populated on registration
// Bidirectional lookup
const TypeMeta* meta = GetMeta(componentId);
ComponentID id = MetaRegistry::Instance().GetComponentId(typeHash);Entity Inspection API
Runtime inspection of entity components for editors:
std::vector<ComponentInfo> components = registry.InspectEntity(entity);
for (const auto& info : components) {
std::cout << "Component: " << info.descriptor->name << "\n";
if (info.meta) {
info.meta->ForEachField([&](const FieldInfo& field) {
// Render field in editor UI
RenderFieldWidget(field, info.data);
});
}
}Resource Inspection API
std::vector<ResourceInfo> resources = registry.InspectResources();
for (const auto& res : resources) {
std::cout << "Resource: " << res.descriptor->name << "\n";
// Access via res.meta and res.data
}Hash-Based Runtime Access
// Get components by type hash (runtime lookup)
void* component = registry.GetComponentByHash(entity, typeHash);
bool has = registry.HasComponentByHash(entity, typeHash);
// Get components by name
void* component = registry.GetComponentByName(entity, "Transform");
// Resources
void* resource = registry.GetResourceByHash(typeHash);
bool has = registry.HasResourceByHash(typeHash);JSON Schema Generation (NEW)
Automatic JSON Schema generation for editor integration:
JsonSchemaGenerator generator;
std::string schema = generator.Generate(*GetMeta<Transform>());Generates:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Transform",
"type": "object",
"properties": {
"x": { "type": "number", "minimum": -1000, "maximum": 1000 },
"y": { "type": "number" },
"z": { "type": "number" }
},
"required": ["x", "y", "z"]
}Architectural Improvements
MetaRegistry
Global singleton for reflection metadata:
- O(1) lookup by type hash via FlatMap
- Bidirectional component ID ↔ type hash mapping
- Thread-safe registration (single-threaded lookup)
- Lazy initialization via static builders
Reflection File Structure
include/Astra/Reflection/
Reflection.hpp # Main include
TypeMeta.hpp # Type metadata container
FieldInfo.hpp # Field descriptor with get/set
EnumInfo.hpp # Enum reflection
Attribute.hpp # Attribute base + common attributes
MetaRegistry.hpp # Global registry
ContainerTraits.hpp # Container type detection
JsonSchema.hpp # JSON schema generation
Macros.hpp # Registration macros
Requirements
- C++20 compatible compiler (GCC 11+, Clang 13+, MSVC 2022+)
- Premake5 for project generation
- Optional: GoogleTest, Google Benchmark
License
MIT License - See LICENSE file for details
Full Changelog: v2.0.0...v3.0.0