From 71ee91fcb1f7a3b2021b5d9d2e33fe95ff0fd2b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20=E2=80=98Touky=E2=80=99=20Huet?= Date: Wed, 22 Apr 2015 03:29:52 +0000 Subject: [PATCH] MultiplMultiScene: Phase 2: No more g_scene access and multiple scene calls support --- build/Lol (vs2013).sln | 14 ++---- src/entity.h | 2 + src/platform/nacl/nacl-instance.cpp | 2 +- src/scene.cpp | 78 ++++++++++++++++++++++++++--- src/scene.h | 33 ++++++++++-- src/ticker.cpp | 47 ++++++++++++++--- src/video.cpp | 5 +- 7 files changed, 148 insertions(+), 33 deletions(-) diff --git a/build/Lol (vs2013).sln b/build/Lol (vs2013).sln index bf43cec6..88970133 100644 --- a/build/Lol (vs2013).sln +++ b/build/Lol (vs2013).sln @@ -757,24 +757,18 @@ Global {81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.ActiveCfg = Release|x64 {81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.Build.0 = Release|x64 {81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Xbox 360.ActiveCfg = Release|Win32 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|ORBIS.ActiveCfg = Debug|ORBIS - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|ORBIS.Build.0 = Debug|ORBIS + {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|ORBIS.ActiveCfg = Debug|Win32 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|Win32.ActiveCfg = Debug|Win32 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|Win32.Build.0 = Debug|Win32 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|x64.ActiveCfg = Debug|x64 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|x64.Build.0 = Debug|x64 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|Xbox 360.ActiveCfg = Debug|Xbox 360 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|Xbox 360.Build.0 = Debug|Xbox 360 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|Xbox 360.Deploy.0 = Debug|Xbox 360 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|ORBIS.ActiveCfg = Release|ORBIS - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|ORBIS.Build.0 = Release|ORBIS + {B9A255A0-2B92-4801-AF6C-354535A6E105}.Debug|Xbox 360.ActiveCfg = Debug|Win32 + {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|ORBIS.ActiveCfg = Release|Win32 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|Win32.ActiveCfg = Release|Win32 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|Win32.Build.0 = Release|Win32 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|x64.ActiveCfg = Release|x64 {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|x64.Build.0 = Release|x64 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|Xbox 360.ActiveCfg = Release|Xbox 360 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|Xbox 360.Build.0 = Release|Xbox 360 - {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|Xbox 360.Deploy.0 = Release|Xbox 360 + {B9A255A0-2B92-4801-AF6C-354535A6E105}.Release|Xbox 360.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/entity.h b/src/entity.h index 212e222d..71b337d9 100644 --- a/src/entity.h +++ b/src/entity.h @@ -41,6 +41,7 @@ struct InitState class Entity { + friend class Scene; friend class Ticker; friend class TickerData; friend class Dict; @@ -146,6 +147,7 @@ private: private: int m_ref, m_autorelease, m_destroy; + uint64_t m_scene_mask = 0; }; } /* namespace lol */ diff --git a/src/platform/nacl/nacl-instance.cpp b/src/platform/nacl/nacl-instance.cpp index a2d93870..93a14c2f 100644 --- a/src/platform/nacl/nacl-instance.cpp +++ b/src/platform/nacl/nacl-instance.cpp @@ -253,7 +253,7 @@ void NaClInputData::Tick(float seconds) //---- void NaClInputData::InitViewportSize() { - if (g_scene) + if (g_scenes.count()) { m_app = vec2(Video::GetSize()); //Dunno if its the good idea. diff --git a/src/scene.cpp b/src/scene.cpp index 51015616..6490b95a 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -27,10 +27,10 @@ namespace lol { /* - * The global g_scene object, initialised by Video::Init + * The global g_scenes object, initialised by Video::Init */ - Scene *Scene::g_scene = nullptr; +array Scene::g_scenes; /* * A quick and dirty Tile structure for 2D blits @@ -55,8 +55,25 @@ class SceneData friend class Scene; private: + SceneData() + { + /* TODO: FIX THAT */ + ASSERT(!(m_used_id & ((uint64_t)1 << 63)), "Too many scenes !!!!"); + m_mask_id = m_used_id; + m_used_id = m_used_id << 1; + } + + /* Mask ID */ + /* TODO: Do a mask class that handles more than 64 slots */ + static uint64_t m_used_id; + uint64_t m_mask_id = 0; + /* New scenegraph */ array m_primitives; + /* Primitives will be kept until: + * - Updated by entity + * - Scene is destroyed */ + map > m_primitives_; /* Old API */ float m_new_line_time; @@ -81,6 +98,7 @@ private: Camera *m_default_cam; array m_camera_stack; }; +uint64_t SceneData::m_used_id = 1; /* * Public Scene class @@ -127,24 +145,64 @@ Scene::~Scene() delete data; } +//----------------------------------------------------------------------------- +Scene* Scene::AddNew(ivec2 size) +{ + Scene::g_scenes << new Scene(size); + return Scene::g_scenes.last(); +} +void Scene::DestroyScene(Scene* scene) +{ + Scene::g_scenes.remove_item(scene); + delete scene; +} +void Scene::DestroyAll() +{ + while (Scene::g_scenes.count()) + delete Scene::g_scenes.pop(); +} +ptrdiff_t Scene::GetCount() +{ + return g_scenes.count(); +} + +//----------------------------------------------------------------------------- +Scene* Scene::GetScene(ptrdiff_t index) +{ + ASSERT(0 <= index && index < g_scenes.count(), "Trying to get a non-existent scene"); + return g_scenes[index]; +} + //----------------------------------------------------------------------------- bool Scene::GetScene(Scene*& scene) { - ASSERT(!!g_scene, "Trying to access a non-ready scene"); - return (scene = g_scene) != nullptr; + ASSERT(!!g_scenes.count(), "Trying to access a non-ready scene"); + return (scene = g_scenes[0]) != nullptr; } //----------------------------------------------------------------------------- bool Scene::GetSceneData(SceneData*& data) { - ASSERT(!!g_scene, "Trying to access a non-ready scene"); - return (data = g_scene->data) != nullptr; + ASSERT(!!g_scenes.count(), "Trying to access a non-ready scene"); + return (data = g_scenes[0]->data) != nullptr; } //----------------------------------------------------------------------------- bool Scene::IsReady() { - return !!g_scene; + return !!g_scenes[0]; +} + +//----------------------------------------------------------------------------- +void Scene::Apply(Entity* entity) +{ + entity->m_scene_mask |= data->m_mask_id; +} + +//----------------------------------------------------------------------------- +bool Scene::IsRelevant(Entity* entity) +{ + return !!(entity->m_scene_mask & data->m_mask_id); } //----------------------------------------------------------------------------- @@ -250,6 +308,12 @@ void Scene::AddPrimitive(Primitive* primitive) data->m_primitives.Push(primitive); } +//----------------------------------------------------------------------------- +void Scene::AddPrimitive(Entity* entity, Primitive* primitive) +{ + data->m_primitives_[(uint32_t)entity /* I don't like that */].push(primitive, nullptr); +} + //----------------------------------------------------------------------------- void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale, float angle) { diff --git a/src/scene.h b/src/scene.h index 997385ef..6d711a4b 100644 --- a/src/scene.h +++ b/src/scene.h @@ -42,25 +42,49 @@ public: private: }; +class PrimitiveSettings +{ + friend class Scene; + +public: + PrimitiveSettings() { } + virtual ~PrimitiveSettings() { } + virtual void ApplyTo(Primitive* primitive) const { } + +private: +}; + +//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- class Scene { friend class Video; - friend class TickerData; //TODO: Smells shitty - + private: - static Scene *g_scene; + static array g_scenes; Scene(ivec2 size); ~Scene(); +public: + static Scene* AddNew(ivec2 size); + static void DestroyScene(Scene* scene); + static void DestroyAll(); + static ptrdiff_t GetCount(); + static Scene* GetScene(ptrdiff_t index); +private: static bool GetScene(Scene*& scene); static bool GetSceneData(SceneData*& data); public: static bool IsReady(); + //TODO: don't like the name + void Apply(Entity* entity); + bool IsRelevant(Entity* entity); - static Camera *GetCamera(int cam_idx=-1); +public: + static Camera *GetCamera(int cam_idx = -1); private: static int PushCamera(Scene* scene, Camera *cam); static void PopCamera(Scene* scene, Camera *cam); @@ -74,6 +98,7 @@ public: /* New scenegraph */ void AddPrimitive(Mesh const &mesh, mat4 const &matrix); void AddPrimitive(Primitive* primitive); + void AddPrimitive(Entity* entity, Primitive* primitive); /* FIXME: this should be deprecated -- it doesn't really match * the architecture we want to build */ diff --git a/src/ticker.cpp b/src/ticker.cpp index b155d635..03b81fee 100644 --- a/src/ticker.cpp +++ b/src/ticker.cpp @@ -57,7 +57,8 @@ public: private: /* Entity management */ array m_todolist, m_autolist; - array m_list[Entity::ALLGROUP_END]; //TODO: Add NO-DRAW entity support + array m_list[Entity::ALLGROUP_END]; + array m_scenes[Entity::ALLGROUP_END]; ptrdiff_t nentities; /* Fixed framerate management */ @@ -328,10 +329,32 @@ void TickerData::GameThreadTick() { Entity *e = data->m_todolist.Last(); - data->m_todolist.Remove(-1); - data->m_list[e->m_gamegroup].Push(e); + //If the entity has no mask, default it + if (e->m_scene_mask == 0) + { + Scene::GetScene(0)->Apply(e); + } + + data->m_todolist.remove(-1); + data->m_list[e->m_gamegroup].push(e); if (e->m_drawgroup != Entity::DRAWGROUP_NONE) - data->m_list[e->m_drawgroup].Push(e); + { + if (data->m_scenes[e->m_drawgroup].count() < Scene::GetCount()) + data->m_scenes[e->m_drawgroup].resize(Scene::GetCount()); + + ptrdiff_t add = 0; + for (ptrdiff_t i = 0; i < Scene::GetCount(); i++) + { + //If entity is concerned by this scene, add it in the list + if (Scene::GetScene(i)->IsRelevant(e)) + { + data->m_list[e->m_drawgroup].insert(e, data->m_scenes[e->m_drawgroup][i]); + add++; + } + //Update scene index + data->m_scenes[e->m_drawgroup][i] += add; + } + } // Initialize the entity e->InitGame(); @@ -340,10 +363,9 @@ void TickerData::GameThreadTick() /* Tick objects for the game loop */ for (int g = Entity::GAMEGROUP_BEGIN; g < Entity::GAMEGROUP_END && !data->quit /* Stop as soon as required */; ++g) { - for (int i = 0; i < data->m_list[g].Count() && !data->quit /* Stop as soon as required */; ++i) + for (ptrdiff_t i = 0; i < data->m_list[g].Count() && !data->quit /* Stop as soon as required */; ++i) { Entity *e = data->m_list[g][i]; - if (!e->m_destroy) { #if !LOL_BUILD_RELEASE @@ -374,6 +396,8 @@ void TickerData::DrawThreadTick() /* Tick objects for the draw loop */ for (int g = Entity::DRAWGROUP_BEGIN; g < Entity::DRAWGROUP_END && !data->quit /* Stop as soon as required */; ++g) { + ptrdiff_t scene_idx = 0; + //Scene::GetScene[scene_idx]->EnableDisplay(); //TODO switch (g) { case Entity::DRAWGROUP_BEGIN: @@ -384,9 +408,16 @@ void TickerData::DrawThreadTick() break; } - //Stop as soon as required for (int i = 0; i < data->m_list[g].Count() && !data->quit /* Stop as soon as required */; ++i) { + //We're outside of the range of the current scene, on to the next + if (i >= data->m_scenes[g][scene_idx]) + { + //Scene::GetScene[scene_idx]->DisableDisplay(); //TODO + scene_idx++; + //Scene::GetScene[scene_idx]->EnableDisplay(); //TODO + } + Entity *e = data->m_list[g][i]; if (!e->m_destroy) @@ -397,7 +428,7 @@ void TickerData::DrawThreadTick() e->GetName(), e); e->m_tickstate = Entity::STATE_PRETICK_DRAW; #endif - e->TickDraw(data->deltatime, *Scene::g_scene); + e->TickDraw(data->deltatime, *Scene::GetScene(scene_idx)); #if !LOL_BUILD_RELEASE if (e->m_tickstate != Entity::STATE_POSTTICK_DRAW) Log::Error("entity %s [%p] missed super draw tick\n", diff --git a/src/video.cpp b/src/video.cpp index 45c5aef8..e679763e 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -46,7 +46,7 @@ DebugRenderMode VideoData::render_mode = DebugRenderMode::Default; void Video::Setup(ivec2 size) { g_renderer = new Renderer(size); - Scene::g_scene = new Scene(size); + Scene::AddNew(size); /* Initialise reasonable scene default properties */ SetDebugRenderMode(DebugRenderMode::Default); @@ -94,8 +94,7 @@ DebugRenderMode Video::GetDebugRenderMode() void Video::Destroy() { - delete Scene::g_scene; - Scene::g_scene = nullptr; + Scene::DestroyAll(); delete g_renderer; g_renderer = nullptr;