Merge branch 'move'

move
Marc Zinnschlag 9 years ago
commit d5067201d0

@ -26,7 +26,7 @@ opencs_units_noqt (model/world
universalid record commands columnbase columnimp scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
idcompletionmanager metadata defaultgmsts infoselectwrapper
idcompletionmanager metadata defaultgmsts infoselectwrapper commandmacro
)
opencs_hdrs_noqt (model/world
@ -85,7 +85,7 @@ opencs_units (view/widget
opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode
previewwidget editmode instancemode instanceselectionmode instancemovemode
)
opencs_units_noqt (view/render

@ -1,5 +1,7 @@
#include "cellcoordinates.hpp"
#include <cmath>
#include <ostream>
#include <sstream>
@ -7,6 +9,9 @@ CSMWorld::CellCoordinates::CellCoordinates() : mX (0), mY (0) {}
CSMWorld::CellCoordinates::CellCoordinates (int x, int y) : mX (x), mY (y) {}
CSMWorld::CellCoordinates::CellCoordinates (const std::pair<int, int>& coordinates)
: mX (coordinates.first), mY (coordinates.second) {}
int CSMWorld::CellCoordinates::getX() const
{
return mX;
@ -49,6 +54,13 @@ std::pair<CSMWorld::CellCoordinates, bool> CSMWorld::CellCoordinates::fromId (
return std::make_pair (CellCoordinates(), false);
}
std::pair<int, int> CSMWorld::CellCoordinates::coordinatesToCellIndex (float x, float y)
{
const int cellSize = 8192;
return std::make_pair (std::floor (x/cellSize), std::floor (y/cellSize));
}
bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right)
{
return left.getX()==right.getX() && left.getY()==right.getY();

@ -3,6 +3,7 @@
#include <iosfwd>
#include <string>
#include <utility>
#include <QMetaType>
@ -19,6 +20,8 @@ namespace CSMWorld
CellCoordinates (int x, int y);
CellCoordinates (const std::pair<int, int>& coordinates);
int getX() const;
int getY() const;
@ -34,6 +37,8 @@ namespace CSMWorld
///
/// \note The worldspace part of \a id is ignored
static std::pair<CellCoordinates, bool> fromId (const std::string& id);
static std::pair<int, int> coordinatesToCellIndex (float x, float y);
};
bool operator== (const CellCoordinates& left, const CellCoordinates& right);

@ -11,6 +11,7 @@
#include "record.hpp"
#include "commands.hpp"
#include "idtableproxymodel.hpp"
#include "commandmacro.hpp"
std::vector<std::string> CSMWorld::CommandDispatcher::getDeletableRecords() const
{
@ -171,10 +172,9 @@ void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, cons
if (modifyCell.get())
{
mDocument.getUndoStack().beginMacro (modifyData->text());
mDocument.getUndoStack().push (modifyData.release());
mDocument.getUndoStack().push (modifyCell.release());
mDocument.getUndoStack().endMacro();
CommandMacro macro (mDocument.getUndoStack());
macro.push (modifyData.release());
macro.push (modifyCell.release());
}
else
mDocument.getUndoStack().push (modifyData.release());
@ -194,9 +194,7 @@ void CSMWorld::CommandDispatcher::executeDelete()
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
if (rows.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
CommandMacro macro (mDocument.getUndoStack(), rows.size()>1 ? "Delete multiple records" : "");
for (std::vector<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
{
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
@ -204,7 +202,7 @@ void CSMWorld::CommandDispatcher::executeDelete()
if (mId.getType() == UniversalId::Type_Referenceables)
{
mDocument.getUndoStack().push ( new CSMWorld::DeleteCommand (model, id,
macro.push (new CSMWorld::DeleteCommand (model, id,
static_cast<CSMWorld::UniversalId::Type>(model.data (model.index (
model.getModelIndex (id, columnIndex).row(),
model.findColumnIndex (CSMWorld::Columns::ColumnId_RecordType))).toInt())));
@ -212,9 +210,6 @@ void CSMWorld::CommandDispatcher::executeDelete()
else
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id));
}
if (rows.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeRevert()
@ -231,25 +226,19 @@ void CSMWorld::CommandDispatcher::executeRevert()
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
if (rows.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
CommandMacro macro (mDocument.getUndoStack(), rows.size()>1 ? "Revert multiple records" : "");
for (std::vector<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
{
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
toString().toUtf8().constData();
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id));
macro.push (new CSMWorld::RevertCommand (model, id));
}
if (rows.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeExtendedDelete()
{
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Extended delete of multiple records"));
CommandMacro macro (mDocument.getUndoStack(), mExtendedTypes.size()>1 ? tr ("Extended delete of multiple records") : "");
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
iter!=mExtendedTypes.end(); ++iter)
@ -276,20 +265,15 @@ void CSMWorld::CommandDispatcher::executeExtendedDelete()
Misc::StringUtils::lowerCase (record.get().mCell)))
continue;
mDocument.getUndoStack().push (
new CSMWorld::DeleteCommand (model, record.get().mId));
macro.push (new CSMWorld::DeleteCommand (model, record.get().mId));
}
}
}
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeExtendedRevert()
{
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Extended revert of multiple records"));
CommandMacro macro (mDocument.getUndoStack(), mExtendedTypes.size()>1 ? tr ("Extended revert of multiple records") : "");
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
iter!=mExtendedTypes.end(); ++iter)
@ -313,12 +297,8 @@ void CSMWorld::CommandDispatcher::executeExtendedRevert()
Misc::StringUtils::lowerCase (record.get().mCell)))
continue;
mDocument.getUndoStack().push (
new CSMWorld::RevertCommand (model, record.get().mId));
macro.push (new CSMWorld::RevertCommand (model, record.get().mId));
}
}
}
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}

@ -0,0 +1,26 @@
#include "commandmacro.hpp"
#include <QUndoStack>
#include <QUndoCommand>
CSMWorld::CommandMacro::CommandMacro (QUndoStack& undoStack, const QString& description)
: mUndoStack (undoStack), mDescription (description), mStarted (false)
{}
CSMWorld::CommandMacro::~CommandMacro()
{
if (mStarted)
mUndoStack.endMacro();
}
void CSMWorld::CommandMacro::push (QUndoCommand *command)
{
if (!mStarted)
{
mUndoStack.beginMacro (mDescription.isEmpty() ? command->text() : mDescription);
mStarted = true;
}
mUndoStack.push (command);
}

