make scenes drop target for referenceables

drop
Marc Zinnschlag 9 years ago
parent ece40b1e96
commit 7dd7be7f0e

@ -1,8 +1,13 @@
#include "instancemode.hpp"
#include <QDragEnterEvent>
#include "../../model/prefs/state.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/commands.hpp"
#include "elements.hpp"
#include "object.hpp"
#include "worldspacewidget.hpp"
@ -55,3 +60,82 @@ void CSVRender::InstanceMode::secondarySelectPressed (osg::ref_ptr<TagBase> tag)
}
}
}
void CSVRender::InstanceMode::dragEnterEvent (QDragEnterEvent *event)
{
if (const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData()))
{
if (!mime->fromDocument (getWorldspaceWidget().getDocument()))
return;
/// \todo document check
if (mime->holdsType (CSMWorld::UniversalId::Type_Referenceable))
event->accept();
}
}
void CSVRender::InstanceMode::dropEvent (QDropEvent* event)
{
if (const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData()))
{
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
if (!mime->fromDocument (document))
return;
osg::Vec3f insertPoint = getWorldspaceWidget().getIntersectionPoint (event->pos());
std::string cellId = getWorldspaceWidget().getCellId (insertPoint);
bool dropped = false;
std::vector<CSMWorld::UniversalId> ids = mime->getData();
CSMWorld::IdTable& referencesTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_References));
CSMWorld::IdTable& cellTable = dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
for (std::vector<CSMWorld::UniversalId>::const_iterator iter (ids.begin());
iter!=ids.end(); ++iter)
if (mime->isReferencable (iter->getType()))
{
// create reference
std::auto_ptr<CSMWorld::CreateCommand> createCommand (
new CSMWorld::CreateCommand (
referencesTable, document.getData().getReferences().getNewId()));
createCommand->addValue (referencesTable.findColumnIndex (
CSMWorld::Columns::ColumnId_Cell), QString::fromUtf8 (cellId.c_str()));
createCommand->addValue (referencesTable.findColumnIndex (
CSMWorld::Columns::ColumnId_PositionXPos), insertPoint.x());
createCommand->addValue (referencesTable.findColumnIndex (
CSMWorld::Columns::ColumnId_PositionYPos), insertPoint.y());
createCommand->addValue (referencesTable.findColumnIndex (
CSMWorld::Columns::ColumnId_PositionZPos), insertPoint.z());
createCommand->addValue (referencesTable.findColumnIndex (
CSMWorld::Columns::ColumnId_ReferenceableId),
QString::fromUtf8 (iter->getId().c_str()));
// increase reference count in cell
QModelIndex countIndex = cellTable.getModelIndex (cellId,
cellTable.findColumnIndex (CSMWorld::Columns::ColumnId_RefNumCounter));
int count = cellTable.data (countIndex).toInt();
std::auto_ptr<CSMWorld::ModifyCommand> incrementCommand (
new CSMWorld::ModifyCommand (cellTable, countIndex, count+1));
document.getUndoStack().beginMacro (createCommand->text());
document.getUndoStack().push (createCommand.release());
document.getUndoStack().push (incrementCommand.release());
document.getUndoStack().endMacro();
dropped = true;
}
if (dropped)
event->accept();
}
}

@ -20,6 +20,10 @@ namespace CSVRender
virtual void primarySelectPressed (osg::ref_ptr<TagBase> tag);
virtual void secondarySelectPressed (osg::ref_ptr<TagBase> tag);
virtual void dragEnterEvent (QDragEnterEvent *event);
virtual void dropEvent (QDropEvent* event);
};
}

@ -504,6 +504,17 @@ void CSVRender::PagedWorldspaceWidget::clearSelection (int elementMask)
flagAsModified();
}
std::string CSVRender::PagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const
{
const int cellSize = 8192;
CSMWorld::CellCoordinates cellCoordinates (
static_cast<int> (std::floor (point.x()/cellSize)),
static_cast<int> (std::floor (point.y()/cellSize)));
return cellCoordinates.getId (mWorldspace);
}
CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector (
CSVWidget::SceneToolbar *parent)
{

@ -96,6 +96,8 @@ namespace CSVRender
/// \param elementMask Elements to be affected by the clear operation
virtual void clearSelection (int elementMask);
virtual std::string getCellId (const osg::Vec3f& point) const;
protected:
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool);

@ -108,6 +108,11 @@ void CSVRender::UnpagedWorldspaceWidget::clearSelection (int elementMask)
flagAsModified();
}
std::string CSVRender::UnpagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const
{
return mCellId;
}
void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{

@ -46,6 +46,8 @@ namespace CSVRender
/// \param elementMask Elements to be affected by the clear operation
virtual void clearSelection (int elementMask);
virtual std::string getCellId (const osg::Vec3f& point) const;
private:
virtual void referenceableDataChanged (const QModelIndex& topLeft,

@ -315,6 +315,54 @@ CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument()
return mDocument;
}
osg::Vec3f CSVRender::WorldspaceWidget::getIntersectionPoint (const QPoint& localPos,
unsigned int interactionMask, bool ignoreHidden) const
{
// (0,0) is considered the lower left corner of an OpenGL window
int x = localPos.x();
int y = height() - localPos.y();
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector (
new osgUtil::LineSegmentIntersector (osgUtil::Intersector::WINDOW, x, y));
intersector->setIntersectionLimit (osgUtil::LineSegmentIntersector::NO_LIMIT);
osgUtil::IntersectionVisitor visitor (intersector);
unsigned int mask = interactionMask;
if (ignoreHidden)
mask &= getVisibilityMask();
visitor.setTraversalMask (mask << 1);
mView->getCamera()->accept (visitor);
for (osgUtil::LineSegmentIntersector::Intersections::iterator iter = intersector->getIntersections().begin();
iter!=intersector->getIntersections().end(); ++iter)
{
// reject back-facing polygons
osg::Vec3f normal = osg::Matrix::transform3x3 (
iter->getWorldIntersectNormal(), mView->getCamera()->getViewMatrix());
if (normal.z()>=0)
return iter->getWorldIntersectPoint();
}
osg::Matrixd matrix;
matrix.preMult (mView->getCamera()->getViewport()->computeWindowMatrix());
matrix.preMult (mView->getCamera()->getProjectionMatrix());
matrix.preMult (mView->getCamera()->getViewMatrix());
matrix = osg::Matrixd::inverse (matrix);
osg::Vec3d start = matrix.preMult (intersector->getStart());
osg::Vec3d end = matrix.preMult (intersector->getEnd());
osg::Vec3d direction = end-start;
direction.normalize();
return start+direction * 50;
}
void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event)
{
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());

@ -127,6 +127,19 @@ namespace CSVRender
/// \param elementMask Elements to be affected by the clear operation
virtual void clearSelection (int elementMask) = 0;
/// Return the next intersection point with scene elements matched by
/// \a interactionMask based on \a localPos and the camera vector.
/// If there is no such point, instead a point "in front" of \a localPos will be
/// returned.
///
/// \param ignoreHidden ignore elements specified in interactionMask that are
/// flagged as not visible.
osg::Vec3f getIntersectionPoint (const QPoint& localPos,
unsigned int interactionMask = Element_Reference | Element_Terrain,
bool ignoreHidden = false) const;
virtual std::string getCellId (const osg::Vec3f& point) const = 0;
protected:
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle2 *tool);

Loading…
Cancel
Save