Big changes
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <sophia/console/console_command_registry.hpp>
|
||||
#include <sophia/frame_info.hpp>
|
||||
#include <sophia/resource_registry_ref.hpp>
|
||||
#include <sophia/scene_registry.hpp>
|
||||
#include <sophia/types.hpp>
|
||||
#include <sophia/ui/debug_ui.hpp>
|
||||
#include <sophia/ui/panel_registry.hpp>
|
||||
@@ -47,6 +48,7 @@ class Application {
|
||||
|
||||
ResourceRegistryRef resources();
|
||||
PanelRegistry& panels() { return this->panelRegistry; }
|
||||
SceneRegistry& scenes() { return this->sceneRegistry; }
|
||||
UI& ui() { return this->_ui; }
|
||||
|
||||
DebugUI& debugUI() { return this->_debugUI; }
|
||||
@@ -60,6 +62,7 @@ class Application {
|
||||
void drawMesh(MeshHandle handle, const glm::mat4& transform);
|
||||
|
||||
/**
|
||||
* !TEMP !TODO remove this func eventually
|
||||
* Chooses where the scene is rendered. An invalid handle (the default) means
|
||||
* the swapchain; a target created with
|
||||
* ResourceRegistryRef::create<RenderTarget>() redirects it offscreen, and the
|
||||
@@ -78,6 +81,7 @@ class Application {
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
PanelRegistry panelRegistry;
|
||||
SceneRegistry sceneRegistry;
|
||||
UI _ui;
|
||||
|
||||
DebugUI _debugUI;
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace sophia {
|
||||
|
||||
class Mesh;
|
||||
class RenderTarget;
|
||||
class Scene;
|
||||
class ResourceRegistry;
|
||||
|
||||
template <typename T>
|
||||
@@ -32,11 +31,6 @@ struct ResourceTraits<RenderTarget> {
|
||||
using Handle = RenderTargetHandle;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ResourceTraits<Scene> {
|
||||
using Handle = SceneHandle;
|
||||
};
|
||||
|
||||
class ResourceRegistryRef {
|
||||
public:
|
||||
template <typename T>
|
||||
@@ -52,7 +46,6 @@ class ResourceRegistryRef {
|
||||
glm::vec2 getExtent(RenderTargetHandle handle) const;
|
||||
|
||||
bool isAlive(RenderTargetHandle handle) const;
|
||||
bool isAlive(SceneHandle handle) const;
|
||||
|
||||
template <typename T>
|
||||
void release(typename ResourceTraits<T>::Handle handle);
|
||||
@@ -70,8 +63,6 @@ class ResourceRegistryRef {
|
||||
RenderTargetHandle createResource(std::type_identity<RenderTarget>,
|
||||
u32 width = 1, u32 height = 1);
|
||||
|
||||
SceneHandle createResource(std::type_identity<Scene>);
|
||||
|
||||
ResourceRegistry* registry;
|
||||
};
|
||||
|
||||
@@ -84,7 +75,4 @@ void ResourceRegistryRef::release<Mesh>(MeshHandle handle);
|
||||
template <>
|
||||
void ResourceRegistryRef::release<RenderTarget>(RenderTargetHandle handle);
|
||||
|
||||
template <>
|
||||
void ResourceRegistryRef::release<Scene>(SceneHandle handle);
|
||||
|
||||
} // namespace sophia
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
// The camera a render request uses when it doesn't name one. Null until set.
|
||||
entt::entity getActiveCamera() const { return activeCamera; }
|
||||
void setActiveCamera(entt::entity camera) { activeCamera = camera; }
|
||||
|
||||
private:
|
||||
entt::registry registry;
|
||||
entt::entity activeCamera = entt::null;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <sophia/handles.hpp>
|
||||
#include <sophia/scene.hpp>
|
||||
#include <sophia/util/pool.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class SceneRegistry {
|
||||
public:
|
||||
SceneRegistry(const SceneRegistry&) = delete;
|
||||
SceneRegistry& operator=(const SceneRegistry&) = delete;
|
||||
|
||||
SceneRegistry() = default;
|
||||
~SceneRegistry() = default;
|
||||
|
||||
SceneHandle create() { return pool.create(); }
|
||||
|
||||
const Scene& get(SceneHandle handle) const { return pool.get(handle); }
|
||||
Scene& get(SceneHandle handle) { return pool.get(handle); }
|
||||
|
||||
void release(SceneHandle handle) { pool.release(handle); }
|
||||
bool isAlive(SceneHandle handle) const { return pool.isAlive(handle); }
|
||||
|
||||
u32 size() const { return pool.size(); }
|
||||
|
||||
private:
|
||||
Pool<Scene, SceneHandle> pool{"Scene"};
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <sophia/ui/dock_layout.hpp>
|
||||
#include <sophia/ui/panel.hpp>
|
||||
#include <sophia/util/assert.hpp>
|
||||
#include <sophia/util/pool.hpp>
|
||||
#include <string_view>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
@@ -21,17 +22,17 @@ class PanelRegistry {
|
||||
PanelRegistry() = default;
|
||||
~PanelRegistry() = default;
|
||||
|
||||
PanelHandle add(std::unique_ptr<Panel> panel);
|
||||
PanelHandle add(std::unique_ptr<Panel> panel) {
|
||||
return pool.add(std::move(panel));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
PanelHandle emplace(Args&&... args) {
|
||||
return add(std::make_unique<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
const Panel& get(PanelHandle handle) const;
|
||||
Panel& get(PanelHandle handle) {
|
||||
return const_cast<Panel&>(std::as_const(*this).get(handle));
|
||||
}
|
||||
const Panel& get(PanelHandle handle) const { return pool.get(handle); }
|
||||
Panel& get(PanelHandle handle) { return pool.get(handle); }
|
||||
|
||||
template <typename T>
|
||||
const T& get(PanelHandle handle) const {
|
||||
@@ -46,19 +47,17 @@ class PanelRegistry {
|
||||
return const_cast<T&>(std::as_const(*this).template get<T>(handle));
|
||||
}
|
||||
|
||||
void remove(PanelHandle handle);
|
||||
bool isValid(PanelHandle handle) const;
|
||||
void remove(PanelHandle handle) { pool.release(handle); }
|
||||
bool isValid(PanelHandle handle) const { return pool.isAlive(handle); }
|
||||
|
||||
template <typename T>
|
||||
const T* find() const {
|
||||
for (const Slot& slot : slots) {
|
||||
if (slot.panel) {
|
||||
if (const T* panel = dynamic_cast<const T*>(slot.panel.get())) {
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
const T* result = nullptr;
|
||||
pool.findIf([&result](const Panel& panel) {
|
||||
result = dynamic_cast<const T*>(&panel);
|
||||
return result != nullptr;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -67,29 +66,22 @@ class PanelRegistry {
|
||||
}
|
||||
|
||||
const Panel* find(std::string_view name) const {
|
||||
for (const Slot& slot : slots) {
|
||||
if (slot.panel && slot.panel->getName() == name) {
|
||||
return slot.panel.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return pool.findIf(
|
||||
[name](const Panel& panel) { return panel.getName() == name; });
|
||||
}
|
||||
|
||||
Panel* find(std::string_view name) {
|
||||
return const_cast<Panel*>(std::as_const(*this).find(name));
|
||||
}
|
||||
|
||||
u32 size() const;
|
||||
u32 size() const { return pool.size(); }
|
||||
u32 visibleCount() const;
|
||||
|
||||
std::vector<std::string_view> names() const {
|
||||
std::vector<std::string_view> result;
|
||||
result.reserve(slots.size());
|
||||
for (const Slot& slot : slots) {
|
||||
if (slot.panel) {
|
||||
result.push_back(slot.panel->getName());
|
||||
}
|
||||
}
|
||||
result.reserve(pool.size());
|
||||
pool.forEach(
|
||||
[&result](const Panel& panel) { result.push_back(panel.getName()); });
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -101,13 +93,7 @@ class PanelRegistry {
|
||||
const DockLayout& getDefaultLayout() const { return defaultLayout; }
|
||||
|
||||
private:
|
||||
struct Slot {
|
||||
std::unique_ptr<Panel> panel;
|
||||
u32 generation = 0;
|
||||
};
|
||||
|
||||
std::vector<Slot> slots;
|
||||
std::vector<u32> freeList;
|
||||
Pool<Panel, PanelHandle> pool{"Panel"};
|
||||
DockLayout defaultLayout;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <sophia/types.hpp>
|
||||
#include <sophia/util/assert.hpp>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
template <typename T, typename HandleType>
|
||||
class Pool {
|
||||
public:
|
||||
explicit Pool(const char* name) : name{name} {}
|
||||
|
||||
Pool(const Pool&) = delete;
|
||||
Pool& operator=(const Pool&) = delete;
|
||||
|
||||
template <typename... Args>
|
||||
HandleType create(Args&&... args) {
|
||||
return add(std::make_unique<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
HandleType add(std::unique_ptr<T> item) {
|
||||
if (!freeList.empty()) {
|
||||
u32 index = freeList.back();
|
||||
freeList.pop_back();
|
||||
slots[index].item = std::move(item);
|
||||
return HandleType{index, slots[index].generation};
|
||||
}
|
||||
|
||||
slots.push_back(Slot{std::move(item), 0});
|
||||
return HandleType{static_cast<u32>(slots.size() - 1), 0};
|
||||
}
|
||||
|
||||
T& get(HandleType handle) {
|
||||
return const_cast<T&>(std::as_const(*this).get(handle));
|
||||
}
|
||||
|
||||
const T& get(HandleType handle) const { return *validate(handle).item; }
|
||||
|
||||
void release(HandleType handle) {
|
||||
validate(handle);
|
||||
|
||||
Slot& slot = slots[handle.index];
|
||||
slot.item.reset();
|
||||
slot.generation = (slot.generation + 1) & GENERATION_MASK;
|
||||
freeList.push_back(handle.index);
|
||||
}
|
||||
|
||||
bool isAlive(HandleType handle) const {
|
||||
return handle.isValid() && handle.index < slots.size() &&
|
||||
slots[handle.index].generation == handle.generation &&
|
||||
slots[handle.index].item != nullptr;
|
||||
}
|
||||
|
||||
u32 size() const { return static_cast<u32>(slots.size() - freeList.size()); }
|
||||
|
||||
template <typename Fn>
|
||||
void forEach(Fn&& fn) {
|
||||
for (Slot& slot : slots) {
|
||||
if (slot.item) {
|
||||
fn(*slot.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
void forEach(Fn&& fn) const {
|
||||
for (const Slot& slot : slots) {
|
||||
if (slot.item) {
|
||||
fn(*slot.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Predicate>
|
||||
T* findIf(Predicate&& predicate) {
|
||||
return const_cast<T*>(
|
||||
std::as_const(*this).findIf(std::forward<Predicate>(predicate)));
|
||||
}
|
||||
|
||||
template <typename Predicate>
|
||||
const T* findIf(Predicate&& predicate) const {
|
||||
for (const Slot& slot : slots) {
|
||||
if (slot.item && predicate(*slot.item)) {
|
||||
return slot.item.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr u32 GENERATION_MASK = (1u << 12) - 1;
|
||||
|
||||
struct Slot {
|
||||
std::unique_ptr<T> item;
|
||||
u32 generation = 0;
|
||||
};
|
||||
|
||||
const Slot& validate(HandleType handle) const {
|
||||
SOPHIA_ASSERT(handle.isValid(), "invalid handle:", name);
|
||||
SOPHIA_ASSERT(handle.index < slots.size(), name,
|
||||
"handle index out of range:", handle.index);
|
||||
|
||||
const Slot& slot = slots[handle.index];
|
||||
SOPHIA_ASSERT(slot.generation == handle.generation, "stale", name,
|
||||
"handle (generation mismatch):", handle.index);
|
||||
SOPHIA_ASSERT(slot.item != nullptr, name,
|
||||
"handle refers to a released item:", handle.index);
|
||||
return slot;
|
||||
}
|
||||
|
||||
const char* name;
|
||||
std::vector<Slot> slots;
|
||||
std::vector<u32> freeList;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
Reference in New Issue
Block a user