1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-18 18:40:06 +00:00

Scale from center of selection.

This commit is contained in:
Aesylwinn 2016-08-12 17:11:37 -04:00
parent 388917df89
commit 571969cd65
2 changed files with 51 additions and 10 deletions

View File

@ -59,6 +59,36 @@ osg::Quat CSVRender::InstanceMode::eulerToQuat(const osg::Vec3f& euler) const
return zr * yr * xr; return zr * yr * xr;
} }
osg::Vec3f CSVRender::InstanceMode::getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const
{
osg::Vec3f center = osg::Vec3f(0, 0, 0);
int objectCount = 0;
for (std::vector<osg::ref_ptr<TagBase> >::const_iterator iter (selection.begin()); iter!=selection.end(); ++iter)
{
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
{
const ESM::Position& position = objectTag->mObject->getPosition();
center += osg::Vec3f(position.pos[0], position.pos[1], position.pos[2]);
++objectCount;
}
}
center /= objectCount;
return center;
}
osg::Vec3f CSVRender::InstanceMode::getScreenCoords(const osg::Vec3f& pos)
{
osg::Matrix viewMatrix = getWorldspaceWidget().getCamera()->getViewMatrix();
osg::Matrix projMatrix = getWorldspaceWidget().getCamera()->getProjectionMatrix();
osg::Matrix windowMatrix = getWorldspaceWidget().getCamera()->getViewport()->computeWindowMatrix();
osg::Matrix combined = viewMatrix * projMatrix * windowMatrix;
return pos * combined;
}
CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent)
: EditMode (worldspaceWidget, QIcon (":placeholder"), Mask_Reference, "Instance editing", : EditMode (worldspaceWidget, QIcon (":placeholder"), Mask_Reference, "Instance editing",
parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None), parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None),
@ -223,14 +253,16 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
objectTag->mObject->setEdited (Object::Override_Scale); objectTag->mObject->setEdited (Object::Override_Scale);
mDragMode = DragMode_Scale; mDragMode = DragMode_Scale;
// Calculate scale // Calculate scale factor
int widgetWidth = getWorldspaceWidget().width(); std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
osg::Vec3f center = getScreenCoords(getSelectionCenter(selection));
int widgetHeight = getWorldspaceWidget().height(); int widgetHeight = getWorldspaceWidget().height();
int x = pos.x() - widgetWidth / 2; float dx = pos.x() - center.x();
int y = pos.y() - widgetHeight / 2; float dy = (widgetHeight - pos.y()) - center.y();
mUnitScaleDist = std::sqrt(x * x + y * y); mUnitScaleDist = std::sqrt(dx * dx + dy * dy);
} }
} }
} }
@ -258,6 +290,8 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
osg::Vec3f offset; osg::Vec3f offset;
osg::Quat rotation; osg::Quat rotation;
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
if (mDragMode == DragMode_Move) if (mDragMode == DragMode_Move)
{ {
osg::Vec3f eye, centre, up; osg::Vec3f eye, centre, up;
@ -330,20 +364,22 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
} }
else if (mDragMode == DragMode_Scale) else if (mDragMode == DragMode_Scale)
{ {
int widgetWidth = getWorldspaceWidget().width(); osg::Vec3f center = getScreenCoords(getSelectionCenter(selection));
// Calculate scaling distance/rate
int widgetHeight = getWorldspaceWidget().height(); int widgetHeight = getWorldspaceWidget().height();
int x = pos.x() - widgetWidth / 2; float dx = pos.x() - center.x();
int y = pos.y() - widgetHeight / 2; float dy = (widgetHeight - pos.y()) - center.y();
float dist = std::sqrt(x * x + y * y); float dist = std::sqrt(dx * dx + dy * dy);
float scale = dist / mUnitScaleDist; float scale = dist / mUnitScaleDist;
// Only uniform scaling is currently supported // Only uniform scaling is currently supported
offset = osg::Vec3f(scale, scale, scale); offset = osg::Vec3f(scale, scale, scale);
} }
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference); // 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)
{ {
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get())) if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))

View File

@ -1,6 +1,7 @@
#ifndef CSV_RENDER_INSTANCEMODE_H #ifndef CSV_RENDER_INSTANCEMODE_H
#define CSV_RENDER_INSTANCEMODE_H #define CSV_RENDER_INSTANCEMODE_H
#include <osg/ref_ptr>
#include <osg/Quat> #include <osg/Quat>
#include <osg/Vec3f> #include <osg/Vec3f>
@ -13,6 +14,7 @@ namespace CSVWidget
namespace CSVRender namespace CSVRender
{ {
class TagBase;
class InstanceSelectionMode; class InstanceSelectionMode;
class InstanceMode : public EditMode class InstanceMode : public EditMode
@ -40,6 +42,9 @@ namespace CSVRender
osg::Vec3f quatToEuler(const osg::Quat& quat) const; osg::Vec3f quatToEuler(const osg::Quat& quat) const;
osg::Quat eulerToQuat(const osg::Vec3f& euler) const; osg::Quat eulerToQuat(const osg::Vec3f& euler) const;
osg::Vec3f getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const;
osg::Vec3f getScreenCoords(const osg::Vec3f& pos);
public: public:
InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0);