// validForDisplay bool SAppBase::validForDisplay() { if (D3D().isDeviceLost()) return false; return /*m_bRun && */m_bInit; }
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) { std::ofstream logFile("logFile.txt", std::ofstream::trunc); Logger::addOutput(Logger::Level::DEBUG_L, logFile); Logger::addOutput(Logger::Level::INFO, std::cout); if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) { Logger::log(Logger::Level::ERROR_L, "Initializing window failed!"); return -1; } Direct3D D3D(g_hWnd); Logger::log(Logger::Level::INFO, "Initializing input..."); g_input = Input(); D3D.init(&g_input); __int64 cntsPerSec = 0; QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec); float secsPerCnt = 1.0f / (float)cntsPerSec; __int64 prevTimeStamp = 0; QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp); Logger::log(Logger::Level::INFO, "Initializing complete starting program"); // Main message loop MSG msg = {0}; while(WM_QUIT != msg.message) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { __int64 currTimeStamp = 0; QueryPerformanceCounter((LARGE_INTEGER*)&currTimeStamp); float dt = (currTimeStamp - prevTimeStamp) * secsPerCnt; POINT tempSize; tempSize.x = (LONG)(WIDTH * 0.5f); tempSize.y = (LONG)(HEIGHT * 0.5f); ClientToScreen(g_hWnd, &tempSize); SetCursorPos(tempSize.x, tempSize.y); ShowCursor(false); //render D3D.update(dt); D3D.draw(); prevTimeStamp = currTimeStamp; } } D3D.release(); logFile.close(); return (int) msg.wParam; }
// onException void SAppBase::onException(const std::vector<std::string>& callstack, const std::string& message) { m_bException = true; if (D3D().isDeviceLost()) throw(message); DialogMgr().removeAll(); DialogMgr().activeBranch()->addChild(new DlgFatal(callstack, message)); }
// render // guaranteed to be called only after init void SAppBase::render() { if (D3DD().Present( NULL, NULL, NULL, NULL ) == D3DERR_DEVICELOST) D3D().onDeviceLost(); if (D3D().beginScene()) { DialogMgr().draw(); if (options().get<bool>("Debug", "ShowFPS")) { char buf[128]; sprintf(buf, "fps: %f (locked %d fps)", 1.0f / (float)(m_totalFrameTime), (int)(m_updateLoopFreq)); Font().get("arial")->write(D3DPaint(), buf, 0, 0); D3DPaint().draw(); } D3D().endScene(); } }
// MsgProc LRESULT WINAPI SAppBase::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: PostQuitMessage(0); return 0; // this is nice and all, but for efficiency reasons we really need to ensure update then draw, in that order. /* case WM_PAINT: if (validForDisplay()) render(); ValidateRect( hWnd, NULL ); return 0;*/ case WM_SYSCHAR: // resize if (wParam == 13) D3D().toggleFullscreen(); return 0; case WM_SHOWWINDOW: /*Input().onWindowActivate(hWnd); DialogMgr().setActiveOSWindow(0);*/ return 0; case WM_ACTIVATE: if (LOWORD(wParam) != WA_INACTIVE) { DialogMgr().setActiveOSWindow(0); } return 0; } if (m_bInit) { HRESULT ret = Input().keyMsg(msg, wParam, lParam); if (ret != -1) return ret; } return DefWindowProc(hWnd, msg, wParam, lParam); }
// destruct SAppBase::~SAppBase() { DestroyWindow(m_hWnd); delete m_mainLoopStep; delete m_pDlgMgrSingleton; delete m_textureAnimation; delete m_particles; //delete m_ruby; // collect final garbage before app shutdown ptrGCManager.garbage->collectAll(); for (SavedConfigs::iterator configIt = m_savedConfigs.begin(); configIt != m_savedConfigs.end(); ++configIt) { Config* config = configIt->second.first; if (m_bInit && config->dirty()) { const Path& path = configIt->second.second; try { otextstream streamConfigOut(path.open(std::ios::out)); config->services()[0]->save(streamConfigOut); } catch (ExceptionFilesystem& e) { dlog << "Couldn't open config file for write: " << e.what() << dlog.endl; }; } delete config; } for (Configs::iterator configIt = m_configs.begin(); configIt != m_configs.end(); ++configIt) { delete configIt->second; } delete m_sound; // must destroy directx objects here, or ExitProcess in shutdown sequence will term for us and leak memory D3D().destroy(); Input().destroy(); }
// constructor DlgFatal::DlgFatal(const std::vector<std::string>& callstack, const std::string& message) { Font().set("arial"); m_pTex = D3D().loadTextureFromResource("Skull", RT_BITMAP); m_pBox = new UITextBox; m_pBox->setSize(Point2(0.85f, 0.375f)); m_pBox->setPos(Point2(0.075f, 0.1875f)); m_pBox->setInputEnabled(false); m_pBox->setAlign(UITextBox::CENTER); m_pBox->setVAlign(UITextBox::VCENTER); m_pBox->setWrap(true); m_pBox->setFont("smallarial"); m_pBox->setText(join(callstack, " <- ") + message); m_pButton = new UIButton; m_pButton->onClick = delegate(&DlgFatal::onExit); m_pButton->setText("Exit And Cry"); m_pButton->setPos(Point2(m_pBox->pos().x + ((m_pBox->size().x - m_pButton->size().x) * 0.5f), 0.75f - m_pButton->size().y - 0.025f)); }
void SAppBase::init() { // setup logging dlog.add(new dlogprinterfile(Path::localSettings(Path("log.txt")))); derr.add(new dlogprinterfile(Path::localSettings(Path("errors.txt")))); loadConfig("options.ini", true); m_options = &config("options.ini"); loadConfig("ui.ini", true); m_ui = &config("ui.ini"); loadConfig("materials.ini"); m_materials = &config("materials.ini"); std::string uistylesConfigName = m_options->get("UI", "StyleFile", std::string("uistyles.ini")); loadConfig(uistylesConfigName); m_uiStyles = &config(uistylesConfigName); // Heap debugging if (hasCmdLineOption("heapdebug")) { #if IS_MSVC int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF; _CrtSetDbgFlag( tmpFlag ); #else throw("Heap debugging is only enabled in MSVC builds."); #endif } // create log dlog << m_appName << " - " << getCPUVendorID() << " " << getCPUTicksPerSecond() / 1000000.0f << " Mhz" << dlog.endl; // get default window icon, if available // tbd:mingw: fix //HICON groupIcon = LoadIcon(GetModuleHandle(0), "APP"); // Register the window class. WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, StaticMsgProc, 0L, sizeof(LONG), GetModuleHandle(NULL), /*groupIcon*/0, LoadCursor(0, IDC_ARROW), NULL, NULL, m_appName.c_str(), NULL }; RegisterClassEx( &wc ); //FreeResource(groupIcon); // Create the application's window. m_hWnd = CreateWindow( m_appName.c_str(), m_appName.c_str(), WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, GetDesktopWindow(), NULL, wc.hInstance, NULL ); if (!m_hWnd) throwf("Couldn't create a window."); // setup device bool windowed = hasCmdLineOption("w"); Point2i fullscreenSize = options().get("Render", "FullscreenSize", Point2i(1024, 768)); Point2i windowedSize = options().get("Render", "WindowedSize", Point2i(640, 480)); D3D().newDevice( windowed, fullscreenSize.x, fullscreenSize.y, windowedSize.x, windowedSize.y ); createFonts(); // create dialog mgr m_pDlgMgrSingleton = new SDialogMgr; if (!Input().create(GetModuleHandle(NULL))) throwf("Couldn't create input"); if (!Input().createMouse(m_hWnd)) throwf("Couldn't create mouse"); // setup ui DialogMgr().create(); m_textureAnimation = new TextureAnimationManager("animations.ini"); m_particles = new ParticleFactory("particles.ini", m_textureAnimation->set("particles")); m_spriteFX = new SpriteFXFactory("spritefx.ini"); timer().restart(); m_updateLoopFreq = options().get("Game", "UpdateLoopFreq", 0.0f); // create sound std::string soundProvider = options().get("Sound", "Provider", std::string("FMODProvider")); dlog << "AppBase: Initialising sound provider '" << soundProvider << "'" << dlog.endl; m_sound = (ISoundProvider*)Base::newObject(soundProvider); if (!m_sound) throwf("Couldn't initialize sound provider '" + soundProvider + "'"); // music manager loadConfig("music.ini"); loadConfig("musicmanager.ini"); m_music = new MusicManager; // Add sounds path filesystem().addFileMethod(new FileMethodDiskRelative(pathResources() + m_options->get("Sound", "SoundsPath", std::string("media\\sounds")))); // make main loop update thread #if USE_FIBERS m_mainLoopStep = new ThreadStepper(ThreadStepper::Delegate(this, (ThreadStepper::Delegate::FuncType)&SAppBase::doMainLoopUpdate)); add(*m_mainLoopStep); #endif }