@ -0,0 +1,34 @@
#ifndef CSM_WOLRD_COMMANDMACRO_H
#define CSM_WOLRD_COMMANDMACRO_H
class QUndoStack;
class QUndoCommand;
#include <QString>
namespace CSMWorld
{
class CommandMacro
{
QUndoStack& mUndoStack;
QString mDescription;
bool mStarted;
/// not implemented
CommandMacro (const CommandMacro&);
/// not implemented
CommandMacro& operator= (const CommandMacro&);
public:
/// If \a description is empty, the description of the first command is used.
CommandMacro (QUndoStack& undoStack, const QString& description = "");
~CommandMacro();
void push (QUndoCommand *command);
};
}
#endif

@ -2,6 +2,10 @@
#include <cmath>
#include <sstream>
#include "cellcoordinates.hpp"
CSMWorld::CellRef::CellRef()
{
mRefNum.mIndex = 0;
@ -10,8 +14,5 @@ CSMWorld::CellRef::CellRef()
std::pair<int, int> CSMWorld::CellRef::getCellIndex() const
{
const int cellSize = 8192;
return std::make_pair (
std::floor (mPos.pos[0]/cellSize), std::floor (mPos.pos[1]/cellSize));
return CellCoordinates::coordinatesToCellIndex (mPos.pos[0], mPos.pos[1]);
}

@ -51,7 +51,12 @@ bool CSVRender::Cell::addObjects (int start, int end)
{
std::string id = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mId);
mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false)));
std::auto_ptr<Object> object (new Object (mData, mCellNode, id, false));
if (mSubModeElementMask & Mask_Reference)
object->setSubMode (mSubMode);
mObjects.insert (std::make_pair (id, object.release()));
modified = true;
}
}
@ -61,7 +66,8 @@ bool CSVRender::Cell::addObjects (int start, int end)
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
bool deleted)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
mSubModeElementMask (0)
{
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
@ -349,3 +355,35 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getSelection (un
return result;
}
std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getEdited (unsigned int elementMask) const
{
std::vector<osg::ref_ptr<TagBase> > result;
if (elementMask & Mask_Reference)
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
iter!=mObjects.end(); ++iter)
if (iter->second->isEdited())
result.push_back (iter->second->getTag());
return result;
}
void CSVRender::Cell::setSubMode (int subMode, unsigned int elementMask)
{
mSubMode = subMode;
mSubModeElementMask = elementMask;
if (elementMask & Mask_Reference)
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
iter!=mObjects.end(); ++iter)
iter->second->setSubMode (subMode);
}
void CSVRender::Cell::reset (unsigned int elementMask)
{
if (elementMask & Mask_Reference)
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
iter!=mObjects.end(); ++iter)
iter->second->reset();
}

@ -47,6 +47,8 @@ namespace CSVRender
std::auto_ptr<CellMarker> mCellMarker;
std::auto_ptr<CellBorder> mCellBorder;
bool mDeleted;
int mSubMode;
unsigned int mSubModeElementMask;
/// Ignored if cell does not have an object with the given ID.
///
@ -118,6 +120,14 @@ namespace CSVRender
bool isDeleted() const;
std::vector<osg::ref_ptr<TagBase> > getSelection (unsigned int elementMask) const;
std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask) const;
void setSubMode (int subMode, unsigned int elementMask);
/// Erase all overrides and restore the visual representation of the cell to its
/// true state.
void reset (unsigned int elementMask);
};
}

@ -70,3 +70,8 @@ void CSVRender::EditMode::dragEnterEvent (QDragEnterEvent *event) {}
void CSVRender::EditMode::dropEvent (QDropEvent* event) {}
void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {}
int CSVRender::EditMode::getSubMode() const
{
return -1;
}

@ -92,6 +92,9 @@ namespace CSVRender
/// Default-implementation: ignored
virtual void dragMoveEvent (QDragMoveEvent *event);
/// Default: return -1
virtual int getSubMode() const;
};
}

