1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-30 09:36:43 +00:00

Add raytrace to dragCompleted. Implement node drag connection,

node and edge removal, and some fixes.
This commit is contained in:
Aesylwinn 2016-05-16 17:25:02 -04:00
parent 6fbc10dbba
commit aea2380c2b
9 changed files with 247 additions and 29 deletions

View file

@ -59,7 +59,7 @@ bool CSVRender::EditMode::secondarySelectStartDrag (const WorldspaceHitResult& h
void CSVRender::EditMode::drag (int diffX, int diffY, double speedFactor) {} void CSVRender::EditMode::drag (int diffX, int diffY, double speedFactor) {}
void CSVRender::EditMode::dragCompleted() {} void CSVRender::EditMode::dragCompleted(const WorldspaceHitResult& hit) {}
void CSVRender::EditMode::dragAborted() {} void CSVRender::EditMode::dragAborted() {}

View file

@ -74,7 +74,7 @@ namespace CSVRender
virtual void drag (int diffX, int diffY, double speedFactor); virtual void drag (int diffX, int diffY, double speedFactor);
/// Default-implementation: ignored /// Default-implementation: ignored
virtual void dragCompleted(); virtual void dragCompleted(const WorldspaceHitResult& hit);
/// Default-implementation: ignored /// Default-implementation: ignored
/// ///

View file

@ -244,7 +244,7 @@ void CSVRender::InstanceMode::drag (int diffX, int diffY, double speedFactor)
} }
} }
void CSVRender::InstanceMode::dragCompleted() void CSVRender::InstanceMode::dragCompleted(const WorldspaceHitResult& hit)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = std::vector<osg::ref_ptr<TagBase> > selection =
getWorldspaceWidget().getEdited (Mask_Reference); getWorldspaceWidget().getEdited (Mask_Reference);

View file

@ -55,7 +55,7 @@ namespace CSVRender
virtual void drag (int diffX, int diffY, double speedFactor); virtual void drag (int diffX, int diffY, double speedFactor);
virtual void dragCompleted(); virtual void dragCompleted(const WorldspaceHitResult& hit);
/// \note dragAborted will not be called, if the drag is aborted via changing /// \note dragAborted will not be called, if the drag is aborted via changing
/// editing mode /// editing mode

View file

