Merge branch 'marker'

openmw-37
Marc Zinnschlag 9 years ago
commit 6c65081643

@ -90,7 +90,7 @@ opencs_units (view/render
opencs_units_noqt (view/render
lighting lightingday lightingnight
lightingbright object cell terrainstorage tagbase
lightingbright object cell terrainstorage tagbase cellarrow
)
opencs_hdrs_noqt (view/render

@ -32,6 +32,23 @@ std::string CSMWorld::CellCoordinates::getId (const std::string& worldspace) con
return stream.str();
}
std::pair<CSMWorld::CellCoordinates, bool> CSMWorld::CellCoordinates::fromId (
const std::string& id)
{
// no worldspace for now, needs to be changed for 1.1
if (!id.empty() && id[0]=='#')
{
int x, y;
char ignore;
std::istringstream stream (id);
if (stream >> ignore >> x >> y)
return std::make_pair (CellCoordinates (x, y), true);
}
return std::make_pair (CellCoordinates(), false);
}
bool CSMWorld::operator== (const CellCoordinates& left, const CellCoordinates& right)
{
return left.getX()==right.getX() && left.getY()==right.getY();

@ -28,6 +28,12 @@ namespace CSMWorld
std::string getId (const std::string& worldspace) const;
///< Return the ID for the cell at these coordinates.
/// \return first: CellCoordinates (or 0, 0 if cell does not have coordinates),
/// second: is cell paged?
///
/// \note The worldspace part of \a id is ignored
static std::pair<CellCoordinates, bool> fromId (const std::string& id);
};
bool operator== (const CellCoordinates& left, const CellCoordinates& right);

@ -9,6 +9,7 @@
#include "../../model/world/columns.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/refcollection.hpp"
#include "../../model/world/cellcoordinates.hpp"
#include "elements.hpp"
#include "terrainstorage.hpp"
@ -50,33 +51,39 @@ bool CSVRender::Cell::addObjects (int start, int end)
return modified;
}
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mX(0), mY(0)
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
bool deleted)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted)
{
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
if (result.second)
mCoordinates = result.first;
mCellNode = new osg::Group;
rootNode->addChild(mCellNode);
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
int rows = references.rowCount();
if (!mDeleted)
{
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
addObjects (0, rows-1);
int rows = references.rowCount();
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
int landIndex = land.searchId(mId);
if (landIndex != -1)
{
const ESM::Land& esmLand = land.getRecord(mId).get();
addObjects (0, rows-1);
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
int landIndex = land.searchId(mId);
if (landIndex != -1)
{
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Element_Terrain<<1));
mTerrain->loadCell(esmLand.mX,
esmLand.mY);
const ESM::Land& esmLand = land.getRecord(mId).get();
mX = esmLand.mX;
mY = esmLand.mY;
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
{
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Element_Terrain<<1));
mTerrain->loadCell(esmLand.mX,
esmLand.mY);
}
}
}
}
@ -122,6 +129,9 @@ bool CSVRender::Cell::referenceableAboutToBeRemoved (const QModelIndex& parent,
bool CSVRender::Cell::referenceDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
if (mDeleted)
return false;
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
@ -189,6 +199,9 @@ bool CSVRender::Cell::referenceAboutToBeRemoved (const QModelIndex& parent, int
if (parent.isValid())
return false;
if (mDeleted)
return false;
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
@ -209,6 +222,9 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
if (parent.isValid())
return false;
if (mDeleted)
return false;
return addObjects (start, end);
}
@ -232,3 +248,31 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode)
}
}
}
void CSVRender::Cell::setCellArrows (int mask)
{
for (int i=0; i<4; ++i)
{
CellArrow::Direction direction = static_cast<CellArrow::Direction> (1<<i);
bool enable = mask & direction;
if (enable!=(mCellArrows[i].get()!=0))
{
if (enable)
mCellArrows[i].reset (new CellArrow (mCellNode, direction, mCoordinates));
else
mCellArrows[i].reset (0);
}
}
}
CSMWorld::CellCoordinates CSVRender::Cell::getCoordinates() const
{
return mCoordinates;
}
bool CSVRender::Cell::isDeleted() const
{
return mDeleted;
}

