1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-20 02:53:51 +00:00

Fix separate drop, refactor for code reuse

This commit is contained in:
uramer 2021-01-28 22:10:33 +01:00
parent d984d13b1c
commit 36cd818155
2 changed files with 54 additions and 83 deletions

View file

@ -802,39 +802,15 @@ void CSVRender::InstanceMode::deleteSelectedInstances(bool active)
getWorldspaceWidget().clearSelection (Mask_Reference); getWorldspaceWidget().clearSelection (Mask_Reference);
} }
void CSVRender::InstanceMode::dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight) void CSVRender::InstanceMode::dropInstance(CSVRender::Object* object, float dropHeight)
{ {
osg::Vec3d point = object->getPosition().asVec3();
osg::Vec3d start = point;
start.z() += objectHeight;
osg::Vec3d end = point;
end.z() = std::numeric_limits<float>::lowest();
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector (new osgUtil::LineSegmentIntersector(
osgUtil::Intersector::MODEL, start, end) );
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
osgUtil::IntersectionVisitor visitor(intersector);
if (dropMode == TerrainSep)
visitor.setTraversalMask(Mask_Terrain);
if (dropMode == CollisionSep)
visitor.setTraversalMask(Mask_Terrain | Mask_Reference);
mParentNode->accept(visitor);
osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
if (it != intersector->getIntersections().end())
{
osgUtil::LineSegmentIntersector::Intersection intersection = *it;
ESM::Position position = object->getPosition();
object->setEdited(Object::Override_Position); object->setEdited(Object::Override_Position);
position.pos[2] = intersection.getWorldIntersectPoint().z() + objectHeight; ESM::Position position = object->getPosition();
position.pos[2] -= dropHeight;
object->setPosition(position.pos); object->setPosition(position.pos);
} }
}
float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight) float CSVRender::InstanceMode::calculateDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight)
{ {
osg::Vec3d point = object->getPosition().asVec3(); osg::Vec3d point = object->getPosition().asVec3();
@ -848,9 +824,9 @@ float CSVRender::InstanceMode::getDropHeight(DropMode dropMode, CSVRender::Objec
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT); intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
osgUtil::IntersectionVisitor visitor(intersector); osgUtil::IntersectionVisitor visitor(intersector);
if (dropMode == Terrain) if (dropMode & Terrain)
visitor.setTraversalMask(Mask_Terrain); visitor.setTraversalMask(Mask_Terrain);
if (dropMode == Collision) if (dropMode & Collision)
visitor.setTraversalMask(Mask_Terrain | Mask_Reference); visitor.setTraversalMask(Mask_Terrain | Mask_Reference);
mParentNode->accept(visitor); mParentNode->accept(visitor);
@ -897,19 +873,30 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman
CSMWorld::CommandMacro macro (undoStack, commandMsg); CSMWorld::CommandMacro macro (undoStack, commandMsg);
DropObjectDataHandler dropObjectDataHandler(&getWorldspaceWidget()); DropObjectHeightHandler dropObjectDataHandler(&getWorldspaceWidget());
switch (dropMode) if(dropMode & Separate)
{ {
case Terrain: int counter = 0;
case Collision: for (osg::ref_ptr<TagBase> tag : selection)
if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
{
float objectHeight = dropObjectDataHandler.mObjectHeights[counter];
float dropHeight = calculateDropHeight(dropMode, objectTag->mObject, objectHeight);
dropInstance(objectTag->mObject, dropHeight);
objectTag->mObject->apply(macro);
counter++;
}
}
else
{ {
float smallestDropHeight = std::numeric_limits<float>::max(); float smallestDropHeight = std::numeric_limits<float>::max();
int counter = 0; int counter = 0;
for (osg::ref_ptr<TagBase> tag : selection) for (osg::ref_ptr<TagBase> tag : selection)
if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get())) if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
{ {
float thisDrop = getDropHeight(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]); float objectHeight = dropObjectDataHandler.mObjectHeights[counter];
float thisDrop = calculateDropHeight(dropMode, objectTag->mObject, objectHeight);
if (thisDrop < smallestDropHeight) if (thisDrop < smallestDropHeight)
smallestDropHeight = thisDrop; smallestDropHeight = thisDrop;
counter++; counter++;
@ -917,32 +904,13 @@ void CSVRender::InstanceMode::handleDropMethod(DropMode dropMode, QString comman
for (osg::ref_ptr<TagBase> tag : selection) for (osg::ref_ptr<TagBase> tag : selection)
if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get())) if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(tag.get()))
{ {
objectTag->mObject->setEdited (Object::Override_Position); dropInstance(objectTag->mObject, smallestDropHeight);
ESM::Position position = objectTag->mObject->getPosition();
position.pos[2] -= smallestDropHeight;
objectTag->mObject->setPosition(position.pos);
objectTag->mObject->apply(macro); objectTag->mObject->apply(macro);
} }
} }
break;
case TerrainSep:
case CollisionSep:
{
int counter = 0;
for(osg::ref_ptr<TagBase> tag: selection)
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (tag.get()))
{
dropInstance(dropMode, objectTag->mObject, dropObjectDataHandler.mObjectHeights[counter]);
objectTag->mObject->apply (macro);
counter++;
}
}
break;
}
} }
CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worldspacewidget) CSVRender::DropObjectHeightHandler::DropObjectHeightHandler(WorldspaceWidget* worldspacewidget)
: mWorldspaceWidget(worldspacewidget) : mWorldspaceWidget(worldspacewidget)
{ {
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference); std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference);
@ -969,7 +937,7 @@ CSVRender::DropObjectDataHandler::DropObjectDataHandler(WorldspaceWidget* worlds
} }
} }
CSVRender::DropObjectDataHandler::~DropObjectDataHandler() CSVRender::DropObjectHeightHandler::~DropObjectHeightHandler()
{ {
std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference); std::vector<osg::ref_ptr<TagBase> > selection = mWorldspaceWidget->getSelection (Mask_Reference);
int counter = 0; int counter = 0;

View file

@ -28,10 +28,13 @@ namespace CSVRender
enum DropMode enum DropMode
{ {
Collision, Separate = 0x1,
Terrain,
CollisionSep, Collision = 0b10,
TerrainSep Terrain = 0b100,
CollisionSep = Collision | Separate,
TerrainSep = Terrain | Separate,
}; };
CSVWidget::SceneToolMode *mSubMode; CSVWidget::SceneToolMode *mSubMode;
@ -53,8 +56,8 @@ namespace CSVRender
osg::Vec3f getProjectionSpaceCoords(const osg::Vec3f& pos); osg::Vec3f getProjectionSpaceCoords(const osg::Vec3f& pos);
osg::Vec3f getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart); osg::Vec3f getMousePlaneCoords(const QPoint& point, const osg::Vec3d& dragStart);
void handleSelectDrag(const QPoint& pos); void handleSelectDrag(const QPoint& pos);
void dropInstance(DropMode dropMode, CSVRender::Object* object, float objectHeight); void dropInstance(CSVRender::Object* object, float objectHeight);
float getDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight); float calculateDropHeight(DropMode dropMode, CSVRender::Object* object, float objectHeight);
public: public:
@ -116,11 +119,11 @@ namespace CSVRender
}; };
/// \brief Helper class to handle object mask data in safe way /// \brief Helper class to handle object mask data in safe way
class DropObjectDataHandler class DropObjectHeightHandler
{ {
public: public:
DropObjectDataHandler(WorldspaceWidget* worldspacewidget); DropObjectHeightHandler(WorldspaceWidget* worldspacewidget);
~DropObjectDataHandler(); ~DropObjectHeightHandler();
std::vector<float> mObjectHeights; std::vector<float> mObjectHeights;
private: private: