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