@ -8,6 +8,7 @@
#include "../../model/world/idtable.hpp"
#include "../../model/world/idtree.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/commandmacro.hpp"
#include "../widget/scenetoolbar.hpp"
#include "../widget/scenetoolmode.hpp"
@ -18,10 +19,17 @@
#include "worldspacewidget.hpp"
#include "pagedworldspacewidget.hpp"
#include "instanceselectionmode.hpp"
#include "instancemovemode.hpp"
int CSVRender::InstanceMode::getSubModeFromId (const std::string& id) const
{
return id=="move" ? 0 : (id=="rotate" ? 1 : 2);
}
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent)
: EditMode (worldspaceWidget, QIcon (":placeholder"), Mask_Reference, "Instance editing",
parent), mSubMode (0), mSelectionMode (0)
parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None),
mDragAxis (-1), mLocked (false)
{
}
@ -30,12 +38,7 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
if (!mSubMode)
{
mSubMode = new CSVWidget::SceneToolMode (toolbar, "Edit Sub-Mode");
mSubMode->addButton (":placeholder", "move",
"Move selected instances"
"<ul><li>Use primary edit to move instances around freely</li>"
"<li>Use secondary edit to move instances around within the grid</li>"
"</ul>"
"<font color=Red>Not implemented yet</font color>");
mSubMode->addButton (new InstanceMoveMode (this), "move");
mSubMode->addButton (":placeholder", "rotate",
"Rotate selected instances"
"<ul><li>Use primary edit to rotate instances freely</li>"
@ -48,19 +51,33 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
"<li>Use secondary edit to scale instances along the grid</li>"
"</ul>"
"<font color=Red>Not implemented yet</font color>");
mSubMode->setButton (mSubModeId);
connect (mSubMode, SIGNAL (modeChanged (const std::string&)),
this, SLOT (subModeChanged (const std::string&)));
}
if (!mSelectionMode)
mSelectionMode = new InstanceSelectionMode (toolbar, getWorldspaceWidget());
mDragMode = DragMode_None;
EditMode::activate (toolbar);
toolbar->addTool (mSubMode);
toolbar->addTool (mSelectionMode);
std::string subMode = mSubMode->getCurrentId();
getWorldspaceWidget().setSubMode (getSubModeFromId (subMode), Mask_Reference);
}
void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar)
{
mDragMode = DragMode_None;
getWorldspaceWidget().reset (Mask_Reference);
if (mSelectionMode)
{
toolbar->removeTool (mSelectionMode);
@ -78,6 +95,14 @@ void CSVRender::InstanceMode::deactivate (CSVWidget::SceneToolbar *toolbar)
EditMode::deactivate (toolbar);
}
void CSVRender::InstanceMode::setEditLock (bool locked)
{
mLocked = locked;
if (mLocked)
getWorldspaceWidget().abortDrag();
}
void CSVRender::InstanceMode::primaryEditPressed (osg::ref_ptr<TagBase> tag)
{
if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue())
@ -120,6 +145,173 @@ void CSVRender::InstanceMode::secondarySelectPressed (osg::ref_ptr<TagBase> tag)
}
}
bool CSVRender::InstanceMode::primaryEditStartDrag (osg::ref_ptr<TagBase> tag)
{
if (mDragMode!=DragMode_None || mLocked)
return false;
if (tag && CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue())
{
getWorldspaceWidget().clearSelection (Mask_Reference);
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
{
CSVRender::Object* object = objectTag->mObject;
object->setSelected (true);
}
}
std::vector<osg::ref_ptr<TagBase> > selection =
getWorldspaceWidget().getSelection (Mask_Reference);
if (selection.empty())
return false;
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
iter!=selection.end(); ++iter)
{
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
{
objectTag->mObject->setEdited (Object::Override_Position);
}
}
// \todo check for sub-mode
if (CSVRender::ObjectMarkerTag *objectTag = dynamic_cast<CSVRender::ObjectMarkerTag *> (tag.get()))
{
mDragAxis = objectTag->mAxis;
}
else
mDragAxis = -1;
mDragMode = DragMode_Move;
return true;
}
bool CSVRender::InstanceMode::secondaryEditStartDrag (osg::ref_ptr<TagBase> tag)
{
if (mLocked)
return false;
return false;
}
void CSVRender::InstanceMode::drag (int diffX, int diffY, double speedFactor)
{
osg::Vec3f eye;
osg::Vec3f centre;
osg::Vec3f up;
getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up);
osg::Vec3f offset;
if (diffY)
offset += up * diffY * speedFactor;
if (diffX)
offset += ((centre-eye) ^ up) * diffX * speedFactor;
switch (mDragMode)
{
case DragMode_Move:
{
if (mDragAxis!=-1)
for (int i=0; i<3; ++i)
if (i!=mDragAxis)
offset[i] = 0;
std::vector<osg::ref_ptr<TagBase> > selection =
getWorldspaceWidget().getEdited (Mask_Reference);
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
iter!=selection.end(); ++iter)
{
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
{
ESM::Position position = objectTag->mObject->getPosition();
for (int i=0; i<3; ++i)
position.pos[i] += offset[i];
objectTag->mObject->setPosition (position.pos);
}
}
break;
}
case DragMode_None: break;
}
}
void CSVRender::InstanceMode::dragCompleted()
{
std::vector<osg::ref_ptr<TagBase> > selection =
getWorldspaceWidget().getEdited (Mask_Reference);
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description;
switch (mDragMode)
{
case DragMode_Move: description = "Move Instances"; break;
case DragMode_None: break;
}
CSMWorld::CommandMacro macro (undoStack, description);
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
iter!=selection.end(); ++iter)
{
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
{
objectTag->mObject->apply (macro);
}
}
mDragMode = DragMode_None;
}
void CSVRender::InstanceMode::dragAborted()
{
getWorldspaceWidget().reset (Mask_Reference);
mDragMode = DragMode_None;
}
void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
{
if (mDragMode==DragMode_Move)
{
osg::Vec3f eye;
osg::Vec3f centre;
osg::Vec3f up;
getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up);
osg::Vec3f offset = centre - eye;
offset.normalize();
offset *= diff * speedFactor;
std::vector<osg::ref_ptr<TagBase> > selection =
getWorldspaceWidget().getEdited (Mask_Reference);
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin());
iter!=selection.end(); ++iter)
{
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
{
ESM::Position position = objectTag->mObject->getPosition();
for (int i=0; i<3; ++i)
position.pos[i] += offset[i];
objectTag->mObject->setPosition (position.pos);
}
}
}
}
void CSVRender::InstanceMode::dragEnterEvent (QDragEnterEvent *event)
{
if (const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData()))
@ -243,11 +435,10 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event)
new CSMWorld::ModifyCommand (cellTable, countIndex, count+1));
}
document.getUndoStack().beginMacro (createCommand->text());
document.getUndoStack().push (createCommand.release());
CSMWorld::CommandMacro macro (document.getUndoStack());
macro.push (createCommand.release());
if (incrementCommand.get())
document.getUndoStack().push (incrementCommand.release());
document.getUndoStack().endMacro();
macro.push (incrementCommand.release());
dropped = true;
}
@ -256,3 +447,15 @@ void CSVRender::InstanceMode::dropEvent (QDropEvent* event)
event->accept();
}
}
int CSVRender::InstanceMode::getSubMode() const
{
return mSubMode ? getSubModeFromId (mSubMode->getCurrentId()) : 0;
}
void CSVRender::InstanceMode::subModeChanged (const std::string& id)
{
mSubModeId = id;
getWorldspaceWidget().abortDrag();
getWorldspaceWidget().setSubMode (getSubModeFromId (id), Mask_Reference);
}

