From 195020df46d6d921c401884f20d9b2d845b3ef04 Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Fri, 18 Jan 2019 03:46:59 +0100 Subject: [PATCH] Use unique_ptr to handle TextureData --- rwcore/data/Clump.hpp | 4 +- rwcore/gl/TextureData.hpp | 10 ++--- rwcore/loaders/LoaderDFF.cpp | 5 +-- rwcore/loaders/LoaderDFF.hpp | 8 ++-- rwcore/loaders/LoaderTXD.cpp | 27 ++++++------- rwengine/src/engine/GameData.cpp | 49 ++++++++++++++--------- rwengine/src/engine/GameData.hpp | 9 ++++- rwengine/src/objects/ProjectileObject.cpp | 4 +- rwengine/src/render/GameRenderer.cpp | 6 +-- rwengine/src/render/MapRenderer.cpp | 13 +++--- rwengine/src/render/TextRenderer.cpp | 8 ++-- rwengine/src/render/VisualFX.hpp | 4 +- rwengine/src/render/WaterRenderer.cpp | 8 ++-- rwgame/HUDDrawer.cpp | 10 ++--- rwviewer/views/ModelViewer.cpp | 2 +- 15 files changed, 90 insertions(+), 77 deletions(-) diff --git a/rwcore/data/Clump.hpp b/rwcore/data/Clump.hpp index 73ca5314..af430940 100644 --- a/rwcore/data/Clump.hpp +++ b/rwcore/data/Clump.hpp @@ -145,10 +145,10 @@ struct Geometry { struct Texture { std::string name; std::string alphaName; - TextureData::Handle texture; + TextureData* texture = nullptr; template - Texture(String1&& _name, String2&& _alphaName, const TextureData::Handle &_texture) + Texture(String1&& _name, String2&& _alphaName, TextureData* _texture) : name(std::forward(_name)) , alphaName(std::forward(_alphaName)) , texture(_texture) { diff --git a/rwcore/gl/TextureData.hpp b/rwcore/gl/TextureData.hpp index c5baa667..575e3117 100644 --- a/rwcore/gl/TextureData.hpp +++ b/rwcore/gl/TextureData.hpp @@ -4,9 +4,9 @@ #include #include -#include #include #include +#include /** * Stores a handle and metadata about a loaded texture. @@ -33,11 +33,9 @@ public: return hasAlpha; } - typedef std::shared_ptr Handle; - - static Handle create(GLuint name, const glm::ivec2& size, + static auto create(GLuint name, const glm::ivec2& size, bool transparent) { - return std::make_shared(name, size, transparent); + return std::make_unique(name, size, transparent); } private: @@ -45,6 +43,6 @@ private: glm::ivec2 size; bool hasAlpha; }; -using TextureArchive = std::map; +using TextureArchive = std::unordered_map>; #endif diff --git a/rwcore/loaders/LoaderDFF.cpp b/rwcore/loaders/LoaderDFF.cpp index 599180b9..c0bb48fd 100644 --- a/rwcore/loaders/LoaderDFF.cpp +++ b/rwcore/loaders/LoaderDFF.cpp @@ -363,9 +363,8 @@ void LoaderDFF::readTexture(Geometry::Material &material, std::transform(name.begin(), name.end(), name.begin(), ::tolower); std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower); - TextureData::Handle textureinst = - texturelookup ? texturelookup(name, alpha) : nullptr; - material.textures.emplace_back(std::move(name), std::move(alpha), textureinst); + auto textureInstPtr = textureLookup ? textureLookup(name, alpha) : nullptr; + material.textures.emplace_back(std::move(name), std::move(alpha), textureInstPtr); } void LoaderDFF::readGeometryExtension(const GeometryPtr &geom, diff --git a/rwcore/loaders/LoaderDFF.hpp b/rwcore/loaders/LoaderDFF.hpp index fd550ecf..292d9b76 100644 --- a/rwcore/loaders/LoaderDFF.hpp +++ b/rwcore/loaders/LoaderDFF.hpp @@ -25,19 +25,19 @@ public: class LoaderDFF { public: - using TextureLookupCallback = std::function; + using TextureLookupCallback = + std::function; using GeometryList = std::vector; using FrameList = std::vector; ClumpPtr loadFromMemory(const FileContentsInfo& file); void setTextureLookupCallback(const TextureLookupCallback& tlc) { - texturelookup = tlc; + textureLookup = tlc; } private: - TextureLookupCallback texturelookup; + TextureLookupCallback textureLookup; FrameList readFrameList(const RWBStream& stream); diff --git a/rwcore/loaders/LoaderTXD.cpp b/rwcore/loaders/LoaderTXD.cpp index e28a73b3..d1c91d3f 100644 --- a/rwcore/loaders/LoaderTXD.cpp +++ b/rwcore/loaders/LoaderTXD.cpp @@ -12,16 +12,18 @@ #include "platform/FileHandle.hpp" #include "rw/debug.hpp" -GLuint gErrorTextureData[] = {0xFFFF00FF, 0xFF000000, 0xFF000000, 0xFFFF00FF}; -GLuint gDebugTextureData[] = {0xFF0000FF, 0xFF00FF00}; -GLuint gTextureRed[] = {0xFF0000FF}; -GLuint gTextureGreen[] = {0xFF00FF00}; -GLuint gTextureBlue[] = {0xFFFF0000}; +namespace { +constexpr GLuint gErrorTextureData[] = {0xFFFF00FF, 0xFF000000, 0xFF000000, 0xFFFF00FF}; +constexpr GLuint gDebugTextureData[] = {0xFF0000FF, 0xFF00FF00}; +constexpr GLuint gTextureRed[] = {0xFF0000FF}; +constexpr GLuint gTextureGreen[] = {0xFF00FF00}; +constexpr GLuint gTextureBlue[] = {0xFFFF0000}; +} // namespace static -TextureData::Handle getErrorTexture() { - static GLuint errTexName = 0; - static TextureData::Handle tex; +std::unique_ptr getErrorTexture() { + GLuint errTexName = 0; + std::unique_ptr tex = nullptr; if (errTexName == 0) { glGenTextures(1, &errTexName); glBindTexture(GL_TEXTURE_2D, errTexName); @@ -51,9 +53,8 @@ void processPalette(uint32_t* fullColor, RW::BinaryStreamSection& rootSection) { } } -static -TextureData::Handle createTexture(RW::BSTextureNative& texNative, - RW::BinaryStreamSection& rootSection) { +static std::unique_ptr createTexture( + RW::BSTextureNative& texNative, RW::BinaryStreamSection& rootSection) { // TODO: Exception handling. if (texNative.platform != 8) { RW_ERROR("Unsupported texture platform " << std::dec @@ -191,9 +192,7 @@ bool TextureLoader::loadFromMemory(const FileContentsInfo& file, std::transform(name.begin(), name.end(), name.begin(), ::tolower); std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower); - auto texture = createTexture(texNative, rootSection); - - inTextures[name] = texture; + inTextures[name] = createTexture(texNative, rootSection); } return true; diff --git a/rwengine/src/engine/GameData.cpp b/rwengine/src/engine/GameData.cpp index 2f9f20f7..83829d4d 100644 --- a/rwengine/src/engine/GameData.cpp +++ b/rwengine/src/engine/GameData.cpp @@ -48,13 +48,12 @@ void GameData::load() { /// @todo cuts.img files should be loaded differently to gta3.img loadIMG("anim/cuts.img"); - textureslots["particle"] = loadTextureArchive("particle.txd"); - textureslots["icons"] = loadTextureArchive("icons.txd"); - textureslots["hud"] = loadTextureArchive("hud.txd"); - textureslots["fonts"] = loadTextureArchive("fonts.txd"); - textureslots["generic"] = loadTextureArchive("generic.txd"); - auto misc = loadTextureArchive("misc.txd"); - textureslots["generic"].insert(misc.begin(), misc.end()); + textureSlots["particle"] = loadTextureArchive("particle.txd"); + textureSlots["icons"] = loadTextureArchive("icons.txd"); + textureSlots["hud"] = loadTextureArchive("hud.txd"); + textureSlots["fonts"] = loadTextureArchive("fonts.txd"); + textureSlots["generic"] = loadTextureArchive("generic.txd"); + loadToTextureArchive("misc.txd", textureSlots["generic"]); loadCarcols("data/carcols.dat"); loadWeather("data/timecyc.dat"); @@ -362,12 +361,12 @@ void GameData::loadTXD(const std::string& name) { currenttextureslot = slot; // Check if this texture slot is loaded already - auto slotit = textureslots.find(slot); - if (slotit != textureslots.end()) { + auto slotit = textureSlots.find(slot); + if (slotit != textureSlots.end()) { return; } - textureslots[slot] = loadTextureArchive(name); + textureSlots[slot] = loadTextureArchive(name); } TextureArchive GameData::loadTextureArchive(const std::string& name) { @@ -390,6 +389,21 @@ TextureArchive GameData::loadTextureArchive(const std::string& name) { return textures; } +void GameData::loadToTextureArchive(const std::string& name, + TextureArchive& archive) { + RW_PROFILE_COUNTER_ADD("loadTextureArchive", 1); + /// @todo refactor loadTXD to use correct file locations + auto file = index.openFile(name); + if (!file.data) { + logger->error("Data", "Failed to open txd: " + name); + } + + TextureLoader l; + if (!l.loadFromMemory(file, archive)) { + logger->error("Data", "Error loading txd: " + name); + } +} + void GameData::getNameAndLod(std::string& name, int& lod) { auto lodpos = name.rfind("_l"); if (lodpos != std::string::npos) { @@ -696,22 +710,21 @@ void GameData::loadSplash(const std::string& name) { std::string lower(name); std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); - auto splashTXD = loadTextureArchive(lower + ".txd"); - textureslots["generic"].insert(splashTXD.begin(), splashTXD.end()); + textureSlots["generic"] = loadTextureArchive(lower + ".txd"); engine->state->currentSplash = lower; } -TextureData::Handle GameData::findSlotTexture(const std::string &slot, const std::string &texture) const { - auto slotit = textureslots.find(slot); - if (slotit == textureslots.end()) { +TextureData* GameData::findSlotTexture(const std::string &slot, const std::string &texture) const { + auto slotIt = textureSlots.find(slot); + if (slotIt == textureSlots.end()) { return nullptr; } - auto textureit = slotit->second.find(texture); - if (textureit == slotit->second.end()) { + auto textureIt = slotIt->second.find(texture); + if (textureIt == slotIt->second.end()) { return nullptr; } - return textureit->second; + return textureIt->second.get(); } ZoneData *GameData::findZone(const std::string &name) { diff --git a/rwengine/src/engine/GameData.hpp b/rwengine/src/engine/GameData.hpp index 68edff43..aa819f85 100644 --- a/rwengine/src/engine/GameData.hpp +++ b/rwengine/src/engine/GameData.hpp @@ -130,6 +130,11 @@ public: */ TextureArchive loadTextureArchive(const std::string& name); + /** + * Loads to named a texture archive from the game data + */ + void loadToTextureArchive(const std::string& name, TextureArchive& archive); + /** * Converts combined {name}_l{LOD} into name and lod. */ @@ -190,7 +195,7 @@ public: void loadSplash(const std::string& name); - TextureData::Handle findSlotTexture(const std::string& slot, + TextureData* findSlotTexture(const std::string& slot, const std::string& texture) const; FileIndex index; @@ -260,7 +265,7 @@ public: /** * Texture slots, containing loaded textures. */ - std::map textureslots; + std::unordered_map textureSlots; /** * Texture atlases. diff --git a/rwengine/src/objects/ProjectileObject.cpp b/rwengine/src/objects/ProjectileObject.cpp index 0615f533..185257f1 100644 --- a/rwengine/src/objects/ProjectileObject.cpp +++ b/rwengine/src/objects/ProjectileObject.cpp @@ -86,8 +86,8 @@ void ProjectileObject::explode() { auto& explosion = engine->createParticleEffect(); - auto tex = engine->data->findSlotTexture("particle", "explo02"); - explosion.texture = tex; + auto texPtr = engine->data->findSlotTexture("particle", "explo02"); + explosion.texture = texPtr; explosion.size = glm::vec2(exp_size); explosion.starttime = engine->getGameTime(); explosion.lifetime = 0.5f; diff --git a/rwengine/src/render/GameRenderer.cpp b/rwengine/src/render/GameRenderer.cpp index 8c41ea1b..d9712f0b 100644 --- a/rwengine/src/render/GameRenderer.cpp +++ b/rwengine/src/render/GameRenderer.cpp @@ -270,9 +270,9 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera, GLuint splashTexName = 0; const auto fc = world->state->fadeColour; if ((fc.r + fc.g + fc.b) == 0 && !world->state->currentSplash.empty()) { - auto splash = world->data->findSlotTexture("generic", world->state->currentSplash); - if (splash) { - splashTexName = splash->getName(); + auto splashTexPtr = world->data->findSlotTexture("generic", world->state->currentSplash); + if (splashTexPtr) { + splashTexName = splashTexPtr->getName(); } } diff --git a/rwengine/src/render/MapRenderer.cpp b/rwengine/src/render/MapRenderer.cpp index 6bca91b3..d3ee60fb 100644 --- a/rwengine/src/render/MapRenderer.cpp +++ b/rwengine/src/render/MapRenderer.cpp @@ -125,8 +125,8 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { for (int m = 0; m < MAP_BLOCK_SIZE; ++m) { std::string num = (m < 10 ? "0" : ""); std::string name = "radar" + num + std::to_string(m); - auto texture = world->data->findSlotTexture(name, name); - dp.textures = {{texture->getName()}}; + auto texturePtr = world->data->findSlotTexture(name, name); + dp.textures = {{texturePtr->getName()}}; dp.count = 4; @@ -151,9 +151,8 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { glDisable(GL_STENCIL_TEST); // We only need the outer ring if we're clipping. glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO); - TextureData::Handle radarDisc = - data->findSlotTexture("hud", "radardisc"); - dp.textures = {{radarDisc->getName()}}; + auto radarDiscTexPtr = data->findSlotTexture("hud", "radardisc"); + dp.textures = {{radarDiscTexPtr->getName()}}; glm::mat4 model{1.0f}; model = glm::translate(model, glm::vec3(mi.screenPosition, 0.0f)); @@ -265,8 +264,8 @@ void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view, GLuint tex = 0; if (!texture.empty()) { - auto sprite = data->findSlotTexture("hud", texture); - tex = sprite->getName(); + auto spriteTexPtr = data->findSlotTexture("hud", texture); + tex = spriteTexPtr->getName(); } renderer.setUniform(rectProg.get(), "colour", colour); diff --git a/rwengine/src/render/TextRenderer.cpp b/rwengine/src/render/TextRenderer.cpp index 8126840d..7748e760 100644 --- a/rwengine/src/render/TextRenderer.cpp +++ b/rwengine/src/render/TextRenderer.cpp @@ -143,8 +143,8 @@ TextRenderer::TextRenderer(GameRenderer &renderer) : renderer(renderer) { } void TextRenderer::setFontTexture(font_t font, const std::string& textureName) { - auto ftexture = renderer.getData().findSlotTexture("fonts", textureName); - const glm::u32vec2 textureSize = ftexture->getSize(); + auto fTexturePtr = renderer.getData().findSlotTexture("fonts", textureName); + const glm::u32vec2 textureSize = fTexturePtr->getSize(); glm::u8vec2 glyphOffset{textureSize.x / 16, textureSize.x / 16}; if (font != FONT_PAGER) { glyphOffset.y += glyphOffset.y / 4; @@ -344,8 +344,8 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti, dp.start = 0; dp.blendMode = BlendMode::BLEND_ALPHA; dp.count = gb.getCount(); - auto ftexture = renderer.getData().findSlotTexture("fonts", fontMetaData.textureName); - dp.textures = {{ftexture->getName()}}; + auto fTexturePtr = renderer.getData().findSlotTexture("fonts", fontMetaData.textureName); + dp.textures = {{fTexturePtr->getName()}}; dp.depthMode = DepthMode::OFF; renderer.getRenderer().drawArrays(glm::mat4(1.0f), &db, dp); diff --git a/rwengine/src/render/VisualFX.hpp b/rwengine/src/render/VisualFX.hpp index 03402081..8546f13f 100644 --- a/rwengine/src/render/VisualFX.hpp +++ b/rwengine/src/render/VisualFX.hpp @@ -1,4 +1,4 @@ -#ifndef _RWENGINE_VISUALFX_HPP_ +#ifndef _RWENGINE_VISUALFX_HPP_ #define _RWENGINE_VISUALFX_HPP_ #include @@ -50,7 +50,7 @@ struct ParticleFX final : public VisualFX { float lifetime{-1.f}; /** Texture name */ - TextureData::Handle texture; + TextureData* texture = nullptr; /** Size of particle */ glm::vec2 size{1.f, 1.f}; diff --git a/rwengine/src/render/WaterRenderer.cpp b/rwengine/src/render/WaterRenderer.cpp index 7ca6a399..4adbef82 100644 --- a/rwengine/src/render/WaterRenderer.cpp +++ b/rwengine/src/render/WaterRenderer.cpp @@ -102,9 +102,9 @@ void WaterRenderer::setDataTexture(GLuint fbBinding, GLuint dataTex) { void WaterRenderer::render(GameRenderer &renderer, GameWorld* world) { auto& r = renderer.getRenderer(); - auto waterTex = world->data->findSlotTexture("particle", "water_old"); - RW_CHECK(waterTex != nullptr, "Water texture is null"); - if (waterTex == nullptr) { + auto waterTexPtr = world->data->findSlotTexture("particle", "water_old"); + RW_CHECK(waterTexPtr != nullptr, "Water texture is null"); + if (waterTexPtr == nullptr) { // Can't render water if we don't have a texture. return; } @@ -147,7 +147,7 @@ void WaterRenderer::render(GameRenderer &renderer, GameWorld* world) { r.setUniform(waterProg.get(), "inverseVP", ivp); wdp.count = gridGeom.getCount(); - wdp.textures = {{waterTex->getName(), dataTexture}}; + wdp.textures = {{waterTexPtr->getName(), dataTexture}}; r.drawArrays(m, &gridDraw, wdp); diff --git a/rwgame/HUDDrawer.cpp b/rwgame/HUDDrawer.cpp index 3bbbf265..cba07d75 100644 --- a/rwgame/HUDDrawer.cpp +++ b/rwgame/HUDDrawer.cpp @@ -203,12 +203,12 @@ void HUDDrawer::drawPlayerInfo(ai::PlayerController* player, GameWorld* world, itemTextureName = "detonator"; } - TextureData::Handle itemTexture = + auto itemTexturePtr = render.getData().findSlotTexture("hud", itemTextureName); - RW_CHECK(itemTexture != nullptr, "Item has 0 texture"); - if (itemTexture != nullptr) { - RW_CHECK(itemTexture->getName() != 0, "Item has 0 texture"); - render.drawTexture(itemTexture.get(), + RW_CHECK(itemTexturePtr != nullptr, "Item has 0 texture"); + if (itemTexturePtr != nullptr) { + RW_CHECK(itemTexturePtr->getName() != 0, "Item has 0 texture"); + render.drawTexture(itemTexturePtr, glm::vec4(iconX, iconY, hudParameters.uiWeaponSize, hudParameters.uiWeaponSize)); } diff --git a/rwviewer/views/ModelViewer.cpp b/rwviewer/views/ModelViewer.cpp index 6241583f..cc915fc5 100644 --- a/rwviewer/views/ModelViewer.cpp +++ b/rwviewer/views/ModelViewer.cpp @@ -44,7 +44,7 @@ void ModelViewer::showObject(uint16_t object) { LoaderDFF dffLoader; dffLoader.setTextureLookupCallback( [&](const std::string& texture, const std::string&) { - return textures.at(texture); + return textures.at(texture).get(); }); auto file = world()->data->index.openFile(modelName);