diff --git a/src/base/log.cpp b/src/base/log.cpp index 69a04d08..ffe3ae8a 100644 --- a/src/base/log.cpp +++ b/src/base/log.cpp @@ -95,7 +95,7 @@ void Log::Helper(MessageType type, char const *fmt, va_list ap) array widechar; widechar.Resize(buf.Count() + 1); - MultiByteToWideChar(CP_UTF8, 0, buf.C(), buf.Count() + 1, widechar.Data(), widechar.Count()); + MultiByteToWideChar(CP_UTF8, 0, buf.C(), (int)buf.Count() + 1, widechar.Data(), widechar.Count()); OutputDebugStringW(widechar.Data()); # else fprintf(stderr, "%s: ", prefix[type]); diff --git a/src/lolimgui.h b/src/lolimgui.h index 64209bf8..5634834f 100644 --- a/src/lolimgui.h +++ b/src/lolimgui.h @@ -174,7 +174,7 @@ protected: }; //----------------------------------------------------------------------------- -class PrimitiveLolImGui : public Primitive +class PrimitiveLolImGui : public PrimitiveSource { public: PrimitiveLolImGui() { } diff --git a/src/mesh/primitive.h b/src/mesh/primitive.h index 618cbe5d..6f1f5834 100644 --- a/src/mesh/primitive.h +++ b/src/mesh/primitive.h @@ -18,7 +18,7 @@ namespace lol { -class PrimitiveMesh : public Primitive +class PrimitiveMesh : public PrimitiveSource { friend class Scene; diff --git a/src/scene.cpp b/src/scene.cpp index 2834a2e1..75c6b0a9 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -69,11 +69,15 @@ private: uint64_t m_mask_id = 0; /* New scenegraph */ - array m_primitives; - /* Primitives will be kept until: + array m_primitives; + /* Primitives are shared by all scenes. + * Renderers are scene-dependent. They get the primitive in the identical slot to render with the given scene + * Primitives and renderers will be kept until: * - Updated by entity * - Scene is destroyed */ - map > m_primitives_; + map > m_prim_renderers; + static map > m_prim_sources; + static mutex m_prim_mutex; /* Old API */ float m_new_line_time; @@ -99,6 +103,8 @@ private: array m_camera_stack; }; uint64_t SceneData::m_used_id = 1; +map > SceneData::m_prim_sources; +mutex SceneData::m_prim_mutex; /* * Public Scene class @@ -255,17 +261,125 @@ void Scene::Reset() } //----------------------------------------------------------------------------- -void Scene::AddPrimitive(Primitive* primitive) +void Scene::AddPrimitive(PrimitiveSource* primitive) { data->m_primitives.Push(primitive); } -//----------------------------------------------------------------------------- -void Scene::AddPrimitive(Entity* entity, Primitive* primitive) +//---- Primitive source stuff ------------------------------------------------- +#define _ENT_IDX (uintptr_t)entity /* TOUKY: I don't like that. hash should be fixed to handle these custom stuff */ +//---- Primitive source stuff ------------------------------------------------- +ptrdiff_t Scene::HasPrimitiveSource(Entity* entity) +{ + ASSERT(entity); + ptrdiff_t count; + SceneData::m_prim_mutex.lock(); + { + count = SceneData::m_prim_sources[_ENT_IDX].count(); + } + SceneData::m_prim_mutex.unlock(); + return count; +} +ptrdiff_t Scene::AddPrimitiveSource(Entity* entity, PrimitiveSource* source) +{ + ASSERT(entity); + ptrdiff_t count; + SceneData::m_prim_mutex.lock(); + { + count = SceneData::m_prim_sources[_ENT_IDX].count(); + SceneData::m_prim_sources[_ENT_IDX].push(source); + } + SceneData::m_prim_mutex.unlock(); + return count; +} +void Scene::SetPrimitiveSource(ptrdiff_t index, Entity* entity, PrimitiveSource* source) +{ + ASSERT(entity); + PrimitiveSource* old = nullptr; + SceneData::m_prim_mutex.lock(); + { + ASSERT(0 <= index && index < SceneData::m_prim_sources[_ENT_IDX].count()); + old = SceneData::m_prim_sources[_ENT_IDX][index]; + SceneData::m_prim_sources[_ENT_IDX][index] = source; + } + SceneData::m_prim_mutex.unlock(); + + //Delete old AFTER having released the lock + if (old) delete old; +} +void Scene::ReleasePrimitiveSource(ptrdiff_t index, Entity* entity) { - /* FIXME: data->m_primitives_ is never emptied or even used. */ - data->m_primitives_[(uintptr_t)entity /* I don't like that */].push(primitive, nullptr); + ASSERT(entity); + PrimitiveSource* old = nullptr; + SceneData::m_prim_mutex.lock(); + { + ASSERT(0 <= index && index < SceneData::m_prim_sources[_ENT_IDX].count()); + old = SceneData::m_prim_sources[_ENT_IDX][index]; + SceneData::m_prim_sources[_ENT_IDX].remove(index); + } + SceneData::m_prim_mutex.unlock(); + + //Delete old AFTER having released the lock + if (old) delete old; } +void Scene::ReleaseAllPrimitiveSource(Entity* entity) +{ + ASSERT(entity); + array oldies; + SceneData::m_prim_mutex.lock(); + { + oldies.reserve(SceneData::m_prim_sources[_ENT_IDX].count()); + for (PrimitiveSource* source : SceneData::m_prim_sources[_ENT_IDX]) + oldies << source; + SceneData::m_prim_sources[_ENT_IDX].empty(); + } + SceneData::m_prim_mutex.unlock(); + + //Delete oldies AFTER having released the lock + for (PrimitiveSource* old : oldies) + if (old) delete old; +} + +//---- Primitive renderer stuff ----------------------------------------------- +ptrdiff_t Scene::HasPrimitiveRenderer(Entity* entity) +{ + ASSERT(entity); + return data->m_prim_renderers[_ENT_IDX].count(); +} +ptrdiff_t Scene::AddPrimitiveRenderer(Entity* entity, PrimitiveRenderer* renderer) +{ + ASSERT(entity); + data->m_prim_renderers[_ENT_IDX].push(renderer); + return data->m_prim_renderers[_ENT_IDX].count() - 1; +} +void Scene::SetPrimitiveRenderer(ptrdiff_t index, Entity* entity, PrimitiveRenderer* renderer) +{ + ASSERT(entity && renderer); + ASSERT(0 <= index && index < data->m_prim_renderers[_ENT_IDX].count()); + ASSERT(data->m_prim_renderers[_ENT_IDX][index]); + delete data->m_prim_renderers[_ENT_IDX][index]; + data->m_prim_renderers[_ENT_IDX][index] = renderer; +} +void Scene::ReleasePrimitiveRenderer(ptrdiff_t index, Entity* entity) +{ + ASSERT(entity); + ASSERT(0 <= index && index < data->m_prim_renderers[_ENT_IDX].count()); + ASSERT(data->m_prim_renderers[_ENT_IDX][index]); + delete data->m_prim_renderers[_ENT_IDX][index]; + data->m_prim_renderers[_ENT_IDX].remove(index); +} +void Scene::ReleaseAllPrimitiveRenderer(Entity* entity) +{ + ASSERT(entity); + for (PrimitiveRenderer* renderer : data->m_prim_renderers[_ENT_IDX]) + { + ASSERT(renderer); + delete renderer; + } +} +//---- Primitive source stuff ------------------------------------------------- +#undef _ENT_IDX //(uintptr_t)entity /* TOUKY: I don't like that. hash should be fixed to handle these custom stuff */ +//---- Primitive source stuff ------------------------------------------------- //----------------------------------------------------------------------------- void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale, float angle) @@ -360,10 +474,20 @@ void Scene::RenderPrimitives() /* TODO: this should be the main entry for rendering of all * primitives found in the scene graph. When we have one. */ - for (Primitive* p : data->m_primitives) + for (PrimitiveSource* p : data->m_primitives) { p->Render(*this); } + /* new scenegraph */ + array keys = data->m_prim_renderers.keys(); + for (uintptr_t key : keys) + { + for (ptrdiff_t idx = 0; idx < data->m_prim_renderers[key].count(); ++idx) + { + /* TODO: Not sure if thread compliant */ + data->m_prim_renderers[key][idx]->Render(idx < SceneData::m_prim_sources[key].count() ? SceneData::m_prim_sources[key][idx] : nullptr); + } + } } //----------------------------------------------------------------------------- diff --git a/src/scene.h b/src/scene.h index 84e289e3..9a2f7b7f 100644 --- a/src/scene.h +++ b/src/scene.h @@ -30,26 +30,26 @@ namespace lol class SceneData; //----------------------------------------------------------------------------- -class Primitive +class PrimitiveSource { friend class Scene; public: - Primitive() { } - virtual ~Primitive() { } + PrimitiveSource() { } + virtual ~PrimitiveSource() { } virtual void Render(Scene& scene) { } private: }; -class PrimitiveSettings +class PrimitiveRenderer { friend class Scene; public: - PrimitiveSettings() { } - virtual ~PrimitiveSettings() { } - virtual void ApplyTo(Primitive* primitive) const { UNUSED(primitive); } + PrimitiveRenderer() { } + virtual ~PrimitiveRenderer() { } + virtual void Render(PrimitiveSource* primitive) const { UNUSED(primitive); } private: }; @@ -69,8 +69,7 @@ private: public: static void AddNew(ivec2 size); -private: - //Private because I don't know if we should have it +private: //Private because I don't know if we should have it static void DestroyScene(Scene* scene); private: static void DestroyAll(); @@ -93,8 +92,38 @@ public: void Reset(); /* New scenegraph */ - void AddPrimitive(Primitive* primitive); - void AddPrimitive(Entity* entity, Primitive* primitive); + void AddPrimitive(PrimitiveSource* primitive); + + /* === Primitive source stuff === */ + /* Returns the number of primitive source set to the given entity */ + ptrdiff_t HasPrimitiveSource(Entity* entity); + /* Add a primitive sources linked to the given entity + * Returns the slot number */ + ptrdiff_t AddPrimitiveSource(Entity* entity, PrimitiveSource* source); + /* Update the primitive source at index linked to the given entity + * Deletes the old one + * The slot is kept even if source == nullptr */ + void SetPrimitiveSource(ptrdiff_t index, Entity* entity, PrimitiveSource* source); + /* Remove primitive source at index set to the given entity */ + void ReleasePrimitiveSource(ptrdiff_t index, Entity* entity); + /* Remove all primitive source set to the given entity */ + void ReleaseAllPrimitiveSource(Entity* entity); + + /* === Primitive renderer stuff === */ + /* Returns the number of primitive renderer set to the given entity */ + ptrdiff_t HasPrimitiveRenderer(Entity* entity); + /* Add a primitive renderer linked to the given entity + * Returns the slot number */ + ptrdiff_t AddPrimitiveRenderer(Entity* entity, PrimitiveRenderer* renderer); + /* Update the primitive renderer linked to the given entity + * Deletes the old one + * Will assert if renderer == nullptr */ + void SetPrimitiveRenderer(ptrdiff_t index, Entity* entity, PrimitiveRenderer* renderer); + /* Remove primitive renderer at index set to the given entity */ + void ReleasePrimitiveRenderer(ptrdiff_t index, Entity* entity); + /* Remove all primitive renderer set to the given entity */ + void ReleaseAllPrimitiveRenderer(Entity* entity); + /* FIXME: this should be deprecated -- it doesn't really match * the architecture we want to build */