Merged pull request #1680

0.6.3
Marc Zinnschlag 7 years ago
commit e30ade81be

@ -81,14 +81,14 @@ opencs_units_noqt (view/world
opencs_units (view/widget opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit scenetooltoggle2 scenetooltexturebrush completerpopup coloreditor colorpickerpopup droplineedit
) )
opencs_units (view/render opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode instancemovemode previewwidget editmode instancemode instanceselectionmode instancemovemode
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
cellwater cellwater terraintexturemode
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render

@ -222,7 +222,15 @@ void CSMPrefs::State::declare()
EnumValues insertOutsideVisibleCell; EnumValues insertOutsideVisibleCell;
insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway); insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway);
declareCategory ("Scene Drops"); 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 ("3D Scene Editing");
declareInt ("distance", "Drop Distance", 50). declareInt ("distance", "Drop Distance", 50).
setTooltip ("If an instance drop can not be placed against another object at the " setTooltip ("If an instance drop can not be placed against another object at the "
"insert point, it will be placed by this distance from the insert point instead"); "insert point, it will be placed by this distance from the insert point instead");
@ -230,6 +238,12 @@ void CSMPrefs::State::declare()
addValues (insertOutsideCell); addValues (insertOutsideCell);
declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert). declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert).
addValues (insertOutsideVisibleCell); 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);
declareInt ("texturebrush-maximumsize", "Maximum texture brush size", 50).
setMin (1);
declareCategory ("Key Bindings"); declareCategory ("Key Bindings");

@ -11,11 +11,6 @@ namespace CSMWorld
bool LandTextureTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const bool LandTextureTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const
{ {
int columnIndex = mSourceModel->findColumnIndex(Columns::ColumnId_Modification);
QModelIndex index = mSourceModel->index(sourceRow, columnIndex);
if (mSourceModel->data(index).toInt() != RecordBase::State_ModifiedOnly)
return false;
return IdTableProxyModel::filterAcceptsRow(sourceRow, sourceParent); return IdTableProxyModel::filterAcceptsRow(sourceRow, sourceParent);
} }
} }