@ -45,6 +45,8 @@ namespace CSVRender
, mPathgridCollection(mData.getPathgrids()) , mPathgridCollection(mData.getPathgrids())
, mId(pathgridId) , mId(pathgridId)
, mCoords(coordinates) , mCoords(coordinates)
, mConnectionIndicator(false)
, mConnectionNode(0)
, mParent(parent) , mParent(parent)
, mPathgridGeometry(0) , mPathgridGeometry(0)
, mSelectedGeometry(0) , mSelectedGeometry(0)
@ -161,9 +163,21 @@ namespace CSVRender
mSelectedNode->setPosition(mSelectedNode->getPosition() + offset); mSelectedNode->setPosition(mSelectedNode->getPosition() + offset);
} }
void Pathgrid::setupConnectionIndicator(unsigned short node)
{
mConnectionIndicator = true;
mConnectionNode = node;
recreateSelectedGeometry();
}
void Pathgrid::resetMove() void Pathgrid::resetMove()
{ {
mSelectedNode->setPosition(osg::Vec3f(0,0,0)); mSelectedNode->setPosition(osg::Vec3f(0,0,0));
if (mConnectionIndicator)
{
mConnectionIndicator = false;
recreateSelectedGeometry();
}
} }
void Pathgrid::applyPoint(CSMWorld::CommandMacro& commands, const osg::Vec3d& worldPos) void Pathgrid::applyPoint(CSMWorld::CommandMacro& commands, const osg::Vec3d& worldPos)
@ -249,18 +263,88 @@ namespace CSVRender
point.mZ + offsetZ)); point.mZ + offsetZ));
} }
} }
resetMove();
} }
void Pathgrid::applyEdge(CSMWorld::CommandMacro& commands, unsigned short node1, unsigned short node2) void Pathgrid::applyEdge(CSMWorld::CommandMacro& commands, unsigned short node1, unsigned short node2)
{ {
// TODO const CSMWorld::Pathgrid* source = getPathgridSource();
if (source)
{
addEdge(commands, *source, node1, node2);
}
} }
void Pathgrid::applyEdges(CSMWorld::CommandMacro& commands, unsigned short node) void Pathgrid::applyEdges(CSMWorld::CommandMacro& commands, unsigned short node)
{ {
// TODO const CSMWorld::Pathgrid* source = getPathgridSource();
if (source)
{
for (size_t i = 0; i < mSelected.size(); ++i)
{
addEdge(commands, *source, node, mSelected[i]);
}
}
}
void Pathgrid::applyRemoveNodes(CSMWorld::CommandMacro& commands)
{
// Source is aquired here to ensure a pathgrid exists
const CSMWorld::Pathgrid* source = getPathgridSource();
if (source)
{
// Want to remove from end of row first
std::sort(mSelected.begin(), mSelected.end(), std::greater<int>());
CSMWorld::IdTree* model = dynamic_cast<CSMWorld::IdTree*>(mData.getTableModel(
CSMWorld::UniversalId::Type_Pathgrids));
int parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridPoints);
for (std::vector<unsigned short>::iterator row = mSelected.begin(); row != mSelected.end(); ++row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, static_cast<int>(*row), parentColumn));
}
}
clearSelected();
}
void Pathgrid::applyRemoveEdges(CSMWorld::CommandMacro& commands)
{
const CSMWorld::Pathgrid* source = getPathgridSource();
if (source)
{
// Want to remove from end of row first
std::set<int, std::greater<int> > rowsToRemove;
for (size_t i = 0; i <= mSelected.size(); ++i)
{
for (size_t j = i + 1; j < mSelected.size(); ++j)
{
int row = edgeExists(*source, mSelected[i], mSelected[j]);
if (row != -1)
{
rowsToRemove.insert(row);
}
row = edgeExists(*source, mSelected[j], mSelected[i]);
if (row != -1)
{
rowsToRemove.insert(row);
}
}
}
CSMWorld::IdTree* model = dynamic_cast<CSMWorld::IdTree*>(mData.getTableModel(
CSMWorld::UniversalId::Type_Pathgrids));
int parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridEdges);
std::set<int, std::greater<int> >::iterator row;
for (row = rowsToRemove.begin(); row != rowsToRemove.end(); ++row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, *row, parentColumn));
}
}
} }
osg::ref_ptr<PathgridTag> Pathgrid::getTag() const osg::ref_ptr<PathgridTag> Pathgrid::getTag() const
@ -303,8 +387,25 @@ namespace CSVRender
void Pathgrid::recreateSelectedGeometry(const CSMWorld::Pathgrid& source) void Pathgrid::recreateSelectedGeometry(const CSMWorld::Pathgrid& source)
{ {
removeSelectedGeometry(); removeSelectedGeometry();
mSelectedGeometry = SceneUtil::createPathgridSelectedWireframe(source, mSelected);
mSelectedGeode->addDrawable(mSelectedGeometry); if (mConnectionIndicator)
{
NodeList tempList = NodeList(mSelected);
NodeList::iterator searchResult = std::find(tempList.begin(), tempList.end(), mConnectionNode);
if (searchResult != tempList.end())
tempList.erase(searchResult);
tempList.push_back(mConnectionNode);
mSelectedGeometry = SceneUtil::createPathgridSelectedWireframe(source, tempList);
mSelectedGeode->addDrawable(mSelectedGeometry);
}
else
{
mSelectedGeometry = SceneUtil::createPathgridSelectedWireframe(source, mSelected);
mSelectedGeode->addDrawable(mSelectedGeometry);
}
} }
void Pathgrid::removePathgridGeometry() void Pathgrid::removePathgridGeometry()
@ -335,4 +436,49 @@ namespace CSVRender
return 0; return 0;
} }
int Pathgrid::edgeExists(const CSMWorld::Pathgrid& source, unsigned short node1, unsigned short node2)
{
for (size_t i = 0; i < source.mEdges.size(); ++i)
{
if (source.mEdges[i].mV0 == node1 && source.mEdges[i].mV1 == node2)
return static_cast<int>(i);
}
return -1;
}
void Pathgrid::addEdge(CSMWorld::CommandMacro& commands, const CSMWorld::Pathgrid& source, unsigned short node1,
unsigned short node2)
{
CSMWorld::IdTree* model = dynamic_cast<CSMWorld::IdTree*>(mData.getTableModel(
CSMWorld::UniversalId::Type_Pathgrids));
int recordIndex = mPathgridCollection.getIndex(mId);
int parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridEdges);
int edge0Column = mPathgridCollection.searchNestedColumnIndex(parentColumn,
CSMWorld::Columns::ColumnId_PathgridEdge0);
int edge1Column = mPathgridCollection.searchNestedColumnIndex(parentColumn,
CSMWorld::Columns::ColumnId_PathgridEdge1);
QModelIndex parent = model->index(recordIndex, parentColumn);
int row = static_cast<int>(source.mEdges.size());
if (edgeExists(source, node1, node2) == -1)
{
commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge0Column, parent), node1));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge1Column, parent), node2));
++row;
}
if (edgeExists(source, node2, node1) == -1)
{
commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge0Column, parent), node2));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge1Column, parent), node1));
}
}
} }