@ -15,8 +15,21 @@ namespace CSVRender
class InstanceMode : public EditMode
{
Q_OBJECT
enum DragMode
{
DragMode_None,
DragMode_Move
};
CSVWidget::SceneToolMode *mSubMode;
std::string mSubModeId;
InstanceSelectionMode *mSelectionMode;
DragMode mDragMode;
int mDragAxis;
bool mLocked;
int getSubModeFromId (const std::string& id) const;
public:
@ -26,6 +39,8 @@ namespace CSVRender
virtual void deactivate (CSVWidget::SceneToolbar *toolbar);
virtual void setEditLock (bool locked);
virtual void primaryEditPressed (osg::ref_ptr<TagBase> tag);
virtual void secondaryEditPressed (osg::ref_ptr<TagBase> tag);
@ -34,9 +49,29 @@ namespace CSVRender
virtual void secondarySelectPressed (osg::ref_ptr<TagBase> tag);
virtual bool primaryEditStartDrag (osg::ref_ptr<TagBase> tag);
virtual bool secondaryEditStartDrag (osg::ref_ptr<TagBase> tag);
virtual void drag (int diffX, int diffY, double speedFactor);
virtual void dragCompleted();
/// \note dragAborted will not be called, if the drag is aborted via changing
/// editing mode
virtual void dragAborted();
virtual void dragWheel (int diff, double speedFactor);
virtual void dragEnterEvent (QDragEnterEvent *event);
virtual void dropEvent (QDropEvent* event);
virtual int getSubMode() const;
private slots:
void subModeChanged (const std::string& id);
};
}

@ -0,0 +1,12 @@
#include "instancemovemode.hpp"
CSVRender::InstanceMoveMode::InstanceMoveMode (QWidget *parent)
: ModeButton (QIcon (QPixmap (":placeholder")),
"Move selected instances"
"<ul><li>Use primary edit to move instances around freely</li>"
"<li>Use secondary edit to move instances around within the grid</li>"
"</ul>"
"<font color=Red>Grid move not implemented yet</font color>",
parent)
{}

@ -0,0 +1,18 @@
#ifndef CSV_RENDER_INSTANCEMOVEMODE_H
#define CSV_RENDER_INSTANCEMOVEMODE_H
#include "../widget/modebutton.hpp"
namespace CSVRender
{
class InstanceMoveMode : public CSVWidget::ModeButton
{
Q_OBJECT
public:
InstanceMoveMode (QWidget *parent = 0);
};
}
#endif

