diff --git a/rwengine/src/render/MapRenderer.cpp b/rwengine/src/render/MapRenderer.cpp index 58bb061e..41bf66fc 100644 --- a/rwengine/src/render/MapRenderer.cpp +++ b/rwengine/src/render/MapRenderer.cpp @@ -169,11 +169,11 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { glm::vec2 plyblip(player->getPosition()); float hdg = glm::roll(player->getRotation()); drawBlip(plyblip, view, mi, "radar_centre", - glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 18.0f, mi.rotation - hdg); + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), defaultBlipSize, mi.rotation - hdg); } drawBlip(mi.worldCenter + glm::vec2(0.f, mi.worldSize), view, mi, - "radar_north", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 24.f); + "radar_north", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), radarNorthBlipSize); for (auto& radarBlip : world->state->radarBlips) { const auto& blip = radarBlip.second; @@ -194,7 +194,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { const auto& texture = blip.texture; if (!texture.empty()) { drawBlip(blippos, view, mi, texture, - glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 18.0f); + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), defaultBlipSize); } else { // Colours from http://www.gtamodding.com/wiki/0165 (colors not // specific to that opcode!) @@ -232,7 +232,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { 1.0f // Note: Alpha is not controlled by blip ); - drawBlip(blippos, view, mi, colour, blip.size * 2.0f); + drawBlip(blippos, view, mi, colour, blip.size * otherBlipsScalingFactor * 2.0f); } } @@ -289,3 +289,9 @@ void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view, renderer->setUniform(rectProg.get(), "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); glDrawArrays(GL_LINE_LOOP, 0, 4); } + +void MapRenderer::setHUDScale(const float scale) { + defaultBlipSize *= scale; + radarNorthBlipSize *= scale; + otherBlipsScalingFactor = scale; +} diff --git a/rwengine/src/render/MapRenderer.hpp b/rwengine/src/render/MapRenderer.hpp index 2e1fc70b..ee8a29fe 100644 --- a/rwengine/src/render/MapRenderer.hpp +++ b/rwengine/src/render/MapRenderer.hpp @@ -39,6 +39,7 @@ public: MapRenderer(std::shared_ptr renderer, GameData* data); void draw(GameWorld* world, const MapInfo& mi); + void setHUDScale(const float scale); private: GameData* data; @@ -50,6 +51,10 @@ private: GeometryBuffer circleGeom; DrawBuffer circle; + float radarNorthBlipSize = 24.f; + float defaultBlipSize = 18.f; + float otherBlipsScalingFactor = 1.f; + std::unique_ptr rectProg; void prepareBlip(const glm::vec2& coord, const glm::mat4& view, diff --git a/rwgame/DrawUI.cpp b/rwgame/DrawUI.cpp index abf6ec43..1d6f70d2 100644 --- a/rwgame/DrawUI.cpp +++ b/rwgame/DrawUI.cpp @@ -35,15 +35,29 @@ constexpr float ui_mapSize = 150.f; constexpr float ui_worldSizeMin = 200.f; constexpr float ui_worldSizeMax = 300.f; +static float hudScale = 1.f; +static float final_ui_textSize = ui_textSize; +static float final_ui_textHeight = ui_textHeight; +static float final_ui_elementMargin = ui_elementMargin; +static float final_ui_outerMargin = ui_outerMargin; +static float final_ui_infoMargin = ui_infoMargin; +static float final_ui_weaponSize = ui_weaponSize; +static float final_ui_ammoSize = ui_ammoSize; +static float final_ui_ammoHeight = ui_ammoHeight; +static float final_ui_wantedLevelHeight = ui_wantedLevelHeight; +static float final_ui_scriptTimerHeight = ui_scriptTimerHeight; +static float final_ui_armourOffset = ui_armourOffset; +static float final_ui_mapSize = ui_mapSize; + void drawScriptTimer(GameWorld* world, GameRenderer* render) { if (world->state->scriptTimerVariable) { float scriptTimerTextX = static_cast( - render->getRenderer()->getViewport().x - ui_outerMargin); - float scriptTimerTextY = ui_scriptTimerHeight; + render->getRenderer()->getViewport().x - final_ui_outerMargin); + float scriptTimerTextY = final_ui_scriptTimerHeight; TextRenderer::TextInfo ti; ti.font = FONT_PRICEDOWN; - ti.size = ui_textSize; + ti.size = final_ui_textSize; ti.align = TextRenderer::TextInfo::TextAlignment::Right; { @@ -84,12 +98,12 @@ void drawMap(ViewCamera& currentView, PlayerController* player, const glm::ivec2& vp = render->getRenderer()->getViewport(); glm::vec2 mapTop = - glm::vec2(ui_outerMargin, vp.y - (ui_outerMargin + ui_mapSize)); + glm::vec2(final_ui_outerMargin, vp.y - (final_ui_outerMargin + final_ui_mapSize)); glm::vec2 mapBottom = - glm::vec2(ui_outerMargin + ui_mapSize, vp.y - ui_outerMargin); + glm::vec2(final_ui_outerMargin + final_ui_mapSize, vp.y - final_ui_outerMargin); map.screenPosition = (mapTop + mapBottom) / 2.f; - map.screenSize = ui_mapSize * 0.95f; + map.screenSize = final_ui_mapSize * 0.95f; render->map.draw(world, map); } @@ -98,17 +112,17 @@ void drawMap(ViewCamera& currentView, PlayerController* player, void drawPlayerInfo(PlayerController* player, GameWorld* world, GameRenderer* render) { float infoTextX = static_cast(render->getRenderer()->getViewport().x - - (ui_outerMargin + ui_weaponSize + ui_infoMargin)); + (final_ui_outerMargin + final_ui_weaponSize + ui_infoMargin)); float infoTextY = 0.f + ui_outerMargin; float iconX = static_cast(render->getRenderer()->getViewport().x - - (ui_outerMargin + ui_weaponSize)); - float iconY = ui_outerMargin; - float wantedX = static_cast(render->getRenderer()->getViewport().x - ui_outerMargin); - float wantedY = ui_wantedLevelHeight; + (final_ui_outerMargin + final_ui_weaponSize)); + float iconY = final_ui_outerMargin; + float wantedX = static_cast(render->getRenderer()->getViewport().x - final_ui_outerMargin); + float wantedY = final_ui_wantedLevelHeight; TextRenderer::TextInfo ti; ti.font = FONT_PRICEDOWN; - ti.size = ui_textSize; + ti.size = final_ui_textSize; ti.align = TextRenderer::TextInfo::TextAlignment::Right; { @@ -128,7 +142,7 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, render->text.renderText(ti); - infoTextY += ui_textHeight; + infoTextY += final_ui_textHeight; { std::stringstream ss; @@ -147,7 +161,7 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, ti.screenPosition = glm::vec2(infoTextX, infoTextY); render->text.renderText(ti); - infoTextY += ui_textHeight; + infoTextY += final_ui_textHeight; if ((world->state->hudFlash != HudFlash::FlashHealth && player->getCharacter()->getCurrentState().health > ui_lowHealth) || @@ -178,11 +192,11 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, ti.baseColour = ui_shadowColour; ti.screenPosition = - glm::vec2(infoTextX + 1.f - ui_armourOffset, infoTextY + 1.f); + glm::vec2(infoTextX + 1.f - final_ui_armourOffset, infoTextY + 1.f); render->text.renderText(ti); ti.baseColour = ui_armourColour; - ti.screenPosition = glm::vec2(infoTextX - ui_armourOffset, infoTextY); + ti.screenPosition = glm::vec2(infoTextX - final_ui_armourOffset, infoTextY); render->text.renderText(ti); } @@ -231,7 +245,7 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, RW_CHECK(itemTexture->getName() != 0, "Item has 0 texture"); render->drawTexture( itemTexture.get(), - glm::vec4(iconX, iconY, ui_weaponSize, ui_weaponSize)); + glm::vec4(iconX, iconY, final_ui_weaponSize, final_ui_weaponSize)); } if (weapon->fireType != WeaponData::MELEE) { @@ -263,10 +277,10 @@ void drawPlayerInfo(PlayerController* player, GameWorld* world, ti.baseColour = ui_shadowColour; ti.font = FONT_ARIAL; - ti.size = ui_ammoSize; + ti.size = final_ui_ammoSize; ti.align = TextRenderer::TextInfo::TextAlignment::Center; - ti.screenPosition = glm::vec2(iconX + ui_weaponSize / 2.f, - iconY + ui_weaponSize - ui_ammoHeight); + ti.screenPosition = glm::vec2(iconX + final_ui_weaponSize / 2.f, + iconY + final_ui_weaponSize - final_ui_ammoHeight); render->text.renderText(ti); } } @@ -292,7 +306,7 @@ void drawOnScreenText(GameWorld* world, GameRenderer* renderer) { for (auto& l : alltext) { for (auto& t : l) { - ti.size = static_cast(t.size); + ti.size = static_cast(t.size * hudScale); ti.font = t.font; ti.text = t.text; ti.wrapX = t.wrapX; @@ -330,3 +344,19 @@ void drawOnScreenText(GameWorld* world, GameRenderer* renderer) { } } } + +void setHUDScale(const float scale) { + hudScale = scale; + final_ui_textSize = ui_textSize * scale; + final_ui_textHeight = ui_textHeight * scale; + final_ui_elementMargin = ui_elementMargin * scale; + final_ui_outerMargin = ui_outerMargin * scale; + final_ui_infoMargin = ui_infoMargin * scale; + final_ui_weaponSize = ui_weaponSize * scale; + final_ui_ammoSize = ui_ammoSize * scale; + final_ui_ammoHeight = ui_ammoHeight * scale; + final_ui_wantedLevelHeight = ui_wantedLevelHeight * scale; + final_ui_scriptTimerHeight = ui_scriptTimerHeight * scale; + final_ui_armourOffset = ui_armourOffset * scale; + final_ui_mapSize = ui_mapSize * scale; +} diff --git a/rwgame/DrawUI.hpp b/rwgame/DrawUI.hpp index 38f113f2..74969da3 100644 --- a/rwgame/DrawUI.hpp +++ b/rwgame/DrawUI.hpp @@ -10,4 +10,6 @@ void drawHUD(ViewCamera& currentView, PlayerController* player, void drawOnScreenText(GameWorld* world, GameRenderer* renderer); +void setHUDScale(const float scale); + #endif diff --git a/rwgame/GameConfig.cpp b/rwgame/GameConfig.cpp index 247f62ec..576f4573 100644 --- a/rwgame/GameConfig.cpp +++ b/rwgame/GameConfig.cpp @@ -129,6 +129,22 @@ struct IntTranslator { } }; +struct FloatTranslator { + typedef std::string internal_type; + typedef float external_type; + boost::optional get_value(const internal_type &str) { + boost::optional res; + try { + res = std::stof(stripComments(str)); + } catch (std::invalid_argument &) { + } + return res; + } + boost::optional put_value(const external_type &f) { + return std::to_string(f); + } +}; + GameConfig::ParseResult GameConfig::saveConfig() { auto configPath = getConfigPath().string(); return parseConfig(ParseType::CONFIG, "", ParseType::FILE, configPath); @@ -229,6 +245,7 @@ GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType, auto boolt = BoolTranslator(); auto patht = PathTranslator(); auto intt = IntTranslator(); + auto floatt = FloatTranslator(); // Add new configuration parameters here. // Additionally, add them to the unit test. @@ -237,6 +254,7 @@ GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType, read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3", patht, false); read_config("game.language", this->m_gameLanguage, "american", deft); + read_config("game.hud_scale", this->m_HUDscale, 1.f, floatt); read_config("input.invert_y", this->m_inputInvertY, false, boolt); diff --git a/rwgame/GameConfig.hpp b/rwgame/GameConfig.hpp index 2c7a4eaa..682f68d0 100644 --- a/rwgame/GameConfig.hpp +++ b/rwgame/GameConfig.hpp @@ -231,6 +231,9 @@ public: bool getWindowFullscreen() const { return m_windowFullscreen; } + float getHUDScale() const { + return m_HUDscale; + } static rwfs::path getDefaultConfigPath(); private: @@ -272,6 +275,9 @@ private: /// Set the window to fullscreen bool m_windowFullscreen = false; + + /// HUD scale parameter + float m_HUDscale = 1.f; }; #endif diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index d1d75e58..de8656e9 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -108,6 +108,9 @@ RWGame::RWGame(Logger& log, int argc, char* argv[]) } }); + setHUDScale(config.getHUDScale()); + renderer.map.setHUDScale(config.getHUDScale()); + log.info("Game", "Started"); RW_TIMELINE_LEAVE("Startup"); }