@ -14,6 +14,7 @@
#endif
#include "object.hpp"
#include "cellarrow.hpp"
class QModelIndex;
@ -25,6 +26,7 @@ namespace osg
namespace CSMWorld
{
class Data;
class CellCoordinates;
}
namespace CSVRender
@ -36,8 +38,9 @@ namespace CSVRender
osg::ref_ptr<osg::Group> mCellNode;
std::map<std::string, Object *> mObjects;
std::auto_ptr<Terrain::TerrainGrid> mTerrain;
int mX;
int mY;
CSMWorld::CellCoordinates mCoordinates;
std::auto_ptr<CellArrow> mCellArrows[4];
bool mDeleted;
/// Ignored if cell does not have an object with the given ID.
///
@ -60,7 +63,10 @@ namespace CSVRender
public:
Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id);
/// \note Deleted covers both cells that are deleted and cells that don't exist in
/// the first place.
Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
bool deleted = false);
~Cell();
@ -86,6 +92,13 @@ namespace CSVRender
bool referenceAdded (const QModelIndex& parent, int start, int end);
void setSelection (int elementMask, Selection mode);
void setCellArrows (int mask);
/// Returns 0, 0 in case of an unpaged cell.
CSMWorld::CellCoordinates getCoordinates() const;
bool isDeleted() const;
};
}

@ -0,0 +1,161 @@
#include "cellarrow.hpp"
#include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/PrimitiveSet>
#include "elements.hpp"
CSVRender::CellArrowTag::CellArrowTag (CellArrow *arrow)
: TagBase (Element_CellArrow), mArrow (arrow)
{}
CSVRender::CellArrow *CSVRender::CellArrowTag::getCellArrow() const
{
return mArrow;
}
void CSVRender::CellArrow::adjustTransform()
{
// position
const int cellSize = 8192;
const int offset = cellSize / 2 + 800;
int x = mCoordinates.getX()*cellSize + cellSize/2;
int y = mCoordinates.getY()*cellSize + cellSize/2;
float xr = 0;
float yr = 0;
float zr = 0;
float angle = osg::DegreesToRadians (90.0f);
switch (mDirection)
{
case Direction_North: y += offset; xr = -angle; zr = angle; break;
case Direction_West: x -= offset; yr = -angle; break;
case Direction_South: y -= offset; xr = angle; zr = angle; break;
case Direction_East: x += offset; yr = angle; break;
};
mBaseNode->setPosition (osg::Vec3f (x, y, 0));
// orientation
osg::Quat xr2 (xr, osg::Vec3f (1,0,0));
osg::Quat yr2 (yr, osg::Vec3f (0,1,0));
osg::Quat zr2 (zr, osg::Vec3f (0,0,1));
mBaseNode->setAttitude (zr2*yr2*xr2);
}
void CSVRender::CellArrow::buildShape()
{
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
const int arrowWidth = 4000;
const int arrowLength = 1500;
const int arrowHeight = 500;
osg::Vec3Array *vertices = new osg::Vec3Array;
for (int i2=0; i2<2; ++i2)
for (int i=0; i<2; ++i)
{
float height = i ? -arrowHeight/2 : arrowHeight/2;
vertices->push_back (osg::Vec3f (height, -arrowWidth/2, 0));
vertices->push_back (osg::Vec3f (height, arrowWidth/2, 0));
vertices->push_back (osg::Vec3f (height, 0, arrowLength));
}
geometry->setVertexArray (vertices);
osg::DrawElementsUShort *primitives = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0);
// top
primitives->push_back (0);
primitives->push_back (1);
primitives->push_back (2);
// bottom
primitives->push_back (5);
primitives->push_back (4);
primitives->push_back (3);
// back
primitives->push_back (3+6);
primitives->push_back (4+6);
primitives->push_back (1+6);
primitives->push_back (3+6);
primitives->push_back (1+6);
primitives->push_back (0+6);
// sides
primitives->push_back (0+6);
primitives->push_back (2+6);
primitives->push_back (5+6);
primitives->push_back (0+6);
primitives->push_back (5+6);
primitives->push_back (3+6);
primitives->push_back (4+6);
primitives->push_back (5+6);
primitives->push_back (2+6);
primitives->push_back (4+6);
primitives->push_back (2+6);
primitives->push_back (1+6);
geometry->addPrimitiveSet (primitives);
osg::Vec4Array *colours = new osg::Vec4Array;
for (int i=0; i<6; ++i)
colours->push_back (osg::Vec4f (1.0f, 0.0f, 0.0f, 1.0f));
for (int i=0; i<6; ++i)
colours->push_back (osg::Vec4f (0.8f, (i==2 || i==5) ? 0.6f : 0.4f, 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);
mBaseNode->addChild (geode);
}
CSVRender::CellArrow::CellArrow (osg::Group *cellNode, Direction direction,
const CSMWorld::CellCoordinates& coordinates)
: mDirection (direction), mParentNode (cellNode), mCoordinates (coordinates)
{
mBaseNode = new osg::PositionAttitudeTransform;
mBaseNode->setUserData (new CellArrowTag (this));
mParentNode->addChild (mBaseNode);
// 0x1 reserved for separating cull and update visitors
mBaseNode->setNodeMask (Element_CellArrow<<1);
adjustTransform();
buildShape();
}
CSVRender::CellArrow::~CellArrow()
{
mParentNode->removeChild (mBaseNode);
}
CSMWorld::CellCoordinates CSVRender::CellArrow::getCoordinates() const
{
return mCoordinates;
}
CSVRender::CellArrow::Direction CSVRender::CellArrow::getDirection() const
{
return mDirection;
}