@ -9,12 +9,18 @@
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/PrimitiveSet>
#include <osgFX/Scribe>
#include "../../model/world/data.hpp"
#include "../../model/world/ref.hpp"
#include "../../model/world/refidcollection.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/universalid.hpp"
#include "../../model/world/commandmacro.hpp"
#include "../../model/world/cellcoordinates.hpp"
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/lightutil.hpp>
@ -50,6 +56,11 @@ QString CSVRender::ObjectTag::getToolTip (bool hideBasics) const
}
CSVRender::ObjectMarkerTag::ObjectMarkerTag (Object* object, int axis)
: ObjectTag (object), mAxis (axis)
{}
void CSVRender::Object::clear()
{
}
@ -130,18 +141,20 @@ void CSVRender::Object::adjustTransform()
if (mReferenceId.empty())
return;
const CSMWorld::CellRef& reference = getReference();
ESM::Position position = getPosition();
// position
mBaseNode->setPosition(mForceBaseToZero ? osg::Vec3() : osg::Vec3f(reference.mPos.pos[0], reference.mPos.pos[1], reference.mPos.pos[2]));
mRootNode->setPosition(mForceBaseToZero ? osg::Vec3() : osg::Vec3f(position.pos[0], position.pos[1], position.pos[2]));
// orientation
osg::Quat xr (-reference.mPos.rot[0], osg::Vec3f(1,0,0));
osg::Quat yr (-reference.mPos.rot[1], osg::Vec3f(0,1,0));
osg::Quat zr (-reference.mPos.rot[2], osg::Vec3f(0,0,1));
osg::Quat xr (-position.rot[0], osg::Vec3f(1,0,0));
osg::Quat yr (-position.rot[1], osg::Vec3f(0,1,0));
osg::Quat zr (-position.rot[2], osg::Vec3f(0,0,1));
mBaseNode->setAttitude(zr*yr*xr);
mBaseNode->setScale(osg::Vec3(reference.mScale, reference.mScale, reference.mScale));
float scale = getScale();
mBaseNode->setScale(osg::Vec3(scale, scale, scale));
}
const CSMWorld::CellRef& CSVRender::Object::getReference() const
@ -152,10 +165,147 @@ const CSMWorld::CellRef& CSVRender::Object::getReference() const
return mData.getReferences().getRecord (mReferenceId).get();
}
void CSVRender::Object::updateMarker()
{
for (int i=0; i<3; ++i)
{
if (mMarker[i])
{
mRootNode->removeChild (mMarker[i]);
mMarker[i] = osg::ref_ptr<osg::Node>();
}
if (mSelected)
{
if (mSubMode==0)
{
mMarker[i] = makeMarker (i);
mMarker[i]->setUserData(new ObjectMarkerTag (this, i));
mRootNode->addChild (mMarker[i]);
}
}
}
}
osg::ref_ptr<osg::Node> CSVRender::Object::makeMarker (int axis)
{
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
const float shaftWidth = 10;
const float shaftBaseLength = 50;
const float headWidth = 30;
const float headLength = 30;
float shaftLength = shaftBaseLength + mBaseNode->getBound().radius();
// shaft
osg::Vec3Array *vertices = new osg::Vec3Array;
for (int i=0; i<2; ++i)
{
float length = i ? shaftLength : 0;
vertices->push_back (getMarkerPosition (-shaftWidth/2, -shaftWidth/2, length, axis));
vertices->push_back (getMarkerPosition (-shaftWidth/2, shaftWidth/2, length, axis));
vertices->push_back (getMarkerPosition (shaftWidth/2, shaftWidth/2, length, axis));
vertices->push_back (getMarkerPosition (shaftWidth/2, -shaftWidth/2, length, axis));
}
// head backside
vertices->push_back (getMarkerPosition (-headWidth/2, -headWidth/2, shaftLength, axis));
vertices->push_back (getMarkerPosition (-headWidth/2, headWidth/2, shaftLength, axis));
vertices->push_back (getMarkerPosition (headWidth/2, headWidth/2, shaftLength, axis));
vertices->push_back (getMarkerPosition (headWidth/2, -headWidth/2, shaftLength, axis));
// head
vertices->push_back (getMarkerPosition (0, 0, shaftLength+headLength, axis));
geometry->setVertexArray (vertices);
osg::DrawElementsUShort *primitives = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0);
// shaft
for (int i=0; i<4; ++i)
{
int i2 = i==3 ? 0 : i+1;
primitives->push_back (i);
primitives->push_back (4+i);
primitives->push_back (i2);
primitives->push_back (4+i);
primitives->push_back (4+i2);
primitives->push_back (i2);
}
// cap
primitives->push_back (0);
primitives->push_back (1);
primitives->push_back (2);
primitives->push_back (2);
primitives->push_back (3);
primitives->push_back (0);
// head, backside
primitives->push_back (0+8);
primitives->push_back (1+8);
primitives->push_back (2+8);
primitives->push_back (2+8);
primitives->push_back (3+8);
primitives->push_back (0+8);
for (int i=0; i<4; ++i)
{
primitives->push_back (12);
primitives->push_back (8+(i==3 ? 0 : i+1));
primitives->push_back (8+i);
}
geometry->addPrimitiveSet (primitives);
osg::Vec4Array *colours = new osg::Vec4Array;
for (int i=0; i<8; ++i)
colours->push_back (osg::Vec4f (axis==0 ? 1.0f : 0.2f, axis==1 ? 1.0f : 0.2f,
axis==2 ? 1.0f : 0.2f, 1.0f));
for (int i=8; i<8+4+1; ++i)
colours->push_back (osg::Vec4f (axis==0 ? 1.0f : 0.0f, axis==1 ? 1.0f : 0.0f,
axis==2 ? 1.0f : 0.0f, 1.0f));
geometry->setColorArray (colours, osg::Array::BIND_PER_VERTEX);
geometry->getOrCreateStateSet()->setMode (GL_LIGHTING, osg::StateAttribute::OFF);
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
geode->addDrawable (geometry);
return geode;
}
osg::Vec3f CSVRender::Object::getMarkerPosition (float x, float y, float z, int axis)
{
switch (axis)
{
case 2: return osg::Vec3f (x, y, z);
case 0: return osg::Vec3f (z, x, y);
case 1: return osg::Vec3f (y, z, x);
default:
throw std::logic_error ("invalid axis for marker geometry");
}
}
CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
const std::string& id, bool referenceable, bool forceBaseToZero)
: mData (data), mBaseNode(0), mSelected(false), mParentNode(parentNode), mResourceSystem(data.getResourceSystem().get()), mForceBaseToZero (forceBaseToZero)
: mData (data), mBaseNode(0), mSelected(false), mParentNode(parentNode), mResourceSystem(data.getResourceSystem().get()), mForceBaseToZero (forceBaseToZero),
mScaleOverride (1), mOverrideFlags (0), mSubMode (-1)
{
mRootNode = new osg::PositionAttitudeTransform;
mBaseNode = new osg::PositionAttitudeTransform;
mBaseNode->addCullCallback(new SceneUtil::LightListCallback);
@ -163,9 +313,11 @@ CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
mBaseNode->setUserData(new ObjectTag(this));
parentNode->addChild(mBaseNode);
mRootNode->addChild (mBaseNode);
mBaseNode->setNodeMask(Mask_Reference);
parentNode->addChild (mRootNode);
mRootNode->setNodeMask(Mask_Reference);
if (referenceable)
{
@ -179,14 +331,14 @@ CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
adjustTransform();
update();
updateMarker();
}
CSVRender::Object::~Object()
{
clear();
mParentNode->removeChild(mBaseNode);
mParentNode->removeChild(mOutline);
mParentNode->removeChild (mRootNode);
}
void CSVRender::Object::setSelected(bool selected)
@ -194,15 +346,17 @@ void CSVRender::Object::setSelected(bool selected)
mSelected = selected;
mOutline->removeChild(mBaseNode);
mParentNode->removeChild(mOutline);
mParentNode->removeChild(mBaseNode);
mRootNode->removeChild(mOutline);
mRootNode->removeChild(mBaseNode);
if (selected)
{
mOutline->addChild(mBaseNode);
mParentNode->addChild(mOutline);
mRootNode->addChild(mOutline);
}
else
mParentNode->addChild(mBaseNode);
mRootNode->addChild(mBaseNode);
updateMarker();
}
bool CSVRender::Object::getSelected() const
@ -221,6 +375,7 @@ bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
{
adjustTransform();
update();
updateMarker();
return true;
}
@ -271,6 +426,7 @@ bool CSVRender::Object::referenceDataChanged (const QModelIndex& topLeft,
references.getData (index, columnIndex).toString().toUtf8().constData();
update();
updateMarker();
}
return true;
@ -293,3 +449,148 @@ osg::ref_ptr<CSVRender::TagBase> CSVRender::Object::getTag() const
{
return static_cast<CSVRender::TagBase *> (mBaseNode->getUserData());
}
bool CSVRender::Object::isEdited() const
{
return mOverrideFlags;
}
void CSVRender::Object::setEdited (int flags)
{
bool discard = mOverrideFlags & ~flags;
int added = flags & ~mOverrideFlags;
mOverrideFlags = flags;
if (added & Override_Position)
for (int i=0; i<3; ++i)
mPositionOverride.pos[i] = getReference().mPos.pos[i];
if (added & Override_Rotation)
for (int i=0; i<3; ++i)
mPositionOverride.rot[i] = getReference().mPos.rot[i];
if (added & Override_Scale)
mScaleOverride = getReference().mScale;
if (discard)
adjustTransform();
}
ESM::Position CSVRender::Object::getPosition() const
{
ESM::Position position = getReference().mPos;
if (mOverrideFlags & Override_Position)
for (int i=0; i<3; ++i)
position.pos[i] = mPositionOverride.pos[i];
if (mOverrideFlags & Override_Rotation)
for (int i=0; i<3; ++i)
position.rot[i] = mPositionOverride.rot[i];
return position;
}
float CSVRender::Object::getScale() const
{
return mOverrideFlags & Override_Scale ? mScaleOverride : getReference().mScale;
}
void CSVRender::Object::setPosition (const float position[3])
{
mOverrideFlags |= Override_Position;
for (int i=0; i<3; ++i)
mPositionOverride.pos[i] = position[i];
adjustTransform();
}
void CSVRender::Object::setRotation (const float rotation[3])
{
mOverrideFlags |= Override_Rotation;
for (int i=0; i<3; ++i)
mPositionOverride.rot[i] = rotation[i];
adjustTransform();
}
void CSVRender::Object::setScale (float scale)
{
mOverrideFlags |= Override_Scale;
mScaleOverride = scale;
adjustTransform();
}
void CSVRender::Object::apply (CSMWorld::CommandMacro& commands)
{
const CSMWorld::RefCollection& collection = mData.getReferences();
QAbstractItemModel *model = mData.getTableModel (CSMWorld::UniversalId::Type_References);
int recordIndex = collection.getIndex (mReferenceId);
if (mOverrideFlags & Override_Position)
{
for (int i=0; i<3; ++i)
{
int column = collection.findColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (
CSMWorld::Columns::ColumnId_PositionXPos+i));
commands.push (new CSMWorld::ModifyCommand (*model,
model->index (recordIndex, column), mPositionOverride.pos[i]));
}
int column = collection.findColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (
CSMWorld::Columns::ColumnId_Cell));
std::pair<int, int> cellIndex = collection.getRecord (recordIndex).get().getCellIndex();
/// \todo figure out worldspace (not important until multiple worldspaces are supported)
std::string cellId = CSMWorld::CellCoordinates (cellIndex).getId ("");
commands.push (new CSMWorld::ModifyCommand (*model,
model->index (recordIndex, column), QString::fromUtf8 (cellId.c_str())));
}
if (mOverrideFlags & Override_Rotation)
{
for (int i=0; i<3; ++i)
{
int column = collection.findColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (
CSMWorld::Columns::ColumnId_PositionXRot+i));
commands.push (new CSMWorld::ModifyCommand (*model,
model->index (recordIndex, column), mPositionOverride.rot[i]));
}
}
if (mOverrideFlags & Override_Scale)
{
int column = collection.findColumnIndex (CSMWorld::Columns::ColumnId_Scale);
commands.push (new CSMWorld::ModifyCommand (*model,
model->index (recordIndex, column), mScaleOverride));
}
mOverrideFlags = 0;
}
void CSVRender::Object::setSubMode (int subMode)
{
if (subMode!=mSubMode)
{
mSubMode = subMode;
updateMarker();
}
}
void CSVRender::Object::reset()
{
mOverrideFlags = 0;
adjustTransform();
updateMarker();
}