@ -551,7 +551,7 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event)
if (noCell) if (noCell)
{ {
std::string mode = CSMPrefs::get()["Scene Drops"]["outside-drop"].toString(); std::string mode = CSMPrefs::get()["3D Scene Editing"]["outside-drop"].toString();
// target cell does not exist // target cell does not exist
if (mode=="Discard") if (mode=="Discard")
@ -585,7 +585,7 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event)
{ {
// target cell exists, but is not shown // target cell exists, but is not shown
std::string mode = std::string mode =
CSMPrefs::get()["Scene Drops"]["outside-visible-drop"].toString(); CSMPrefs::get()["3D Scene Editing"]["outside-visible-drop"].toString();
if (mode=="Discard") if (mode=="Discard")
return; return;

@ -21,6 +21,7 @@
#include "mask.hpp" #include "mask.hpp"
#include "cameracontroller.hpp" #include "cameracontroller.hpp"
#include "cellarrow.hpp" #include "cellarrow.hpp"
#include "terraintexturemode.hpp"
bool CSVRender::PagedWorldspaceWidget::adjustCells() bool CSVRender::PagedWorldspaceWidget::adjustCells()
{ {
@ -136,7 +137,7 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain shape editing"), new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain shape editing"),
"terrain-shape"); "terrain-shape");
tool->addButton ( tool->addButton (
new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain texture editing"), new TerrainTextureMode (this, tool),
"terrain-texture"); "terrain-texture");
tool->addButton ( tool->addButton (
new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain vertex paint editing"), new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain vertex paint editing"),

@ -0,0 +1,542 @@
#include "terraintexturemode.hpp"
#include <string>
#include <sstream>
#include <QWidget>
#include <QIcon>
#include <QEvent>
#include <QDropEvent>
#include <QDragEnterEvent>
#include <QDrag>
#include <components/esm/loadland.hpp>
#include "../widget/modebutton.hpp"
#include "../widget/scenetoolbar.hpp"
#include "../widget/scenetooltexturebrush.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"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/world/universalid.hpp"
#include "editmode.hpp"
#include "pagedworldspacewidget.hpp"
#include "mask.hpp"
#include "object.hpp" // Something small needed regarding pointers from here ()
#include "worldspacewidget.hpp"
CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent)
: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent),
mBrushTexture("L0#0"),
mBrushSize(0),
mBrushShape(0),
mTextureBrushScenetool(0)
{
}
void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar)
{
if(!mTextureBrushScenetool)
{
mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush", getWorldspaceWidget().getDocument());
connect(mTextureBrushScenetool, SIGNAL (clicked()), mTextureBrushScenetool, SLOT (activate()));
connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int)));
connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int)));
connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int)));
connect(mTextureBrushScenetool, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string)));
connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string)));
connect(mTextureBrushScenetool, SIGNAL(passEvent(QDropEvent*)), this, SLOT(handleDropEvent(QDropEvent*)));
connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool->mTextureBrushWindow, SLOT(setBrushTexture(std::string)));
connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool, SLOT(updateBrushHistory(std::string)));
}
EditMode::activate(toolbar);
toolbar->addTool (mTextureBrushScenetool);
}
void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar)
{
if(mTextureBrushScenetool)
{
toolbar->removeTool (mTextureBrushScenetool);
delete mTextureBrushScenetool;
mTextureBrushScenetool = 0;
}
EditMode::deactivate(toolbar);
}
void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult& hit) // Apply changes here
{
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Land));
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
mCellId = getWorldspaceWidget().getCellId (hit.worldPos);
QUndoStack& undoStack = document.getUndoStack();
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
int index = landtexturesCollection.searchId(mBrushTexture);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit == true)
{
undoStack.beginMacro ("Edit texture records");
if(allowLandTextureEditing(mCellId)==true)
{
undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId));
editTerrainTextureGrid(hit);
}
undoStack.endMacro();
}
}
void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit)
{
}
void CSVRender::TerrainTextureMode::secondarySelectPressed(const WorldspaceHitResult& hit)
{
}
bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos)
{
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Land));
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
mCellId = getWorldspaceWidget().getCellId (hit.worldPos);
QUndoStack& undoStack = document.getUndoStack();
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
int index = landtexturesCollection.searchId(mBrushTexture);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
{
undoStack.beginMacro ("Edit texture records");
if(allowLandTextureEditing(mCellId)==true && hit.hit == true)
{
undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId));
editTerrainTextureGrid(hit);
}
}
return true;
}
bool CSVRender::TerrainTextureMode::secondaryEditStartDrag (const QPoint& pos)
{
return false;
}
bool CSVRender::TerrainTextureMode::primarySelectStartDrag (const QPoint& pos)
{
return false;
}
bool CSVRender::TerrainTextureMode::secondarySelectStartDrag (const QPoint& pos)
{
return false;
}
void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor)
{
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
int index = landtexturesCollection.searchId(mBrushTexture);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit == true)
{
editTerrainTextureGrid(hit);
}
}
void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) {
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
QUndoStack& undoStack = document.getUndoStack();
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
int index = landtexturesCollection.searchId(mBrushTexture);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
{
undoStack.endMacro();
}
}
void CSVRender::TerrainTextureMode::dragAborted() {
}
void CSVRender::TerrainTextureMode::dragWheel (int diff, double speedFactor) {}
void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) {
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped
return;
if (mime->holdsType (CSMWorld::UniversalId::Type_LandTexture))
{
const std::vector<CSMWorld::UniversalId> ids = mime->getData();
for (const CSMWorld::UniversalId& uid : ids)
{
mBrushTexture = uid.getId();
emit passBrushTexture(mBrushTexture);
}
}
if (mime->holdsType (CSMWorld::UniversalId::Type_Texture))
{
const std::vector<CSMWorld::UniversalId> ids = mime->getData();
for (const CSMWorld::UniversalId& uid : ids)
{
std::string textureFileName = uid.toString();
createTexture(textureFileName);
emit passBrushTexture(mBrushTexture);
}
}
}
void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitResult& hit)
{
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Land));
mCellId = getWorldspaceWidget().getCellId (hit.worldPos);
if(allowLandTextureEditing(mCellId)==true) {}
std::pair<CSMWorld::CellCoordinates, bool> cellCoordinates_pair = CSMWorld::CellCoordinates::fromId (mCellId);
int cellX = cellCoordinates_pair.first.getX();
int cellY = cellCoordinates_pair.first.getY();
// The coordinates of hit in mCellId
int xHitInCell (float(((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize) - 0.5));
int yHitInCell (float(((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize) + 0.5));
if (xHitInCell < 0)
{
xHitInCell = xHitInCell + landTextureSize;
cellX = cellX - 1;
}
if (yHitInCell > 15)
{
yHitInCell = yHitInCell - landTextureSize;
cellY = cellY + 1;
}
mCellId = "#" + std::to_string(cellX) + " " + std::to_string(cellY);
if(allowLandTextureEditing(mCellId)==true) {}
std::string iteratedCellId;
int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex);
std::size_t hashlocation = mBrushTexture.find("#");
std::string mBrushTextureInt = mBrushTexture.substr (hashlocation+1);
int brushInt = stoi(mBrushTexture.substr (hashlocation+1))+1; // All indices are offset by +1
float rf = mBrushSize/2;
int r = (mBrushSize/2)+1;
float distance = 0;
if (mBrushShape == 0)
{
CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>();
CSMWorld::LandTexturesColumn::DataType mNew(mPointer);
if(allowLandTextureEditing(mCellId)==true)
{
mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt;
pushEditToCommand(mNew, document, landTable, mCellId);
}
}
if (mBrushShape == 1)
{
int upperLeftCellX = cellX - std::floor(r / landTextureSize);
int upperLeftCellY = cellY - std::floor(r / landTextureSize);
if (xHitInCell - (r % landTextureSize) < 0) upperLeftCellX--;
if (yHitInCell - (r % landTextureSize) < 0) upperLeftCellY--;
int lowerrightCellX = cellX + std::floor(r / landTextureSize);
int lowerrightCellY = cellY + std::floor(r / landTextureSize);
if (xHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellX++;
if (yHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellY++;
for(int i_cell = upperLeftCellX; i_cell <= lowerrightCellX; i_cell++)
{
for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++)
{
iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell);
if(allowLandTextureEditing(iteratedCellId)==true)
{
CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>();
CSMWorld::LandTexturesColumn::DataType mNew(mPointer);
for(int i = 0; i < landTextureSize; i++)
{
for(int j = 0; j < landTextureSize; j++)
{
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);
}
}
}
}
if (mBrushShape == 2)
{
int upperLeftCellX = cellX - std::floor(r / landTextureSize);
int upperLeftCellY = cellY - std::floor(r / landTextureSize);
if (xHitInCell - (r % landTextureSize) < 0) upperLeftCellX--;
if (yHitInCell - (r % landTextureSize) < 0) upperLeftCellY--;
int lowerrightCellX = cellX + std::floor(r / landTextureSize);
int lowerrightCellY = cellY + std::floor(r / landTextureSize);
if (xHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellX++;
if (yHitInCell + (r % landTextureSize) > landTextureSize - 1) lowerrightCellY++;
for(int i_cell = upperLeftCellX; i_cell <= lowerrightCellX; i_cell++)
{
for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++)
{
iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell);
if(allowLandTextureEditing(iteratedCellId)==true)
{
CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value<CSMWorld::LandTexturesColumn::DataType>();
CSMWorld::LandTexturesColumn::DataType mNew(mPointer);
for(int i = 0; i < landTextureSize; i++)
{
for(int j = 0; j < landTextureSize; j++)
{
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);
}
}
}
}
if (mBrushShape == 3)
{
// Not implemented
}
}
void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, std::string cellId)
{
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
QVariant changedLand;
changedLand.setValue(newLandGrid);
QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex)));
QUndoStack& undoStack = document.getUndoStack();
undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId));
undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand));
}
void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName)
{
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
QUndoStack& undoStack = document.getUndoStack();
std::string newId;
int counter=0;
bool freeIndexFound = false;
do {
const size_t maxCounter = std::numeric_limits<uint16_t>::max() - 1;
try
{
newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter);
if (ltexTable.getRecord(newId).isDeleted() == 0) counter = (counter + 1) % maxCounter;
} catch (const std::exception& e)
{
newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter);
freeIndexFound = true;
}
} while (freeIndexFound == false);
std::size_t idlocation = textureFileName.find("Texture: ");
textureFileName = textureFileName.substr (idlocation + 9);
QVariant textureNameVariant;
QVariant textureFileNameVariant;
textureFileNameVariant.setValue(QString::fromStdString(textureFileName));
undoStack.beginMacro ("Add land texture record");
undoStack.push (new CSMWorld::CreateCommand (ltexTable, newId));
QModelIndex index(ltexTable.getModelIndex (newId, ltexTable.findColumnIndex (CSMWorld::Columns::ColumnId_Texture)));
undoStack.push (new CSMWorld::ModifyCommand(ltexTable, index, textureFileNameVariant));
undoStack.endMacro();
mBrushTexture = newId;
}
bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId)
{
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Land));
CSMWorld::IdTree& cellTable = dynamic_cast<CSMWorld::IdTree&> (
*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()["3D Scene Editing"]["outside-landedit"].toString();
// target cell does not exist
if (mode=="Discard")
return false;
if (mode=="Create cell and land, then edit")
{
std::unique_ptr<CSMWorld::CreateCommand> 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<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
{
CSMWorld::CellSelection selection = paged->getCellSelection();
selection.add (CSMWorld::CellCoordinates::fromId (cellId).first);
paged->setCellSelection (selection);
}
}
}
else if (CSVRender::PagedWorldspaceWidget *paged =
dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&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()["3D Scene Editing"]["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()["3D Scene Editing"]["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) {
}
void CSVRender::TerrainTextureMode::setBrushSize(int brushSize)
{
mBrushSize = brushSize;
}
void CSVRender::TerrainTextureMode::setBrushShape(int brushShape)
{
mBrushShape = brushShape;
}
void CSVRender::TerrainTextureMode::setBrushTexture(std::string brushTexture)
{
mBrushTexture = brushTexture;
}

@ -0,0 +1,100 @@
#ifndef CSV_RENDER_TERRAINTEXTUREMODE_H
#define CSV_RENDER_TERRAINTEXTUREMODE_H
#include "editmode.hpp"
#include <string>
#include <QWidget>
#include <QEvent>
#include "../../model/world/data.hpp"
#include "../../model/world/land.hpp"
#include "../../model/doc/document.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/landtexture.hpp"
namespace CSVWidget
{
class SceneToolTextureBrush;
}
namespace CSVRender
{
class TerrainTextureMode : public EditMode
{
Q_OBJECT
public:
/// \brief Editmode for terrain texture grid
TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr);
/// \brief Create single command for one-click texture editing
void primaryEditPressed (const WorldspaceHitResult& hit);
/// \brief Open brush settings window
void primarySelectPressed(const WorldspaceHitResult&);
void secondarySelectPressed(const WorldspaceHitResult&);
void activate(CSVWidget::SceneToolbar*);
void deactivate(CSVWidget::SceneToolbar*);
/// \brief Start texture editing command macro
virtual bool primaryEditStartDrag (const QPoint& pos);
virtual bool secondaryEditStartDrag (const QPoint& pos);
virtual bool primarySelectStartDrag (const QPoint& pos);
virtual bool secondarySelectStartDrag (const QPoint& pos);
/// \brief Handle texture edit behavior during dragging
virtual void drag (const QPoint& pos, int diffX, int diffY, double speedFactor);
/// \brief End texture editing command macro
virtual void dragCompleted(const QPoint& pos);
virtual void dragAborted();
virtual void dragWheel (int diff, double speedFactor);
virtual void dragMoveEvent (QDragMoveEvent *event);
/// \brief Handle brush mechanics, maths regarding worldspace hit etc.
void editTerrainTextureGrid (const WorldspaceHitResult& hit);
/// \brief Push texture edits to command macro
void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, std::string cellId);
/// \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:
std::string mCellId;
std::string mBrushTexture;
int mBrushSize;
int mBrushShape;
CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool;
const int cellSize {ESM::Land::REAL_SIZE};
const int landSize {ESM::Land::LAND_SIZE};
const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE};
signals:
void passBrushTexture(std::string brushTexture);
public slots:
void handleDropEvent(QDropEvent *event);
void setBrushSize(int brushSize);
void setBrushShape(int brushShape);
void setBrushTexture(std::string brushShape);
};
}
#endif

