diff --git a/rwengine/include/WorkContext.hpp b/rwengine/include/WorkContext.hpp index f1a2de16..0d074b0d 100644 --- a/rwengine/include/WorkContext.hpp +++ b/rwengine/include/WorkContext.hpp @@ -74,12 +74,10 @@ class WorkContext std::mutex _inMutex; std::mutex _outMutex; - GameWorld* _world; - public: - WorkContext(GameWorld* world = nullptr) - : _worker(this), _world(world) { } + WorkContext() + : _worker(this) { } void queueJob( WorkJob* job ) { @@ -100,8 +98,6 @@ public: return (getWorkQueue().size() + getCompleteQueue().size()) == 0; } - GameWorld* getWorld() const { return _world; } - void update(); }; diff --git a/rwengine/include/engine/GameData.hpp b/rwengine/include/engine/GameData.hpp index 75b4795d..41e5ecf5 100644 --- a/rwengine/include/engine/GameData.hpp +++ b/rwengine/include/engine/GameData.hpp @@ -44,14 +44,14 @@ private: std::string splash; Logger* logger; - + WorkContext* workContext; public: /** * ctor * @param path Path to the root of the game data. */ - GameData(Logger* log, const std::string& path = ""); + GameData(Logger* log, WorkContext* work, const std::string& path = ""); ~GameData(); GameWorld* engine; diff --git a/rwengine/include/engine/GameState.hpp b/rwengine/include/engine/GameState.hpp index b6d1bd91..ebe42c3a 100644 --- a/rwengine/include/engine/GameState.hpp +++ b/rwengine/include/engine/GameState.hpp @@ -94,6 +94,9 @@ struct BlipData { } }; +/** + * Global Gameplay data, that mostly persists across game saves. + */ struct GameState { unsigned int currentProgress; @@ -166,34 +169,8 @@ struct GameState std::map radarBlips; - GameState() : - currentProgress(0), - maxProgress(1), - numMissions(0), - numHiddenPackages(0), - numHiddenPackagesDiscovered(0), - numUniqueJumps(0), - numRampages(0), - maxWantedLevel(0), - player(nullptr), - currentWeather(0), - scriptOnMissionFlag(nullptr), - fadeOut(true), - fadeStart(0.f), - fadeTime(0.f), - fadeSound(false), - skipCutscene(false), - isIntroPlaying(false), - currentCutscene(nullptr), - cutsceneStartTime(-1.f), - isCinematic(false), - hour(0), - minute(0), - cameraNear(0.1f), - cameraFixed(false), - cameraTarget(nullptr) - {} - + GameState(); + /** * Adds a blip to the state, returning it's ID. */ diff --git a/rwengine/include/engine/GameWorld.hpp b/rwengine/include/engine/GameWorld.hpp index 7e11a7f1..3edbd3f1 100644 --- a/rwengine/include/engine/GameWorld.hpp +++ b/rwengine/include/engine/GameWorld.hpp @@ -61,7 +61,7 @@ class GameWorld { public: - GameWorld(Logger* log, GameData* dat); + GameWorld(Logger* log, WorkContext* work, GameData* dat); ~GameWorld(); diff --git a/rwengine/include/render/GameRenderer.hpp b/rwengine/include/render/GameRenderer.hpp index 05c41aef..52950e2c 100644 --- a/rwengine/include/render/GameRenderer.hpp +++ b/rwengine/include/render/GameRenderer.hpp @@ -43,9 +43,9 @@ class Renderer; */ class GameRenderer { - /** Pointer to the world instance */ - GameWorld* engine; - + /** Game data to use for rendering */ + GameData* data; + /** Logger to output messages */ Logger* logger; @@ -76,7 +76,9 @@ class GameRenderer /** Transparent objects are queued into this list */ std::vector transparentDrawQueue; + // Temporary variables used during rendering float _renderAlpha; + GameWorld* _renderWorld; /** Internal non-descript VAOs */ GLuint vao, debugVAO; @@ -91,7 +93,7 @@ class GameRenderer public: - GameRenderer(Logger* log, GameWorld*); + GameRenderer(Logger* log, GameData* data); ~GameRenderer(); /** Number of culling events */ @@ -113,7 +115,9 @@ public: DrawBuffer cylinderBuffer; GeometryBuffer cylinderGeometry; - + + GameData* getData() const { return data; } + /** * Renders the world using the parameters of the passed Camera. * Note: The camera's near and far planes are overriden by weather effects. @@ -123,7 +127,7 @@ public: * - draws water surfaces * - draws the skybox */ - void renderWorld(const ViewCamera &camera, float alpha); + void renderWorld(GameWorld* world, const ViewCamera &camera, float alpha); /** * @brief draws a CharacterObject and any item they are holding. @@ -160,7 +164,7 @@ public: /** * Renders the effects (Particles, Lighttrails etc) */ - void renderEffects(); + void renderEffects(GameWorld* world); /** * @brief Draws the current on screen text. diff --git a/rwengine/include/render/MapRenderer.hpp b/rwengine/include/render/MapRenderer.hpp index bbcfcf99..a6a46d46 100644 --- a/rwengine/include/render/MapRenderer.hpp +++ b/rwengine/include/render/MapRenderer.hpp @@ -1,6 +1,7 @@ #pragma once #include +class GameData; class GameWorld; #define MAP_BLOCK_SIZE 63 @@ -26,15 +27,15 @@ public: glm::vec2 mapScreenTop; }; - MapRenderer(GameWorld* world, Renderer* renderer); + MapRenderer(Renderer* renderer, GameData* data); glm::vec2 worldToMap(const glm::vec2& coord); glm::vec2 mapToScreen(const glm::vec2& map, const MapInfo& mi); - void draw(const MapInfo& mi); + void draw(GameWorld* world, const MapInfo& mi); private: - GameWorld* world; + GameData* data; Renderer* renderer; GeometryBuffer rectGeom; diff --git a/rwengine/include/render/TextRenderer.hpp b/rwengine/include/render/TextRenderer.hpp index 4a2bf711..145e628a 100644 --- a/rwengine/include/render/TextRenderer.hpp +++ b/rwengine/include/render/TextRenderer.hpp @@ -5,7 +5,6 @@ #define GAME_FONTS 3 #define GAME_GLYPHS 192 -class GameWorld; class GameRenderer; /** * @brief Handles rendering of bitmap font textures. @@ -53,7 +52,7 @@ public: float widthFrac; }; - TextRenderer(GameWorld* engine, GameRenderer* renderer); + TextRenderer(GameRenderer* renderer); ~TextRenderer(); void setFontTexture( int index, const std::string& font ); @@ -63,8 +62,7 @@ public: private: std::string fonts[GAME_FONTS]; GlyphInfo glyphData[GAME_GLYPHS]; - - GameWorld* engine; + GameRenderer* renderer; Renderer::ShaderProgram* textShader; diff --git a/rwengine/src/engine/GameData.cpp b/rwengine/src/engine/GameData.cpp index a09c8e3f..8d4d4fc1 100644 --- a/rwengine/src/engine/GameData.cpp +++ b/rwengine/src/engine/GameData.cpp @@ -80,8 +80,8 @@ std::string fixPath(std::string path) { } -GameData::GameData(Logger* log, const std::string& path) -: datpath(path), logger(log), engine(nullptr) +GameData::GameData(Logger* log, WorkContext* work, const std::string& path) +: datpath(path), logger(log), workContext(work), engine(nullptr) { } @@ -421,10 +421,10 @@ void GameData::loadTXD(const std::string& name, bool async) loadedFiles[name] = true; - auto j = new LoadTextureArchiveJob(this->engine->_work, this, name); + auto j = new LoadTextureArchiveJob(workContext, this, name); if( async ) { - this->engine->_work->queueJob( j ); + workContext->queueJob( j ); } else { j->work(); @@ -446,10 +446,10 @@ void GameData::loadDFF(const std::string& name, bool async) models[realname] = ModelRef( new ResourceHandle(realname) ); auto job = new BackgroundLoaderJob - { this->engine->_work, &this->index, name, models[realname] }; + { workContext, &this->index, name, models[realname] }; if( async ) { - this->engine->_work->queueJob( job ); + workContext->queueJob( job ); } else { job->work(); diff --git a/rwengine/src/engine/GameState.cpp b/rwengine/src/engine/GameState.cpp index 455a3e63..15d2e1e8 100644 --- a/rwengine/src/engine/GameState.cpp +++ b/rwengine/src/engine/GameState.cpp @@ -1,5 +1,35 @@ #include +GameState::GameState() : +currentProgress(0), +maxProgress(1), +numMissions(0), +numHiddenPackages(0), +numHiddenPackagesDiscovered(0), +numUniqueJumps(0), +numRampages(0), +maxWantedLevel(0), +player(nullptr), +currentWeather(0), +scriptOnMissionFlag(nullptr), +fadeOut(true), +fadeStart(0.f), +fadeTime(0.f), +fadeSound(false), +skipCutscene(false), +isIntroPlaying(false), +currentCutscene(nullptr), +cutsceneStartTime(-1.f), +isCinematic(false), +hour(0), +minute(0), +cameraNear(0.1f), +cameraFixed(false), +cameraTarget(nullptr) +{ + +} + int GameState::addRadarBlip(BlipData& blip) { int l = 0; diff --git a/rwengine/src/engine/GameWorld.cpp b/rwengine/src/engine/GameWorld.cpp index 6a51f123..9a7cbf68 100644 --- a/rwengine/src/engine/GameWorld.cpp +++ b/rwengine/src/engine/GameWorld.cpp @@ -74,9 +74,9 @@ public: } }; -GameWorld::GameWorld(Logger* log, GameData* dat) +GameWorld::GameWorld(Logger* log, WorkContext* work, GameData* dat) : logger(log), gameTime(0.f), data(dat), randomEngine(rand()), - _work( new WorkContext( this ) ), cutsceneAudio(nullptr), missionAudio(nullptr), + _work( work ), cutsceneAudio(nullptr), missionAudio(nullptr), paused(false) { data->engine = this; @@ -94,8 +94,6 @@ GameWorld::GameWorld(Logger* log, GameData* dat) GameWorld::~GameWorld() { - delete _work; - for(auto o : objects) { delete o; } diff --git a/rwengine/src/render/GameRenderer.cpp b/rwengine/src/render/GameRenderer.cpp index 0edf6356..4a02896f 100644 --- a/rwengine/src/render/GameRenderer.cpp +++ b/rwengine/src/render/GameRenderer.cpp @@ -66,9 +66,9 @@ std::vector sspaceRect = { GeometryBuffer ssRectGeom; DrawBuffer ssRectDraw; -GameRenderer::GameRenderer(Logger* log, GameWorld* engine) - : engine(engine), logger(log), renderer(new OpenGLRenderer), _renderAlpha(0.f), - map(engine, renderer), water(this), text(engine, this) +GameRenderer::GameRenderer(Logger* log, GameData* _data) + : data(_data), logger(log), renderer(new OpenGLRenderer), _renderAlpha(0.f), + _renderWorld(nullptr), map(renderer, _data), water(this), text(this) { logger->info("Renderer", renderer->getIDString()); @@ -235,9 +235,10 @@ void GameRenderer::setupRender() glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); } -void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) +void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float alpha) { _renderAlpha = alpha; + _renderWorld = world; // Store the input camera, _camera = camera; @@ -246,11 +247,11 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) glBindVertexArray( vao ); - float tod = engine->state.hour + engine->state.minute/60.f; + float tod = world->state.hour + world->state.minute/60.f; // Requires a float 0-24 - auto weatherID = static_cast(engine->state.currentWeather * 24); - auto weather = engine->data->weatherLoader.getWeatherData(weatherID, tod); + auto weatherID = static_cast(world->state.currentWeather * 24); + auto weather = world->data->weatherLoader.getWeatherData(weatherID, tod); glm::vec3 skyTop = weather.skyTopColor; glm::vec3 skyBottom = weather.skyBottomColor; @@ -265,7 +266,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) }; sunDirection = glm::normalize(sunDirection); - _camera.frustum.near = engine->state.cameraNear; + _camera.frustum.near = world->state.cameraNear; _camera.frustum.far = weather.farClipping; auto view = _camera.getView(); @@ -295,7 +296,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) renderer->pushDebugGroup("Objects"); renderer->pushDebugGroup("Dynamic"); - for( GameObject* object : engine->objects ) { + for( GameObject* object : world->objects ) { if(! object->visible ) { continue; @@ -314,7 +315,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) renderVehicle(static_cast(object)); break; case GameObject::Instance: - if(! engine->shouldBeOnGrid(object) ) + if(! world->shouldBeOnGrid(object) ) { renderInstance(static_cast(object)); } @@ -337,15 +338,15 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) // Draw the static instance objects. k = % culled int c = 0, k = 0; - for(auto& cell : engine->worldGrid ) + for(auto& cell : world->worldGrid ) { c++; int y = c % WORLD_GRID_WIDTH; int x = c / WORLD_GRID_WIDTH; float cellhalf = WORLD_CELL_SIZE/2.f; float radius = cell.boundingRadius; - auto world = glm::vec3(glm::vec2(x,y) * glm::vec2(WORLD_CELL_SIZE) - glm::vec2(WORLD_GRID_SIZE/2.f) + glm::vec2(cellhalf), 0.f); - if( _camera.frustum.intersects(world, radius) ) + auto worldp = glm::vec3(glm::vec2(x,y) * glm::vec2(WORLD_CELL_SIZE) - glm::vec2(WORLD_GRID_SIZE/2.f) + glm::vec2(cellhalf), 0.f); + if( _camera.frustum.intersects(worldp, radius) ) { for( auto& inst : cell.instances ) { @@ -374,12 +375,12 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) profObjects = renderer->popDebugGroup(); // Render arrows above anything that isn't radar only (or hidden) - ModelRef& arrowModel = engine->data->models["arrow"]; + ModelRef& arrowModel = world->data->models["arrow"]; if( arrowModel && arrowModel->resource ) { - auto arrowTex = engine->data->textures[{"copblue",""}]; + auto arrowTex = world->data->textures[{"copblue",""}]; auto arrowFrame = arrowModel->resource->findFrame( "arrow" ); - for( auto& blip : engine->state.radarBlips ) + for( auto& blip : world->state.radarBlips ) { if( blip.second.display == BlipData::Show ) { @@ -394,7 +395,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) model = glm::translate( model, blip.second.coord ); } - float a = engine->gameTime * glm::pi(); + float a = world->gameTime * glm::pi(); model = glm::translate( model, glm::vec3(0.f, 0.f, 2.5f + glm::sin( a ) * 0.5f) ); model = glm::rotate( model, a, glm::vec3(0.f, 0.f, 1.f) ); model = glm::scale( model, glm::vec3(1.5f, 1.5f, 1.5f) ); @@ -419,7 +420,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) // Draw goal indicators glDepthMask(GL_FALSE); renderer->useProgram( particleProg ); - for(auto& i : engine->getAreaIndicators()) + for(auto& i : world->getAreaIndicators()) { renderAreaIndicator( &i ); } @@ -427,7 +428,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) renderer->pushDebugGroup("Water"); - water.render(this, engine); + water.render(this, world); profWater = renderer->popDebugGroup(); @@ -448,27 +449,27 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) profSky = renderer->popDebugGroup(); renderer->pushDebugGroup("Effects"); - renderEffects(); + renderEffects(world); profEffects = renderer->popDebugGroup(); glDisable(GL_DEPTH_TEST); GLuint splashTexName = 0; - auto fc = engine->state.fadeColour; - if((fc.r + fc.g + fc.b) == 0 && engine->state.currentSplash.size() > 0) { - auto splash = engine->data->findTexture(engine->state.currentSplash); + auto fc = world->state.fadeColour; + if((fc.r + fc.g + fc.b) == 0 && world->state.currentSplash.size() > 0) { + auto splash = world->data->findTexture(world->state.currentSplash); if ( splash ) { splashTexName = splash->getName(); } } - if( (engine->state.isCinematic || engine->state.currentCutscene ) && splashTexName != 0 ) { + if( (world->state.isCinematic || world->state.currentCutscene ) && splashTexName != 0 ) { renderLetterbox(); } - float fadeTimer = engine->gameTime - engine->state.fadeStart; - if( fadeTimer < engine->state.fadeTime || !engine->state.fadeOut ) { + float fadeTimer = world->gameTime - world->state.fadeStart; + if( fadeTimer < world->state.fadeTime || !world->state.fadeOut ) { glUseProgram(ssRectProgram); glUniform2f(ssRectOffset, 0.f, 0.f); glUniform2f(ssRectSize, 1.f, 1.f); @@ -484,11 +485,11 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) } float fadeFrac = 0.f; - if( engine->state.fadeTime > 0.f ) { - fadeFrac = std::min(fadeTimer / engine->state.fadeTime, 1.f); + if( world->state.fadeTime > 0.f ) { + fadeFrac = std::min(fadeTimer / world->state.fadeTime, 1.f); } - float a = engine->state.fadeOut ? 1.f - fadeFrac : fadeFrac; + float a = world->state.fadeOut ? 1.f - fadeFrac : fadeFrac; glm::vec4 fadeNormed(fc.r / 255.f, fc.g/ 255.f, fc.b/ 255.f, a); @@ -498,7 +499,7 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - if( (engine->state.isCinematic || engine->state.currentCutscene ) && splashTexName == 0 ) { + if( (world->state.isCinematic || world->state.currentCutscene ) && splashTexName == 0 ) { renderLetterbox(); } @@ -561,9 +562,9 @@ void GameRenderer::renderVehicle(VehicleObject *vehicle) // Draw wheels n' stuff for( size_t w = 0; w < vehicle->info->wheels.size(); ++w) { - auto woi = engine->data->findObjectType(vehicle->vehicle->wheelModelID); + auto woi = data->findObjectType(vehicle->vehicle->wheelModelID); if( woi ) { - Model* wheelModel = engine->data->models["wheels"]->resource; + Model* wheelModel = data->models["wheels"]->resource; auto& wi = vehicle->physVehicle->getWheelInfo(w); if( wheelModel ) { // Construct our own matrix so we can use the local transform @@ -607,8 +608,8 @@ void GameRenderer::renderInstance(InstanceObject *instance) { if(instance->object && instance->object->timeOn != instance->object->timeOff) { // Update rendering flags. - if(engine->getHour() < instance->object->timeOn - && engine->getHour() > instance->object->timeOff) { + if(_renderWorld->getHour() < instance->object->timeOn + && _renderWorld->getHour() > instance->object->timeOff) { return; } } @@ -703,9 +704,9 @@ void GameRenderer::renderPickup(PickupObject *pickup) if( ! pickup->isEnabled() ) return; glm::mat4 modelMatrix = glm::translate(glm::mat4(), pickup->getPosition()); - modelMatrix = glm::rotate(modelMatrix, engine->gameTime, glm::vec3(0.f, 0.f, 1.f)); + modelMatrix = glm::rotate(modelMatrix, _renderWorld->gameTime, glm::vec3(0.f, 0.f, 1.f)); - auto odata = engine->data->findObjectType(pickup->getModelID()); + auto odata = data->findObjectType(pickup->getModelID()); Model* model = nullptr; ModelFrame* itemModel = nullptr; @@ -713,7 +714,7 @@ void GameRenderer::renderPickup(PickupObject *pickup) /// @todo Better determination of is this object a weapon. if( odata->ID >= 170 && odata->ID <= 184 ) { - auto weapons = engine->data->models["weapons"]; + auto weapons = data->models["weapons"]; if( weapons && weapons->resource && odata ) { model = weapons->resource; itemModel = weapons->resource->findFrame(odata->modelName + "_l0"); @@ -725,7 +726,7 @@ void GameRenderer::renderPickup(PickupObject *pickup) } else { - auto handle = engine->data->models[odata->modelName]; + auto handle = data->models[odata->modelName]; if ( handle && handle->resource ) { model = handle->resource; @@ -746,7 +747,7 @@ void GameRenderer::renderPickup(PickupObject *pickup) void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene) { - if(!engine->state.currentCutscene) return; + if(!_renderWorld->state.currentCutscene) return; if(!cutscene->model->resource) { @@ -756,7 +757,7 @@ void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene) glm::mat4 matrixModel; if( cutscene->getParentActor() ) { - matrixModel = glm::translate(matrixModel, engine->state.currentCutscene->meta.sceneOffset + glm::vec3(0.f, 0.f, 1.f)); + matrixModel = glm::translate(matrixModel, _renderWorld->state.currentCutscene->meta.sceneOffset + glm::vec3(0.f, 0.f, 1.f)); //matrixModel = cutscene->getParentActor()->getTimeAdjustedTransform(_renderAlpha); //matrixModel = glm::translate(matrixModel, glm::vec3(0.f, 0.f, 1.f)); glm::mat4 localMatrix; @@ -768,7 +769,7 @@ void GameRenderer::renderCutsceneObject(CutsceneObject *cutscene) matrixModel = matrixModel * localMatrix; } else { - matrixModel = glm::translate(matrixModel, engine->state.currentCutscene->meta.sceneOffset + glm::vec3(0.f, 0.f, 1.f)); + matrixModel = glm::translate(matrixModel, _renderWorld->state.currentCutscene->meta.sceneOffset + glm::vec3(0.f, 0.f, 1.f)); } float mindist = 100000.f; @@ -793,8 +794,8 @@ void GameRenderer::renderProjectile(ProjectileObject *projectile) { glm::mat4 modelMatrix = projectile->getTimeAdjustedTransform(_renderAlpha); - auto odata = engine->data->findObjectType(projectile->getProjectileInfo().weapon->modelID); - auto weapons = engine->data->models["weapons"]; + auto odata = data->findObjectType(projectile->getProjectileInfo().weapon->modelID); + auto weapons = data->models["weapons"]; if( weapons && weapons->resource ) { auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0"); auto matrix = glm::inverse(itemModel->getTransform()); @@ -837,8 +838,8 @@ void GameRenderer::renderWheel(Model* model, const glm::mat4 &matrix, const std: void GameRenderer::renderItem(InventoryItem *item, const glm::mat4 &modelMatrix) { // srhand - std::shared_ptr odata = engine->data->findObjectType(item->getModelID()); - auto weapons = engine->data->models["weapons"]; + std::shared_ptr odata = data->findObjectType(item->getModelID()); + auto weapons = data->models["weapons"]; if( weapons && weapons->resource ) { auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0"); auto matrix = glm::inverse(itemModel->getTransform()); @@ -878,7 +879,7 @@ void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& model { auto& tC = mat.textures[0].name; auto& tA = mat.textures[0].alphaName; - tex = engine->data->findTexture(tC, tA); + tex = data->findTexture(tC, tA); if( ! tex ) { //logger->warning("Renderer", "Missing texture: " + tC + " " + tA); @@ -935,10 +936,10 @@ void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info) { glm::mat4 m(1.f); m = glm::translate(m, info->position); - glm::vec3 scale = info->radius + 0.15f * glm::sin(engine->gameTime * 5.f); + glm::vec3 scale = info->radius + 0.15f * glm::sin(_renderWorld->gameTime * 5.f); Renderer::DrawParameters dp; - dp.textures = {engine->data->findTexture("cloud1")->getName()}; + dp.textures = {data->findTexture("cloud1")->getName()}; dp.ambient = 1.f; dp.colour = glm::u8vec4(50, 100, 255, 1); dp.start = 0; @@ -951,20 +952,20 @@ void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info) glm::vec3 final = scale * glm::pow(0.9f, i + 1.0f); mt = glm::scale(mt, glm::vec3(final.x, final.y, 1.0f + i * 0.1f)); int reverse = (i % 2 ? 1 : -1); - mt = glm::rotate(mt, reverse * engine->gameTime * 0.5f, glm::vec3(0.f, 0.f, 1.f) ); + mt = glm::rotate(mt, reverse * _renderWorld->gameTime * 0.5f, glm::vec3(0.f, 0.f, 1.f) ); renderer->drawArrays(mt, &cylinderBuffer, dp); } } -void GameRenderer::renderEffects() +void GameRenderer::renderEffects(GameWorld* world) { renderer->useProgram( particleProg ); auto cpos = _camera.position; auto cfwd = glm::normalize(glm::inverse(_camera.rotation) * glm::vec3(0.f, 1.f, 0.f)); - auto& effects = engine->effects; + auto& effects = world->effects; std::sort( effects.begin(), effects.end(), [&](const VisualFX* a, const VisualFX* b) { diff --git a/rwengine/src/render/MapRenderer.cpp b/rwengine/src/render/MapRenderer.cpp index 84bf3a5d..eebccc11 100644 --- a/rwengine/src/render/MapRenderer.cpp +++ b/rwengine/src/render/MapRenderer.cpp @@ -38,8 +38,8 @@ void main() })"; -MapRenderer::MapRenderer(GameWorld* world, Renderer* renderer) -: world( world ), renderer(renderer) +MapRenderer::MapRenderer(Renderer* renderer, GameData* _data) +: data(_data), renderer(renderer) { rectGeom.uploadVertices({ {-.5f, .5f}, @@ -72,7 +72,7 @@ glm::vec2 MapRenderer::mapToScreen(const glm::vec2& map, const MapInfo& mi) return screenSize + screenCenter; } -void MapRenderer::draw(const MapInfo& mi) +void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { renderer->pushDebugGroup("Map"); renderer->useProgram(rectProg); @@ -198,7 +198,7 @@ void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& model, const GLuint tex = 0; if ( !texture.empty() ) { - auto sprite= world->data->findTexture(texture); + auto sprite= data->findTexture(texture); tex = sprite->getName(); renderer->setUniform(rectProg, "colour", glm::vec4(0.f)); } diff --git a/rwengine/src/render/TextRenderer.cpp b/rwengine/src/render/TextRenderer.cpp index 869840ed..4336c3ba 100644 --- a/rwengine/src/render/TextRenderer.cpp +++ b/rwengine/src/render/TextRenderer.cpp @@ -105,8 +105,8 @@ TextRenderer::TextInfo::TextInfo() } -TextRenderer::TextRenderer(GameWorld* engine, GameRenderer* renderer) -: fonts({}), engine(engine), renderer(renderer) +TextRenderer::TextRenderer(GameRenderer* renderer) +: fonts({}), renderer(renderer) { textShader = renderer->getRenderer()->createShader( TextVertexShader, TextFragmentShader ); @@ -235,7 +235,7 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti) Renderer::DrawParameters dp; dp.start = 0; dp.count = gb.getCount(); - auto ftexture = engine->data->findTexture(fonts[ti.font]); + auto ftexture = renderer->getData()->findTexture(fonts[ti.font]); dp.textures = {ftexture->getName()}; renderer->getRenderer()->drawArrays(glm::mat4(), &db, dp); diff --git a/rwengine/tests/test_GameData.cpp b/rwengine/tests/test_GameData.cpp index c9ccf8bd..63229567 100644 --- a/rwengine/tests/test_GameData.cpp +++ b/rwengine/tests/test_GameData.cpp @@ -6,8 +6,8 @@ BOOST_AUTO_TEST_SUITE(GameDataTests) BOOST_AUTO_TEST_CASE(test_object_data) { - GameData gd(&Global::get().log, Global::getGamePath()); - GameWorld gw(&Global::get().log, &gd); + GameData gd(&Global::get().log, &Global::get().work, Global::getGamePath()); + GameWorld gw(&Global::get().log, &Global::get().work, &gd); gd.load(); diff --git a/rwgame/DrawUI.cpp b/rwgame/DrawUI.cpp index c11c4907..789f151c 100644 --- a/rwgame/DrawUI.cpp +++ b/rwgame/DrawUI.cpp @@ -29,7 +29,7 @@ void drawMap(PlayerController* player, GameWorld* world, GameRenderer* render) map.center = glm::vec2(player->getCharacter()->getPosition()); } - render->map.draw(map); + render->map.draw(world, map); } void drawHUD(PlayerController* player, GameWorld* world, GameRenderer* render) diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index 2dc83114..c14d4cde 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -26,7 +26,7 @@ DebugDraw* debug; StdOutReciever logPrinter; RWGame::RWGame(const std::string& gamepath, int argc, char* argv[]) - : engine(nullptr), renderer(nullptr), script(nullptr), inFocus(true), + : state(nullptr), engine(nullptr), renderer(nullptr), script(nullptr), inFocus(true), showDebugStats(false), showDebugPaths(false), accum(0.f), timescale(1.f) { @@ -89,19 +89,17 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[]) throw std::runtime_error("Invalid game directory path, is " +envname+ " set?"); } - data = new GameData(&log, gamepath); + data = new GameData(&log, &work, gamepath); - engine = new GameWorld(&log, data); - // Initalize all the archives. - engine->data->loadIMG("/models/gta3"); + data->loadIMG("/models/gta3"); //engine->data.loadIMG("/models/txd"); - engine->data->loadIMG("/anim/cuts"); + data->loadIMG("/anim/cuts"); - engine->data->load(); + data->load(); // Initialize renderer - renderer = new GameRenderer(&log, engine); + renderer = new GameRenderer(&log, data); // Set up text renderer renderer->text.setFontTexture(0, "pager"); @@ -111,22 +109,23 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[]) debug = new DebugDraw; debug->setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits); debug->setShaderProgram(renderer->worldProg); - engine->dynamicsWorld->setDebugDrawer(debug); - engine->data->loadDynamicObjects(gamepath + "/data/object.dat"); + data->loadDynamicObjects(gamepath + "/data/object.dat"); /// @TODO language choices. - engine->data->loadGXT("english.gxt"); + data->loadGXT("english.gxt"); - getRenderer()->water.setWaterTable(data->waterHeights, 48, engine->data->realWater, 128*128); + getRenderer()->water.setWaterTable(data->waterHeights, 48, data->realWater, 128*128); for(int m = 0; m < MAP_BLOCK_SIZE; ++m) { std::string num = (m < 10 ? "0" : ""); std::string name = "radar" + num + std::to_string(m); - engine->data->loadTXD(name + ".txd"); + data->loadTXD(name + ".txd"); } + newGame(); + auto loading = new LoadingState(this); if( newgame ) { @@ -147,6 +146,20 @@ RWGame::~RWGame() delete script; delete renderer; delete engine; + delete state; +} + +void RWGame::newGame() +{ + if( state != nullptr ) + { + log.error("Game", "Cannot start a new game: game is already running."); + return; + } + + state = new GameState; + engine = new GameWorld(&log, &work, data); + engine->dynamicsWorld->setDebugDrawer(debug); } void RWGame::startScript(const std::string& name) @@ -417,7 +430,7 @@ void RWGame::render(float alpha, float time) renderer->getRenderer()->pushDebugGroup("World"); - renderer->renderWorld(viewCam, alpha); + renderer->renderWorld(engine, viewCam, alpha); auto rendertime = renderer->getRenderer()->popDebugGroup(); diff --git a/rwgame/RWGame.hpp b/rwgame/RWGame.hpp index 35a94e16..882e3695 100644 --- a/rwgame/RWGame.hpp +++ b/rwgame/RWGame.hpp @@ -13,11 +13,14 @@ class RWGame { Logger log; + GameState* state; GameData* data; GameWorld* engine; // must be allocated after Logger setup. GameRenderer* renderer; ScriptMachine* script; + // Background worker + WorkContext work; sf::RenderWindow window; sf::Clock clock; bool inFocus; @@ -35,6 +38,16 @@ public: int run(); + /** + * Initalizes a new game + */ + void newGame(); + + GameState* getState() const + { + return state; + } + GameWorld* getWorld() const { return engine; diff --git a/rwgame/pausestate.cpp b/rwgame/pausestate.cpp index e4c924fd..c1cc0186 100644 --- a/rwgame/pausestate.cpp +++ b/rwgame/pausestate.cpp @@ -39,7 +39,7 @@ void PauseState::draw(GameRenderer* r) map.mapScreenTop = glm::vec2(vp.x, vp.y); map.mapScreenBottom = glm::vec2(0.f, 0.f); - game->getRenderer()->map.draw(map); + game->getRenderer()->map.draw(getWorld(), map); State::draw(r); } diff --git a/rwviewer/ViewerWindow.cpp b/rwviewer/ViewerWindow.cpp index cf9a3a13..c4048363 100644 --- a/rwviewer/ViewerWindow.cpp +++ b/rwviewer/ViewerWindow.cpp @@ -149,9 +149,9 @@ void ViewerWindow::loadGame(const QString &path) QDir gameDir( path ); if( gameDir.exists() && path.size() > 0 ) { - gameData = new GameData( &engineLog, gameDir.absolutePath().toStdString() ); - gameWorld = new GameWorld( &engineLog, gameData ); - renderer = new GameRenderer(&engineLog, gameWorld); + gameData = new GameData( &engineLog, &work, gameDir.absolutePath().toStdString() ); + gameWorld = new GameWorld( &engineLog, &work, gameData ); + renderer = new GameRenderer(&engineLog, gameData ); viewerWidget->setRenderer(renderer); gameWorld->data->load(); diff --git a/rwviewer/ViewerWindow.hpp b/rwviewer/ViewerWindow.hpp index b8658427..7dcc133f 100644 --- a/rwviewer/ViewerWindow.hpp +++ b/rwviewer/ViewerWindow.hpp @@ -19,6 +19,7 @@ class ViewerWindow : public QMainWindow Q_OBJECT Logger engineLog; + WorkContext work; GameData* gameData; GameWorld* gameWorld; diff --git a/tests/test_globals.hpp b/tests/test_globals.hpp index 73ebfbf4..b7d3ba41 100644 --- a/tests/test_globals.hpp +++ b/tests/test_globals.hpp @@ -38,13 +38,14 @@ public: GameData* d; GameWorld* e; Logger log; + WorkContext work; Global() { wnd.create(sf::VideoMode(640, 360), "Testing"); glewExperimental = GL_TRUE; glewInit(); - d = new GameData(&log, getGamePath()); - e = new GameWorld(&log, d); + d = new GameData(&log, &work, getGamePath()); + e = new GameWorld(&log, &work, d); e->data->loadIMG("/models/gta3"); e->data->loadIMG("/anim/cuts");