@ -8,14 +8,19 @@
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <components/esm/defs.hpp>
#include "tagbase.hpp"
class QModelIndex;
class QUndoStack;
namespace osg
{
class PositionAttitudeTransform;
class Group;
class Node;
class Geode;
}
namespace osgFX
@ -32,6 +37,7 @@ namespace CSMWorld
{
class Data;
struct CellRef;
class CommandMacro;
}
namespace CSVRender
@ -50,18 +56,43 @@ namespace CSVRender
virtual QString getToolTip (bool hideBasics) const;
};
class ObjectMarkerTag : public ObjectTag
{
public:
ObjectMarkerTag (Object* object, int axis);
int mAxis;
};
class Object
{
const CSMWorld::Data& mData;
public:
enum OverrideFlags
{
Override_Position = 1,
Override_Rotation = 2,
Override_Scale = 4
};
private:
CSMWorld::Data& mData;
std::string mReferenceId;
std::string mReferenceableId;
osg::ref_ptr<osg::PositionAttitudeTransform> mRootNode;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
osg::ref_ptr<osgFX::Scribe> mOutline;
bool mSelected;
osg::Group* mParentNode;
Resource::ResourceSystem* mResourceSystem;
bool mForceBaseToZero;
ESM::Position mPositionOverride;
int mScaleOverride;
int mOverrideFlags;
osg::ref_ptr<osg::Node> mMarker[3];
int mSubMode;
/// Not implemented
Object (const Object&);
@ -82,6 +113,12 @@ namespace CSVRender
/// Throws an exception if *this was constructed with referenceable
const CSMWorld::CellRef& getReference() const;
void updateMarker();
osg::ref_ptr<osg::Node> makeMarker (int axis);
osg::Vec3f getMarkerPosition (float x, float y, float z, int axis);
public:
Object (CSMWorld::Data& data, osg::Group *cellNode,
@ -116,6 +153,33 @@ namespace CSVRender
std::string getReferenceableId() const;
osg::ref_ptr<TagBase> getTag() const;
/// Is there currently an editing operation running on this object?
bool isEdited() const;
void setEdited (int flags);
ESM::Position getPosition() const;
float getScale() const;
/// Set override position.
void setPosition (const float position[3]);
/// Set override rotation
void setRotation (const float rotation[3]);
/// Set override scale
void setScale (float scale);
/// Apply override changes via command and end edit mode
void apply (CSMWorld::CommandMacro& commands);
void setSubMode (int subMode);
/// Erase all overrides and restore the visual representation of the object to its
/// true state.
void reset();
};
}

@ -309,10 +309,13 @@ void CSVRender::PagedWorldspaceWidget::addCellToScene (
bool deleted = index==-1 ||
cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted;
Cell *cell = new Cell (mDocument.getData(), mRootNode, coordinates.getId (mWorldspace),
deleted);
std::auto_ptr<Cell> cell (
new Cell (mDocument.getData(), mRootNode, coordinates.getId (mWorldspace),
deleted));
EditMode *editMode = getEditMode();
cell->setSubMode (editMode->getSubMode(), editMode->getInteractionMask());
mCells.insert (std::make_pair (coordinates, cell));
mCells.insert (std::make_pair (coordinates, cell.release()));
}
void CSVRender::PagedWorldspaceWidget::removeCellFromScene (
@ -555,6 +558,37 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::PagedWorldspaceWidget:
return result;
}
std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::PagedWorldspaceWidget::getEdited (
unsigned int elementMask) const
{
std::vector<osg::ref_ptr<CSVRender::TagBase> > result;
for (std::map<CSMWorld::CellCoordinates, Cell *>::const_iterator iter = mCells.begin();
iter!=mCells.end(); ++iter)
{
std::vector<osg::ref_ptr<CSVRender::TagBase> > cellResult =
iter->second->getEdited (elementMask);
result.insert (result.end(), cellResult.begin(), cellResult.end());
}
return result;
}
void CSVRender::PagedWorldspaceWidget::setSubMode (int subMode, unsigned int elementMask)
{
for (std::map<CSMWorld::CellCoordinates, Cell *>::const_iterator iter = mCells.begin();
iter!=mCells.end(); ++iter)
iter->second->setSubMode (subMode, elementMask);
}
void CSVRender::PagedWorldspaceWidget::reset (unsigned int elementMask)
{
for (std::map<CSMWorld::CellCoordinates, Cell *>::const_iterator iter = mCells.begin();
iter!=mCells.end(); ++iter)
iter->second->reset (elementMask);
}
CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector (
CSVWidget::SceneToolbar *parent)
{

@ -112,6 +112,14 @@ namespace CSVRender
virtual std::vector<osg::ref_ptr<TagBase> > getSelection (unsigned int elementMask)
const;
virtual std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask)
const;
virtual void setSubMode (int subMode, unsigned int elementMask);
/// Erase all overrides and restore the visual representation to its true state.
virtual void reset (unsigned int elementMask);
protected:
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool);