@ -445,7 +445,7 @@ CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick (const QPo
// Default placement // Default placement
direction.normalize(); direction.normalize();
direction *= CSMPrefs::get()["Scene Drops"]["distance"].toInt(); direction *= CSMPrefs::get()["3D Scene Editing"]["distance"].toInt();
WorldspaceHitResult hit = { false, 0, 0, 0, 0, start + direction }; WorldspaceHitResult hit = { false, 0, 0, 0, 0, start + direction };
return hit; return hit;
@ -648,6 +648,12 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
mDragX = event->posF().x(); mDragX = event->posF().x();
mDragY = height() - event->posF().y(); mDragY = height() - event->posF().y();
#endif #endif
if (mDragMode == InteractionType_PrimaryEdit)
{
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
editMode.drag (event->pos(), mDragX, mDragY, mDragFactor); // note: terraintexturemode only uses pos
}
} }
} }
else else

@ -0,0 +1,362 @@
#include "scenetooltexturebrush.hpp"
#include <QFrame>
#include <QIcon>
#include <QTableWidget>
#include <QHBoxLayout>
#include <QWidget>
#include <QSpinBox>
#include <QGroupBox>
#include <QSlider>
#include <QEvent>
#include <QDropEvent>
#include <QButtonGroup>
#include <QVBoxLayout>
#include <QDragEnterEvent>
#include <QDrag>
#include <QTableWidget>
#include <QHeaderView>
#include <QApplication>
#include <QSizePolicy>
#include "scenetool.hpp"
#include "../../model/doc/document.hpp"
#include "../../model/prefs/state.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/idcollection.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/landtexture.hpp"
#include "../../model/world/universalid.hpp"
CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *parent)
: QGroupBox(title, parent)
{
mBrushSizeSlider = new QSlider(Qt::Horizontal);
mBrushSizeSlider->setTickPosition(QSlider::TicksBothSides);
mBrushSizeSlider->setTickInterval(10);
mBrushSizeSlider->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt());
mBrushSizeSlider->setSingleStep(1);
mBrushSizeSpinBox = new QSpinBox;
mBrushSizeSpinBox->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt());
mBrushSizeSpinBox->setSingleStep(1);
mLayoutSliderSize = new QHBoxLayout;
mLayoutSliderSize->addWidget(mBrushSizeSlider);
mLayoutSliderSize->addWidget(mBrushSizeSpinBox);
connect(mBrushSizeSlider, SIGNAL(valueChanged(int)), mBrushSizeSpinBox, SLOT(setValue(int)));
connect(mBrushSizeSpinBox, SIGNAL(valueChanged(int)), mBrushSizeSlider, SLOT(setValue(int)));
setLayout(mLayoutSliderSize);
}
CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QWidget *parent)
: QFrame(parent, Qt::Popup),
mBrushShape(0),
mBrushSize(0),
mBrushTexture("L0#0"),
mDocument(document)
{
mBrushTextureLabel = "Selected texture: " + mBrushTexture + " ";
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
int index = landtexturesCollection.searchId(mBrushTexture);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
{
mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value<QString>());
} else
{
mBrushTextureLabel = "No selected texture or invalid texture";
mSelectedBrush = new QLabel(QString::fromStdString(mBrushTextureLabel));
}
QVBoxLayout *layoutMain = new QVBoxLayout;
layoutMain->setSpacing(0);
layoutMain->setContentsMargins(4,0,4,4);
QHBoxLayout *layoutHorizontal = new QHBoxLayout;
layoutHorizontal->setSpacing(0);
layoutHorizontal->setContentsMargins (QMargins (0, 0, 0, 0));
configureButtonInitialSettings(mButtonPoint);
configureButtonInitialSettings(mButtonSquare);
configureButtonInitialSettings(mButtonCircle);
configureButtonInitialSettings(mButtonCustom);
mButtonPoint->setToolTip (toolTipPoint);
mButtonSquare->setToolTip (toolTipSquare);
mButtonCircle->setToolTip (toolTipCircle);
mButtonCustom->setToolTip (toolTipCustom);
QButtonGroup* brushButtonGroup = new QButtonGroup(this);
brushButtonGroup->addButton(mButtonPoint);
brushButtonGroup->addButton(mButtonSquare);
brushButtonGroup->addButton(mButtonCircle);
brushButtonGroup->addButton(mButtonCustom);
brushButtonGroup->setExclusive(true);
layoutHorizontal->addWidget(mButtonPoint, 0, Qt::AlignTop);
layoutHorizontal->addWidget(mButtonSquare, 0, Qt::AlignTop);
layoutHorizontal->addWidget(mButtonCircle, 0, Qt::AlignTop);
layoutHorizontal->addWidget(mButtonCustom, 0, Qt::AlignTop);
mHorizontalGroupBox = new QGroupBox(tr(""));
mHorizontalGroupBox->setLayout(layoutHorizontal);
layoutMain->addWidget(mHorizontalGroupBox);
layoutMain->addWidget(mSizeSliders);
layoutMain->addWidget(mSelectedBrush);
setLayout(layoutMain);
connect(mButtonPoint, SIGNAL(clicked()), this, SLOT(setBrushShape()));
connect(mButtonSquare, SIGNAL(clicked()), this, SLOT(setBrushShape()));
connect(mButtonCircle, SIGNAL(clicked()), this, SLOT(setBrushShape()));
connect(mButtonCustom, SIGNAL(clicked()), this, SLOT(setBrushShape()));
}
void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton *button)
{
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
button->setContentsMargins (QMargins (0, 0, 0, 0));
button->setIconSize (QSize (48-6, 48-6));
button->setFixedSize (48, 48);
button->setCheckable(true);
}
void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture)
{
mBrushTexture = brushTexture;
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
int columnModification = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Modification);
int index = landtexturesCollection.searchId(mBrushTexture);
// Check if texture exists in current plugin
if(landtexturesCollection.getData(index, columnModification).value<int>() == 0)
{
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
QUndoStack& undoStack = mDocument.getUndoStack();
QVariant textureFileNameVariant;
textureFileNameVariant.setValue(landtexturesCollection.getData(index, landTextureFilename).value<QString>());
std::size_t hashlocation = mBrushTexture.find("#");
std::string mBrushTexturePlugin = "L0#" + mBrushTexture.substr (hashlocation+1);
int indexPlugin = landtexturesCollection.searchId(mBrushTexturePlugin);
// Reindex texture if needed
if (indexPlugin != -1 && !landtexturesCollection.getRecord(indexPlugin).isDeleted())
{
int counter=0;
bool freeIndexFound = false;
do {
const size_t maxCounter = std::numeric_limits<uint16_t>::max() - 1;
mBrushTexturePlugin = CSMWorld::LandTexture::createUniqueRecordId(0, counter);
if (landtexturesCollection.searchId(mBrushTexturePlugin) != -1 && landtexturesCollection.getRecord(mBrushTexturePlugin).isDeleted() == 0) counter = (counter + 1) % maxCounter;
else freeIndexFound = true;
} while (freeIndexFound == false);
}
undoStack.beginMacro ("Add land texture record");
undoStack.push (new CSMWorld::CloneCommand (ltexTable, mBrushTexture, mBrushTexturePlugin, CSMWorld::UniversalId::Type_LandTexture));
undoStack.endMacro();
mBrushTexture = mBrushTexturePlugin;
emit passTextureId(mBrushTexture);
}
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
{
mBrushTextureLabel = "Selected texture: " + mBrushTexture + " ";
mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel) + landtexturesCollection.getData(index, landTextureFilename).value<QString>());
} else
{
mBrushTextureLabel = "No selected texture or invalid texture";
mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel));
}
emit passBrushShape(mBrushShape); // update icon
}
void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize)
{
mBrushSize = brushSize;
emit passBrushSize(mBrushSize);
}
void CSVWidget::TextureBrushWindow::setBrushShape()
{
if(mButtonPoint->isChecked()) mBrushShape = 0;
if(mButtonSquare->isChecked()) mBrushShape = 1;
if(mButtonCircle->isChecked()) mBrushShape = 2;
if(mButtonCustom->isChecked()) mBrushShape = 3;
emit passBrushShape(mBrushShape);
}
void CSVWidget::SceneToolTextureBrush::adjustToolTips()
{
}
CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip, CSMDoc::Document& document)
: SceneTool (parent, Type_TopAction),
mToolTip (toolTip),
mDocument (document),
mTextureBrushWindow(new TextureBrushWindow(document, this))
{
mBrushHistory.resize(1);
mBrushHistory[0] = "L0#0";
setAcceptDrops(true);
connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int)));
setButtonIcon(mTextureBrushWindow->mBrushShape);
mPanel = new QFrame (this, Qt::Popup);
QHBoxLayout *layout = new QHBoxLayout (mPanel);
layout->setContentsMargins (QMargins (0, 0, 0, 0));
mTable = new QTableWidget (0, 2, this);
mTable->setShowGrid (true);
mTable->verticalHeader()->hide();
mTable->horizontalHeader()->hide();
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
mTable->horizontalHeader()->setSectionResizeMode (0, QHeaderView::Stretch);
mTable->horizontalHeader()->setSectionResizeMode (1, QHeaderView::Stretch);
#else
mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch);
mTable->horizontalHeader()->setResizeMode (1, QHeaderView::Stretch);
#endif
mTable->setSelectionMode (QAbstractItemView::NoSelection);
layout->addWidget (mTable);
connect (mTable, SIGNAL (clicked (const QModelIndex&)),
this, SLOT (clicked (const QModelIndex&)));
}
void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape)
{
QString tooltip = "Brush settings <p>Currently selected: ";
if(brushShape == 0)
{
setIcon (QIcon (QPixmap (":scenetoolbar/brush-point")));
tooltip += dynamic_cast<QString&> (mTextureBrushWindow->toolTipPoint);
}
if(brushShape == 1)
{
setIcon (QIcon (QPixmap (":scenetoolbar/brush-square")));
tooltip += dynamic_cast<QString&> (mTextureBrushWindow->toolTipSquare);
}
if(brushShape == 2)
{
setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle")));
tooltip += dynamic_cast<QString&> (mTextureBrushWindow->toolTipCircle);
}
if(brushShape == 3)
{
setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom")));
tooltip += dynamic_cast<QString&> (mTextureBrushWindow->toolTipCustom);
}
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
int index = landtexturesCollection.searchId(mTextureBrushWindow->mBrushTexture);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
{
tooltip += "<p>Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture) + " ";
tooltip += landtexturesCollection.getData(index, landTextureFilename).value<QString>();
} else
{
tooltip += "<p>No selected texture or invalid texture";
}
tooltip += "<br>(drop texture here to change)";
setToolTip (tooltip);
}
void CSVWidget::SceneToolTextureBrush::showPanel (const QPoint& position)
{
updatePanel();
mPanel->move (position);
mPanel->show();
}
void CSVWidget::SceneToolTextureBrush::updatePanel()
{
mTable->setRowCount (mBrushHistory.size());
for (int i = mBrushHistory.size()-1; i >= 0; --i)
{
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
int index = landtexturesCollection.searchId(mBrushHistory[i]);
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
{
mTable->setItem (i, 1, new QTableWidgetItem (landtexturesCollection.getData(index, landTextureFilename).value<QString>()));
mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i])));
} else
{
mTable->setItem (i, 1, new QTableWidgetItem ("Invalid/deleted texture"));
mTable->setItem (i, 0, new QTableWidgetItem (QString::fromStdString(mBrushHistory[i])));
}
}
}
void CSVWidget::SceneToolTextureBrush::updateBrushHistory (const std::string& brushTexture)
{
mBrushHistory.insert(mBrushHistory.begin(), brushTexture);
if(mBrushHistory.size() > 5) mBrushHistory.pop_back();
}
void CSVWidget::SceneToolTextureBrush::clicked (const QModelIndex& index)
{
if (index.column()==0 || index.column()==1)
{
std::string brushTexture = mBrushHistory[index.row()];
std::swap(mBrushHistory[index.row()], mBrushHistory[0]);
mTextureBrushWindow->setBrushTexture(brushTexture);
emit passTextureId(brushTexture);
updatePanel();
mPanel->hide();
}
}
void CSVWidget::SceneToolTextureBrush::activate ()
{
QPoint position = QCursor::pos();
mTextureBrushWindow->mSizeSliders->mBrushSizeSlider->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt());
mTextureBrushWindow->mSizeSliders->mBrushSizeSpinBox->setRange(1, CSMPrefs::get()["3D Scene Editing"]["texturebrush-maximumsize"].toInt());
mTextureBrushWindow->move (position);
mTextureBrushWindow->show();
}
void CSVWidget::SceneToolTextureBrush::dragEnterEvent (QDragEnterEvent *event)
{
emit passEvent(event);
event->accept();
}
void CSVWidget::SceneToolTextureBrush::dropEvent (QDropEvent *event)
{
emit passEvent(event);
event->accept();
}

