From baa707b5e3e8cf020c7717a1b681f7abaccb1f64 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 29 Apr 2018 15:17:06 +0300 Subject: [PATCH] User setting for selective cell editing or new land creation --- apps/opencs/model/prefs/state.cpp | 12 + .../opencs/view/render/terraintexturemode.cpp | 216 +++++++++++++----- .../opencs/view/render/terraintexturemode.hpp | 3 + 3 files changed, 171 insertions(+), 60 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 8a9dad7f3..6cbc33766 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -222,6 +222,14 @@ void CSMPrefs::State::declare() EnumValues insertOutsideVisibleCell; insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway); + EnumValue createAndLandEdit ("Create cell and land, then edit"); + EnumValue showAndLandEdit ("Show cell and edit"); + EnumValue dontLandEdit ("Discard"); + EnumValues landeditOutsideCell; + landeditOutsideCell.add (createAndLandEdit).add (dontLandEdit); + EnumValues landeditOutsideVisibleCell; + landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit); + declareCategory ("Scene Drops"); declareInt ("distance", "Drop Distance", 50). setTooltip ("If an instance drop can not be placed against another object at the " @@ -230,6 +238,10 @@ void CSMPrefs::State::declare() addValues (insertOutsideCell); declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert). addValues (insertOutsideVisibleCell); + declareEnum ("outside-landedit", "Handling land edit outside of cells", createAndLandEdit). + addValues (landeditOutsideCell); + declareEnum ("outside-visible-landedit", "Handling land edit outside of visible cells", showAndLandEdit). + addValues (landeditOutsideVisibleCell); declareCategory ("Key Bindings"); diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 97856c20c..3468d4cd9 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -22,11 +22,13 @@ #include "../widget/scenetoolbar.hpp" #include "../../model/doc/document.hpp" +#include "../../model/prefs/state.hpp" #include "../../model/world/columnbase.hpp" #include "../../model/world/commandmacro.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idtree.hpp" #include "../../model/world/land.hpp" #include "../../model/world/landtexture.hpp" #include "../../model/world/resourcetable.hpp" @@ -186,8 +188,11 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult QUndoStack& undoStack = document.getUndoStack(); undoStack.beginMacro ("Edit texture records"); - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); - editTerrainTextureGrid(hit); + if(allowLandTextureEditing(mCellId)==true) + { + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + editTerrainTextureGrid(hit); + } undoStack.endMacro(); } @@ -213,8 +218,11 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) QUndoStack& undoStack = document.getUndoStack(); undoStack.beginMacro ("Edit texture records"); - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); - editTerrainTextureGrid(hit); + if(allowLandTextureEditing(mCellId)==true) + { + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); + editTerrainTextureGrid(hit); + } return true; } @@ -299,7 +307,12 @@ void CSVRender::TerrainTextureMode::handlePrimarySelectOnModeButton () { void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit) { + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + mCellId = getWorldspaceWidget().getCellId (hit.worldPos); + if(allowLandTextureEditing(mCellId)==true) {} std::pair cellCoordinates_pair = CSMWorld::CellCoordinates::fromId (mCellId); @@ -321,13 +334,10 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } mCellId = "#" + std::to_string(cellX) + " " + std::to_string(cellY); + if(allowLandTextureEditing(mCellId)==true) {} std::string iteratedCellId; - CSMDoc::Document& document = getWorldspaceWidget().getDocument(); - CSMWorld::IdTable& landTable = dynamic_cast ( - *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); - int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex); std::size_t hashlocation = mBrushTexture.find("#"); @@ -342,8 +352,12 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; - pushEditToCommand(mNew, document, landTable, mCellId); + + if(allowLandTextureEditing(mCellId)==true) + { + mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; + pushEditToCommand(mNew, document, landTable, mCellId); + } } if (mBrushShape == 1) @@ -363,32 +377,35 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - for(int i = 0; i < landTextureSize; i++) + if(allowLandTextureEditing(iteratedCellId)==true) { - for(int j = 0; j < landTextureSize; j++) + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + for(int i = 0; i < landTextureSize; i++) { - - if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + for(int j = 0; j < landTextureSize; j++) { - mNew[j*landTextureSize+i] = brushInt; - } - else - { - int distanceX(0); - int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; - if (i_cell == cellX) distanceX = abs(i-xHitInCell); - if (j_cell == cellY) distanceY = abs(j-yHitInCell); - if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; + + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + { + mNew[j*landTextureSize+i] = brushInt; + } + else + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; + } } } + pushEditToCommand(mNew, document, landTable, iteratedCellId); } - pushEditToCommand(mNew, document, landTable, iteratedCellId); } } } @@ -410,45 +427,49 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); - for(int i = 0; i < landTextureSize; i++) + if(allowLandTextureEditing(iteratedCellId)==true) { - for(int j = 0; j < landTextureSize; j++) + CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + for(int i = 0; i < landTextureSize; i++) { - - if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + for(int j = 0; j < landTextureSize; j++) { - int distanceX(0); - int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize* abs(i_cell-cellX) + i; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; - if (i_cell == cellX) distanceX = abs(i-xHitInCell); - if (j_cell == cellY) distanceY = abs(j-yHitInCell); - distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < rf) mNew[j*landTextureSize+i] = brushInt; - } - else - { - int distanceX(0); - int distanceY(0); - if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; - if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; - if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; - if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; - if (i_cell == cellX) distanceX = abs(i-xHitInCell); - if (j_cell == cellY) distanceY = abs(j-yHitInCell); - distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize* abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + } + else + { + int distanceX(0); + int distanceY(0); + if (i_cell < cellX) distanceX = xHitInCell + landTextureSize * abs(i_cell-cellX) - i; + if (j_cell < cellY) distanceY = yHitInCell + landTextureSize * abs(j_cell-cellY) - j; + if (i_cell > cellX) distanceX = -xHitInCell + landTextureSize * abs(i_cell-cellX) + i; + if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; + if (i_cell == cellX) distanceX = abs(i-xHitInCell); + if (j_cell == cellY) distanceY = abs(j-yHitInCell); + distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + } } } + pushEditToCommand(mNew, document, landTable, iteratedCellId); } - pushEditToCommand(mNew, document, landTable, iteratedCellId); } } } + if (mBrushShape == 3) { // Not implemented @@ -510,6 +531,81 @@ void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) undoStack.endMacro(); } +bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) +{ + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + CSMWorld::IdTree& cellTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); + + bool noCell = document.getData().getCells().searchId (cellId)==-1; + bool noLand = document.getData().getLand().searchId (cellId)==-1; + + if (noCell) + { + std::string mode = CSMPrefs::get()["Scene Drops"]["outside-landedit"].toString(); + + // target cell does not exist + if (mode=="Discard") + return false; + + if (mode=="Create cell and land, then edit") + { + std::unique_ptr createCommand ( + new CSMWorld::CreateCommand (cellTable, cellId)); + int parentIndex = cellTable.findColumnIndex (CSMWorld::Columns::ColumnId_Cell); + int index = cellTable.findNestedColumnIndex (parentIndex, CSMWorld::Columns::ColumnId_Interior); + createCommand->addNestedValue (parentIndex, index, false); + document.getUndoStack().push (createCommand.release()); + + if (CSVRender::PagedWorldspaceWidget *paged = + dynamic_cast (&getWorldspaceWidget())) + { + CSMWorld::CellSelection selection = paged->getCellSelection(); + selection.add (CSMWorld::CellCoordinates::fromId (cellId).first); + paged->setCellSelection (selection); + } + } + } + else if (CSVRender::PagedWorldspaceWidget *paged = + dynamic_cast (&getWorldspaceWidget())) + { + CSMWorld::CellSelection selection = paged->getCellSelection(); + if (!selection.has (CSMWorld::CellCoordinates::fromId (cellId).first)) + { + // target cell exists, but is not shown + std::string mode = + CSMPrefs::get()["Scene Drops"]["outside-visible-landedit"].toString(); + + if (mode=="Discard") + return false; + + if (mode=="Show cell and edit") + { + selection.add (CSMWorld::CellCoordinates::fromId (cellId).first); + paged->setCellSelection (selection); + } + } + } + + if (noLand) + { + std::string mode = CSMPrefs::get()["Scene Drops"]["outside-landedit"].toString(); + + // target cell does not exist + if (mode=="Discard") + return false; + + if (mode=="Create cell and land, then edit") + { + document.getUndoStack().push (new CSMWorld::CreateCommand (landTable, cellId)); + } + } + + return true; +} + void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { } diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index f6fde3544..dcf16040e 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -126,6 +126,9 @@ namespace CSVRender /// \brief Create new land texture record from texture asset void createTexture(std::string textureFileName); + /// \brief Create new cell and land if needed + bool allowLandTextureEditing(std::string textureFileName); + private: TextureBrushWindow *textureBrushWindow; std::string mCellId;