@ -120,6 +120,12 @@ bool RenderWidget::eventFilter(QObject* obj, QEvent* event)
return QObject::eventFilter(obj, event);
}
osg::Camera *RenderWidget::getCamera()
{
return mView->getCamera();
}
// --------------------------------------------------
CompositeViewer::CompositeViewer()

@ -21,6 +21,7 @@ namespace Resource
namespace osg
{
class Group;
class Camera;
}
namespace CSVWidget
@ -47,6 +48,8 @@ namespace CSVRender
bool eventFilter(QObject *, QEvent *);
osg::Camera *getCamera();
protected:
osg::ref_ptr<osgViewer::View> mView;

@ -131,6 +131,22 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::UnpagedWorldspaceWidge
return mCell->getSelection (elementMask);
}
std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::UnpagedWorldspaceWidget::getEdited (
unsigned int elementMask) const
{
return mCell->getEdited (elementMask);
}
void CSVRender::UnpagedWorldspaceWidget::setSubMode (int subMode, unsigned int elementMask)
{
mCell->setSubMode (subMode, elementMask);
}
void CSVRender::UnpagedWorldspaceWidget::reset (unsigned int elementMask)
{
mCell->reset (elementMask);
}
void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{

@ -60,6 +60,14 @@ namespace CSVRender
virtual std::vector<osg::ref_ptr<TagBase> > getSelection (unsigned int elementMask)
const;
virtual std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask)
const;
virtual void setSubMode (int subMode, unsigned int elementMask);
/// Erase all overrides and restore the visual representation to its true state.
virtual void reset (unsigned int elementMask);
private:
virtual void referenceableDataChanged (const QModelIndex& topLeft,

@ -364,6 +364,18 @@ osg::Vec3f CSVRender::WorldspaceWidget::getIntersectionPoint (const QPoint& loca
return start + direction * CSMPrefs::get()["Scene Drops"]["distance"].toInt();
}
void CSVRender::WorldspaceWidget::abortDrag()
{
if (mDragging)
{
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
editMode.dragAborted();
mDragging = false;
mDragMode.clear();
}
}
void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event)
{
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
@ -573,6 +585,7 @@ void CSVRender::WorldspaceWidget::editModeChanged (const std::string& id)
{
dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()).setEditLock (mLocked);
mDragging = false;
mDragMode.clear();
}
void CSVRender::WorldspaceWidget::showToolTip()
@ -736,13 +749,7 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event)
{
if(event->key() == Qt::Key_Escape)
{
if (mDragging)
{
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
editMode.dragAborted();
mDragging = false;
}
abortDrag();
}
else
RenderWidget::keyPressEvent(event);
@ -761,3 +768,8 @@ void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr<TagBase> tag, c
else if (button=="s-select")
editMode.secondarySelectPressed (tag);
}
CSVRender::EditMode *CSVRender::WorldspaceWidget::getEditMode()
{
return dynamic_cast<CSVRender::EditMode *> (mEditMode->getCurrent());
}

@ -35,6 +35,7 @@ namespace CSVRender
{
class TagBase;
class CellArrow;
class EditMode;
class WorldspaceWidget : public SceneWidget
{
@ -152,6 +153,20 @@ namespace CSVRender
virtual std::vector<osg::ref_ptr<TagBase> > getSelection (unsigned int elementMask)
const = 0;
virtual std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask)
const = 0;
virtual void setSubMode (int subMode, unsigned int elementMask) = 0;
/// Erase all overrides and restore the visual representation to its true state.
virtual void reset (unsigned int elementMask) = 0;
/// \note Drags will be automatically aborted when the aborting is triggered
/// (either explicitly or implicitly) from within this class. This function only
/// needs to be called, when the drag abort is triggered externally (e.g. from
/// an edit mode).
void abortDrag();
protected:
/// Visual elements in a scene
@ -181,6 +196,8 @@ namespace CSVRender
virtual void handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button,
bool shift);
EditMode *getEditMode();
private:
void dragEnterEvent(QDragEnterEvent *event);

