1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-15 09:39:53 +00:00

render marker

This commit is contained in:
Marc Zinnschlag 2016-03-01 15:48:34 +01:00
parent 6f619ea85f
commit a19ac72215
16 changed files with 278 additions and 6 deletions

View File

@ -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);
@ -359,3 +365,14 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getEdited (unsig
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);
}

View File

@ -45,6 +45,8 @@ namespace CSVRender
std::auto_ptr<CellArrow> mCellArrows[4];
std::auto_ptr<CellMarker> mCellMarker;
bool mDeleted;
int mSubMode;
unsigned int mSubModeElementMask;
/// Ignored if cell does not have an object with the given ID.
///
@ -118,6 +120,8 @@ namespace CSVRender
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);
};
}

View File

@ -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;
}

View File

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

View File

@ -20,6 +20,11 @@
#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), mDragMode (DragMode_None)
@ -44,6 +49,9 @@ 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>");
connect (mSubMode, SIGNAL (modeChanged (const std::string&)),
this, SLOT (subModeChanged (const std::string&)));
}
if (!mSelectionMode)
@ -55,6 +63,10 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *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)
@ -402,3 +414,13 @@ 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)
{
getWorldspaceWidget().setSubMode (getSubModeFromId (id), Mask_Reference);
}

View File

@ -27,6 +27,8 @@ namespace CSVRender
InstanceSelectionMode *mSelectionMode;
DragMode mDragMode;
int getSubModeFromId (const std::string& id) const;
public:
InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0);
@ -56,6 +58,12 @@ namespace CSVRender
virtual void dragEnterEvent (QDragEnterEvent *event);
virtual void dropEvent (QDropEvent* event);
virtual int getSubMode() const;
private slots:
void subModeChanged (const std::string& id);
};
}

View File

@ -9,6 +9,8 @@
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/PrimitiveSet>
#include <osgFX/Scribe>
@ -52,6 +54,11 @@ QString CSVRender::ObjectTag::getToolTip (bool hideBasics) const
}
CSVRender::ObjectMarkerTag::ObjectMarkerTag (Object* object, int axis)
: TagBase (Mask_Reference), mObject (object), mAxis (axis)
{}
void CSVRender::Object::clear()
{
}
@ -156,10 +163,144 @@ 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 0: return osg::Vec3f (x, y, z);
case 1: return osg::Vec3f (z, x, y);
case 2: 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),
mScaleOverride (1), mOverrideFlags (0)
mScaleOverride (1), mOverrideFlags (0), mSubMode (-1)
{
mRootNode = new osg::PositionAttitudeTransform;
@ -188,6 +329,7 @@ CSVRender::Object::Object (CSMWorld::Data& data, osg::Group* parentNode,
adjustTransform();
update();
updateMarker();
}
CSVRender::Object::~Object()
@ -211,6 +353,8 @@ void CSVRender::Object::setSelected(bool selected)
}
else
mRootNode->addChild(mBaseNode);
updateMarker();
}
bool CSVRender::Object::getSelected() const
@ -229,6 +373,7 @@ bool CSVRender::Object::referenceableDataChanged (const QModelIndex& topLeft,
{
adjustTransform();
update();
updateMarker();
return true;
}
@ -279,6 +424,7 @@ bool CSVRender::Object::referenceDataChanged (const QModelIndex& topLeft,
references.getData (index, columnIndex).toString().toUtf8().constData();
update();
updateMarker();
}
return true;
@ -419,3 +565,12 @@ void CSVRender::Object::apply (QUndoStack& undoStack)
mOverrideFlags = 0;
}
void CSVRender::Object::setSubMode (int subMode)
{
if (subMode!=mSubMode)
{
mSubMode = subMode;
updateMarker();
}
}

View File

@ -19,6 +19,8 @@ namespace osg
{
class PositionAttitudeTransform;
class Group;
class Node;
class Geode;
}
namespace osgFX
@ -53,6 +55,15 @@ namespace CSVRender
virtual QString getToolTip (bool hideBasics) const;
};
class ObjectMarkerTag : public TagBase
{
public:
ObjectMarkerTag (Object* object, int axis);
Object* mObject;
int mAxis;
};
class Object
{
@ -80,6 +91,8 @@ namespace CSVRender
ESM::Position mPositionOverride;
int mScaleOverride;
int mOverrideFlags;
osg::ref_ptr<osg::Node> mMarker[3];
int mSubMode;
/// Not implemented
Object (const Object&);
@ -100,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,
@ -155,6 +174,8 @@ namespace CSVRender
/// Apply override changes via command and end edit mode
void apply (QUndoStack& undoStack);
void setSubMode (int subMode);
};
}

View File

@ -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 (
@ -572,6 +575,13 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::PagedWorldspaceWidget:
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);
}
CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector (
CSVWidget::SceneToolbar *parent)
{

View File

@ -115,6 +115,8 @@ namespace CSVRender
virtual std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask)
const;
virtual void setSubMode (int subMode, unsigned int elementMask);
protected:
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool);

View File

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

View File

@ -63,6 +63,8 @@ namespace CSVRender
virtual std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask)
const;
virtual void setSubMode (int subMode, unsigned int elementMask);
private:
virtual void referenceableDataChanged (const QModelIndex& topLeft,

View File

@ -761,3 +761,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());
}

View File

@ -35,6 +35,7 @@ namespace CSVRender
{
class TagBase;
class CellArrow;
class EditMode;
class WorldspaceWidget : public SceneWidget
{
@ -155,6 +156,8 @@ namespace CSVRender
virtual std::vector<osg::ref_ptr<TagBase> > getEdited (unsigned int elementMask)
const = 0;
virtual void setSubMode (int subMode, unsigned int elementMask) = 0;
protected:
/// Visual elements in a scene
@ -184,6 +187,8 @@ namespace CSVRender
virtual void handleMouseClick (osg::ref_ptr<TagBase> tag, const std::string& button,
bool shift);
EditMode *getEditMode();
private:
void dragEnterEvent(QDragEnterEvent *event);

View File

@ -96,6 +96,11 @@ CSVWidget::ModeButton *CSVWidget::SceneToolMode::getCurrent()
return mCurrent;
}
std::string CSVWidget::SceneToolMode::getCurrentId() const
{
return mButtons.find (mCurrent)->second;
}
void CSVWidget::SceneToolMode::selected()
{
std::map<ModeButton *, std::string>::const_iterator iter =

View File

@ -56,6 +56,9 @@ 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;
signals:
void modeChanged (const std::string& id);