#include "Window.h" #include #include "Renderer.h" #include "AudioManager.h" #include "VolumeControl.h" #include "Log.h" #include "Settings.h" #include #include "views/ViewController.h" #include "components/HelpComponent.h" #include "components/ImageComponent.h" Window::Window() : mNormalizeNextUpdate(false), mFrameTimeElapsed(0), mFrameCountElapsed(0), mAverageDeltaTime(10), mAllowSleep(true) { mInputManager = new InputManager(this); mViewController = new ViewController(this); mHelp = new HelpComponent(this); mBackgroundOverlay = new ImageComponent(this); mBackgroundOverlay->setImage(":/scroll_gradient.png"); pushGui(mViewController); } Window::~Window() { delete mViewController; // this would get deleted down below, but just to be safe, delete it here delete mBackgroundOverlay; //delete all our GUIs while(peekGui()) delete peekGui(); delete mHelp; delete mInputManager; } void Window::pushGui(GuiComponent* gui) { mGuiStack.push_back(gui); setHelpPrompts(gui->getHelpPrompts()); } void Window::removeGui(GuiComponent* gui) { for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++) { if(*i == gui) { i = mGuiStack.erase(i); if(i == mGuiStack.end() && mGuiStack.size()) // we just popped the stack and the stack is not empty setHelpPrompts(mGuiStack.back()->getHelpPrompts()); return; } } } GuiComponent* Window::peekGui() { if(mGuiStack.size() == 0) return NULL; return mGuiStack.back(); } bool Window::init(unsigned int width, unsigned int height) { if(!Renderer::init(width, height)) { LOG(LogError) << "Renderer failed to initialize!"; return false; } mInputManager->init(); ResourceManager::getInstance()->reloadAll(); //keep a reference to the default fonts, so they don't keep getting destroyed/recreated if(mDefaultFonts.empty()) { mDefaultFonts.push_back(Font::get(FONT_SIZE_SMALL)); mDefaultFonts.push_back(Font::get(FONT_SIZE_MEDIUM)); mDefaultFonts.push_back(Font::get(FONT_SIZE_LARGE)); } mBackgroundOverlay->setResize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight()); // update our help because font sizes probably changed if(peekGui()) setHelpPrompts(peekGui()->getHelpPrompts()); return true; } void Window::deinit() { mInputManager->deinit(); ResourceManager::getInstance()->unloadAll(); Renderer::deinit(); } void Window::input(InputConfig* config, Input input) { if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_g && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) { // toggle debug grid with Ctrl-G Settings::getInstance()->setBool("DebugGrid", !Settings::getInstance()->getBool("DebugGrid")); } else if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_t && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) { // toggle TextComponent debug view with Ctrl-T Settings::getInstance()->setBool("DebugText", !Settings::getInstance()->getBool("DebugText")); } else if(config->isMappedTo("mastervolup", input)) { VolumeControl::getInstance()->setVolume(VolumeControl::getInstance()->getVolume() + 5); } else if(config->isMappedTo("mastervoldown", input)) { VolumeControl::getInstance()->setVolume(VolumeControl::getInstance()->getVolume() - 5); } else { if(peekGui()) this->peekGui()->input(config, input); } } void Window::update(int deltaTime) { if(mNormalizeNextUpdate) { mNormalizeNextUpdate = false; if(deltaTime > mAverageDeltaTime) deltaTime = mAverageDeltaTime; } mFrameTimeElapsed += deltaTime; mFrameCountElapsed++; if(mFrameTimeElapsed > 500) { mAverageDeltaTime = mFrameTimeElapsed / mFrameCountElapsed; if(Settings::getInstance()->getBool("DrawFramerate")) { std::stringstream ss; // fps ss << std::fixed << std::setprecision(1) << (1000.0f * (float)mFrameCountElapsed / (float)mFrameTimeElapsed) << "fps, "; ss << std::fixed << std::setprecision(2) << ((float)mFrameTimeElapsed / (float)mFrameCountElapsed) << "ms"; // vram float vramUsageMb = (TextureResource::getTotalMemUsage() + Font::getTotalMemUsage()) / 1000.0f / 1000.0f; ss << "\nVRAM: " << vramUsageMb << "mb"; mFrameDataText = std::unique_ptr(mDefaultFonts.at(1)->buildTextCache(ss.str(), 50.f, 50.f, 0xFF00FFFF)); } mFrameTimeElapsed = 0; mFrameCountElapsed = 0; } if(peekGui()) peekGui()->update(deltaTime); } void Window::render() { Eigen::Affine3f transform = Eigen::Affine3f::Identity(); // draw only bottom and top of GuiStack (if they are different) if(mGuiStack.size()) { auto& bottom = mGuiStack.front(); auto& top = mGuiStack.back(); bottom->render(transform); if(bottom != top) { mBackgroundOverlay->render(transform); top->render(transform); } } // draw everything /*const unsigned int drawBGAfter = mGuiStack.size() > 1 ? mGuiStack.size() - 2 : mGuiStack.size(); for(unsigned int i = 0; i < mGuiStack.size(); i++) { mGuiStack.at(i)->render(transform); if(i == drawBGAfter) mBackgroundOverlay->render(transform); }*/ mHelp->render(transform); if(Settings::getInstance()->getBool("DrawFramerate")) { Renderer::setMatrix(Eigen::Affine3f::Identity()); mDefaultFonts.at(1)->renderTextCache(mFrameDataText.get()); } } void Window::normalizeNextUpdate() { mNormalizeNextUpdate = true; } bool Window::getAllowSleep() { return mAllowSleep; } void Window::setAllowSleep(bool sleep) { mAllowSleep = sleep; } void Window::renderLoadingScreen() { Renderer::setMatrix(Eigen::Affine3f::Identity()); Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x000000FF); mDefaultFonts.at(2)->drawCenteredText("LOADING", 0, (Renderer::getScreenHeight() - mDefaultFonts.at(2)->getHeight()) / 2.0f , 0xFFFFFFFF); Renderer::swapBuffers(); } void Window::setHelpPrompts(const std::vector& prompts) { mHelp->clearPrompts(); std::vector addPrompts; std::map seenMap; for(auto it = prompts.begin(); it != prompts.end(); it++) { // only add it if the same icon hasn't already been added if(seenMap.insert(std::make_pair(it->first, true)).second) addPrompts.push_back(*it); } // sort prompts so it goes [dpad_all] [dpad_u/d] [dpad_l/r] [a/b/x/y/l/r] [start/select] std::sort(addPrompts.begin(), addPrompts.end(), [](const HelpPrompt& a, const HelpPrompt& b) -> bool { static const char* map[] = { "up/down/left/right", "up/down", "left/right", "a", "b", "x", "y", "l", "r", "start", "select", NULL }; int i = 0; while(map[i] != NULL) { if(a.first == map[i]) return true; else if(b.first == map[i]) return false; i++; } return true; }); mHelp->setPrompts(addPrompts); }