Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295#include "pathgridmode.hpp"
#include <QIcon>
#include <components/misc/scalableicon.hpp>#include <components/sceneutil/pathgridutil.hpp>
#include "../../model/prefs/state.hpp"
#include "../../model/world/commandmacro.hpp"
#include "../widget/scenetoolbar.hpp"
#include "cell.hpp"#include "mask.hpp"#include "pathgrid.hpp"#include "pathgridselectionmode.hpp"#include "worldspacewidget.hpp"
#include <apps/opencs/model/doc/document.hpp>#include <apps/opencs/model/prefs/category.hpp>#include <apps/opencs/model/prefs/setting.hpp>#include <apps/opencs/view/render/editmode.hpp>#include <apps/opencs/view/render/tagbase.hpp>
#include <osg/Camera>#include <osg/Matrixd>#include <osg/Vec3d>#include <osg/ref_ptr>
#include <vector>
class QPoint;class QUndoStack;class QWidget;
namespace CSVRender{ PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent) : EditMode(worldspaceWidget, Misc::ScalableIcon::load(":scenetoolbar/editing-pathgrid"), Mask_Pathgrid | Mask_Terrain | Mask_Reference, getTooltip(), parent) , mDragMode(DragMode::None) , mFromNode(0) , mSelectionMode(nullptr) { }
QString PathgridMode::getTooltip() { return QString( "Pathgrid editing" "<ul><li>Press {scene-edit-primary} to add a node to the cursor location</li>" "<li>Press {scene-edit-secondary} to connect the selected nodes to the node beneath the cursor</li>" "<li>Press {scene-edit-primary} and drag to move selected nodes</li>" "<li>Press {scene-edit-secondary} and drag to connect one node to another</li>" "</ul><p>Note: Only a single cell's pathgrid may be edited at a time"); }
void PathgridMode::activate(CSVWidget::SceneToolbar* toolbar) { if (!mSelectionMode) { mSelectionMode = new PathgridSelectionMode(toolbar, getWorldspaceWidget()); }
EditMode::activate(toolbar); toolbar->addTool(mSelectionMode); }
void PathgridMode::deactivate(CSVWidget::SceneToolbar* toolbar) { if (mSelectionMode) { toolbar->removeTool(mSelectionMode); delete mSelectionMode; mSelectionMode = nullptr; } }
void PathgridMode::primaryOpenPressed(const WorldspaceHitResult& hitResult) {}
void PathgridMode::primaryEditPressed(const WorldspaceHitResult& hitResult) { if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue() && dynamic_cast<PathgridTag*>(hitResult.tag.get())) { primarySelectPressed(hitResult); } else if (Cell* cell = getWorldspaceWidget().getCell(hitResult.worldPos)) { if (cell->getPathgrid()) { // Add node QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack(); QString description = "Add node";
CSMWorld::CommandMacro macro(undoStack, description); cell->getPathgrid()->applyPoint(macro, hitResult.worldPos); } } }
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(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) { getWorldspaceWidget().clearSelection(Mask_Pathgrid);
if (hit.tag) { if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) { mLastId = tag->getPathgrid()->getId(); unsigned short node = SceneUtil::getPathgridNode(hit.index0); tag->getPathgrid()->toggleSelected(node); } } }
void PathgridMode::secondarySelectPressed(const WorldspaceHitResult& hit) { if (hit.tag) { if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) { if (tag->getPathgrid()->getId() != mLastId) { getWorldspaceWidget().clearSelection(Mask_Pathgrid); mLastId = tag->getPathgrid()->getId(); }
unsigned short node = SceneUtil::getPathgridNode(hit.index0); tag->getPathgrid()->toggleSelected(node);
return; } }
getWorldspaceWidget().clearSelection(Mask_Pathgrid); }
bool PathgridMode::primaryEditStartDrag(const QPoint& pos) { std::vector<osg::ref_ptr<TagBase>> selection = getWorldspaceWidget().getSelection(Mask_Pathgrid);
if (CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue()) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask());
if (dynamic_cast<PathgridTag*>(hit.tag.get())) { primarySelectPressed(hit); selection = getWorldspaceWidget().getSelection(Mask_Pathgrid); } }
if (!selection.empty()) { mDragMode = DragMode::Move; return true; }
return false; }
bool PathgridMode::secondaryEditStartDrag(const QPoint& pos) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask()); if (hit.tag) { if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) { mDragMode = DragMode::Edge; mEdgeId = tag->getPathgrid()->getId(); mFromNode = SceneUtil::getPathgridNode(hit.index0);
tag->getPathgrid()->setDragOrigin(mFromNode); return true; } }
return false; }
void PathgridMode::drag(const QPoint& pos, int diffX, int diffY, double speedFactor) { if (mDragMode == DragMode::Move) { 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())) { osg::Vec3d eye, center, up, offset; getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt(eye, center, up);
offset = (up * diffY * speedFactor) + (((center - eye) ^ up) * diffX * speedFactor);
tag->getPathgrid()->moveSelected(offset); } } } else if (mDragMode == DragMode::Edge) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask());
Cell* cell = getWorldspaceWidget().getCell(hit.worldPos); if (cell && cell->getPathgrid()) { PathgridTag* tag = nullptr; if (hit.tag && (tag = dynamic_cast<PathgridTag*>(hit.tag.get())) && tag->getPathgrid()->getId() == mEdgeId) { unsigned short node = SceneUtil::getPathgridNode(hit.index0); cell->getPathgrid()->setDragEndpoint(node); } else { cell->getPathgrid()->setDragEndpoint(hit.worldPos); } } } }
void PathgridMode::dragCompleted(const QPoint& pos) { if (mDragMode == DragMode::Move) { 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 = "Move pathgrid node(s)";
CSMWorld::CommandMacro macro(undoStack, description); tag->getPathgrid()->applyPosition(macro); } } } else if (mDragMode == DragMode::Edge) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask());
if (hit.tag) { if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) { if (tag->getPathgrid()->getId() == mEdgeId) { unsigned short toNode = SceneUtil::getPathgridNode(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; getWorldspaceWidget().reset(Mask_Pathgrid); }
void PathgridMode::dragAborted() { getWorldspaceWidget().reset(Mask_Pathgrid); }}