mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 10:22:52 +01:00
Merge pull request #179 from darkf/exit
Rework how exiting and cleanup is handled.
This commit is contained in:
commit
4f79258a32
@ -35,6 +35,7 @@ StdOutReciever logPrinter;
|
||||
RWGame::RWGame(int argc, char* argv[])
|
||||
: config("openrw.ini")
|
||||
, state(nullptr), world(nullptr), renderer(nullptr), script(nullptr),
|
||||
window(nullptr), work(nullptr),
|
||||
debugScript(false), inFocus(true),
|
||||
showDebugStats(false), showDebugPaths(false), showDebugPhysics(false),
|
||||
accum(0.f), timescale(1.f)
|
||||
@ -90,8 +91,11 @@ RWGame::RWGame(int argc, char* argv[])
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||
throw std::runtime_error("Failed to initialize SDL2!");
|
||||
|
||||
window.create(w, h, fullscreen);
|
||||
window.hideCursor();
|
||||
window = new GameWindow();
|
||||
window->create(w, h, fullscreen);
|
||||
window->hideCursor();
|
||||
|
||||
work = new WorkContext();
|
||||
|
||||
log.addReciever(&logPrinter);
|
||||
log.info("Game", "Game directory: " + config.getGameDataPath());
|
||||
@ -101,7 +105,7 @@ RWGame::RWGame(int argc, char* argv[])
|
||||
throw std::runtime_error("Invalid game directory path: " + config.getGameDataPath());
|
||||
}
|
||||
|
||||
data = new GameData(&log, &work, config.getGameDataPath());
|
||||
data = new GameData(&log, work, config.getGameDataPath());
|
||||
|
||||
// Initalize all the archives.
|
||||
data->loadIMG("/models/gta3");
|
||||
@ -168,10 +172,30 @@ RWGame::RWGame(int argc, char* argv[])
|
||||
|
||||
RWGame::~RWGame()
|
||||
{
|
||||
log.info("Game", "Beginning cleanup");
|
||||
|
||||
log.info("Game", "Stopping work queue");
|
||||
work->stop();
|
||||
|
||||
log.info("Game", "Cleaning up scripts");
|
||||
delete script;
|
||||
|
||||
log.info("Game", "Cleaning up renderer");
|
||||
delete renderer;
|
||||
|
||||
log.info("Game", "Cleaning up world");
|
||||
delete world;
|
||||
|
||||
log.info("Game", "Cleaning up state");
|
||||
delete state;
|
||||
|
||||
log.info("Game", "Cleaning up window");
|
||||
delete window;
|
||||
|
||||
log.info("Game", "Cleaning up work queue");
|
||||
delete work;
|
||||
|
||||
log.info("Game", "Done cleaning up");
|
||||
}
|
||||
|
||||
void RWGame::newGame()
|
||||
@ -183,7 +207,7 @@ void RWGame::newGame()
|
||||
}
|
||||
|
||||
state = new GameState();
|
||||
world = new GameWorld(&log, &work, data);
|
||||
world = new GameWorld(&log, work, data);
|
||||
world->dynamicsWorld->setDebugDrawer(debug);
|
||||
|
||||
// Associate the new world with the new state and vice versa
|
||||
@ -294,8 +318,8 @@ int RWGame::run()
|
||||
{
|
||||
last_clock_time = clock.now();
|
||||
|
||||
// Loop until the window is closed or we run out of state.
|
||||
while (window.isOpen() && StateManager::get().states.size()) {
|
||||
// Loop until we run out of states.
|
||||
while (StateManager::get().states.size()) {
|
||||
State* state = StateManager::get().states.back();
|
||||
|
||||
RW_PROFILE_FRAME_BOUNDARY();
|
||||
@ -305,7 +329,7 @@ int RWGame::run()
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
window.close();
|
||||
StateManager::get().clear();
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
@ -343,14 +367,14 @@ int RWGame::run()
|
||||
|
||||
RW_PROFILE_BEGIN("Update");
|
||||
if ( accum >= GAME_TIMESTEP ) {
|
||||
RW_PROFILE_BEGIN("state");
|
||||
StateManager::get().tick(GAME_TIMESTEP);
|
||||
RW_PROFILE_END();
|
||||
|
||||
if (StateManager::get().states.size() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
RW_PROFILE_BEGIN("state");
|
||||
StateManager::get().tick(GAME_TIMESTEP);
|
||||
RW_PROFILE_END();
|
||||
|
||||
RW_PROFILE_BEGIN("engine");
|
||||
tick(GAME_TIMESTEP);
|
||||
RW_PROFILE_END();
|
||||
@ -385,7 +409,7 @@ int RWGame::run()
|
||||
|
||||
renderProfile();
|
||||
|
||||
window.swap();
|
||||
window->swap();
|
||||
}
|
||||
|
||||
if( httpserver_thread )
|
||||
@ -483,7 +507,7 @@ void RWGame::render(float alpha, float time)
|
||||
|
||||
getRenderer()->getRenderer()->swap();
|
||||
|
||||
glm::ivec2 windowSize = window.getSize();
|
||||
glm::ivec2 windowSize = window->getSize();
|
||||
renderer->setViewport(windowSize.x, windowSize.y);
|
||||
|
||||
ViewCamera viewCam;
|
||||
|
@ -28,11 +28,11 @@ class RWGame
|
||||
GameRenderer* renderer;
|
||||
ScriptMachine* script;
|
||||
// Background worker
|
||||
WorkContext work;
|
||||
WorkContext *work;
|
||||
bool debugScript;
|
||||
HttpServer* httpserver = nullptr;
|
||||
std::thread* httpserver_thread = nullptr;
|
||||
GameWindow window;
|
||||
GameWindow *window;
|
||||
std::chrono::steady_clock clock;
|
||||
std::chrono::steady_clock::time_point last_clock_time;
|
||||
|
||||
@ -79,7 +79,7 @@ public:
|
||||
|
||||
GameWindow& getWindow()
|
||||
{
|
||||
return window;
|
||||
return *window;
|
||||
}
|
||||
|
||||
ScriptMachine* getScript() const
|
||||
|
@ -80,6 +80,11 @@ struct StateManager
|
||||
}
|
||||
|
||||
std::deque<State*> states;
|
||||
|
||||
void clear()
|
||||
{
|
||||
states.clear();
|
||||
}
|
||||
|
||||
void enter(State* state)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ void MenuState::enterMainMenu()
|
||||
m->addEntry(Menu::lambda("Load Game", [=] { enterLoadMenu(); }));
|
||||
m->addEntry(Menu::lambda("Test", [=] { StateManager::get().enter(new IngameState(game, true, "test")); }));
|
||||
m->addEntry(Menu::lambda("Options", [] { RW_UNIMPLEMENTED("Options Menu"); }));
|
||||
m->addEntry(Menu::lambda("Exit", [=] { getWindow().close(); }));
|
||||
m->addEntry(Menu::lambda("Exit", [] { StateManager::get().clear(); }));
|
||||
this->enterMenu(m);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ PauseState::PauseState(RWGame* game)
|
||||
m->offset = glm::vec2( 200.f, 200.f );
|
||||
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
|
||||
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
|
||||
m->addEntry(Menu::lambda("Exit", [&] { getWindow().close(); }));
|
||||
m->addEntry(Menu::lambda("Exit", [] { StateManager::get().clear(); }));
|
||||
this->enterMenu(m);
|
||||
}
|
||||
|
||||
|
@ -12,20 +12,21 @@ void WorkContext::workNext()
|
||||
{
|
||||
WorkJob* j = nullptr;
|
||||
|
||||
_inMutex.lock();
|
||||
if( ! _workQueue.empty() ) {
|
||||
j = _workQueue.front();
|
||||
_workQueue.pop();
|
||||
{
|
||||
std::lock_guard<std::mutex> guard( _inMutex );
|
||||
|
||||
if( ! _workQueue.empty() ) {
|
||||
j = _workQueue.front();
|
||||
_workQueue.pop();
|
||||
}
|
||||
}
|
||||
_inMutex.unlock();
|
||||
|
||||
if( j == nullptr ) return;
|
||||
|
||||
j->work();
|
||||
|
||||
_outMutex.lock();
|
||||
|
||||
std::lock_guard<std::mutex> guard( _outMutex );
|
||||
_completeQueue.push(j);
|
||||
_outMutex.unlock();
|
||||
}
|
||||
|
||||
void WorkContext::update()
|
||||
|
@ -5,8 +5,11 @@
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
class WorkContext;
|
||||
|
||||
@ -16,7 +19,7 @@ class LoadWorker
|
||||
|
||||
public:
|
||||
|
||||
bool _running;
|
||||
std::atomic<bool> _running;
|
||||
std::thread _thread;
|
||||
void start();
|
||||
|
||||
@ -66,26 +69,32 @@ class GameWorld;
|
||||
*/
|
||||
class WorkContext
|
||||
{
|
||||
std::unique_ptr<LoadWorker> _worker;
|
||||
|
||||
std::queue<WorkJob*> _workQueue;
|
||||
std::queue<WorkJob*> _completeQueue;
|
||||
|
||||
LoadWorker _worker;
|
||||
|
||||
std::mutex _inMutex;
|
||||
std::mutex _outMutex;
|
||||
|
||||
public:
|
||||
|
||||
WorkContext()
|
||||
: _worker(this) { }
|
||||
: _worker(new LoadWorker(this)) { }
|
||||
|
||||
void queueJob( WorkJob* job )
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_inMutex);
|
||||
std::lock_guard<std::mutex> guard( _inMutex );
|
||||
_workQueue.push( job );
|
||||
}
|
||||
|
||||
// Called by the worker thread - don't touch;
|
||||
void stop()
|
||||
{
|
||||
// Stop serving the queue.
|
||||
_worker.reset(nullptr);
|
||||
}
|
||||
|
||||
// Called by the worker thread - don't touch
|
||||
void workNext();
|
||||
|
||||
const std::queue<WorkJob*> getWorkQueue() const { return _workQueue; }
|
||||
|
Loading…
Reference in New Issue
Block a user