Groups and components

This commit is contained in:
2026-04-12 04:04:40 +03:00
parent 5377d1a75a
commit 21879c2784
6 changed files with 126 additions and 36 deletions

View File

@@ -9,10 +9,10 @@
#include "../ui/FurnitureTemplateEditor.hpp"
// Register CellGrid component
REGISTER_COMPONENT("Cell Grid", CellGridComponent, CellGridEditor)
REGISTER_COMPONENT_GROUP("Cell Grid", "Cell Grid", CellGridComponent, CellGridEditor)
{
registry.registerComponent<CellGridComponent>(
"Cell Grid",
"Cell Grid", "Cell Grid",
std::make_unique<CellGridEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<CellGridComponent>()) {
@@ -28,10 +28,10 @@ REGISTER_COMPONENT("Cell Grid", CellGridComponent, CellGridEditor)
}
// Register Lot component
REGISTER_COMPONENT("Lot", LotComponent, LotEditor)
REGISTER_COMPONENT_GROUP("Lot", "Cell Grid", LotComponent, LotEditor)
{
registry.registerComponent<LotComponent>(
"Lot",
"Lot", "Cell Grid",
std::make_unique<LotEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<LotComponent>()) {
@@ -47,10 +47,10 @@ REGISTER_COMPONENT("Lot", LotComponent, LotEditor)
}
// Register District component
REGISTER_COMPONENT("District", DistrictComponent, DistrictEditor)
REGISTER_COMPONENT_GROUP("District", "Cell Grid", DistrictComponent, DistrictEditor)
{
registry.registerComponent<DistrictComponent>(
"District",
"District", "Cell Grid",
std::make_unique<DistrictEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<DistrictComponent>()) {
@@ -66,10 +66,10 @@ REGISTER_COMPONENT("District", DistrictComponent, DistrictEditor)
}
// Register Town component
REGISTER_COMPONENT("Town", TownComponent, TownEditor)
REGISTER_COMPONENT_GROUP("Town", "Cell Grid", TownComponent, TownEditor)
{
registry.registerComponent<TownComponent>(
"Town",
"Town", "Cell Grid",
std::make_unique<TownEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<TownComponent>()) {
@@ -85,10 +85,10 @@ REGISTER_COMPONENT("Town", TownComponent, TownEditor)
}
// Register Roof component
REGISTER_COMPONENT("Roof", RoofComponent, RoofEditor)
REGISTER_COMPONENT_GROUP("Roof", "Cell Grid", RoofComponent, RoofEditor)
{
registry.registerComponent<RoofComponent>(
"Roof",
"Roof", "Cell Grid",
std::make_unique<RoofEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<RoofComponent>()) {
@@ -104,10 +104,10 @@ REGISTER_COMPONENT("Roof", RoofComponent, RoofEditor)
}
// Register Room component
REGISTER_COMPONENT("Room", RoomComponent, RoomEditor)
REGISTER_COMPONENT_GROUP("Room", "Cell Grid", RoomComponent, RoomEditor)
{
registry.registerComponent<RoomComponent>(
"Room",
"Room", "Cell Grid",
std::make_unique<RoomEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<RoomComponent>()) {
@@ -123,10 +123,10 @@ REGISTER_COMPONENT("Room", RoomComponent, RoomEditor)
}
// Register FurnitureTemplate component
REGISTER_COMPONENT("Furniture Template", FurnitureTemplateComponent, FurnitureTemplateEditor)
REGISTER_COMPONENT_GROUP("Furniture Template", "Cell Grid", FurnitureTemplateComponent, FurnitureTemplateEditor)
{
registry.registerComponent<FurnitureTemplateComponent>(
"Furniture Template",
"Furniture Template", "Cell Grid",
std::make_unique<FurnitureTemplateEditor>(),
[sceneMgr](flecs::entity e) {
if (!e.has<FurnitureTemplateComponent>()) {

View File

@@ -4,10 +4,10 @@
#include <OgreMaterialManager.h>
// Register ProceduralMaterial component
REGISTER_COMPONENT("Procedural Material", ProceduralMaterialComponent, ProceduralMaterialEditor)
REGISTER_COMPONENT_GROUP("Procedural Material", "Material", ProceduralMaterialComponent, ProceduralMaterialEditor)
{
registry.registerComponent<ProceduralMaterialComponent>(
"Procedural Material",
"Procedural Material", "Material",
std::make_unique<ProceduralMaterialEditor>(sceneMgr),
// Adder
[sceneMgr](flecs::entity e) {

View File

@@ -3,10 +3,10 @@
#include "../ui/ProceduralTextureEditor.hpp"
// Register ProceduralTexture component
REGISTER_COMPONENT("Procedural Texture", ProceduralTextureComponent, ProceduralTextureEditor)
REGISTER_COMPONENT_GROUP("Procedural Texture", "Material", ProceduralTextureComponent, ProceduralTextureEditor)
{
registry.registerComponent<ProceduralTextureComponent>(
"Procedural Texture",
"Procedural Texture", "Material",
std::make_unique<ProceduralTextureEditor>(),
// Adder
[sceneMgr](flecs::entity e) {

View File

@@ -78,7 +78,7 @@ void EditorUISystem::registerComponentEditors()
// Register Transform component
auto transformEditor = std::make_unique<TransformEditor>();
m_componentRegistry.registerComponent<TransformComponent>(
"Transform", std::move(transformEditor),
"Transform", "Transform", std::move(transformEditor),
// Adder
[this](flecs::entity e) {
if (!e.has<TransformComponent>()) {
@@ -109,7 +109,7 @@ void EditorUISystem::registerComponentEditors()
// Register Renderable component
auto renderableEditor = std::make_unique<RenderableEditor>(m_sceneMgr);
m_componentRegistry.registerComponent<RenderableComponent>(
"Renderable", std::move(renderableEditor),
"Renderable", "Rendering", std::move(renderableEditor),
// Adder
[this](flecs::entity e) {
if (!e.has<RenderableComponent>()) {
@@ -133,7 +133,7 @@ void EditorUISystem::registerComponentEditors()
// Register RigidBody component
auto rigidBodyEditor = std::make_unique<RigidBodyEditor>();
m_componentRegistry.registerComponent<RigidBodyComponent>(
"Rigid Body", std::move(rigidBodyEditor),
"Rigid Body", "Physics", std::move(rigidBodyEditor),
// Adder
[this](flecs::entity e) {
if (!e.has<RigidBodyComponent>()) {
@@ -150,7 +150,7 @@ void EditorUISystem::registerComponentEditors()
// Register PhysicsCollider component
auto colliderEditor = std::make_unique<PhysicsColliderEditor>(m_sceneMgr);
m_componentRegistry.registerComponent<PhysicsColliderComponent>(
"Physics Collider", std::move(colliderEditor),
"Physics Collider", "Physics", std::move(colliderEditor),
// Adder
[this](flecs::entity e) {
if (!e.has<PhysicsColliderComponent>()) {
@@ -679,16 +679,34 @@ void EditorUISystem::renderAddComponentMenu(flecs::entity entity)
ImGui::Text("Add Component:");
ImGui::Separator();
// Dynamically list all registered components that the entity doesn't have
// Group components by their group name
auto groups = m_componentRegistry.getGroups();
bool hasAny = false;
m_componentRegistry.forEach([&](const std::type_index& type, const ComponentRegistry::ComponentInfo& info) {
if (!m_componentRegistry.entityHasComponent(entity, type)) {
hasAny = true;
if (ImGui::MenuItem(info.name)) {
m_componentRegistry.addComponentByType(entity, type);
for (const auto& group : groups) {
// Count components in this group that the entity doesn't have
int availableCount = 0;
m_componentRegistry.forEachInGroup(group.c_str(), [&](const std::type_index& type, const ComponentRegistry::ComponentInfo& info) {
if (!m_componentRegistry.entityHasComponent(entity, type)) {
availableCount++;
}
});
if (availableCount == 0) continue;
hasAny = true;
// Create a submenu for each group
if (ImGui::BeginMenu(group.c_str())) {
m_componentRegistry.forEachInGroup(group.c_str(), [&](const std::type_index& type, const ComponentRegistry::ComponentInfo& info) {
if (!m_componentRegistry.entityHasComponent(entity, type)) {
if (ImGui::MenuItem(info.name)) {
m_componentRegistry.addComponentByType(entity, type);
}
}
});
ImGui::EndMenu();
}
});
}
if (!hasAny) {
ImGui::TextDisabled("All components added");

View File

@@ -50,8 +50,22 @@ private:
* [](flecs::entity e) { ... },
* [](flecs::entity e) { ... });
* }
*
* Or with a group:
* REGISTER_COMPONENT_GROUP("My Component", "Group Name", MyComponent, MyComponentEditor)
* {
* registry.registerComponent<MyComponent>(
* name, group, std::make_unique<MyComponentEditor>(...),
* [](flecs::entity e) { ... },
* [](flecs::entity e) { ... });
* }
*/
#define REGISTER_COMPONENT(nameStr, ComponentType, EditorType) \
REGISTER_COMPONENT_GROUP(nameStr, "Miscellaneous", ComponentType, EditorType)
#define REGISTER_COMPONENT_GROUP(nameStr, groupStr, ComponentType, EditorType) \
static const char* ComponentType##_name = nameStr; \
static const char* ComponentType##_group = groupStr; \
static void register_##ComponentType(ComponentRegistry& registry, \
Ogre::SceneManager* sceneMgr, \
EditorPhysicsSystem* physics); \

View File

@@ -6,6 +6,8 @@
#include <memory>
#include <functional>
#include <vector>
#include <set>
#include <string>
#include <flecs.h>
#include "ComponentEditor.hpp"
@@ -31,6 +33,7 @@ class ComponentRegistry {
public:
struct ComponentInfo {
const char *name;
const char *group; // Group name for menu organization (nullptr = "Miscellaneous")
std::unique_ptr<IComponentEditor> editor;
ComponentAdder adder;
ComponentRemover remover;
@@ -50,19 +53,36 @@ public:
/**
* Register a component type with its editor and add/remove functions
* @param name Display name for the component
* @param group Group name for menu organization (nullptr for "Miscellaneous")
* @param editor The editor for this component
* @param adder Function to add the component to an entity
* @param remover Function to remove the component from an entity
*/
template<typename T>
void registerComponent(const char *name, const char *group,
std::unique_ptr<ComponentEditor<T>> editor,
ComponentAdder adder, ComponentRemover remover)
{
ComponentInfo info;
info.name = name;
info.group = group ? group : "Miscellaneous";
info.editor = std::move(editor);
info.adder = adder;
info.remover = remover;
info.checker = [](flecs::entity e) { return e.has<T>(); };
m_components[std::type_index(typeid(T))] = std::move(info);
}
/**
* Backward-compatible overload (defaults to "Miscellaneous" group)
*/
template<typename T>
void registerComponent(const char *name,
std::unique_ptr<ComponentEditor<T>> editor,
ComponentAdder adder, ComponentRemover remover)
{
ComponentInfo info;
info.name = name;
info.editor = std::move(editor);
info.adder = adder;
info.remover = remover;
info.checker = [](flecs::entity e) { return e.has<T>(); };
m_components[std::type_index(typeid(T))] = std::move(info);
registerComponent<T>(name, nullptr, std::move(editor), adder, remover);
}
/**
@@ -185,6 +205,44 @@ public:
* Get the number of registered components
*/
size_t getComponentCount() const { return m_components.size(); }
/**
* Get all unique group names
*/
std::vector<std::string> getGroups() const {
std::set<std::string> groups;
for (const auto& pair : m_components) {
groups.insert(pair.second.group);
}
return std::vector<std::string>(groups.begin(), groups.end());
}
/**
* Get all component types in a specific group
*/
std::vector<std::type_index> getComponentsInGroup(const char* group) const {
std::vector<std::type_index> types;
const char* groupName = group ? group : "Miscellaneous";
for (const auto& pair : m_components) {
if (std::string(pair.second.group) == groupName) {
types.push_back(pair.first);
}
}
return types;
}
/**
* Iterate over all registered components in a specific group
*/
template<typename Func>
void forEachInGroup(const char* group, Func&& func) const {
const char* groupName = group ? group : "Miscellaneous";
for (const auto& pair : m_components) {
if (std::string(pair.second.group) == groupName) {
func(pair.first, pair.second);
}
}
}
private:
std::unordered_map<std::type_index, ComponentInfo> m_components;