@ -0,0 +1,117 @@
#ifndef CSV_WIDGET_SCENETOOLTEXTUREBRUSH_H
#define CSV_WIDGET_SCENETOOLTEXTUREBRUSH_H
#include <QIcon>
#include <QFrame>
#include <QModelIndex>
#include <QWidget>
#include <QLabel>
#include <QSpinBox>
#include <QGroupBox>
#include <QSlider>
#include <QEvent>
#include <QHBoxLayout>
#include <QPushButton>
#include "scenetool.hpp"
#include "../../model/doc/document.hpp"
class QTableWidget;
namespace CSVWidget
{
/// \brief Layout-box for some brush button settings
class BrushSizeControls : public QGroupBox
{
Q_OBJECT
public:
BrushSizeControls(const QString &title, QWidget *parent);
QSlider *mBrushSizeSlider;
QSpinBox *mBrushSizeSpinBox;
private:
QHBoxLayout *mLayoutSliderSize;
};
/// \brief Brush settings window
class TextureBrushWindow : public QFrame
{
Q_OBJECT
public:
TextureBrushWindow(CSMDoc::Document& document, QWidget *parent = 0);
void configureButtonInitialSettings(QPushButton *button);
QPushButton *mButtonPoint = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-point")), "", this);
QPushButton *mButtonSquare = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-square")), "", this);
QPushButton *mButtonCircle = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-circle")), "", this);
QPushButton *mButtonCustom = new QPushButton(QIcon (QPixmap (":scenetoolbar/brush-custom")), "", this);
QString toolTipPoint = "Paint single point";
QString toolTipSquare = "Paint with square brush";
QString toolTipCircle = "Paint with circle brush";
QString toolTipCustom = "Paint custom selection (not implemented yet)";
BrushSizeControls* mSizeSliders = new BrushSizeControls("Brush size", this);
int mBrushShape;
int mBrushSize;
std::string mBrushTexture;
private:
CSMDoc::Document& mDocument;
QLabel *mSelectedBrush;
QGroupBox *mHorizontalGroupBox;
std::string mBrushTextureLabel;
public slots:
void setBrushTexture(std::string brushTexture);
void setBrushShape();
void setBrushSize(int brushSize);
signals:
void passBrushSize (int brushSize);
void passBrushShape(int brushShape);
void passTextureId(std::string brushTexture);
};
class SceneToolTextureBrush : public SceneTool
{
Q_OBJECT
QString mToolTip;
CSMDoc::Document& mDocument;
QFrame *mPanel;
QTableWidget *mTable;
std::vector<std::string> mBrushHistory;
private:
void adjustToolTips();
public:
SceneToolTextureBrush (SceneToolbar *parent, const QString& toolTip, CSMDoc::Document& document);
virtual void showPanel (const QPoint& position);
void updatePanel ();
TextureBrushWindow *mTextureBrushWindow;
void dropEvent (QDropEvent *event);
void dragEnterEvent (QDragEnterEvent *event);
public slots:
void setButtonIcon(int brushShape);
void updateBrushHistory (const std::string& mBrushTexture);
void clicked (const QModelIndex& index);
virtual void activate();
signals:
void passEvent(QDropEvent *event);
void passEvent(QDragEnterEvent *event);
void passTextureId(std::string brushTexture);
};
}
#endif

@ -150,5 +150,9 @@
<file alias="selection-mode-cube">selection-mode-cube.png</file> <file alias="selection-mode-cube">selection-mode-cube.png</file>
<file alias="selection-mode-cube-corner">selection-mode-cube-corner.png</file> <file alias="selection-mode-cube-corner">selection-mode-cube-corner.png</file>
<file alias="selection-mode-cube-sphere">selection-mode-cube-sphere.png</file> <file alias="selection-mode-cube-sphere">selection-mode-cube-sphere.png</file>
<file alias="brush-point">brush-point.png</file>
<file alias="brush-square">brush-square.png</file>
<file alias="brush-circle">brush-circle.png</file>
<file alias="brush-custom">brush-custom.png</file>
</qresource> </qresource>
</RCC> </RCC>

Loading…
Cancel
Save