diff --git a/include/Core/Engine.h b/include/Core/Engine.h index 49b5b48..071b1db 100755 --- a/include/Core/Engine.h +++ b/include/Core/Engine.h @@ -83,6 +83,8 @@ #include "GUI/Button.h" #include "Game/GUI/MainMenu.h" #include "Game/GUI/HUD.h" +#include "Game/GUI/ELoadingFrameComplete.h" +#include "Game/GUI/LoadingFrame.h" namespace dd { @@ -91,9 +93,18 @@ class Engine { public: - Engine(int argc, char* argv[]) { - auto config = ResourceManager::Load("Config.ini"); + Engine(int argc, char* argv[]) + { + ResourceManager::RegisterType("Texture"); + ResourceManager::RegisterType("Model"); + ResourceManager::RegisterType("Sound"); + ResourceManager::RegisterType("ConfigFile"); + ResourceManager::RegisterType("ShaderProgram"); + ResourceManager::RegisterType("VertexShader"); + ResourceManager::RegisterType("FragmentShader"); + ResourceManager::LoadPreloadsFromFile(); + auto config = ResourceManager::Load("Config.ini"); LOG_LEVEL = static_cast<_LOG_LEVEL>(config->GetValue("Debug.LogLevel", 1)); m_EventBroker = std::make_shared(); @@ -111,15 +122,11 @@ public: m_FrameStack = new GUI::Frame(m_EventBroker.get()); m_FrameStack->Width = 675; m_FrameStack->Height = 1080; - - if (config->GetValue("Debug.SkipStory", false)) { - Events::GameStart e; - m_EventBroker->Publish(e); - auto hud = new GUI::HUD(m_FrameStack, "HUD"); - } - else { - auto menu = new GUI::MainMenu(m_FrameStack, "MainMenu"); - } + m_MainMenu = new GUI::MainMenu(m_FrameStack, "MainMenu"); + m_MainMenu->Hide(); + m_LoadingFrame = new GUI::LoadingFrame(m_FrameStack, "Loading"); + m_LoadingFrame->SetTexture("Textures/GUI/Loading.png"); + PreloadAllTheShit(); m_InputManager = std::make_shared(m_Renderer->Window(), m_EventBroker); @@ -208,15 +215,28 @@ public: //auto particleEmitter= m_World->AddComponent(Pe); - - - //EVENT_SUBSCRIBE_MEMBER(m_EGameStart, &Engine::OnGameStart); m_EGameStart = decltype(m_EGameStart)(std::bind(&Engine::OnGameStart, this, std::placeholders::_1)); m_EventBroker->Subscribe(m_EGameStart); + m_ELoadingFrameComplete = decltype(m_ELoadingFrameComplete)(std::bind(&Engine::OnLoadingFrameComplete, this, std::placeholders::_1)); + m_EventBroker->Subscribe(m_ELoadingFrameComplete); m_LastTime = glfwGetTime(); } + void PreloadAllTheShit() + { + if (ResourceManager::Load("Config.ini")->GetValue("Debug.SkipPreload", false)) { + m_LoadingFrame->Hide(); + m_MainMenu->Show(); + return; + } + + for (auto& pair : ResourceManager::GetPreloads()) { + m_LoadingFrame->AddResource(pair.first, pair.second); + } + m_LoadingFrame->Preload(); + } + bool Running() const { return !glfwWindowShouldClose(m_Renderer->Window()); } void Tick() @@ -416,6 +436,8 @@ public: private: std::shared_ptr m_EventBroker; GUI::Frame* m_FrameStack = nullptr; + GUI::MainMenu* m_MainMenu = nullptr; + GUI::LoadingFrame* m_LoadingFrame = nullptr; std::shared_ptr m_Renderer; RenderQueueCollection m_RendererQueue; std::shared_ptr m_InputManager; @@ -445,6 +467,17 @@ private: return true; }; + + EventRelay m_ELoadingFrameComplete; + bool OnLoadingFrameComplete(const Events::LoadingFrameComplete& event) + { + if (event.FrameName == "Loading") { + event.Frame->Hide(); + m_MainMenu->Show(); + } + return true; + } + double m_LastTime; }; diff --git a/include/Core/ResourceManager.h b/include/Core/ResourceManager.h index 3cebf4a..83a36e5 100644 --- a/include/Core/ResourceManager.h +++ b/include/Core/ResourceManager.h @@ -22,7 +22,9 @@ #include #include #include +#include #include +#include #include "Util/UnorderedMapPair.h" #include "Util/Factory.h" @@ -70,13 +72,8 @@ public: return s; }*/ - /** Registers the factory function of a resource type - - @tparam T Resource type. - @param factoryFunction Lambda function that creates a new instance of the resource. - */ template - static void RegisterType(std::function factoryFunction); + static void RegisterType(std::string typeName); /** Preloads a resource and caches it for future use @@ -85,6 +82,7 @@ public: */ template static void Preload(std::string resourceName); + static void Preload(std::string resourceType, std::string resourceName); /** Checks if a resource is in cache @@ -101,14 +99,7 @@ public: */ template static T* Load(std::string resourceName, Resource* parent = nullptr); - - /** Fetches a loaded resource - - @tparam T Resource type. - @param resourceName Fully qualified name of the resource to fetch. - */ - template - static T* Fetch(std::string resourceName); + static Resource* Load(std::string resourceType, std::string resourceName, Resource* parent = nullptr); /** Reloads an already loaded resource, keeping its resource ID intact. @@ -116,14 +107,19 @@ public: @param resourceName Fully qualified name of the resource to reload. */ static void Reload(std::string resourceName); + + static void LoadPreloadsFromFile(); + static const std::set>& GetPreloads() { return m_Preloads; } static void Update(); private: + static std::unordered_map m_CompilerTypenameToResourceType; static std::unordered_map> m_FactoryFunctions; // type -> factory function static std::unordered_map, Resource*> m_ResourceCache; // (type, name) -> resource static std::unordered_map m_ResourceFromName; // name -> resource static std::unordered_map m_ResourceParents; // resource -> parent resource + static std::set> m_Preloads; // (type, name) // TODO: Getters for IDs static unsigned int m_CurrentResourceTypeID; @@ -140,93 +136,40 @@ private: static unsigned int GetNewResourceID(unsigned int typeID); // Internal: Create a resource and cache it - template - static T* CreateResource(std::string resourceName, Resource* parent); + static Resource* CreateResource(std::string resourceType, std::string resourceName, Resource* parent); }; template T* ResourceManager::Load(std::string resourceName, Resource* parent /* = nullptr */) { - auto resourceType = typeid(T).name(); - auto it = m_ResourceCache.find(std::make_pair(resourceType, resourceName)); - if (it != m_ResourceCache.end()) - return static_cast(it->second); - - if (m_Preloading) { - LOG_INFO("Preloading resource \"%s\"", resourceName.c_str()); - } else { - LOG_WARNING("Hot-loading resource \"%s\"", resourceName.c_str()); - } - - return CreateResource(resourceName, parent); -} - -template -T* ResourceManager::Fetch(std::string resourceName) -{ - auto resourceType = typeid(T).name(); - auto it = m_ResourceCache.find(std::make_pair(resourceType, resourceName)); - if (it == m_ResourceCache.end()) - { - LOG_ERROR("Failed to fetch resource \"%s\": Resource not loaded!", resourceName.c_str()); + auto resourceTypename = typeid(T).name(); + auto it = m_CompilerTypenameToResourceType.find(resourceTypename); + if (it == m_CompilerTypenameToResourceType.end()) { + LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename); return nullptr; - } else - { - return static_cast(it->second); } + + return static_cast(Load(it->second, resourceName, parent)); } template -void ResourceManager::RegisterType(std::function factoryFunction) +void ResourceManager::RegisterType(std::string typeName) { - m_FactoryFunctions[typeid(T).name()] = factoryFunction; + m_CompilerTypenameToResourceType[typeid(T).name()] = typeName; + m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); }; } template void ResourceManager::Preload(std::string resourceName) { - auto resourceType = typeid(T).name(); - if (IsResourceLoaded(resourceType, resourceName)) - { - LOG_WARNING("Attempted to preload resource \"%s\" multiple times!", resourceName.c_str()); + auto resourceTypename = typeid(T).name(); + auto it = m_CompilerTypenameToResourceType.find(resourceTypename); + if (it == m_CompilerTypenameToResourceType.end()) { + LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceType); return; } - m_Preloading = true; - LOG_INFO("Preloading resource \"%s\"", resourceName.c_str()); - CreateResource(resourceName, nullptr); - m_Preloading = false; -} - -template -T* ResourceManager::CreateResource(std::string resourceName, Resource* parent) -{ - const char* resourceType = typeid(T).name(); - /*auto facIt = m_FactoryFunctions.find(resourceType); - if (facIt == m_FactoryFunctions.end()) - { - LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": Type not registered", resourceName.c_str(), resourceType); - return nullptr; - }*/ - - // Call the factory function - T* resource = new T(resourceName); - // Store IDs - resource->TypeID = GetTypeID(resourceType); - resource->ResourceID = GetNewResourceID(resource->TypeID); - // Cache - m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource; - m_ResourceFromName[resourceName] = resource; - if (parent != nullptr) - { - m_ResourceParents[resource] = parent; - } - if (!boost::filesystem::is_directory(resourceName)) - { - LOG_DEBUG("Adding watch for %s", resourceName.c_str()); - m_FileWatcher.AddWatch(resourceName, fileWatcherCallback); - } - return resource; + Preload(it->second, resourceName); } } diff --git a/include/Game/GUI/LoadingFrame.h b/include/Game/GUI/LoadingFrame.h index 98dced7..6e075d7 100644 --- a/include/Game/GUI/LoadingFrame.h +++ b/include/Game/GUI/LoadingFrame.h @@ -5,7 +5,6 @@ #include "GUI/Slider.h" #include "Core/ResourceManager.h" #include "Game/GUI/ELoadingFrameComplete.h" -#include "Sound/EPlaySound.h" namespace dd { @@ -29,9 +28,9 @@ public: m_Slider->X = Width / 2.f - m_Slider->Width / 2.f; } - void AddTexturePreload(std::string resourceName) + void AddResource(std::string resourceType, std::string resourceName) { - m_Items.push_back(resourceName); + m_Preload.push_back(std::make_pair(resourceType, resourceName)); } void Preload() @@ -48,18 +47,15 @@ public: void Update(double dt) override { if (m_Preloading) { - ResourceManager::Preload(m_Items[m_CurrentItem]); - m_Slider->SetPercentage((m_CurrentItem + 1) / (float)m_Items.size()); + ResourceManager::Preload(m_Preload[m_CurrentItem].first, m_Preload[m_CurrentItem].second); + m_Slider->SetPercentage((m_CurrentItem + 1) / (float)m_Preload.size()); m_CurrentItem++; - if (m_CurrentItem >= m_Items.size()) { + if (m_CurrentItem >= m_Preload.size()) { m_Preloading = false; dd::Events::LoadingFrameComplete e; e.FrameName = Name(); e.Frame = this; EventBroker->Publish(e); - Events::PlaySound se; - se.FilePath = "Sounds/jap-story.wav"; - EventBroker->Publish(se); } } } @@ -67,7 +63,7 @@ public: private: bool m_Preloading = false; int m_CurrentItem = 0; - std::vector m_Items; + std::vector> m_Preload; GUI::Slider* m_Slider = nullptr; }; diff --git a/include/Game/GUI/MainMenu.h b/include/Game/GUI/MainMenu.h index 0cbc950..63e8b8b 100644 --- a/include/Game/GUI/MainMenu.h +++ b/include/Game/GUI/MainMenu.h @@ -2,9 +2,11 @@ #define GUI_MAINMENU_H__ #include "GUI/TextureFrame.h" +#include "Game/GUI/LoadingFrame.h" #include "Game/GUI/MainMenuMain.h" #include "Game/GUI/MainMenuOptions.h" #include "Core/EKeyUp.h" +#include "Game/EGameStart.h" namespace dd { @@ -37,6 +39,18 @@ public: //EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &MainMenu::OnKeyUp); } + void Show() override + { + if (ResourceManager::Load("Config.ini")->GetValue("Debug.SkipMenu", false)) { + Events::GameStart e; + EventBroker->Publish(e); + Hide(); + auto hud = new GUI::HUD(BaseFrame, "HUD"); + } else { + TextureFrame::Show(); + } + } + private: TextureFrame* m_LeftBanner; MainMenuMain* m_MainMenuMain; diff --git a/include/Game/GUI/MainMenuMain.h b/include/Game/GUI/MainMenuMain.h index a033c3d..f78f1d1 100644 --- a/include/Game/GUI/MainMenuMain.h +++ b/include/Game/GUI/MainMenuMain.h @@ -58,6 +58,7 @@ private: if (event.Button == m_SquidoutButton) { m_Parent->Hide(); auto story = new GUI::Story1(BaseFrame, "Story1"); + story->Play(); } return true; diff --git a/include/Game/GUI/Story1.h b/include/Game/GUI/Story1.h index 71fbe97..ff13611 100644 --- a/include/Game/GUI/Story1.h +++ b/include/Game/GUI/Story1.h @@ -3,11 +3,11 @@ #include "Core/ResourceManager.h" #include "Game/GUI/StoryboardFrame.h" -#include "Game/GUI/ELoadingFrameComplete.h" -#include "Game/GUI/LoadingFrame.h" #include "Game/EGameStart.h" #include "Core/EKeyDown.h" #include "Game/GUI/HUD.h" +#include "Sound/EPlaySound.h" +#include "Sound/EStopSound.h" namespace dd { @@ -20,37 +20,8 @@ public: Story1(Frame* parent, std::string name) : StoryboardFrame(parent, name) { - EVENT_SUBSCRIBE_MEMBER(m_ELoadingFrameComplete, &Story1::OnLoadingFrameComplete); EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Story1::OnKeyDown); - m_LoadingFrame = new GUI::LoadingFrame(this, "Story1LoadingFrame"); - m_LoadingFrame->SetTexture("Textures/GUI/Loading.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/Brunn1.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/Brunn2.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/Brunn3.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/Brunn4.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/Brunn5.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene1.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene2.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene3.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene4.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene5.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene6.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene7.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene8.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene9.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene10.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene11.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene12.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene13.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene14.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene15.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene16.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene17.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene18.png"); - m_LoadingFrame->AddTexturePreload("Textures/Story/SubScene19.png"); - m_LoadingFrame->Preload(); - m_Spacebar = new TextureFrame(this, "ZZZSpacebar"); m_Spacebar->SetTexture("Textures/GUI/SpacebarSkip.png"); m_Spacebar->SetRight(Right() - 10); @@ -196,6 +167,14 @@ public: AddTransition(t); } + virtual void Play() override + { + StoryboardFrame::Play(); + Events::PlaySound se; + se.FilePath = "Sounds/jap-story.wav"; + EventBroker->Publish(se); + } + void Update(double dt) override { StoryboardFrame::Update(dt); @@ -209,7 +188,6 @@ public: } private: - GUI::LoadingFrame* m_LoadingFrame = nullptr; TextureFrame* m_Spacebar = nullptr; EventRelay m_EKeyDown; @@ -220,25 +198,17 @@ private: } if (event.KeyCode == GLFW_KEY_SPACE) { - m_LoadingFrame->CancelPreload(); Events::GameStart e; EventBroker->Publish(e); + Events::StopSound se; + se.FilePath = "Sounds/jap-story.wav"; + EventBroker->Publish(se); Hide(); auto hud = new GUI::HUD(BaseFrame, "HUD"); } return true; } - EventRelay m_ELoadingFrameComplete; - bool OnLoadingFrameComplete(const Events::LoadingFrameComplete& event) - { - if (event.FrameName == "Story1LoadingFrame") { - event.Frame->Hide(); - m_Spacebar->Hide(); - Play(); - } - return true; - } }; } diff --git a/include/Game/GUI/StoryboardFrame.h b/include/Game/GUI/StoryboardFrame.h index d5f2d0a..f855507 100644 --- a/include/Game/GUI/StoryboardFrame.h +++ b/include/Game/GUI/StoryboardFrame.h @@ -33,12 +33,12 @@ public: m_Timeline.push_back(transition); } - void Play() + virtual void Play() { m_Playing = true; } - void Skip() + virtual void Skip() { m_Playing = false; OnComplete(); diff --git a/src/game/Core/ResourceManager.cpp b/src/game/Core/ResourceManager.cpp index 2d25e1d..e498a43 100644 --- a/src/game/Core/ResourceManager.cpp +++ b/src/game/Core/ResourceManager.cpp @@ -19,10 +19,12 @@ #include "PrecompiledHeader.h" #include "Core/ResourceManager.h" +std::unordered_map dd::ResourceManager::m_CompilerTypenameToResourceType; std::unordered_map> dd::ResourceManager::m_FactoryFunctions; std::unordered_map, dd::Resource*> dd::ResourceManager::m_ResourceCache; std::unordered_map dd::ResourceManager::m_ResourceFromName; std::unordered_map dd::ResourceManager::m_ResourceParents; +std::set> dd::ResourceManager::m_Preloads; // (type, name) unsigned int dd::ResourceManager::m_CurrentResourceTypeID = 0; std::unordered_map dd::ResourceManager::m_ResourceTypeIDs; std::unordered_map dd::ResourceManager::m_ResourceCount; @@ -82,4 +84,83 @@ void dd::ResourceManager::fileWatcherCallback(std::string path, FileWatcher::Fil void dd::ResourceManager::Update() { m_FileWatcher.Check(); +} + +void dd::ResourceManager::LoadPreloadsFromFile() +{ + std::ifstream f("PreloadResources"); + while (f.good()) { + std::string resourceType; + std::string resourceName; + f >> resourceType >> resourceName; + if (!resourceType.empty() && !resourceType.empty()) { + m_Preloads.insert(std::make_pair(resourceType, resourceName)); + } + } + f.close(); +} + +void dd::ResourceManager::Preload(std::string resourceType, std::string resourceName) +{ + if (IsResourceLoaded(resourceType, resourceName)) + { + //LOG_WARNING("Attempted to preload resource \"%s\" multiple times!", resourceName.c_str()); + return; + } + + m_Preloading = true; + LOG_INFO("Preloading resource \"%s\"", resourceName.c_str()); + CreateResource(resourceType, resourceName, nullptr); + m_Preloading = false; +} + +dd::Resource* dd::ResourceManager::Load(std::string resourceType, std::string resourceName, dd::Resource* parent /*= nullptr*/) +{ + auto it = m_ResourceCache.find(std::make_pair(resourceType, resourceName)); + if (it != m_ResourceCache.end()) + return it->second; + + if (m_Preloading) { + LOG_INFO("Preloading resource \"%s\"", resourceName.c_str()); + } else { + LOG_WARNING("Hot-loading resource \"%s\"", resourceName.c_str()); + + if (m_Preloads.find(std::make_pair(resourceType, resourceName)) == m_Preloads.end()) { + std::ofstream f("PreloadResources", std::ofstream::app); + f << resourceType << " " << resourceName << std::endl; + f.close(); + m_Preloads.insert(std::make_pair(resourceType, resourceName)); + } + } + + return CreateResource(resourceType, resourceName, parent); +} + +dd::Resource* dd::ResourceManager::CreateResource(std::string resourceType, std::string resourceName, dd::Resource* parent) +{ + auto facIt = m_FactoryFunctions.find(resourceType); + if (facIt == m_FactoryFunctions.end()) + { + LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceType); + return nullptr; + } + + // Call the factory function + Resource* resource = facIt->second(resourceName); + // Store IDs + resource->TypeID = GetTypeID(resourceType); + resource->ResourceID = GetNewResourceID(resource->TypeID); + // Cache + m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource; + m_ResourceFromName[resourceName] = resource; + if (parent != nullptr) + { + m_ResourceParents[resource] = parent; + } + if (!boost::filesystem::is_directory(resourceName)) + { + LOG_DEBUG("Adding watch for %s", resourceName.c_str()); + m_FileWatcher.AddWatch(resourceName, fileWatcherCallback); + } + return resource; } \ No newline at end of file