@ -38,6 +38,27 @@ void CSVWidget::SceneToolMode::adjustToolTip (const ModeButton *activeMode)
setToolTip (toolTip);
}
void CSVWidget::SceneToolMode::setButton (std::map<ModeButton *, std::string>::iterator iter)
{
for (std::map<ModeButton *, std::string>::const_iterator iter2 = mButtons.begin();
iter2!=mButtons.end(); ++iter2)
iter2->first->setChecked (iter2==iter);
setIcon (iter->first->icon());
adjustToolTip (iter->first);
if (mCurrent!=iter->first)
{
if (mCurrent)
mCurrent->deactivate (mToolbar);
mCurrent = iter->first;
mCurrent->activate (mToolbar);
}
emit modeChanged (iter->second);
}
CSVWidget::SceneToolMode::SceneToolMode (SceneToolbar *parent, const QString& toolTip)
: SceneTool (parent), mButtonSize (parent->getButtonSize()), mIconSize (parent->getIconSize()),
mToolTip (toolTip), mFirst (0), mCurrent (0), mToolbar (parent)
@ -96,9 +117,25 @@ CSVWidget::ModeButton *CSVWidget::SceneToolMode::getCurrent()
return mCurrent;
}
std::string CSVWidget::SceneToolMode::getCurrentId() const
{
return mButtons.find (mCurrent)->second;
}
void CSVWidget::SceneToolMode::setButton (const std::string& id)
{
for (std::map<ModeButton *, std::string>::iterator iter = mButtons.begin();
iter!=mButtons.end(); ++iter)
if (iter->second==id)
{
setButton (iter);
break;
}
}
void CSVWidget::SceneToolMode::selected()
{
std::map<ModeButton *, std::string>::const_iterator iter =
std::map<ModeButton *, std::string>::iterator iter =
mButtons.find (dynamic_cast<ModeButton *> (sender()));
if (iter!=mButtons.end())
@ -106,22 +143,6 @@ void CSVWidget::SceneToolMode::selected()
if (!iter->first->hasKeepOpen())
mPanel->hide();
for (std::map<ModeButton *, std::string>::const_iterator iter2 = mButtons.begin();
iter2!=mButtons.end(); ++iter2)
iter2->first->setChecked (iter2==iter);
setIcon (iter->first->icon());
adjustToolTip (iter->first);
if (mCurrent!=iter->first)
{
if (mCurrent)
mCurrent->deactivate (mToolbar);
mCurrent = iter->first;
mCurrent->activate (mToolbar);
}
emit modeChanged (iter->second);
setButton (iter);
}
}

@ -41,6 +41,8 @@ namespace CSVWidget
/// items to be added, the function must return true anyway.
virtual bool createContextMenu (QMenu *menu);
void setButton (std::map<ModeButton *, std::string>::iterator iter);
public:
SceneToolMode (SceneToolbar *parent, const QString& toolTip);
@ -56,6 +58,12 @@ namespace CSVWidget
/// Will return a 0-pointer only if the mode does not have any buttons yet.
ModeButton *getCurrent();
/// Must not be called if there aren't any buttons yet.
std::string getCurrentId() const;
/// Manually change the current mode
void setButton (const std::string& id);
signals:
void modeChanged (const std::string& id);

@ -9,6 +9,7 @@
#include "../../model/world/columns.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/idcompletionmanager.hpp"
#include "../../model/world/commandmacro.hpp"
#include "../widget/droplineedit.hpp"
@ -53,10 +54,9 @@ void CSVWorld::ReferenceCreator::pushCommand (std::auto_ptr<CSMWorld::CreateComm
std::auto_ptr<CSMWorld::ModifyCommand> increment (new CSMWorld::ModifyCommand
(cellTable, countIndex, count+1));
getUndoStack().beginMacro (command->text());
CSMWorld::CommandMacro macro (getUndoStack(), command->text());
GenericCreator::pushCommand (command, id);
getUndoStack().push (increment.release());
getUndoStack().endMacro();
macro.push (increment.release());
}
int CSVWorld::ReferenceCreator::getRefNumCount() const
@ -147,11 +147,11 @@ void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId,
cellChanged(); //otherwise ok button will remain disabled
}
CSVWorld::Creator *CSVWorld::ReferenceCreatorFactory::makeCreator (CSMDoc::Document& document,
CSVWorld::Creator *CSVWorld::ReferenceCreatorFactory::makeCreator (CSMDoc::Document& document,
const CSMWorld::UniversalId& id) const
{
return new ReferenceCreator(document.getData(),
document.getUndoStack(),
return new ReferenceCreator(document.getData(),
document.getUndoStack(),
id,
document.getIdCompletionManager());
}

@ -17,6 +17,7 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/world/commandmacro.hpp"
void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event)
{
@ -159,8 +160,7 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId)
QString regionId2 = QString::fromUtf8 (regionId.c_str());
if (selected.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Set Region"));
CSMWorld::CommandMacro macro (mDocument.getUndoStack(), selected.size()>1 ? tr ("Set Region") : "");
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
@ -170,12 +170,8 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId)
QModelIndex index = cellsModel->getModelIndex (cellId,
cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region));
mDocument.getUndoStack().push (
new CSMWorld::ModifyCommand (*cellsModel, index, regionId2));
macro.push (new CSMWorld::ModifyCommand (*cellsModel, index, regionId2));
}
if (selected.size()>1)
mDocument.getUndoStack().endMacro();
}
CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
@ -258,19 +254,15 @@ void CSVWorld::RegionMap::createCells()
CSMWorld::IdTable *cellsModel = &dynamic_cast<CSMWorld::IdTable&> (*
mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
if (selected.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Create cells"));
CSMWorld::CommandMacro macro (mDocument.getUndoStack(), selected.size()>1 ? tr ("Create cells"): "");
for (QModelIndexList::const_iterator iter (selected.begin()); iter!=selected.end(); ++iter)
{
std::string cellId = model()->data (*iter, CSMWorld::RegionMap::Role_CellId).
toString().toUtf8().constData();
mDocument.getUndoStack().push (new CSMWorld::CreateCommand (*cellsModel, cellId));
macro.push (new CSMWorld::CreateCommand (*cellsModel, cellId));
}
if (selected.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSVWorld::RegionMap::setRegion()

@ -4,6 +4,7 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/commandmacro.hpp"
void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QModelIndex& index, int type)
const
@ -36,13 +37,10 @@ void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QM
default: break; // ignore the rest
}
getUndoStack().beginMacro (
"Modify " + model->headerData (index.column(), Qt::Horizontal, Qt::DisplayRole).toString());
CSMWorld::CommandMacro macro (getUndoStack(), "Modify " + model->headerData (index.column(), Qt::Horizontal, Qt::DisplayRole).toString());
getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, type));
getUndoStack().push (new CSMWorld::ModifyCommand (*model, next, value));
getUndoStack().endMacro();
macro.push (new CSMWorld::ModifyCommand (*model, index, type));
macro.push (new CSMWorld::ModifyCommand (*model, next, value));
}
CSVWorld::VarTypeDelegate::VarTypeDelegate (const std::vector<std::pair<int, QString> >& values,

Loading…
Cancel
Save