From d1ea57d7ff7b94899fee521845a11ea1e2d3cf64 Mon Sep 17 00:00:00 2001 From: Karaulov Date: Sun, 11 Dec 2022 23:39:20 +0300 Subject: [PATCH] Bugfixes --- src/bsp/Wad.cpp | 50 +++++++++++--- src/bsp/Wad.h | 12 ++-- src/editor/BspRenderer.cpp | 65 ++---------------- src/editor/BspRenderer.h | 4 +- src/editor/Gui.cpp | 134 ++++++++++++++++++++++++++++--------- src/editor/Renderer.cpp | 14 ++-- 6 files changed, 162 insertions(+), 117 deletions(-) diff --git a/src/bsp/Wad.cpp b/src/bsp/Wad.cpp index 2ed54550..3999902e 100644 --- a/src/bsp/Wad.cpp +++ b/src/bsp/Wad.cpp @@ -33,7 +33,27 @@ Wad::~Wad(void) filedata = NULL; } -bool Wad::readInfo(bool allowempty) +void W_CleanupName(const char* in, char* out) +{ + int i; + int c; + + for (i = 0; i < MAXTEXTURENAME; i++) { + c = in[i]; + if (!c) + break; + + if (c >= 'A' && c <= 'Z') + c += ('a' - 'A'); + out[i] = c; + } + + for (; i < MAXTEXTURENAME; i++) + out[i] = 0; +} + + +bool Wad::readInfo() { std::string file = filename; @@ -62,7 +82,6 @@ bool Wad::readInfo(bool allowempty) int offset = 0; memcpy((char*)&header, &filedata[offset], sizeof(WADHEADER)); - offset += sizeof(WADHEADER); if (std::string(header.szMagic).find("WAD3") != 0) { @@ -87,7 +106,10 @@ bool Wad::readInfo(bool allowempty) dirEntries.clear(); - bool usableTextures = false; + usableTextures = false; + + //logf("D %d %d\n", header.nDirOffset, header.nDir); + for (int i = 0; i < header.nDir; i++) { WADDIRENTRY tmpWadEntry = WADDIRENTRY(); @@ -101,18 +123,19 @@ bool Wad::readInfo(bool allowempty) memcpy((char*)&tmpWadEntry, &filedata[offset], sizeof(WADDIRENTRY)); offset += sizeof(WADDIRENTRY); + W_CleanupName(tmpWadEntry.szName, tmpWadEntry.szName); + dirEntries.push_back(tmpWadEntry); if (dirEntries[i].nType == 0x43) usableTextures = true; } - if (!usableTextures && !allowempty) + if (!usableTextures) { - dirEntries.clear(); - header.nDir = 0; - logf("%s contains no regular textures\n", filename.c_str()); - return false; // we can't use these types of textures (see fonts.wad as an example) + logf("Info: %s contains no regular textures\n", basename(filename).c_str()); + if (!dirEntries.size()) + return false; } return true; @@ -135,7 +158,7 @@ bool Wad::hasTexture(int dirIndex) return true; } -WADTEX* Wad::readTexture(int dirIndex) +WADTEX* Wad::readTexture(int dirIndex, int * texturetype) { if (dirIndex < 0 || dirIndex >= dirEntries.size()) { @@ -145,10 +168,10 @@ WADTEX* Wad::readTexture(int dirIndex) //if (cache != NULL) //return cache[dirIndex]; std::string name = std::string(dirEntries[dirIndex].szName); - return readTexture(name); + return readTexture(name, texturetype); } -WADTEX* Wad::readTexture(const std::string& texname) +WADTEX* Wad::readTexture(const std::string& texname, int * texturetype) { int idx = -1; for (int d = 0; d < header.nDir; d++) @@ -173,6 +196,11 @@ WADTEX* Wad::readTexture(const std::string& texname) int offset = dirEntries[idx].nFilePos; + if (texturetype) + { + *texturetype = dirEntries[idx].nType; + } + BSPMIPTEX mtex = BSPMIPTEX(); memcpy((char*)&mtex, &filedata[offset], sizeof(BSPMIPTEX)); offset += sizeof(BSPMIPTEX); diff --git a/src/bsp/Wad.h b/src/bsp/Wad.h index 1f511191..a21d9700 100644 --- a/src/bsp/Wad.h +++ b/src/bsp/Wad.h @@ -54,6 +54,9 @@ struct WADTEX } }; +#pragma pack(pop) + + class Wad { public: @@ -61,6 +64,7 @@ class Wad unsigned char* filedata = NULL; int fileLen = 0; + bool usableTextures = false; WADHEADER header = WADHEADER(); @@ -71,7 +75,7 @@ class Wad ~Wad(void); - bool readInfo(bool allowempty = false); + bool readInfo(); bool hasTexture(int dirIndex); bool hasTexture(const std::string& name); @@ -80,11 +84,9 @@ class Wad bool write(WADTEX** textures, size_t numTex); bool write(std::vector textures); - WADTEX* readTexture(int dirIndex); - WADTEX* readTexture(const std::string& texname); + WADTEX* readTexture(int dirIndex, int* texturetype = NULL); + WADTEX* readTexture(const std::string& texname, int* texturetype = NULL); }; WADTEX* create_wadtex(const char* name, COLOR3* data, int width, int height); COLOR3* ConvertWadTexToRGB(WADTEX* wadTex); - -#pragma pack(pop) \ No newline at end of file diff --git a/src/editor/BspRenderer.cpp b/src/editor/BspRenderer.cpp index 6aa339a5..5339ccdf 100644 --- a/src/editor/BspRenderer.cpp +++ b/src/editor/BspRenderer.cpp @@ -88,8 +88,6 @@ BspRenderer::BspRenderer(Bsp* _map, ShaderProgram* _bspShader, ShaderProgram* _f memset(&undoLumpState, 0, sizeof(LumpState)); undoEntityState = std::map(); - - mapTexsUsage = std::map>(); } void BspRenderer::loadTextures() @@ -1422,7 +1420,7 @@ BspRenderer::~BspRenderer() } -void BspRenderer::ReuploadTextures() +void BspRenderer::reuploadTextures() { deleteTextures(); @@ -1432,9 +1430,9 @@ void BspRenderer::ReuploadTextures() for (int i = 0; i < map->textureCount; i++) { - if (!glTextures[i]->uploaded) - glTextures[i]->upload(GL_RGB); + glTextures[i]->upload(GL_RGB); } + numLoadedTextures = map->textureCount; texturesLoaded = true; @@ -1460,62 +1458,7 @@ void BspRenderer::delayLoadData() if (!texturesLoaded && texturesFuture.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) { - deleteTextures(); - - glTextures = glTexturesSwap; - - for (int i = 0; i < map->textureCount; i++) - { - if (glTextures[i] && !glTextures[i]->uploaded) - glTextures[i]->upload(GL_RGB); - } - numLoadedTextures = map->textureCount; - - texturesLoaded = true; - preRenderFaces(); - - mapTexsUsage.clear(); - - for (int i = 0; i < map->faceCount; i++) - { - BSPTEXTUREINFO& texinfo = map->texinfos[map->faces[i].iTextureInfo]; - int texOffset = ((int*)map->textures)[texinfo.iMiptex + 1]; - if (texOffset != -1 && texinfo.iMiptex != -1) - { - BSPMIPTEX& tex = *((BSPMIPTEX*)(map->textures + texOffset)); - - if (tex.szName[0] != '\0') - { - if (tex.nOffsets[0] <= 0) - { - bool fondTex = false; - for (auto& s : wads) - { - if (s->hasTexture(tex.szName)) - { - if (!mapTexsUsage[basename(s->filename)].count(tex.szName)) - mapTexsUsage[basename(s->filename)].insert(tex.szName); - - fondTex = true; - } - } - if (!fondTex) - { - if (!mapTexsUsage["notfound"].count(tex.szName)) - mapTexsUsage["notfound"].insert(tex.szName); - } - } - else - { - if (!mapTexsUsage["internal"].count(tex.szName)) - mapTexsUsage["internal"].insert(tex.szName); - } - } - } - } - - if (mapTexsUsage.size()) - logf("Used %d wad files(include map file)\n", (int)mapTexsUsage.size()); + reuploadTextures(); } if (!clipnodesLoaded && clipnodesFuture.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) diff --git a/src/editor/BspRenderer.h b/src/editor/BspRenderer.h index 2a99cef7..1a4dfedb 100644 --- a/src/editor/BspRenderer.h +++ b/src/editor/BspRenderer.h @@ -162,7 +162,7 @@ class BspRenderer void loadTextures(); // will reload them if already loaded void reloadTextures(); - void ReuploadTextures(); + void reuploadTextures(); void updateLightmapInfos(); bool isFinishedLoading(); @@ -236,8 +236,6 @@ class BspRenderer std::map undoEntityState; LumpState undoLumpState = LumpState(); - std::map> mapTexsUsage; - void pushModelUndoState(const std::string& actionDesc, unsigned int targetLumps); void pushEntityUndoState(const std::string& actionDesc, int entIdx); void pushUndoCommand(Command* cmd); diff --git a/src/editor/Gui.cpp b/src/editor/Gui.cpp index 578ae480..59ddf9d2 100644 --- a/src/editor/Gui.cpp +++ b/src/editor/Gui.cpp @@ -951,7 +951,7 @@ void ImportWad(Bsp* map, Renderer* app, std::string path) } for (int i = 0; i < app->mapRenderers.size(); i++) { - app->mapRenderers[i]->reloadTextures(); + app->mapRenderers[i]->reuploadTextures(); } } @@ -1067,7 +1067,7 @@ void Gui::drawMenuBar() } if (ImGui::BeginMenu("Open")) { - if (ImGui::MenuItem("Map", NULL, false, !app->isLoading)) + if (ImGui::MenuItem("Map")) { filterNeeded = true; ifd::FileDialog::Instance().Open("MapOpenDialog", "Select map path", "Map file (*.bsp){.bsp},Wad file (*.wad){.wad},.*", false, g_settings.lastdir); @@ -1080,7 +1080,7 @@ void Gui::drawMenuBar() ImGui::EndTooltip(); } - if (ImGui::MenuItem("Wad", NULL, false, !app->isLoading)) + if (ImGui::MenuItem("Wad")) { filterNeeded = true; ifd::FileDialog::Instance().Open("MapOpenDialog", "Select wad path", "Wad file (*.wad){.wad},.*", false, g_settings.lastdir); @@ -1106,6 +1106,8 @@ void Gui::drawMenuBar() app->clearMaps(); ImGui::EndMenu(); ImGui::EndMainMenuBar(); + app->addMap(new Bsp("")); + app->selectMapId(0); return; } } @@ -1281,6 +1283,8 @@ void Gui::drawMenuBar() for (int i = 0; i < (int)wad->dirEntries.size(); i++) { WADTEX* texture = wad->readTexture(i); + char textureName[MAXTEXTURENAME]; + if (texture->szName[0] != '\0' && strlen(texture->szName) < MAXTEXTURENAME) { logf("Exporting %s from %s to working directory.\n", texture->szName, basename(wad->filename).c_str()); @@ -1440,7 +1444,7 @@ void Gui::drawMenuBar() tmpWad->write(textureList); delete tmpWad; - map->getBspRender()->reloadTextures(); + map->getBspRender()->reuploadTextures(); } } } @@ -1485,7 +1489,7 @@ void Gui::drawMenuBar() { app->reloadMaps(); } - if (ImGui::MenuItem("Validate")) + if (ImGui::MenuItem("Validate", 0, false, !app->isLoading)) { if (map) { @@ -1494,7 +1498,7 @@ void Gui::drawMenuBar() } } ImGui::Separator(); - if (ImGui::MenuItem("Settings", NULL)) + if (ImGui::MenuItem("Settings", 0, false, !app->isLoading)) { if (!showSettingsWidget) { @@ -1791,7 +1795,7 @@ void Gui::drawMenuBar() } } } - map->getBspRender()->reloadTextures(); + map->getBspRender()->reuploadTextures(); } if (ImGui::IsItemHovered() && g.HoveredIdTimer > g_tooltip_delay) { @@ -1833,7 +1837,7 @@ void Gui::drawMenuBar() Entity* newEnt = new Entity(); newEnt->addKeyvalue("origin", origin.toKeyvalueString()); - newEnt->addKeyvalue("classname", "trigger_once"); + newEnt->addKeyvalue("classname", "func_illusionary"); float snapSize = pow(2.0f, app->gridSnapLevel * 1.0f); if (snapSize < 16) @@ -1846,13 +1850,17 @@ void Gui::drawMenuBar() delete newEnt; rend->pushUndoCommand(command); - for (int i = 0; i < map->models[newEnt->getBspModelIdx()].nFaces; i++) + newEnt = map->ents[map->ents.size() - 1]; + if (newEnt && newEnt->getBspModelIdx() >= 0) { - map->faces[map->models[newEnt->getBspModelIdx()].iFirstFace + i].nStyles[0] = 0; + BSPMODEL& model = map->models[newEnt->getBspModelIdx()]; + for (int i = 0; i < model.nFaces; i++) + { + map->faces[model.iFirstFace + i].nStyles[0] = 0; + } } } - if (ImGui::MenuItem("BSP Trigger Model", 0, false, !app->isLoading && map)) { vec3 origin = cameraOrigin + app->cameraForward * 100; @@ -1861,7 +1869,7 @@ void Gui::drawMenuBar() Entity* newEnt = new Entity(); newEnt->addKeyvalue("origin", origin.toKeyvalueString()); - newEnt->addKeyvalue("classname", "func_illusionary"); + newEnt->addKeyvalue("classname", "trigger_once"); float snapSize = pow(2.0f, app->gridSnapLevel * 1.0f); @@ -1878,8 +1886,9 @@ void Gui::drawMenuBar() newEnt = map->ents[map->ents.size() - 1]; if (newEnt && newEnt->getBspModelIdx() >= 0) { - map->models[newEnt->getBspModelIdx()].iFirstFace = 0; - map->models[newEnt->getBspModelIdx()].nFaces = 0; + BSPMODEL& model = map->models[newEnt->getBspModelIdx()]; + model.iFirstFace = 0; + model.nFaces = 0; } } @@ -1904,9 +1913,14 @@ void Gui::drawMenuBar() delete newEnt; rend->pushUndoCommand(command); - for (int i = 0; i < map->models[newEnt->getBspModelIdx()].nFaces; i++) + newEnt = map->ents[map->ents.size() - 1]; + if (newEnt && newEnt->getBspModelIdx() >= 0) { - map->faces[map->models[newEnt->getBspModelIdx()].iFirstFace + i].nStyles[0] = 0; + BSPMODEL& model = map->models[newEnt->getBspModelIdx()]; + for (int i = 0; i < model.nFaces; i++) + { + map->faces[model.iFirstFace + i].nStyles[0] = 0; + } } } ImGui::EndMenu(); @@ -2234,13 +2248,19 @@ void Gui::drawStatusMessage() void Gui::drawDebugWidget() { + static std::map> mapTexsUsage{}; + static double lastupdate = 0.0; + ImGui::SetNextWindowBgAlpha(0.75f); ImGui::SetNextWindowSizeConstraints(ImVec2(200.f, 100.f), ImVec2(FLT_MAX, app->windowHeight * 1.0f)); Bsp* map = app->getSelectedMap(); + BspRenderer* renderer = map ? map->getBspRender() : NULL; int entIdx = app->pickInfo.GetSelectedEnt(); + bool oldShowDebugWidget = showDebugWidget; + if (ImGui::Begin("Debug info", &showDebugWidget)) { @@ -2420,9 +2440,9 @@ void Gui::drawDebugWidget() } } - if (map->getBspRender()->mapTexsUsage.size()) + if (mapTexsUsage.size()) { - for (auto& tmpWad : map->getBspRender()->mapTexsUsage) + for (auto& tmpWad : mapTexsUsage) { if (tmpWad.first == "internal") InternalTextures += (int)tmpWad.second.size(); @@ -2433,10 +2453,10 @@ void Gui::drawDebugWidget() ImGui::Text("Total textures used in map %d", map->textureCount); ImGui::Text("Used %d internal textures of %d", InternalTextures, TotalInternalTextures); - ImGui::Text("Used %d wad files", TotalInternalTextures > 0 ? (int)map->getBspRender()->mapTexsUsage.size() - 1 : (int)map->getBspRender()->mapTexsUsage.size()); + ImGui::Text("Used %d wad files", TotalInternalTextures > 0 ? (int)mapTexsUsage.size() - 1 : (int)mapTexsUsage.size()); ImGui::Text("Used %d wad textures", WadTextures); - for (auto& tmpWad : map->getBspRender()->mapTexsUsage) + for (auto& tmpWad : mapTexsUsage) { if (ImGui::CollapsingHeader((tmpWad.first + "##debug").c_str(), ImGuiTreeNodeFlags_::ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_::ImGuiTreeNodeFlags_Framed)) @@ -2480,6 +2500,56 @@ void Gui::drawDebugWidget() } } + + if ( + ((app->curTime - lastupdate > 5.0 && showDebugWidget) || (oldShowDebugWidget && !showDebugWidget)) + && map && renderer) + { + lastupdate = app->curTime; + mapTexsUsage.clear(); + + for (int i = 0; i < map->faceCount; i++) + { + BSPTEXTUREINFO& texinfo = map->texinfos[map->faces[i].iTextureInfo]; + int texOffset = ((int*)map->textures)[texinfo.iMiptex + 1]; + if (texOffset != -1 && texinfo.iMiptex != -1) + { + BSPMIPTEX& tex = *((BSPMIPTEX*)(map->textures + texOffset)); + + if (tex.szName[0] != '\0') + { + if (tex.nOffsets[0] <= 0) + { + bool fondTex = false; + for (auto& s : renderer->wads) + { + if (s->hasTexture(tex.szName)) + { + if (!mapTexsUsage[basename(s->filename)].count(tex.szName)) + mapTexsUsage[basename(s->filename)].insert(tex.szName); + + fondTex = true; + } + } + if (!fondTex) + { + if (!mapTexsUsage["notfound"].count(tex.szName)) + mapTexsUsage["notfound"].insert(tex.szName); + } + } + else + { + if (!mapTexsUsage["internal"].count(tex.szName)) + mapTexsUsage["internal"].insert(tex.szName); + } + } + } + } + + if (mapTexsUsage.size()) + logf("Debug: Used %d wad files(include map file)\n", (int)mapTexsUsage.size()); + } + ImGui::End(); } @@ -4404,19 +4474,19 @@ void Gui::drawSettings() fixupPath(s.path, FIXUPPATH_SLASH::FIXUPPATH_SLASH_SKIP, FIXUPPATH_SLASH::FIXUPPATH_SLASH_CREATE); } } - app->reloading = true; - app->reloadingGameDir = true; - app->loadFgds(); - app->postLoadFgds(); - app->reloadingGameDir = false; - app->reloading = false; - app->updateEnts(); - for (int i = 0; i < app->mapRenderers.size(); i++) + g_settings.save(); + if (!app->reloading) { - BspRenderer* mapRender = app->mapRenderers[i]; - mapRender->reload(); + app->reloading = true; + app->loadFgds(); + app->postLoadFgds(); + for (int i = 0; i < app->mapRenderers.size(); i++) + { + BspRenderer* mapRender = app->mapRenderers[i]; + mapRender->reload(); + } + app->reloading = false; } - g_settings.save(); } } @@ -6594,7 +6664,7 @@ void Gui::drawTextureTool() validTexture = true; newMiptex = map->add_texture(textureName, (unsigned char*)imageData, wadTex->nWidth, wadTex->nHeight); - mapRenderer->ReuploadTextures(); + mapRenderer->reuploadTextures(); delete[] imageData; delete wadTex; diff --git a/src/editor/Renderer.cpp b/src/editor/Renderer.cpp index eca6ca4b..7d248832 100644 --- a/src/editor/Renderer.cpp +++ b/src/editor/Renderer.cpp @@ -1075,6 +1075,15 @@ void Renderer::renderLoop() if (reloading && fgdFuture.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) { postLoadFgds(); + for (int i = 0; i < mapRenderers.size(); i++) + { + mapRenderers[i]->pointEntRenderer = pointEntRenderer; + mapRenderers[i]->preRenderEnts(); + if (reloadingGameDir) + { + mapRenderers[i]->reloadTextures(); + } + } reloading = reloadingGameDir = false; } @@ -1099,11 +1108,6 @@ void Renderer::postLoadFgds() for (int i = 0; i < mapRenderers.size(); i++) { mapRenderers[i]->pointEntRenderer = pointEntRenderer; - mapRenderers[i]->preRenderEnts(); - if (reloadingGameDir) - { - mapRenderers[i]->reloadTextures(); - } } swapPointEntRenderer = NULL;