View file

@ -71,10 +71,14 @@ namespace CSVRender
void moveSelected(const osg::Vec3d& offset); void moveSelected(const osg::Vec3d& offset);
void resetMove(); void resetMove();
void setupConnectionIndicator(unsigned short node);
void applyPoint(CSMWorld::CommandMacro& commands, const osg::Vec3d& worldPos); void applyPoint(CSMWorld::CommandMacro& commands, const osg::Vec3d& worldPos);
void applyPosition(CSMWorld::CommandMacro& commands); void applyPosition(CSMWorld::CommandMacro& commands);
void applyEdge(CSMWorld::CommandMacro& commands, unsigned short node1, unsigned short node2); void applyEdge(CSMWorld::CommandMacro& commands, unsigned short node1, unsigned short node2);
void applyEdges(CSMWorld::CommandMacro& commands, unsigned short node); void applyEdges(CSMWorld::CommandMacro& commands, unsigned short node);
void applyRemoveNodes(CSMWorld::CommandMacro& commands);
void applyRemoveEdges(CSMWorld::CommandMacro& commands);
osg::ref_ptr<PathgridTag> getTag() const; osg::ref_ptr<PathgridTag> getTag() const;
@ -88,6 +92,8 @@ namespace CSVRender
CSMWorld::CellCoordinates mCoords; CSMWorld::CellCoordinates mCoords;
NodeList mSelected; NodeList mSelected;
bool mConnectionIndicator;
unsigned short mConnectionNode;
osg::Group* mParent; osg::Group* mParent;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode; osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
@ -106,6 +112,11 @@ namespace CSVRender
const CSMWorld::Pathgrid* getPathgridSource(); const CSMWorld::Pathgrid* getPathgridSource();
int edgeExists(const CSMWorld::Pathgrid& source, unsigned short node1, unsigned short node2);
void addEdge(CSMWorld::CommandMacro& commands, const CSMWorld::Pathgrid& source, unsigned short node1,
unsigned short node2);
void removeEdge(CSMWorld::CommandMacro& commands, const CSMWorld::Pathgrid& source, unsigned short node1,
unsigned short node2);
}; };
} }

View file

