Groups and components
This commit is contained in:
@@ -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>()) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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); \
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user