mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 17:49:41 +00:00
Merge branch 'instanceselectiontools' into 'master'
[OpenMW-CS] Cube and sphere instance selection See merge request OpenMW/openmw!485
This commit is contained in:
commit
f7d7186c39
16 changed files with 627 additions and 25 deletions
|
@ -93,6 +93,7 @@
|
||||||
Feature #2386: Distant Statics in the form of Object Paging
|
Feature #2386: Distant Statics in the form of Object Paging
|
||||||
Feature #2404: Levelled List can not be placed into a container
|
Feature #2404: Levelled List can not be placed into a container
|
||||||
Feature #2686: Timestamps in openmw.log
|
Feature #2686: Timestamps in openmw.log
|
||||||
|
Feature #3171: OpenMW-CS: Instance drag selection
|
||||||
Feature #4894: Consider actors as obstacles for pathfinding
|
Feature #4894: Consider actors as obstacles for pathfinding
|
||||||
Feature #5043: Head Bobbing
|
Feature #5043: Head Bobbing
|
||||||
Feature #5199: Improve Scene Colors
|
Feature #5199: Improve Scene Colors
|
||||||
|
|
|
@ -21,7 +21,7 @@ New Features:
|
||||||
- Basics of Collada animations are now supported via osgAnimation plugin (#5456)
|
- Basics of Collada animations are now supported via osgAnimation plugin (#5456)
|
||||||
|
|
||||||
New Editor Features:
|
New Editor Features:
|
||||||
- ?
|
- Instance selection modes are now implemented (centred cube, corner-dragged cube, sphere) with four user-configurable actions (select only, add to selection, remove from selection, invert selection) (#3171)
|
||||||
|
|
||||||
Bug Fixes:
|
Bug Fixes:
|
||||||
- NiParticleColorModifier in NIF files is now properly handled which solves issues regarding particle effects, e.g., smoke and fire (#1952, #3676)
|
- NiParticleColorModifier in NIF files is now properly handled which solves issues regarding particle effects, e.g., smoke and fire (#1952, #3676)
|
||||||
|
|
|
@ -247,6 +247,15 @@ void CSMPrefs::State::declare()
|
||||||
EnumValues landeditOutsideVisibleCell;
|
EnumValues landeditOutsideVisibleCell;
|
||||||
landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit);
|
landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit);
|
||||||
|
|
||||||
|
EnumValue SelectOnly ("Select only");
|
||||||
|
EnumValue SelectAdd ("Add to selection");
|
||||||
|
EnumValue SelectRemove ("Remove from selection");
|
||||||
|
EnumValue selectInvert ("Invert selection");
|
||||||
|
EnumValues primarySelectAction;
|
||||||
|
primarySelectAction.add (SelectOnly).add (SelectAdd).add (SelectRemove).add (selectInvert);
|
||||||
|
EnumValues secondarySelectAction;
|
||||||
|
secondarySelectAction.add (SelectOnly).add (SelectAdd).add (SelectRemove).add (selectInvert);
|
||||||
|
|
||||||
declareCategory ("3D Scene Editing");
|
declareCategory ("3D Scene Editing");
|
||||||
declareInt ("distance", "Drop Distance", 50).
|
declareInt ("distance", "Drop Distance", 50).
|
||||||
setTooltip ("If an instance drop can not be placed against another object at the "
|
setTooltip ("If an instance drop can not be placed against another object at the "
|
||||||
|
@ -276,6 +285,12 @@ void CSMPrefs::State::declare()
|
||||||
declareBool ("open-list-view", "Open displays list view", false).
|
declareBool ("open-list-view", "Open displays list view", false).
|
||||||
setTooltip ("When opening a reference from the scene view, it will open the"
|
setTooltip ("When opening a reference from the scene view, it will open the"
|
||||||
" instance list view instead of the individual instance record view.");
|
" instance list view instead of the individual instance record view.");
|
||||||
|
declareEnum ("primary-select-action", "Action for primary select", SelectOnly).
|
||||||
|
setTooltip("Selection can be chosen between select only, add to selection, remove from selection and invert selection.").
|
||||||
|
addValues (primarySelectAction);
|
||||||
|
declareEnum ("secondary-select-action", "Action for secondary select", SelectAdd).
|
||||||
|
setTooltip("Selection can be chosen between select only, add to selection, remove from selection and invert selection.").
|
||||||
|
addValues (secondarySelectAction);
|
||||||
|
|
||||||
declareCategory ("Key Bindings");
|
declareCategory ("Key Bindings");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <osg/PositionAttitudeTransform>
|
#include <osg/PositionAttitudeTransform>
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
|
@ -496,6 +499,50 @@ void CSVRender::Cell::selectAllWithSameParentId (int elementMask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::handleSelectDrag(Object* object, DragMode dragMode)
|
||||||
|
{
|
||||||
|
if (dragMode == DragMode_Select_Only || dragMode == DragMode_Select_Add)
|
||||||
|
object->setSelected(true);
|
||||||
|
|
||||||
|
else if (dragMode == DragMode_Select_Remove)
|
||||||
|
object->setSelected(false);
|
||||||
|
|
||||||
|
else if (dragMode == DragMode_Select_Invert)
|
||||||
|
object->setSelected (!object->getSelected());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode)
|
||||||
|
{
|
||||||
|
for (auto& object : mObjects)
|
||||||
|
{
|
||||||
|
if (dragMode == DragMode_Select_Only) object.second->setSelected (false);
|
||||||
|
|
||||||
|
if ( ( object.second->getPosition().pos[0] > pointA[0] && object.second->getPosition().pos[0] < pointB[0] ) ||
|
||||||
|
( object.second->getPosition().pos[0] > pointB[0] && object.second->getPosition().pos[0] < pointA[0] ))
|
||||||
|
{
|
||||||
|
if ( ( object.second->getPosition().pos[1] > pointA[1] && object.second->getPosition().pos[1] < pointB[1] ) ||
|
||||||
|
( object.second->getPosition().pos[1] > pointB[1] && object.second->getPosition().pos[1] < pointA[1] ))
|
||||||
|
{
|
||||||
|
if ( ( object.second->getPosition().pos[2] > pointA[2] && object.second->getPosition().pos[2] < pointB[2] ) ||
|
||||||
|
( object.second->getPosition().pos[2] > pointB[2] && object.second->getPosition().pos[2] < pointA[2] ))
|
||||||
|
handleSelectDrag(object.second, dragMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::selectWithinDistance(const osg::Vec3d& point, float distance, DragMode dragMode)
|
||||||
|
{
|
||||||
|
for (auto& object : mObjects)
|
||||||
|
{
|
||||||
|
if (dragMode == DragMode_Select_Only) object.second->setSelected (false);
|
||||||
|
|
||||||
|
float distanceFromObject = (point - object.second->getPosition().asVec3()).length();
|
||||||
|
if (distanceFromObject < distance) handleSelectDrag(object.second, dragMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::setCellArrows (int mask)
|
void CSVRender::Cell::setCellArrows (int mask)
|
||||||
{
|
{
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "../../model/world/cellcoordinates.hpp"
|
#include "../../model/world/cellcoordinates.hpp"
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
|
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
|
||||||
|
@ -152,6 +153,12 @@ namespace CSVRender
|
||||||
// already selected
|
// already selected
|
||||||
void selectAllWithSameParentId (int elementMask);
|
void selectAllWithSameParentId (int elementMask);
|
||||||
|
|
||||||
|
void handleSelectDrag(Object* object, DragMode dragMode);
|
||||||
|
|
||||||
|
void selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode);
|
||||||
|
|
||||||
|
void selectWithinDistance(const osg::Vec3d& pointA, float distance, DragMode dragMode);
|
||||||
|
|
||||||
void setCellArrows (int mask);
|
void setCellArrows (int mask);
|
||||||
|
|
||||||
/// \brief Set marker for this cell.
|
/// \brief Set marker for this cell.
|
||||||
|
|
18
apps/opencs/view/render/instancedragmodes.hpp
Normal file
18
apps/opencs/view/render/instancedragmodes.hpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef CSV_WIDGET_INSTANCEDRAGMODES_H
|
||||||
|
#define CSV_WIDGET_INSTANCEDRAGMODES_H
|
||||||
|
|
||||||
|
namespace CSVRender
|
||||||
|
{
|
||||||
|
enum DragMode
|
||||||
|
{
|
||||||
|
DragMode_None,
|
||||||
|
DragMode_Move,
|
||||||
|
DragMode_Rotate,
|
||||||
|
DragMode_Scale,
|
||||||
|
DragMode_Select_Only,
|
||||||
|
DragMode_Select_Add,
|
||||||
|
DragMode_Select_Remove,
|
||||||
|
DragMode_Select_Invert
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -96,6 +96,33 @@ osg::Vec3f CSVRender::InstanceMode::getScreenCoords(const osg::Vec3f& pos)
|
||||||
return pos * combined;
|
return pos * combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Vec3f CSVRender::InstanceMode::getProjectionSpaceCoords(const osg::Vec3f& pos)
|
||||||
|
{
|
||||||
|
osg::Matrix viewMatrix = getWorldspaceWidget().getCamera()->getViewMatrix();
|
||||||
|
osg::Matrix projMatrix = getWorldspaceWidget().getCamera()->getProjectionMatrix();
|
||||||
|
osg::Matrix combined = viewMatrix * projMatrix;
|
||||||
|
|
||||||
|
return pos * combined;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3f CSVRender::InstanceMode::getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart)
|
||||||
|
{
|
||||||
|
osg::Matrix viewMatrix;
|
||||||
|
viewMatrix.invert(getWorldspaceWidget().getCamera()->getViewMatrix());
|
||||||
|
osg::Matrix projMatrix;
|
||||||
|
projMatrix.invert(getWorldspaceWidget().getCamera()->getProjectionMatrix());
|
||||||
|
osg::Matrix combined = projMatrix * viewMatrix;
|
||||||
|
|
||||||
|
/* calculate viewport normalized coordinates
|
||||||
|
note: is there a reason to use getCamera()->getViewport()->computeWindowMatrix() instead? */
|
||||||
|
float x = (point.x() * 2) / getWorldspaceWidget().getCamera()->getViewport()->width() - 1.0f;
|
||||||
|
float y = 1.0f - (point.y() * 2) / getWorldspaceWidget().getCamera()->getViewport()->height();
|
||||||
|
|
||||||
|
osg::Vec3f mousePlanePoint = osg::Vec3f(x, y, dragStart.z()) * combined;
|
||||||
|
|
||||||
|
return mousePlanePoint;
|
||||||
|
}
|
||||||
|
|
||||||
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent)
|
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget *parent)
|
||||||
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), Mask_Reference | Mask_Terrain, "Instance editing",
|
: EditMode (worldspaceWidget, QIcon (":scenetoolbar/editing-instance"), Mask_Reference | Mask_Terrain, "Instance editing",
|
||||||
parent), mSubMode (nullptr), mSubModeId ("move"), mSelectionMode (nullptr), mDragMode (DragMode_None),
|
parent), mSubMode (nullptr), mSubModeId ("move"), mSelectionMode (nullptr), mDragMode (DragMode_None),
|
||||||
|
@ -146,7 +173,7 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSelectionMode)
|
if (!mSelectionMode)
|
||||||
mSelectionMode = new InstanceSelectionMode (toolbar, getWorldspaceWidget());
|
mSelectionMode = new InstanceSelectionMode (toolbar, getWorldspaceWidget(), mParentNode);
|
||||||
|
|
||||||
mDragMode = DragMode_None;
|
mDragMode = DragMode_None;
|
||||||
|
|
||||||
|
@ -322,6 +349,42 @@ bool CSVRender::InstanceMode::secondaryEditStartDrag (const QPoint& pos)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSVRender::InstanceMode::primarySelectStartDrag (const QPoint& pos)
|
||||||
|
{
|
||||||
|
if (mDragMode!=DragMode_None || mLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string primarySelectAction = CSMPrefs::get()["3D Scene Editing"]["primary-select-action"].toString();
|
||||||
|
|
||||||
|
if ( primarySelectAction == "Select only" ) mDragMode = DragMode_Select_Only;
|
||||||
|
else if ( primarySelectAction == "Add to selection" ) mDragMode = DragMode_Select_Add;
|
||||||
|
else if ( primarySelectAction == "Remove from selection" ) mDragMode = DragMode_Select_Remove;
|
||||||
|
else if ( primarySelectAction == "Invert selection" ) mDragMode = DragMode_Select_Invert;
|
||||||
|
|
||||||
|
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
|
||||||
|
mSelectionMode->setDragStart(hit.worldPos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVRender::InstanceMode::secondarySelectStartDrag (const QPoint& pos)
|
||||||
|
{
|
||||||
|
if (mDragMode!=DragMode_None || mLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string secondarySelectAction = CSMPrefs::get()["3D Scene Editing"]["secondary-select-action"].toString();
|
||||||
|
|
||||||
|
if ( secondarySelectAction == "Select only" ) mDragMode = DragMode_Select_Only;
|
||||||
|
else if ( secondarySelectAction == "Add to selection" ) mDragMode = DragMode_Select_Add;
|
||||||
|
else if ( secondarySelectAction == "Remove from selection" ) mDragMode = DragMode_Select_Remove;
|
||||||
|
else if ( secondarySelectAction == "Invert selection" ) mDragMode = DragMode_Select_Invert;
|
||||||
|
|
||||||
|
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
|
||||||
|
mSelectionMode->setDragStart(hit.worldPos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor)
|
void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor)
|
||||||
{
|
{
|
||||||
osg::Vec3f offset;
|
osg::Vec3f offset;
|
||||||
|
@ -432,6 +495,24 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
||||||
// Only uniform scaling is currently supported
|
// Only uniform scaling is currently supported
|
||||||
offset = osg::Vec3f(scale, scale, scale);
|
offset = osg::Vec3f(scale, scale, scale);
|
||||||
}
|
}
|
||||||
|
else if (mSelectionMode->getCurrentId() == "cube-centre")
|
||||||
|
{
|
||||||
|
osg::Vec3f mousePlanePoint = getMousePlaneCoords(pos, getProjectionSpaceCoords(mSelectionMode->getDragStart()));
|
||||||
|
mSelectionMode->drawSelectionCubeCentre (mousePlanePoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (mSelectionMode->getCurrentId() == "cube-corner")
|
||||||
|
{
|
||||||
|
osg::Vec3f mousePlanePoint = getMousePlaneCoords(pos, getProjectionSpaceCoords(mSelectionMode->getDragStart()));
|
||||||
|
mSelectionMode->drawSelectionCubeCorner (mousePlanePoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (mSelectionMode->getCurrentId() == "sphere")
|
||||||
|
{
|
||||||
|
osg::Vec3f mousePlanePoint = getMousePlaneCoords(pos, getProjectionSpaceCoords(mSelectionMode->getDragStart()));
|
||||||
|
mSelectionMode->drawSelectionSphere (mousePlanePoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply
|
// Apply
|
||||||
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin()); iter!=selection.end(); ++iter)
|
for (std::vector<osg::ref_ptr<TagBase> >::iterator iter (selection.begin()); iter!=selection.end(); ++iter)
|
||||||
|
@ -495,6 +576,22 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
||||||
case DragMode_Move: description = "Move Instances"; break;
|
case DragMode_Move: description = "Move Instances"; break;
|
||||||
case DragMode_Rotate: description = "Rotate Instances"; break;
|
case DragMode_Rotate: description = "Rotate Instances"; break;
|
||||||
case DragMode_Scale: description = "Scale Instances"; break;
|
case DragMode_Scale: description = "Scale Instances"; break;
|
||||||
|
case DragMode_Select_Only :
|
||||||
|
handleSelectDrag(pos);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case DragMode_Select_Add :
|
||||||
|
handleSelectDrag(pos);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case DragMode_Select_Remove :
|
||||||
|
handleSelectDrag(pos);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case DragMode_Select_Invert :
|
||||||
|
handleSelectDrag(pos);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
case DragMode_None: break;
|
case DragMode_None: break;
|
||||||
}
|
}
|
||||||
|
@ -680,6 +777,13 @@ void CSVRender::InstanceMode::subModeChanged (const std::string& id)
|
||||||
getWorldspaceWidget().setSubMode (getSubModeFromId (id), Mask_Reference);
|
getWorldspaceWidget().setSubMode (getSubModeFromId (id), Mask_Reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::InstanceMode::handleSelectDrag(const QPoint& pos)
|
||||||
|
{
|
||||||
|
osg::Vec3f mousePlanePoint = getMousePlaneCoords(pos, getProjectionSpaceCoords(mSelectionMode->getDragStart()));
|
||||||
|
mSelectionMode->dragEnded (mousePlanePoint, mDragMode);
|
||||||
|
mDragMode = DragMode_None;
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
|
void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
|
||||||
{
|
{
|
||||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Reference);
|
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Reference);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
#include "editmode.hpp"
|
#include "editmode.hpp"
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
|
|
||||||
namespace CSVWidget
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
|
@ -25,14 +26,6 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
enum DragMode
|
|
||||||
{
|
|
||||||
DragMode_None,
|
|
||||||
DragMode_Move,
|
|
||||||
DragMode_Rotate,
|
|
||||||
DragMode_Scale
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DropMode
|
enum DropMode
|
||||||
{
|
{
|
||||||
Collision,
|
Collision,
|
||||||
|
@ -57,6 +50,9 @@ namespace CSVRender
|
||||||
|
|
||||||
osg::Vec3f getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const;
|
osg::Vec3f getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const;
|
||||||
osg::Vec3f getScreenCoords(const osg::Vec3f& pos);
|
osg::Vec3f getScreenCoords(const osg::Vec3f& pos);
|
||||||
|
osg::Vec3f getProjectionSpaceCoords(const osg::Vec3f& pos);
|
||||||
|
osg::Vec3f getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart);
|
||||||
|
void handleSelectDrag(const QPoint& pos);
|
||||||
void dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight);
|
void dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight);
|
||||||
float getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight);
|
float getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight);
|
||||||
|
|
||||||
|
@ -84,6 +80,10 @@ namespace CSVRender
|
||||||
|
|
||||||
bool secondaryEditStartDrag (const QPoint& pos) override;
|
bool secondaryEditStartDrag (const QPoint& pos) override;
|
||||||
|
|
||||||
|
bool primarySelectStartDrag(const QPoint& pos) override;
|
||||||
|
|
||||||
|
bool secondarySelectStartDrag(const QPoint& pos) override;
|
||||||
|
|
||||||
void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override;
|
void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override;
|
||||||
|
|
||||||
void dragCompleted(const QPoint& pos) override;
|
void dragCompleted(const QPoint& pos) override;
|
||||||
|
|
|
@ -2,17 +2,24 @@
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QPoint>
|
||||||
|
|
||||||
|
#include <osg/Group>
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/Vec3d>
|
||||||
|
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
#include "../../model/world/commands.hpp"
|
#include "../../model/world/commands.hpp"
|
||||||
|
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
InstanceSelectionMode::InstanceSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget)
|
InstanceSelectionMode::InstanceSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget, osg::Group *cellNode)
|
||||||
: SelectionMode(parent, worldspaceWidget, Mask_Reference)
|
: SelectionMode(parent, worldspaceWidget, Mask_Reference), mParentNode(cellNode)
|
||||||
{
|
{
|
||||||
mSelectSame = new QAction("Extend selection to instances with same object ID", this);
|
mSelectSame = new QAction("Extend selection to instances with same object ID", this);
|
||||||
mDeleteSelection = new QAction("Delete selected instances", this);
|
mDeleteSelection = new QAction("Delete selected instances", this);
|
||||||
|
@ -21,6 +28,342 @@ namespace CSVRender
|
||||||
connect(mDeleteSelection, SIGNAL(triggered()), this, SLOT(deleteSelection()));
|
connect(mDeleteSelection, SIGNAL(triggered()), this, SLOT(deleteSelection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InstanceSelectionMode::~InstanceSelectionMode()
|
||||||
|
{
|
||||||
|
mParentNode->removeChild(mBaseNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::setDragStart(const osg::Vec3d& dragStart)
|
||||||
|
{
|
||||||
|
mDragStart = dragStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
const osg::Vec3d& InstanceSelectionMode::getDragStart()
|
||||||
|
{
|
||||||
|
return mDragStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::dragEnded(const osg::Vec3d& dragEndPoint, DragMode dragMode)
|
||||||
|
{
|
||||||
|
float dragDistance = (mDragStart - dragEndPoint).length();
|
||||||
|
if (mBaseNode) mParentNode->removeChild (mBaseNode);
|
||||||
|
if (getCurrentId() == "cube-centre")
|
||||||
|
{
|
||||||
|
osg::Vec3d pointA(mDragStart[0] - dragDistance, mDragStart[1] - dragDistance, mDragStart[2] - dragDistance);
|
||||||
|
osg::Vec3d pointB(mDragStart[0] + dragDistance, mDragStart[1] + dragDistance, mDragStart[2] + dragDistance);
|
||||||
|
getWorldspaceWidget().selectInsideCube(pointA, pointB, dragMode);
|
||||||
|
}
|
||||||
|
else if (getCurrentId() == "cube-corner")
|
||||||
|
{
|
||||||
|
getWorldspaceWidget().selectInsideCube(mDragStart, dragEndPoint, dragMode);
|
||||||
|
}
|
||||||
|
else if (getCurrentId() == "sphere")
|
||||||
|
{
|
||||||
|
getWorldspaceWidget().selectWithinDistance(mDragStart, dragDistance, dragMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::drawSelectionCubeCentre(const osg::Vec3f& mousePlanePoint)
|
||||||
|
{
|
||||||
|
float dragDistance = (mDragStart - mousePlanePoint).length();
|
||||||
|
drawSelectionCube(mDragStart, dragDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::drawSelectionCubeCorner(const osg::Vec3f& mousePlanePoint)
|
||||||
|
{
|
||||||
|
drawSelectionBox(mDragStart, mousePlanePoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::drawSelectionBox(const osg::Vec3d& pointA, const osg::Vec3d& pointB)
|
||||||
|
{
|
||||||
|
if (mBaseNode) mParentNode->removeChild (mBaseNode);
|
||||||
|
mBaseNode = new osg::PositionAttitudeTransform;
|
||||||
|
mBaseNode->setPosition(pointA);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
|
|
||||||
|
osg::Vec3Array *vertices = new osg::Vec3Array;
|
||||||
|
vertices->push_back (osg::Vec3f (0.0f, 0.0f, 0.0f));
|
||||||
|
vertices->push_back (osg::Vec3f (0.0f, 0.0f, pointB[2] - pointA[2]));
|
||||||
|
vertices->push_back (osg::Vec3f (0.0f, pointB[1] - pointA[1], 0.0f));
|
||||||
|
vertices->push_back (osg::Vec3f (0.0f, pointB[1] - pointA[1], pointB[2] - pointA[2]));
|
||||||
|
|
||||||
|
vertices->push_back (osg::Vec3f (pointB[0] - pointA[0], 0.0f, 0.0f));
|
||||||
|
vertices->push_back (osg::Vec3f (pointB[0] - pointA[0], 0.0f, pointB[2] - pointA[2]));
|
||||||
|
vertices->push_back (osg::Vec3f (pointB[0] - pointA[0], pointB[1] - pointA[1], 0.0f));
|
||||||
|
vertices->push_back (osg::Vec3f (pointB[0] - pointA[0], pointB[1] - pointA[1], pointB[2] - pointA[2]));
|
||||||
|
|
||||||
|
geometry->setVertexArray (vertices);
|
||||||
|
|
||||||
|
osg::DrawElementsUShort *primitives = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0);
|
||||||
|
|
||||||
|
// top
|
||||||
|
primitives->push_back (2);
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (0);
|
||||||
|
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (2);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (5);
|
||||||
|
primitives->push_back (6);
|
||||||
|
|
||||||
|
primitives->push_back (6);
|
||||||
|
primitives->push_back (5);
|
||||||
|
primitives->push_back (7);
|
||||||
|
|
||||||
|
// sides
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (0);
|
||||||
|
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (5);
|
||||||
|
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (2);
|
||||||
|
primitives->push_back (0);
|
||||||
|
|
||||||
|
primitives->push_back (6);
|
||||||
|
primitives->push_back (2);
|
||||||
|
primitives->push_back (4);
|
||||||
|
|
||||||
|
primitives->push_back (6);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (2);
|
||||||
|
|
||||||
|
primitives->push_back (7);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (6);
|
||||||
|
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (5);
|
||||||
|
|
||||||
|
primitives->push_back (5);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (7);
|
||||||
|
|
||||||
|
geometry->addPrimitiveSet (primitives);
|
||||||
|
|
||||||
|
osg::Vec4Array *colours = new osg::Vec4Array;
|
||||||
|
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.5f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.4f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.4f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.4f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
|
||||||
|
geometry->setColorArray (colours, osg::Array::BIND_PER_VERTEX);
|
||||||
|
|
||||||
|
geometry->getOrCreateStateSet()->setMode (GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
geometry->getOrCreateStateSet()->setMode (GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
geometry->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
|
||||||
|
mBaseNode->addChild (geometry);
|
||||||
|
mParentNode->addChild(mBaseNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::drawSelectionCube(const osg::Vec3d& point, float radius)
|
||||||
|
{
|
||||||
|
if (mBaseNode) mParentNode->removeChild (mBaseNode);
|
||||||
|
mBaseNode = new osg::PositionAttitudeTransform;
|
||||||
|
mBaseNode->setPosition(point);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
|
|
||||||
|
osg::Vec3Array *vertices = new osg::Vec3Array;
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
float height = i ? -radius : radius;
|
||||||
|
vertices->push_back (osg::Vec3f (height, -radius, -radius));
|
||||||
|
vertices->push_back (osg::Vec3f (height, -radius, radius));
|
||||||
|
vertices->push_back (osg::Vec3f (height, radius, -radius));
|
||||||
|
vertices->push_back (osg::Vec3f (height, radius, radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
geometry->setVertexArray (vertices);
|
||||||
|
|
||||||
|
osg::DrawElementsUShort *primitives = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLES, 0);
|
||||||
|
|
||||||
|
// top
|
||||||
|
primitives->push_back (2);
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (0);
|
||||||
|
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (2);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (5);
|
||||||
|
primitives->push_back (6);
|
||||||
|
|
||||||
|
primitives->push_back (6);
|
||||||
|
primitives->push_back (5);
|
||||||
|
primitives->push_back (7);
|
||||||
|
|
||||||
|
// sides
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (0);
|
||||||
|
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (5);
|
||||||
|
|
||||||
|
primitives->push_back (4);
|
||||||
|
primitives->push_back (2);
|
||||||
|
primitives->push_back (0);
|
||||||
|
|
||||||
|
primitives->push_back (6);
|
||||||
|
primitives->push_back (2);
|
||||||
|
primitives->push_back (4);
|
||||||
|
|
||||||
|
primitives->push_back (6);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (2);
|
||||||
|
|
||||||
|
primitives->push_back (7);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (6);
|
||||||
|
|
||||||
|
primitives->push_back (1);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (5);
|
||||||
|
|
||||||
|
primitives->push_back (5);
|
||||||
|
primitives->push_back (3);
|
||||||
|
primitives->push_back (7);
|
||||||
|
|
||||||
|
geometry->addPrimitiveSet (primitives);
|
||||||
|
|
||||||
|
osg::Vec4Array *colours = new osg::Vec4Array;
|
||||||
|
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.5f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.4f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.4f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.3f, 0.3f, 0.4f, 0.2f));
|
||||||
|
colours->push_back (osg::Vec4f (0.9f, 0.9f, 1.0f, 0.2f));
|
||||||
|
|
||||||
|
geometry->setColorArray (colours, osg::Array::BIND_PER_VERTEX);
|
||||||
|
|
||||||
|
geometry->getOrCreateStateSet()->setMode (GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
geometry->getOrCreateStateSet()->setMode (GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
geometry->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
|
||||||
|
mBaseNode->addChild (geometry);
|
||||||
|
mParentNode->addChild(mBaseNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::drawSelectionSphere(const osg::Vec3f& mousePlanePoint)
|
||||||
|
{
|
||||||
|
float dragDistance = (mDragStart - mousePlanePoint).length();
|
||||||
|
drawSelectionSphere(mDragStart, dragDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceSelectionMode::drawSelectionSphere(const osg::Vec3d& point, float radius)
|
||||||
|
{
|
||||||
|
if (mBaseNode) mParentNode->removeChild (mBaseNode);
|
||||||
|
mBaseNode = new osg::PositionAttitudeTransform;
|
||||||
|
mBaseNode->setPosition(point);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
|
|
||||||
|
osg::Vec3Array *vertices = new osg::Vec3Array;
|
||||||
|
int resolution = 32;
|
||||||
|
float radiusPerResolution = radius / resolution;
|
||||||
|
float reciprocalResolution = 1.0f / resolution;
|
||||||
|
float doubleReciprocalRes = reciprocalResolution * 2;
|
||||||
|
|
||||||
|
osg::Vec4Array *colours = new osg::Vec4Array;
|
||||||
|
|
||||||
|
for (float i = 0.0; i <= resolution; i += 2)
|
||||||
|
{
|
||||||
|
float iShifted = (static_cast<float>(i) - resolution / 2.0f); // i - 16 = -16 ... 16
|
||||||
|
float xPercentile = iShifted * doubleReciprocalRes;
|
||||||
|
float x = xPercentile * radius;
|
||||||
|
float thisRadius = sqrt (radius * radius - x * x);
|
||||||
|
|
||||||
|
//the next row
|
||||||
|
float iShifted2 = (static_cast<float>(i + 1) - resolution / 2.0f);
|
||||||
|
float xPercentile2 = iShifted2 * doubleReciprocalRes;
|
||||||
|
float x2 = xPercentile2 * radius;
|
||||||
|
float thisRadius2 = sqrt (radius * radius - x2 * x2);
|
||||||
|
|
||||||
|
for (int j = 0; j < resolution; ++j)
|
||||||
|
{
|
||||||
|
float vertexX = thisRadius * sin(j * reciprocalResolution * osg::PI * 2);
|
||||||
|
float vertexY = i * radiusPerResolution * 2 - radius;
|
||||||
|
float vertexZ = thisRadius * cos(j * reciprocalResolution * osg::PI * 2);
|
||||||
|
float heightPercentage = (vertexZ + radius) / (radius * 2);
|
||||||
|
vertices->push_back (osg::Vec3f (vertexX, vertexY, vertexZ));
|
||||||
|
colours->push_back (osg::Vec4f (heightPercentage, heightPercentage, heightPercentage, 0.3f));
|
||||||
|
|
||||||
|
float vertexNextRowX = thisRadius2 * sin(j * reciprocalResolution * osg::PI * 2);
|
||||||
|
float vertexNextRowY = (i + 1) * radiusPerResolution * 2 - radius;
|
||||||
|
float vertexNextRowZ = thisRadius2 * cos(j * reciprocalResolution * osg::PI * 2);
|
||||||
|
float heightPercentageNextRow = (vertexZ + radius) / (radius * 2);
|
||||||
|
vertices->push_back (osg::Vec3f (vertexNextRowX, vertexNextRowY, vertexNextRowZ));
|
||||||
|
colours->push_back (osg::Vec4f (heightPercentageNextRow, heightPercentageNextRow, heightPercentageNextRow, 0.3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
geometry->setVertexArray (vertices);
|
||||||
|
|
||||||
|
osg::DrawElementsUShort *primitives = new osg::DrawElementsUShort (osg::PrimitiveSet::TRIANGLE_STRIP, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < resolution; ++i)
|
||||||
|
{
|
||||||
|
//Even
|
||||||
|
for (int j = 0; j < resolution * 2; ++j)
|
||||||
|
{
|
||||||
|
if (i * resolution * 2 + j > static_cast<int>(vertices->size()) - 1) continue;
|
||||||
|
primitives->push_back (i * resolution * 2 + j);
|
||||||
|
}
|
||||||
|
if (i * resolution * 2 > static_cast<int>(vertices->size()) - 1) continue;
|
||||||
|
primitives->push_back (i * resolution * 2);
|
||||||
|
primitives->push_back (i * resolution * 2 + 1);
|
||||||
|
|
||||||
|
//Odd
|
||||||
|
for (int j = 1; j < resolution * 2 - 2; j += 2)
|
||||||
|
{
|
||||||
|
if ((i + 1) * resolution * 2 + j - 1 > static_cast<int>(vertices->size()) - 1) continue;
|
||||||
|
primitives->push_back ((i + 1) * resolution * 2 + j - 1);
|
||||||
|
primitives->push_back (i * resolution * 2 + j + 2);
|
||||||
|
}
|
||||||
|
if ((i + 2) * resolution * 2 - 2 > static_cast<int>(vertices->size()) - 1) continue;
|
||||||
|
primitives->push_back ((i + 2) * resolution * 2 - 2);
|
||||||
|
primitives->push_back (i * resolution * 2 + 1);
|
||||||
|
primitives->push_back ((i + 1) * resolution * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
geometry->addPrimitiveSet (primitives);
|
||||||
|
|
||||||
|
geometry->setColorArray (colours, osg::Array::BIND_PER_VERTEX);
|
||||||
|
|
||||||
|
geometry->getOrCreateStateSet()->setMode (GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
geometry->getOrCreateStateSet()->setMode (GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
geometry->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
|
||||||
|
mBaseNode->addChild (geometry);
|
||||||
|
mParentNode->addChild(mBaseNode);
|
||||||
|
}
|
||||||
|
|
||||||
bool InstanceSelectionMode::createContextMenu(QMenu* menu)
|
bool InstanceSelectionMode::createContextMenu(QMenu* menu)
|
||||||
{
|
{
|
||||||
if (menu)
|
if (menu)
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
#ifndef CSV_RENDER_INSTANCE_SELECTION_MODE_H
|
#ifndef CSV_RENDER_INSTANCE_SELECTION_MODE_H
|
||||||
#define CSV_RENDER_INSTANCE_SELECTION_MODE_H
|
#define CSV_RENDER_INSTANCE_SELECTION_MODE_H
|
||||||
|
|
||||||
|
#include <QPoint>
|
||||||
|
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
#include <osg/Vec3d>
|
||||||
|
|
||||||
#include "selectionmode.hpp"
|
#include "selectionmode.hpp"
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
|
@ -11,8 +17,25 @@ namespace CSVRender
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
InstanceSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget);
|
InstanceSelectionMode(CSVWidget::SceneToolbar* parent, WorldspaceWidget& worldspaceWidget, osg::Group *cellNode);
|
||||||
|
|
||||||
|
~InstanceSelectionMode();
|
||||||
|
|
||||||
|
/// Store the worldspace-coordinate when drag begins
|
||||||
|
void setDragStart(const osg::Vec3d& dragStart);
|
||||||
|
|
||||||
|
/// Store the worldspace-coordinate when drag begins
|
||||||
|
const osg::Vec3d& getDragStart();
|
||||||
|
|
||||||
|
/// Store the screen-coordinate when drag begins
|
||||||
|
void setScreenDragStart(const QPoint& dragStartPoint);
|
||||||
|
|
||||||
|
/// Apply instance selection changes
|
||||||
|
void dragEnded(const osg::Vec3d& dragEndPoint, DragMode dragMode);
|
||||||
|
|
||||||
|
void drawSelectionCubeCentre(const osg::Vec3f& mousePlanePoint );
|
||||||
|
void drawSelectionCubeCorner(const osg::Vec3f& mousePlanePoint );
|
||||||
|
void drawSelectionSphere(const osg::Vec3f& mousePlanePoint );
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// Add context menu items to \a menu.
|
/// Add context menu items to \a menu.
|
||||||
|
@ -25,8 +48,15 @@ namespace CSVRender
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void drawSelectionBox(const osg::Vec3d& pointA, const osg::Vec3d& pointB);
|
||||||
|
void drawSelectionCube(const osg::Vec3d& point, float radius);
|
||||||
|
void drawSelectionSphere(const osg::Vec3d& point, float radius);
|
||||||
|
|
||||||
QAction* mDeleteSelection;
|
QAction* mDeleteSelection;
|
||||||
QAction* mSelectSame;
|
QAction* mSelectSame;
|
||||||
|
osg::Vec3d mDragStart;
|
||||||
|
osg::Group* mParentNode;
|
||||||
|
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
|
|
@ -768,6 +768,22 @@ void CSVRender::PagedWorldspaceWidget::selectAllWithSameParentId (int elementMas
|
||||||
flagAsModified();
|
flagAsModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode)
|
||||||
|
{
|
||||||
|
for (auto& cell : mCells)
|
||||||
|
{
|
||||||
|
cell.second->selectInsideCube (pointA, pointB, dragMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::selectWithinDistance(const osg::Vec3d& point, float distance, DragMode dragMode)
|
||||||
|
{
|
||||||
|
for (auto& cell : mCells)
|
||||||
|
{
|
||||||
|
cell.second->selectWithinDistance (point, distance, dragMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string CSVRender::PagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const
|
std::string CSVRender::PagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const
|
||||||
{
|
{
|
||||||
CSMWorld::CellCoordinates cellCoordinates (
|
CSMWorld::CellCoordinates cellCoordinates (
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "worldspacewidget.hpp"
|
#include "worldspacewidget.hpp"
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
|
|
||||||
namespace CSVWidget
|
namespace CSVWidget
|
||||||
{
|
{
|
||||||
|
@ -120,6 +121,10 @@ namespace CSVRender
|
||||||
/// \param elementMask Elements to be affected by the select operation
|
/// \param elementMask Elements to be affected by the select operation
|
||||||
void selectAllWithSameParentId (int elementMask) override;
|
void selectAllWithSameParentId (int elementMask) override;
|
||||||
|
|
||||||
|
void selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode) override;
|
||||||
|
|
||||||
|
void selectWithinDistance(const osg::Vec3d& point, float distance, DragMode dragMode) override;
|
||||||
|
|
||||||
std::string getCellId (const osg::Vec3f& point) const override;
|
std::string getCellId (const osg::Vec3f& point) const override;
|
||||||
|
|
||||||
Cell* getCell(const osg::Vec3d& point) const override;
|
Cell* getCell(const osg::Vec3d& point) const override;
|
||||||
|
|
|
@ -15,30 +15,27 @@ namespace CSVRender
|
||||||
{
|
{
|
||||||
addButton(":scenetoolbar/selection-mode-cube", "cube-centre",
|
addButton(":scenetoolbar/selection-mode-cube", "cube-centre",
|
||||||
"Centred cube"
|
"Centred cube"
|
||||||
"<ul><li>Drag with {scene-select-primary} (make instances the selection) or {scene-select-secondary} "
|
"<ul><li>Drag with {scene-select-primary} for primary select or {scene-select-secondary} for secondary select "
|
||||||
"(invert selection state) from the centre of the selection cube outwards</li>"
|
"from the centre of the selection cube outwards.</li>"
|
||||||
"<li>The selection cube is aligned to the word space axis</li>"
|
"<li>The selection cube is aligned to the word space axis</li>"
|
||||||
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
||||||
"starting on an instance will have the same effect</li>"
|
"starting on an instance will have the same effect</li>"
|
||||||
"</ul>"
|
"</ul>");
|
||||||
"<font color=Red>Not implemented yet</font color>");
|
|
||||||
addButton(":scenetoolbar/selection-mode-cube-corner", "cube-corner",
|
addButton(":scenetoolbar/selection-mode-cube-corner", "cube-corner",
|
||||||
"Cube corner to corner"
|
"Cube corner to corner"
|
||||||
"<ul><li>Drag with {scene-select-primary} (make instances the selection) or {scene-select-secondary} "
|
"<ul><li>Drag with {scene-select-primary} for primary select or {scene-select-secondary} for secondary select "
|
||||||
"(invert selection state) from one corner of the selection cube to the opposite corner</li>"
|
"from one corner of the selection cube to the opposite corner</li>"
|
||||||
"<li>The selection cube is aligned to the word space axis</li>"
|
"<li>The selection cube is aligned to the word space axis</li>"
|
||||||
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
||||||
"starting on an instance will have the same effect</li>"
|
"starting on an instance will have the same effect</li>"
|
||||||
"</ul>"
|
"</ul>");
|
||||||
"<font color=Red>Not implemented yet</font color>");
|
|
||||||
addButton(":scenetoolbar/selection-mode-cube-sphere", "sphere",
|
addButton(":scenetoolbar/selection-mode-cube-sphere", "sphere",
|
||||||
"Centred sphere"
|
"Centred sphere"
|
||||||
"<ul><li>Drag with {scene-select-primary} (make instances the selection) or {scene-select-secondary} "
|
"<ul><li>Drag with {scene-select-primary} for primary select or {scene-select-secondary} for secondary select "
|
||||||
"(invert selection state) from the centre of the selection sphere outwards</li>"
|
"from the centre of the selection sphere outwards</li>"
|
||||||
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
"<li>If context selection mode is enabled, a drag with {scene-edit-primary} or {scene-edit-secondary} not "
|
||||||
"starting on an instance will have the same effect</li>"
|
"starting on an instance will have the same effect</li>"
|
||||||
"</ul>"
|
"</ul>");
|
||||||
"<font color=Red>Not implemented yet</font color>");
|
|
||||||
|
|
||||||
mSelectAll = new QAction("Select all", this);
|
mSelectAll = new QAction("Select all", this);
|
||||||
mDeselectAll = new QAction("Clear selection", this);
|
mDeselectAll = new QAction("Clear selection", this);
|
||||||
|
|
|
@ -140,6 +140,16 @@ void CSVRender::UnpagedWorldspaceWidget::selectAllWithSameParentId (int elementM
|
||||||
flagAsModified();
|
flagAsModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode)
|
||||||
|
{
|
||||||
|
mCell->selectInsideCube (pointA, pointB, dragMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::selectWithinDistance(const osg::Vec3d& point, float distance, DragMode dragMode)
|
||||||
|
{
|
||||||
|
mCell->selectWithinDistance (point, distance, dragMode);
|
||||||
|
}
|
||||||
|
|
||||||
std::string CSVRender::UnpagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const
|
std::string CSVRender::UnpagedWorldspaceWidget::getCellId (const osg::Vec3f& point) const
|
||||||
{
|
{
|
||||||
return mCellId;
|
return mCellId;
|
||||||
|
|
|
@ -60,6 +60,10 @@ namespace CSVRender
|
||||||
/// \param elementMask Elements to be affected by the select operation
|
/// \param elementMask Elements to be affected by the select operation
|
||||||
void selectAllWithSameParentId (int elementMask) override;
|
void selectAllWithSameParentId (int elementMask) override;
|
||||||
|
|
||||||
|
void selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode) override;
|
||||||
|
|
||||||
|
void selectWithinDistance(const osg::Vec3d& point, float distance, DragMode dragMode) override;
|
||||||
|
|
||||||
std::string getCellId (const osg::Vec3f& point) const override;
|
std::string getCellId (const osg::Vec3f& point) const override;
|
||||||
|
|
||||||
Cell* getCell(const osg::Vec3d& point) const override;
|
Cell* getCell(const osg::Vec3d& point) const override;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
#include "../../model/world/tablemimedata.hpp"
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
|
||||||
|
#include "instancedragmodes.hpp"
|
||||||
#include "scenewidget.hpp"
|
#include "scenewidget.hpp"
|
||||||
#include "mask.hpp"
|
#include "mask.hpp"
|
||||||
|
|
||||||
|
@ -160,6 +161,10 @@ namespace CSVRender
|
||||||
/// \param elementMask Elements to be affected by the select operation
|
/// \param elementMask Elements to be affected by the select operation
|
||||||
virtual void selectAllWithSameParentId (int elementMask) = 0;
|
virtual void selectAllWithSameParentId (int elementMask) = 0;
|
||||||
|
|
||||||
|
virtual void selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode) = 0;
|
||||||
|
|
||||||
|
virtual void selectWithinDistance(const osg::Vec3d& point, float distance, DragMode dragMode) = 0;
|
||||||
|
|
||||||
/// Return the next intersection with scene elements matched by
|
/// Return the next intersection with scene elements matched by
|
||||||
/// \a interactionMask based on \a localPos and the camera vector.
|
/// \a interactionMask based on \a localPos and the camera vector.
|
||||||
/// If there is no such intersection, instead a point "in front" of \a localPos will be
|
/// If there is no such intersection, instead a point "in front" of \a localPos will be
|
||||||
|
|
Loading…
Reference in a new issue