@ -102,6 +102,22 @@ namespace CSVRender
void PathgridMode::secondaryEditPressed(const WorldspaceHitResult& hit) void PathgridMode::secondaryEditPressed(const WorldspaceHitResult& hit)
{ {
if (hit.tag)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{
if (tag->getPathgrid()->isSelected())
{
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0));
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Connect node to selected nodes";
CSMWorld::CommandMacro macro(undoStack, description);
tag->getPathgrid()->applyEdges(macro, node);
}
}
}
} }
void PathgridMode::primarySelectPressed(const WorldspaceHitResult& hit) void PathgridMode::primarySelectPressed(const WorldspaceHitResult& hit)
@ -112,6 +128,7 @@ namespace CSVRender
{ {
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{ {
mLastId = tag->getPathgrid()->getId();
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0));
tag->getPathgrid()->toggleSelected(node); tag->getPathgrid()->toggleSelected(node);
} }
@ -147,12 +164,9 @@ namespace CSVRender
if (!selection.empty()) if (!selection.empty())
{ {
mDragMode = DragMode_Move; mDragMode = DragMode_Move;
return true;
}
else
{
return false;
} }
return true;
} }
bool PathgridMode::secondaryEditStartDrag(const WorldspaceHitResult& hit) bool PathgridMode::secondaryEditStartDrag(const WorldspaceHitResult& hit)
@ -162,12 +176,14 @@ namespace CSVRender
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{ {
mDragMode = DragMode_Edge; mDragMode = DragMode_Edge;
mEdgeId = tag->getPathgrid()->getId();
mFromNode = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); mFromNode = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0));
return true;
tag->getPathgrid()->setupConnectionIndicator(mFromNode);
} }
} }
return false; return true;
} }
void PathgridMode::drag(int diffX, int diffY, double speedFactor) void PathgridMode::drag(int diffX, int diffY, double speedFactor)
@ -189,21 +205,20 @@ namespace CSVRender
} }
else if (mDragMode == DragMode_Edge) else if (mDragMode == DragMode_Edge)
{ {
// TODO make indicators // TODO Add indicator, need raytrace
} }
} }
} }
} }
void PathgridMode::dragCompleted() void PathgridMode::dragCompleted(const WorldspaceHitResult& hit)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid); if (mDragMode == DragMode_Move)
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
{ {
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get())) std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
{ {
if (mDragMode == DragMode_Move) if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
{ {
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack(); QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Move pathgrid node(s)"; QString description = "Move pathgrid node(s)";
@ -211,14 +226,33 @@ namespace CSVRender
CSMWorld::CommandMacro macro(undoStack, description); CSMWorld::CommandMacro macro(undoStack, description);
tag->getPathgrid()->applyPosition(macro); tag->getPathgrid()->applyPosition(macro);
} }
else if (mDragMode == DragMode_Edge) }
}
else if (mDragMode == DragMode_Edge)
{
if (hit.tag)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{ {
// TODO raycast for other node and apply if needed with mFromNode if (tag->getPathgrid()->getId() == mEdgeId)
{
unsigned short toNode = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0));
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Add edge between nodes";
CSMWorld::CommandMacro macro(undoStack, description);
tag->getPathgrid()->applyEdge(macro, mFromNode, toNode);
}
} }
} }
mEdgeId.clear();
mFromNode = 0;
} }
mDragMode = DragMode_None; mDragMode = DragMode_None;
getWorldspaceWidget().reset(Mask_Pathgrid);
} }
void PathgridMode::dragAborted() void PathgridMode::dragAborted()
@ -244,9 +278,35 @@ namespace CSVRender
void PathgridMode::removeSelected() void PathgridMode::removeSelected()
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
{
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Remove selected nodes";
CSMWorld::CommandMacro macro(undoStack, description);
tag->getPathgrid()->applyRemoveNodes(macro);
}
}
} }
void PathgridMode::removeSelectedEdges() void PathgridMode::removeSelectedEdges()
{ {
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
{
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Remove edges between selected nodes";
CSMWorld::CommandMacro macro(undoStack, description);
tag->getPathgrid()->applyRemoveEdges(macro);
}
}
} }
} }

View file

@ -33,7 +33,7 @@ namespace CSVRender
virtual void drag (int diffX, int diffY, double speedFactor); virtual void drag (int diffX, int diffY, double speedFactor);
virtual void dragCompleted(); virtual void dragCompleted(const WorldspaceHitResult& hit);
/// \note dragAborted will not be called, if the drag is aborted via changing /// \note dragAborted will not be called, if the drag is aborted via changing
/// editing mode /// editing mode
@ -48,8 +48,8 @@ namespace CSVRender
DragMode_Edge DragMode_Edge
}; };
std::string mLastId;
DragMode mDragMode; DragMode mDragMode;
std::string mLastId, mEdgeId;
unsigned short mFromNode; unsigned short mFromNode;
QAction* mSelectAll; QAction* mSelectAll;

View file

@ -712,8 +712,9 @@ void CSVRender::WorldspaceWidget::mouseReleaseEvent (QMouseEvent *event)
if (mDragging) if (mDragging)
{ {
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()); EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
WorldspaceHitResult hit = mousePick (event->pos());
editMode.dragCompleted(); editMode.dragCompleted(hit);
mDragging = false; mDragging = false;
} }
else else