@ -0,0 +1,72 @@
#ifndef OPENCS_VIEW_CELLARROW_H
#define OPENCS_VIEW_CELLARROW_H
#include "tagbase.hpp"
#include <osg/ref_ptr>
#include "../../model/world/cellcoordinates.hpp"
namespace osg
{
class PositionAttitudeTransform;
class Group;
}
namespace CSVRender
{
class CellArrow;
class CellArrowTag : public TagBase
{
CellArrow *mArrow;
public:
CellArrowTag (CellArrow *arrow);
CellArrow *getCellArrow() const;
};
class CellArrow
{
public:
enum Direction
{
Direction_North = 1,
Direction_West = 2,
Direction_South = 4,
Direction_East = 8
};
private:
// not implemented
CellArrow (const CellArrow&);
CellArrow& operator= (const CellArrow&);
Direction mDirection;
osg::Group* mParentNode;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
CSMWorld::CellCoordinates mCoordinates;
void adjustTransform();
void buildShape();
public:
CellArrow (osg::Group *cellNode, Direction direction,
const CSMWorld::CellCoordinates& coordinates);
~CellArrow();
CSMWorld::CellCoordinates getCoordinates() const;
Direction getDirection() const;
};
}
#endif

@ -1,8 +1,10 @@
#include "pagedworldspacewidget.hpp"
#include <memory>
#include <sstream>
#include <QMouseEvent>
#include <QApplication>
#include <osgGA/TrackballManipulator>
@ -21,20 +23,19 @@
bool CSVRender::PagedWorldspaceWidget::adjustCells()
{
bool modified = false;
bool wasEmpty = mCells.empty();
const CSMWorld::IdCollection<CSMWorld::Cell>& cells = mDocument.getData().getCells();
{
// remove (or name/region modified)
// remove/update
std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter (mCells.begin());
while (iter!=mCells.end())
{
int index = cells.searchId (iter->first.getId (mWorldspace));
if (!mSelection.has (iter->first) || index==-1 ||
cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted)
if (!mSelection.has (iter->first))
{
// remove
delete iter->second;
mCells.erase (iter++);
@ -42,12 +43,33 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
}
else
{
// check if name or region field has changed
// FIXME: config setting
//std::string name = cells.getRecord(index).get().mName;
//std::string region = cells.getRecord(index).get().mRegion;
// update
int index = cells.searchId (iter->first.getId (mWorldspace));
bool deleted = index==-1 ||
cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted;
if (deleted!=iter->second->isDeleted())
{
modified = true;
std::auto_ptr<Cell> cell (new Cell (mDocument.getData(), mRootNode,
iter->first.getId (mWorldspace), deleted));
// cell marker update goes here
delete iter->second;
iter->second = cell.release();
}
else if (!deleted)
{
// delete state has not changed -> just update
// TODO check if name or region field has changed (cell marker)
// FIXME: config setting
//std::string name = cells.getRecord(index).get().mName;
//std::string region = cells.getRecord(index).get().mRegion;
modified = true;
}
++iter;
}
@ -58,20 +80,43 @@ bool CSVRender::PagedWorldspaceWidget::adjustCells()
for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end();
++iter)
{
int index = cells.searchId (iter->getId (mWorldspace));
if (index > 0 && cells.getRecord (index).mState!=CSMWorld::RecordBase::State_Deleted &&
mCells.find (*iter)==mCells.end())
if (mCells.find (*iter)==mCells.end())
{
Cell *cell = new Cell (mDocument.getData(), mRootNode,
iter->getId (mWorldspace));
mCells.insert (std::make_pair (*iter, cell));
addCellToScene (*iter);
modified = true;
}
}
if (modified)
{
for (std::map<CSMWorld::CellCoordinates, Cell *>::const_iterator iter (mCells.begin());
iter!=mCells.end(); ++iter)
{
int mask = 0;
for (int i=CellArrow::Direction_North; i<=CellArrow::Direction_East; i *= 2)
{
CSMWorld::CellCoordinates coordinates (iter->second->getCoordinates());
switch (i)
{
case CellArrow::Direction_North: coordinates = coordinates.move (0, 1); break;
case CellArrow::Direction_West: coordinates = coordinates.move (-1, 0); break;
case CellArrow::Direction_South: coordinates = coordinates.move (0, -1); break;
case CellArrow::Direction_East: coordinates = coordinates.move (1, 0); break;
}
if (!mSelection.has (coordinates))
mask |= i;
}
iter->second->setCellArrows (mask);
}
}
/// \todo do not overwrite manipulator object
/// \todo move code to useViewHint function
if (modified && wasEmpty)
mView->setCameraManipulator(new osgGA::TrackballManipulator);
return modified;
@ -105,6 +150,76 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons (
"terrain-move");
}
void CSVRender::PagedWorldspaceWidget::handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button)
{
if (tag && tag->getElement()==Element_CellArrow)
{
if (button=="p-edit" || button=="s-edit")
{
if (CellArrowTag *cellArrowTag =
dynamic_cast<CSVRender::CellArrowTag *> (tag.get()))
{
CellArrow *arrow = cellArrowTag->getCellArrow();
CSMWorld::CellCoordinates coordinates = arrow->getCoordinates();
CellArrow::Direction direction = arrow->getDirection();
int x = 0;
int y = 0;
switch (direction)
{
case CellArrow::Direction_North: y = 1; break;
case CellArrow::Direction_West: x = -1; break;
case CellArrow::Direction_South: y = -1; break;
case CellArrow::Direction_East: x = 1; break;
}
bool modified = false;
if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
{
if (button=="p-edit")
addCellSelection (x, y);
else
moveCellSelection (x, y);
modified = true;
}
else
{
CSMWorld::CellCoordinates newCoordinates = coordinates.move (x, y);
if (mCells.find (newCoordinates)==mCells.end())
{
addCellToScene (newCoordinates);
mSelection.add (newCoordinates);
modified = true;
}
if (button=="s-edit")
{
if (mCells.find (coordinates)!=mCells.end())
{
removeCellFromScene (coordinates);
mSelection.remove (coordinates);
modified = true;
}
}
}
if (modified)
adjustCells();
return;
}
}
}
WorldspaceWidget::handleMouseClick (tag, button);
}
void CSVRender::PagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
@ -184,6 +299,72 @@ std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
return stream.str();
}
void CSVRender::PagedWorldspaceWidget::addCellToScene (
const CSMWorld::CellCoordinates& coordinates)
{
const CSMWorld::IdCollection<CSMWorld::Cell>& cells = mDocument.getData().getCells();
int index = cells.searchId (coordinates.getId (mWorldspace));
bool deleted = index==-1 ||
cells.getRecord (index).mState==CSMWorld::RecordBase::State_Deleted;
Cell *cell = new Cell (mDocument.getData(), mRootNode, coordinates.getId (mWorldspace),
deleted);
mCells.insert (std::make_pair (coordinates, cell));
}
void CSVRender::PagedWorldspaceWidget::removeCellFromScene (
const CSMWorld::CellCoordinates& coordinates)
{
std::map<CSMWorld::CellCoordinates, Cell *>::iterator iter = mCells.find (coordinates);
if (iter!=mCells.end())
{
delete iter->second;
mCells.erase (iter);
}
}
void CSVRender::PagedWorldspaceWidget::addCellSelection (int x, int y)
{
CSMWorld::CellSelection newSelection = mSelection;
newSelection.move (x, y);
for (CSMWorld::CellSelection::Iterator iter (newSelection.begin()); iter!=newSelection.end();
++iter)
{
if (mCells.find (*iter)==mCells.end())
{
addCellToScene (*iter);
mSelection.add (*iter);
}
}
}
void CSVRender::PagedWorldspaceWidget::moveCellSelection (int x, int y)
{
CSMWorld::CellSelection newSelection = mSelection;
newSelection.move (x, y);
for (CSMWorld::CellSelection::Iterator iter (mSelection.begin()); iter!=mSelection.end();
++iter)
{
if (!newSelection.has (*iter))
removeCellFromScene (*iter);
}
for (CSMWorld::CellSelection::Iterator iter (newSelection.begin()); iter!=newSelection.end();
++iter)
{
if (!mSelection.has (*iter))
addCellToScene (*iter);
}
mSelection = newSelection;
}
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
: WorldspaceWidget (document, parent), mDocument (document), mWorldspace ("std::default"),
mControlElements(NULL), mDisplayCellCoord(true)

