From 3dd68b5c2752d00712185f5d36e544cd7d69bea8 Mon Sep 17 00:00:00 2001 From: Karaulov Date: Thu, 24 Nov 2022 17:13:27 +0300 Subject: [PATCH] Fixes and preparing to multiple ent selection. Fixes and preparing to multiple ent selection. --- imgui/misc/cpp/imgui_stdlib.cpp | 3 +- src/bsp/Bsp.cpp | 1 - src/editor/BspRenderer.cpp | 18 ++- src/editor/BspRenderer.h | 6 +- src/editor/Command.cpp | 4 +- src/editor/Gui.cpp | 36 +++--- src/editor/Renderer.cpp | 198 +++++++++++++++++++++----------- src/editor/Renderer.h | 4 +- 8 files changed, 162 insertions(+), 108 deletions(-) diff --git a/imgui/misc/cpp/imgui_stdlib.cpp b/imgui/misc/cpp/imgui_stdlib.cpp index c1a3c629..0b0acb0f 100644 --- a/imgui/misc/cpp/imgui_stdlib.cpp +++ b/imgui/misc/cpp/imgui_stdlib.cpp @@ -24,11 +24,10 @@ static int InputTextCallback(ImGuiInputTextCallbackData* data) std::string* str = user_data->Str; if (data->BufTextLen > 0) { - IM_ASSERT(data->Buf == str->c_str()); str->resize(data->BufTextLen); data->Buf = (char*)str->c_str(); } - else + else if (data->Buf == str->c_str()) { str->clear(); } diff --git a/src/bsp/Bsp.cpp b/src/bsp/Bsp.cpp index 99dc6097..19554d44 100644 --- a/src/bsp/Bsp.cpp +++ b/src/bsp/Bsp.cpp @@ -103,7 +103,6 @@ void Bsp::selectModelEnt() { g_app->clearSelection(); g_app->selectMap(map); - g_app->pickInfo.ent = map->ents[n]; g_app->pickInfo.entIdx = n; return; } diff --git a/src/editor/BspRenderer.cpp b/src/editor/BspRenderer.cpp index ea6111b1..58c7c8ce 100644 --- a/src/editor/BspRenderer.cpp +++ b/src/editor/BspRenderer.cpp @@ -1827,7 +1827,7 @@ void BspRenderer::drawPointEntities(int highlightEnt) colorShader->popMatrix(MAT_MODEL); } -bool BspRenderer::pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& tempPickInfo) +bool BspRenderer::pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& tempPickInfo, Bsp** tmpMap) { bool foundBetterPick = false; @@ -1837,15 +1837,15 @@ bool BspRenderer::pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& t } start -= mapOffset; + if (pickModelPoly(start, dir, vec3(0, 0, 0), 0, hullIdx, tempPickInfo)) { - if (tempPickInfo.map || (tempPickInfo.map && map && tempPickInfo.map == map)) + if (*tmpMap || (*tmpMap && map && *tmpMap == map)) { tempPickInfo.entIdx = 0; tempPickInfo.modelIdx = 0; - tempPickInfo.map = map; - tempPickInfo.ent = map->ents[0]; + *tmpMap = map; foundBetterPick = true; } } @@ -1876,12 +1876,11 @@ bool BspRenderer::pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& t if (pickModelPoly(start, dir, renderEnts[i].offset, renderEnts[i].modelIdx, hullIdx, tempPickInfo)) { - if (!tempPickInfo.map || (tempPickInfo.map && map && tempPickInfo.map == map)) + if (!*tmpMap || (*tmpMap && map && *tmpMap == map)) { tempPickInfo.entIdx = i; tempPickInfo.modelIdx = renderEnts[i].modelIdx; - tempPickInfo.map = map; - tempPickInfo.ent = map->ents[i]; + *tmpMap = map; foundBetterPick = true; } } @@ -1892,13 +1891,12 @@ bool BspRenderer::pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& t vec3 maxs = renderEnts[i].offset + renderEnts[i].pointEntCube->maxs; if (pickAABB(start, dir, mins, maxs, tempPickInfo.bestDist)) { - if (!tempPickInfo.map || (tempPickInfo.map && map && tempPickInfo.map == map)) + if (!*tmpMap || (*tmpMap && map && *tmpMap == map)) { tempPickInfo.entIdx = i; tempPickInfo.modelIdx = -1; tempPickInfo.faceIdx = -1; - tempPickInfo.map = map; - tempPickInfo.ent = map->ents[i]; + *tmpMap = map; foundBetterPick = true; } }; diff --git a/src/editor/BspRenderer.h b/src/editor/BspRenderer.h index 23a7d05a..c146fd0d 100644 --- a/src/editor/BspRenderer.h +++ b/src/editor/BspRenderer.h @@ -98,14 +98,10 @@ struct PickInfo int modelIdx; int faceIdx; float bestDist; - Entity* ent; - Bsp* map; PickInfo() { bestDist = 0.0f; entIdx = modelIdx = faceIdx = -1; - ent = NULL; - map = NULL; } }; @@ -129,7 +125,7 @@ class BspRenderer void drawModelClipnodes(int modelIdx, bool highlight, int hullIdx); void drawPointEntities(int highlightEnt); - bool pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& pickInfo); + bool pickPoly(vec3 start, const vec3& dir, int hullIdx, PickInfo& pickInfo, Bsp ** map); bool pickModelPoly(vec3 start, const vec3& dir, vec3 offset, int modelIdx, int hullIdx, PickInfo& pickInfo); bool pickFaceMath(const vec3& start, const vec3& dir, FaceMath& faceMath, float& bestDist); diff --git a/src/editor/Command.cpp b/src/editor/Command.cpp index cd2c8c32..335beedf 100644 --- a/src/editor/Command.cpp +++ b/src/editor/Command.cpp @@ -113,7 +113,7 @@ DeleteEntityCommand::DeleteEntityCommand(std::string desc, PickInfo& pickInfo) { this->entIdx = pickInfo.entIdx; this->entData = new Entity(); - *this->entData = *pickInfo.ent; + *this->entData = *(g_app->getSelectedMap()->ents[entIdx]); this->allowedDuringLoad = true; } @@ -486,7 +486,7 @@ EditBspModelCommand::EditBspModelCommand(std::string desc, PickInfo& pickInfo, L this->newLumps = newLumps; this->allowedDuringLoad = false; this->oldOrigin = oldOrigin; - this->newOrigin = pickInfo.ent->getOrigin(); + this->newOrigin = (g_app->getSelectedMap()->ents[entIdx])->getOrigin(); } EditBspModelCommand::~EditBspModelCommand() diff --git a/src/editor/Gui.cpp b/src/editor/Gui.cpp index 9987d31d..9d22d6bb 100644 --- a/src/editor/Gui.cpp +++ b/src/editor/Gui.cpp @@ -443,20 +443,21 @@ void Gui::draw3dContextMenus() Bsp* map = app->getSelectedMap(); - if (map && app->originHovered) + if (map && app->originHovered && app->pickInfo.entIdx >= 0) { + Entity* ent = map->ents[app->pickInfo.entIdx]; if (ImGui::BeginPopup("ent_context") || ImGui::BeginPopup("empty_context")) { if (ImGui::MenuItem("Center", "")) { - app->transformedOrigin = app->getEntOrigin(map, app->pickInfo.ent); + app->transformedOrigin = app->getEntOrigin(map, ent); app->applyTransform(); app->pickCount++; // force gui refresh } - if (app->pickInfo.ent && ImGui::BeginMenu("Align")) + if (ent && ImGui::BeginMenu("Align")) { - BSPMODEL& model = map->models[app->pickInfo.ent->getBspModelIdx()]; + BSPMODEL& model = map->models[ent->getBspModelIdx()]; if (ImGui::MenuItem("Top")) { @@ -1219,7 +1220,7 @@ void Gui::drawMenuBar() std::string redoTitle = redoCmd ? "Redo " + redoCmd->desc : "Can't redo"; bool canUndo = undoCmd && (!app->isLoading || undoCmd->allowedDuringLoad); bool canRedo = redoCmd && (!app->isLoading || redoCmd->allowedDuringLoad); - bool entSelected = app->pickInfo.ent; + bool entSelected = app->pickInfo.entIdx >= 0; bool mapSelected = map; bool nonWorldspawnEntSelected = entSelected && app->pickInfo.entIdx != 0; @@ -1913,11 +1914,11 @@ void Gui::drawKeyvalueEditor() //ImGui::SetNextWindowContentSize(ImVec2(550, 0.0f)); if (ImGui::Begin("Keyvalue Editor", &showKeyvalueWidget, 0)) { - if (app->pickInfo.ent && app->fgd + if (app->pickInfo.entIdx >= 0 && app->fgd && !app->isLoading && !app->isModelsReloading && !app->reloading) { Bsp* map = app->getSelectedMap(); - Entity* ent = app->pickInfo.ent; + Entity* ent = map->ents[app->pickInfo.entIdx]; std::string cname = ent->keyvalues["classname"]; FgdClass* fgdClass = app->fgd->getFgdClass(cname); @@ -2015,7 +2016,7 @@ void Gui::drawKeyvalueEditor() } else { - if (!app->pickInfo.ent) + if (!app->pickInfo.entIdx) ImGui::Text("No entity selected"); else ImGui::Text("No fgd loaded"); @@ -2627,9 +2628,9 @@ void Gui::drawTransformWidget() bool transformingEnt = false; Entity* ent = NULL; Bsp* map = app->getSelectedMap(); - if (map) + if (map && app->pickInfo.entIdx >= 0) { - ent = app->pickInfo.ent; + ent = map->ents[app->pickInfo.entIdx]; transformingEnt = app->pickInfo.entIdx > 0; } @@ -4228,9 +4229,8 @@ void Gui::drawLimitTab(Bsp* map, int sortMode) if (entIdx < map->ents.size()) { Entity* ent = map->ents[entIdx]; - app->pickInfo.ent = ent; app->pickInfo.entIdx = entIdx; - app->pickInfo.modelIdx = map->ents[entIdx]->getBspModelIdx(); + app->pickInfo.modelIdx = ent->getBspModelIdx(); // map should already be valid if limits are showing if (ImGui::IsMouseDoubleClicked(0)) @@ -4337,7 +4337,7 @@ void Gui::drawEntityReport() for (int k = 0; k < MAX_FILTERS; k++) { - if (keyFilter[k].size()) + if (keyFilter[k].size() && keyFilter[k][0] != '\0') { std::string searchKey = trimSpaces(toLowerCase(keyFilter[k])); @@ -4370,7 +4370,7 @@ void Gui::drawEntityReport() } } } - else if(valueFilter[k].size()) + else if(valueFilter[k].size() && valueFilter[k][0] != '\0') { std::string searchValue = trimSpaces(toLowerCase(valueFilter[k])); bool foundMatch = false; @@ -4476,14 +4476,10 @@ void Gui::drawEntityReport() { if (selectedEnts.find(i) != selectedEnts.end()) { - delete map->ents[i]; - } - else - { - newEnts.push_back(map->ents[i]); + app->deleteEnt(i); } } - map->ents = std::move(newEnts); + app->deselectObject(); map->getBspRender()->preRenderEnts(); reloadLimits(); diff --git a/src/editor/Renderer.cpp b/src/editor/Renderer.cpp index d7e32c6d..8d8d6975 100644 --- a/src/editor/Renderer.cpp +++ b/src/editor/Renderer.cpp @@ -1025,7 +1025,7 @@ void Renderer::loadFgds() void Renderer::drawModelVerts() { Bsp* map = g_app->getSelectedMap(); - if (!modelVertBuff || modelVerts.empty() || !map) + if (!modelVertBuff || modelVerts.empty() || !map || pickInfo.entIdx < 0) return; glClear(GL_DEPTH_BUFFER_BIT); @@ -1150,7 +1150,7 @@ void Renderer::drawModelOrigin() void Renderer::drawTransformAxes() { glClear(GL_DEPTH_BUFFER_BIT); - updateDragAxes(dragDelta); + updateDragAxes(); glDisable(GL_CULL_FACE); if (transformMode == TRANSFORM_SCALE && transformTarget == TRANSFORM_OBJECT) { @@ -1231,8 +1231,6 @@ void Renderer::controls() moveGrabbedEnt(); - globalShortcutControls(); - vertexEditControls(); cameraContextMenus(); @@ -1248,6 +1246,11 @@ void Renderer::controls() shortcutControls(); } + if (!gui->imgui_io->WantTextInput) + { + globalShortcutControls(); + } + oldLeftMouse = curLeftMouse; curLeftMouse = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); oldRightMouse = curRightMouse; @@ -1397,10 +1400,12 @@ void Renderer::cameraPickingControls() } invalidSolid = !map->vertex_manipulation_sync(pickInfo.modelIdx, modelVerts, false, true); gui->reloadLimits(); - - int modelIdx = pickInfo.ent->getBspModelIdx(); - if (modelIdx >= 0) - map->getBspRender()->refreshModel(modelIdx); + if (pickInfo.entIdx >= 0) + { + int modelIdx = map->ents[pickInfo.entIdx]->getBspModelIdx(); + if (modelIdx >= 0) + map->getBspRender()->refreshModel(modelIdx); + } } pickObject(); @@ -1414,10 +1419,15 @@ void Renderer::cameraPickingControls() { draggingAxis = -1; applyTransform(); + - if (pickInfo.ent && undoEntityState->getOrigin() != pickInfo.ent->getOrigin()) + if (pickInfo.entIdx >= 0) { - pushEntityUndoState("Move Entity"); + Entity* ent = SelectedMap->ents[pickInfo.entIdx]; + if (ent && undoEntityState->getOrigin() != ent->getOrigin()) + { + pushEntityUndoState("Move Entity"); + } } } } @@ -1582,7 +1592,8 @@ void Renderer::cameraObjectHovering() PickInfo vertPick = PickInfo(); vertPick.bestDist = FLT_MAX_COORD; - vec3 entOrigin = pickInfo.ent->getOrigin(); + Entity* ent = SelectedMap->ents[pickInfo.entIdx]; + vec3 entOrigin = ent->getOrigin(); hoverEdge = -1; if (!(anyVertSelected && !anyEdgeSelected)) @@ -1684,14 +1695,15 @@ void Renderer::cameraContextMenus() Bsp* map = getSelectedMap(); - map->getBspRender()->pickPoly(pickStart, pickDir, clipnodeRenderHull, tempPick); + map->getBspRender()->pickPoly(pickStart, pickDir, clipnodeRenderHull, tempPick, &map); if (tempPick.entIdx < 0) { for (int i = 0; i < mapRenderers.size(); i++) { - if (getSelectedMap() == mapRenderers[i]->map->parentMap && mapRenderers[i]->pickPoly(pickStart, pickDir, clipnodeRenderHull, tempPick) && tempPick.entIdx > 0) + if (getSelectedMap() == mapRenderers[i]->map->parentMap && mapRenderers[i]->pickPoly(pickStart, pickDir, clipnodeRenderHull, tempPick, &map) && tempPick.entIdx > 0) { + selectMap(map); break; } } @@ -1711,7 +1723,7 @@ void Renderer::cameraContextMenus() void Renderer::moveGrabbedEnt() { // grabbing - if (movingEnt && pickInfo.ent) + if (movingEnt && pickInfo.entIdx) { if (g_scroll != oldScroll) { @@ -1821,7 +1833,12 @@ void Renderer::pickObject() { if (!getSelectedMap()) return; - bool pointEntWasSelected = pickInfo.ent && !pickInfo.ent->isBspModel(); + bool pointEntWasSelected = pickInfo.entIdx >= 0; + if (pointEntWasSelected) + { + Entity* ent = SelectedMap->ents[pickInfo.entIdx]; + pointEntWasSelected = ent && !ent->isBspModel(); + } int oldSelectedEntIdx = pickInfo.entIdx; Bsp* map = getSelectedMap(); @@ -1836,17 +1853,19 @@ void Renderer::pickObject() pickInfo.bestDist = FLT_MAX_COORD; map->getBspRender()->preRenderEnts(); - map->getBspRender()->pickPoly(pickStart, pickDir, clipnodeRenderHull, pickInfo); + map->getBspRender()->pickPoly(pickStart, pickDir, clipnodeRenderHull, pickInfo, &map); for (int i = 0; i < mapRenderers.size(); i++) { if (map == mapRenderers[i]->map->parentMap) { mapRenderers[i]->preRenderEnts(); - mapRenderers[i]->pickPoly(pickStart, pickDir, clipnodeRenderHull, pickInfo); + mapRenderers[i]->pickPoly(pickStart, pickDir, clipnodeRenderHull, pickInfo,&map); } } + selectMap(map); + if (movingEnt && oldEntIdx != pickInfo.entIdx) { ungrabEnt(); @@ -1911,9 +1930,9 @@ void Renderer::pickObject() updateEntConnections(); - if (pickInfo.map && pickInfo.ent) + if (SelectedMap && pickInfo.entIdx) { - selectEnt(pickInfo.map, pickInfo.entIdx); + selectEnt(SelectedMap, pickInfo.entIdx); } } @@ -1940,7 +1959,7 @@ bool Renderer::transformAxisControls() if (showDragAxes && !movingEnt && draggingAxis >= 0) { - Entity* ent = pickInfo.ent; + Entity* ent = map->ents[pickInfo.entIdx]; activeAxes.model[draggingAxis].setColor(activeAxes.hoverColor[draggingAxis]); @@ -2124,12 +2143,12 @@ void Renderer::getPickRay(vec3& start, vec3& pickDir) Bsp* Renderer::getSelectedMap() { // auto select if one map - if (!pickInfo.map && mapRenderers.size() == 1) + if (!SelectedMap && mapRenderers.size() == 1) { - pickInfo.map = mapRenderers[0]->map; + SelectedMap = mapRenderers[0]->map; } - return pickInfo.map; + return SelectedMap; } int Renderer::getSelectedMapId() @@ -2152,21 +2171,21 @@ void Renderer::selectMapId(int id) BspRenderer* s = mapRenderers[i]; if (s->map) { - pickInfo.map = s->map; + SelectedMap = s->map; return; } } - pickInfo.map = NULL; + SelectedMap = NULL; } void Renderer::selectMap(Bsp* map) { - pickInfo.map = map; + SelectedMap = map; } void Renderer::deselectMap(Bsp* map) { - pickInfo.map = NULL; + SelectedMap = NULL; } void Renderer::clearSelection() @@ -2436,8 +2455,7 @@ void Renderer::updateDragAxes(vec3 delta) Entity* ent = NULL; vec3 mapOffset; - if (map && map->getBspRender() && pickInfo.entIdx >= 0 && - pickInfo.entIdx < map->ents.size()) + if (map && map->getBspRender() && pickInfo.entIdx >= 0) { ent = map->ents[pickInfo.entIdx]; mapOffset = map->getBspRender()->mapOffset; @@ -2706,9 +2724,12 @@ void Renderer::updateModelVerts() delete modelOriginBuff; } - if (pickInfo.ent) + + Entity* ent = map->ents[pickInfo.entIdx]; + + if (ent) { - transformedOrigin = oldOrigin = pickInfo.ent->getOrigin(); + transformedOrigin = oldOrigin = ent->getOrigin(); } modelOriginBuff = new VertexBuffer(colorShader, COLOR_4B | POS_3F, &modelOriginCube, 6 * 6, GL_TRIANGLES); @@ -2772,9 +2793,10 @@ void Renderer::updateSelectionSize() } selectionSize = maxs - mins; } - else if (pickInfo.ent) + else if (pickInfo.entIdx >= 0) { - EntCube* cube = pointEntRenderer->getEntCube(pickInfo.ent); + Entity* ent = map->ents[pickInfo.entIdx]; + EntCube* cube = pointEntRenderer->getEntCube(ent); if (cube) selectionSize = cube->maxs - cube->mins; } @@ -2797,21 +2819,22 @@ void Renderer::updateEntConnections() return; } - if (map && pickInfo.ent) + if (map && pickInfo.entIdx >= 0) { - std::vector targetNames = pickInfo.ent->getTargets(); + Entity* ent = map->ents[pickInfo.entIdx]; + std::vector targetNames = ent->getTargets(); std::vector targets; std::vector callers; std::vector callerAndTarget; // both a target and a caller std::string thisName; - if (pickInfo.ent->hasKey("targetname")) + if (ent->hasKey("targetname")) { - thisName = pickInfo.ent->keyvalues["targetname"]; + thisName = ent->keyvalues["targetname"]; } for (int k = 0; k < map->ents.size(); k++) { - Entity* ent = map->ents[k]; + ent = map->ents[k]; if (k == pickInfo.entIdx) continue; @@ -2860,7 +2883,7 @@ void Renderer::updateEntConnections() const COLOR4 callerColor = {0, 255, 255, 255}; const COLOR4 bothColor = {0, 255, 0, 255}; - vec3 srcPos = getEntOrigin(map, pickInfo.ent).flip(); + vec3 srcPos = getEntOrigin(map, ent).flip(); int idx = 0; int cidx = 0; float s = 1.5f; @@ -2897,9 +2920,10 @@ void Renderer::updateEntConnections() void Renderer::updateEntConnectionPositions() { - if (entConnections && pickInfo.ent) + if (entConnections && pickInfo.entIdx) { - vec3 pos = getEntOrigin(getSelectedMap(), pickInfo.ent).flip(); + Entity* ent = SelectedMap->ents[pickInfo.entIdx]; + vec3 pos = getEntOrigin(getSelectedMap(), ent).flip(); cVert* verts = (cVert*)entConnections->data; for (int i = 0; i < entConnections->numVerts; i += 2) @@ -3225,10 +3249,11 @@ void Renderer::moveSelectedVerts(const vec3& delta) } Bsp* map = getSelectedMap(); - if (map) + if (map && pickInfo.entIdx >= 0) { + Entity* ent = SelectedMap->ents[pickInfo.entIdx]; invalidSolid = !map->vertex_manipulation_sync(pickInfo.modelIdx, modelVerts, true, false); - map->getBspRender()->refreshModel(pickInfo.ent->getBspModelIdx()); + map->getBspRender()->refreshModel(ent->getBspModelIdx()); } } @@ -3253,6 +3278,12 @@ bool Renderer::splitModelFace() logf("Exactly 2 edges must be selected before splitting a face\n"); return false; } + if (pickInfo.entIdx < 0) + { + logf("No selected entity\n"); + return false; + } + Entity* ent = map->ents[pickInfo.entIdx]; HullEdge& edge1 = modelEdges[selectedEdges[0]]; HullEdge& edge2 = modelEdges[selectedEdges[1]]; @@ -3283,7 +3314,9 @@ bool Renderer::splitModelFace() }; std::vector modelPlanes; - BSPMODEL& tmodel = map->models[pickInfo.ent->getBspModelIdx()]; + + + BSPMODEL& tmodel = map->models[ent->getBspModelIdx()]; map->getNodePlanes(tmodel.iHeadnodes[0], modelPlanes); // find the plane being split @@ -3360,7 +3393,7 @@ bool Renderer::splitModelFace() // create a new model from the new set of planes std::vector newHullVerts; - if (!map->getModelPlaneIntersectVerts(pickInfo.ent->getBspModelIdx(), modelPlanes, newHullVerts)) + if (!map->getModelPlaneIntersectVerts(ent->getBspModelIdx(), modelPlanes, newHullVerts)) { logf("Can't split here because the model would not be convex\n"); return false; @@ -3398,7 +3431,7 @@ bool Renderer::splitModelFace() // copy textures/UVs from the old model { - BSPMODEL& oldModel = map->models[pickInfo.ent->getBspModelIdx()]; + BSPMODEL& oldModel = map->models[ent->getBspModelIdx()]; for (int i = 0; i < newSolid.faces.size(); i++) { Face& solidFace = newSolid.faces[i]; @@ -3424,7 +3457,7 @@ bool Renderer::splitModelFace() } } - int modelIdx = map->create_solid(newSolid, pickInfo.ent->getBspModelIdx()); + int modelIdx = map->create_solid(newSolid, ent->getBspModelIdx()); for (int i = 0; i < modelVerts.size(); i++) { @@ -3488,10 +3521,16 @@ void Renderer::scaleSelectedVerts(float x, float y, float z) } } Bsp* map = getSelectedMap(); - - invalidSolid = !map->vertex_manipulation_sync(pickInfo.modelIdx, modelVerts, true, false); - map->getBspRender()->refreshModel(pickInfo.ent->getBspModelIdx()); - updateSelectionSize(); + if (map) + { + invalidSolid = !map->vertex_manipulation_sync(pickInfo.modelIdx, modelVerts, true, false); + if (pickInfo.entIdx >= 0) + { + Entity* ent = map->ents[pickInfo.entIdx]; + map->getBspRender()->refreshModel(ent->getBspModelIdx()); + } + updateSelectionSize(); + } } vec3 Renderer::getEdgeControlPoint(std::vector& hullVerts, HullEdge& edge) @@ -3606,10 +3645,16 @@ void Renderer::pasteEnt(bool noModifyOrigin) selectEnt(map, map->ents.size() > 1 ? ((int)map->ents.size() - 1) : 0); } -void Renderer::deleteEnt() +void Renderer::deleteEnt(int entIdx) { - if (pickInfo.entIdx <= 0) + if (pickInfo.entIdx <= 0 && entIdx <= 0) return; + PickInfo tmpPickInfo = pickInfo; + + if (entIdx > 0 && SelectedMap) + { + tmpPickInfo.entIdx = entIdx; + } DeleteEntityCommand* deleteCommand = new DeleteEntityCommand("Delete Entity", pickInfo); deleteCommand->execute(); @@ -3618,7 +3663,6 @@ void Renderer::deleteEnt() void Renderer::deselectObject() { - pickInfo.ent = NULL; pickInfo.entIdx = -1; pickInfo.faceIdx = -1; pickInfo.modelIdx = -1; @@ -3645,13 +3689,18 @@ void Renderer::deselectFaces() void Renderer::selectEnt(Bsp* map, int entIdx) { + Entity* ent = NULL; + if (pickInfo.entIdx >= 0) + { + ent = map->ents[pickInfo.entIdx]; + } pickInfo.entIdx = entIdx; - pickInfo.ent = map->ents[entIdx]; - pickInfo.modelIdx = pickInfo.ent->getBspModelIdx(); + pickInfo.modelIdx = ent ? ent->getBspModelIdx() : -1; updateSelectionSize(); updateEntConnections(); - updateEntityState(pickInfo.ent); - if (pickInfo.ent->isBspModel()) + + updateEntityState(ent); + if (ent && ent->isBspModel()) saveLumpState(map, 0xffffffff, true); pickCount++; // force transform window update } @@ -3665,6 +3714,9 @@ void Renderer::goToCoords(float x, float y, float z) void Renderer::goToEnt(Bsp* map, int entIdx) { + if (entIdx < 0) + return; + Entity* ent = map->ents[entIdx]; vec3 size; @@ -3695,6 +3747,9 @@ void Renderer::ungrabEnt() void Renderer::updateEntityState(Entity* ent) { + if (!ent) + return; + if (!undoEntityState) { undoEntityState = new Entity(); @@ -3719,27 +3774,35 @@ void Renderer::saveLumpState(Bsp* map, int targetLumps, bool deleteOldState) void Renderer::pushEntityUndoState(const std::string& actionDesc) { - if (!pickInfo.ent) + if (!pickInfo.entIdx) { logf("Invalid entity undo state push\n"); return; } + Entity* ent = SelectedMap->ents[pickInfo.entIdx]; + + if (!ent) + { + logf("Invalid entity undo state push 2\n"); + return; + } + bool anythingToUndo = true; - if (undoEntityState->keyOrder.size() == pickInfo.ent->keyOrder.size()) + if (undoEntityState->keyOrder.size() == ent->keyOrder.size()) { bool keyvaluesDifferent = false; for (int i = 0; i < undoEntityState->keyOrder.size(); i++) { std::string oldKey = undoEntityState->keyOrder[i]; - std::string newKey = pickInfo.ent->keyOrder[i]; + std::string newKey = ent->keyOrder[i]; if (oldKey != newKey) { keyvaluesDifferent = true; break; } std::string oldVal = undoEntityState->keyvalues[oldKey]; - std::string newVal = pickInfo.ent->keyvalues[oldKey]; + std::string newVal = ent->keyvalues[oldKey]; if (oldVal != newVal) { keyvaluesDifferent = true; @@ -3755,8 +3818,8 @@ void Renderer::pushEntityUndoState(const std::string& actionDesc) return; // nothing to undo } - pushUndoCommand(new EditEntityCommand(actionDesc, pickInfo, undoEntityState, pickInfo.ent)); - updateEntityState(pickInfo.ent); + pushUndoCommand(new EditEntityCommand(actionDesc, pickInfo, undoEntityState, ent)); + updateEntityState(ent); } void Renderer::pushModelUndoState(const std::string& actionDesc, int targetLumps) @@ -3765,13 +3828,14 @@ void Renderer::pushModelUndoState(const std::string& actionDesc, int targetLumps if (pickInfo.modelIdx <= 0) pickInfo.modelIdx = 0; - // if (pickInfo.ent <= 0) - // pickInfo.ent = 0; + if (pickInfo.entIdx <= 0) + pickInfo.entIdx = 0; if (!map) { logf("Impossible, no map, ent or model idx\n"); return; } + Entity* ent = map->ents[pickInfo.entIdx]; LumpState newLumps = map->duplicate_lumps(targetLumps); @@ -3813,7 +3877,7 @@ void Renderer::pushModelUndoState(const std::string& actionDesc, int targetLumps saveLumpState(map, 0xffffffff, false); // entity origin edits also update the ent origin (TODO: this breaks when moving + scaling something) - updateEntityState(pickInfo.ent); + updateEntityState(ent); } void Renderer::pushUndoCommand(Command* cmd) diff --git a/src/editor/Renderer.h b/src/editor/Renderer.h index bf8a455e..090fab9d 100644 --- a/src/editor/Renderer.h +++ b/src/editor/Renderer.h @@ -171,6 +171,8 @@ class Renderer std::vector selectedFaces; private: + Bsp* SelectedMap = NULL; + GLFWwindow* window; ShaderProgram* bspShader; ShaderProgram* fullBrightBspShader; @@ -341,7 +343,7 @@ class Renderer void cutEnt(); void copyEnt(); void pasteEnt(bool noModifyOrigin); - void deleteEnt(); + void deleteEnt(int entIdx = 0); void scaleSelectedObject(float x, float y, float z); void scaleSelectedObject(vec3 dir, const vec3& fromDir); void scaleSelectedVerts(float x, float y, float z);