@ -53,6 +53,20 @@ namespace CSVRender
virtual std::string getStartupInstruction();
/// \note Does not update the view or any cell marker
void addCellToScene (const CSMWorld::CellCoordinates& coordinates);
/// \note Does not update the view or any cell marker
///
/// \note Calling this function for a cell that is not in the selection is a no-op.
void removeCellFromScene (const CSMWorld::CellCoordinates& coordinates);
/// \note Does not update the view or any cell marker
void addCellSelection (int x, int y);
/// \note Does not update the view or any cell marker
void moveCellSelection (int x, int y);
public:
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
@ -88,6 +102,8 @@ namespace CSVRender
virtual void addEditModeSelectorButtons (CSVWidget::SceneToolMode *tool);
virtual void handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button);
signals:
void cellSelectionChanged (const CSMWorld::CellSelection& selection);

@ -574,14 +574,7 @@ void CSVRender::WorldspaceWidget::mousePressEvent (QMouseEvent *event)
{
osg::ref_ptr<TagBase> tag = mousePick (event);
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
if (button=="p-edit")
editMode.primaryEditPressed (tag);
else if (button=="s-edit")
editMode.secondaryEditPressed (tag);
else if (button=="select")
editMode.selectPressed (tag);
handleMouseClick (tag, button);
}
}
@ -650,3 +643,15 @@ void CSVRender::WorldspaceWidget::keyPressEvent (QKeyEvent *event)
else
RenderWidget::keyPressEvent(event);
}
void CSVRender::WorldspaceWidget::handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button)
{
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
if (button=="p-edit")
editMode.primaryEditPressed (tag);
else if (button=="s-edit")
editMode.secondaryEditPressed (tag);
else if (button=="select")
editMode.selectPressed (tag);
}

@ -27,6 +27,7 @@ namespace CSVWidget
namespace CSVRender
{
class TagBase;
class CellArrow;
class WorldspaceWidget : public SceneWidget
{
@ -132,6 +133,8 @@ namespace CSVRender
virtual void wheelEvent (QWheelEvent *event);
virtual void keyPressEvent (QKeyEvent *event);
virtual void handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button);
private:
void dragEnterEvent(QDragEnterEvent *event);

Loading…
Cancel
Save