mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-28 19:21:04 +00:00
Merge branch 'VA_OpenMW-CS' into 'master'
OpenMW-CS: Issue #3245 Add configurable instance grid, angle, and scale snapping Closes #3245 See merge request OpenMW/openmw!1737
This commit is contained in:
commit
84458baa8b
@ -227,6 +227,7 @@ Programmers
|
|||||||
unelsson
|
unelsson
|
||||||
uramer
|
uramer
|
||||||
viadanna
|
viadanna
|
||||||
|
Vidi_Aquam
|
||||||
Vincent Heuken
|
Vincent Heuken
|
||||||
Vladimir Panteleev (CyberShadow)
|
Vladimir Panteleev (CyberShadow)
|
||||||
vocollapse
|
vocollapse
|
||||||
|
@ -115,6 +115,7 @@
|
|||||||
Feature #2491: Ability to make OpenMW "portable"
|
Feature #2491: Ability to make OpenMW "portable"
|
||||||
Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record
|
Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record
|
||||||
Feature #2780: A way to see current OpenMW version in the console
|
Feature #2780: A way to see current OpenMW version in the console
|
||||||
|
Feature #3245: Grid and angle snapping for the OpenMW-CS
|
||||||
Feature #3616: Allow Zoom levels on the World Map
|
Feature #3616: Allow Zoom levels on the World Map
|
||||||
Feature #4297: Implement APPLIED_ONCE flag for magic effects
|
Feature #4297: Implement APPLIED_ONCE flag for magic effects
|
||||||
Feature #4414: Handle duration of EXTRA SPELL magic effect
|
Feature #4414: Handle duration of EXTRA SPELL magic effect
|
||||||
|
@ -243,6 +243,9 @@ void CSMPrefs::State::declare()
|
|||||||
secondarySelectAction.add (SelectOnly).add (SelectAdd).add (SelectRemove).add (selectInvert);
|
secondarySelectAction.add (SelectOnly).add (SelectAdd).add (SelectRemove).add (selectInvert);
|
||||||
|
|
||||||
declareCategory ("3D Scene Editing");
|
declareCategory ("3D Scene Editing");
|
||||||
|
declareDouble("gridsnap-movement", "Grid snap size", 16);
|
||||||
|
declareDouble("gridsnap-rotation", "Angle snap size", 15);
|
||||||
|
declareDouble("gridsnap-scale", "Scale snap size", 0.25);
|
||||||
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 "
|
||||||
"insert point, it will be placed by this distance from the insert point instead");
|
"insert point, it will be placed by this distance from the insert point instead");
|
||||||
|
@ -12,7 +12,10 @@ namespace CSVRender
|
|||||||
DragMode_Select_Only,
|
DragMode_Select_Only,
|
||||||
DragMode_Select_Add,
|
DragMode_Select_Add,
|
||||||
DragMode_Select_Remove,
|
DragMode_Select_Remove,
|
||||||
DragMode_Select_Invert
|
DragMode_Select_Invert,
|
||||||
|
DragMode_Move_Snap,
|
||||||
|
DragMode_Rotate_Snap,
|
||||||
|
DragMode_Scale_Snap
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,6 +64,11 @@ osg::Quat CSVRender::InstanceMode::eulerToQuat(const osg::Vec3f& euler) const
|
|||||||
return zr * yr * xr;
|
return zr * yr * xr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CSVRender::InstanceMode::roundFloatToMult(const float val, const double mult) const
|
||||||
|
{
|
||||||
|
return round(val / mult) * mult;
|
||||||
|
}
|
||||||
|
|
||||||
osg::Vec3f CSVRender::InstanceMode::getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const
|
osg::Vec3f CSVRender::InstanceMode::getSelectionCenter(const std::vector<osg::ref_ptr<TagBase> >& selection) const
|
||||||
{
|
{
|
||||||
osg::Vec3f center = osg::Vec3f(0, 0, 0);
|
osg::Vec3f center = osg::Vec3f(0, 0, 0);
|
||||||
@ -156,15 +161,13 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar)
|
|||||||
"<ul><li>Use {scene-edit-primary} to rotate instances freely</li>"
|
"<ul><li>Use {scene-edit-primary} to rotate instances freely</li>"
|
||||||
"<li>Use {scene-edit-secondary} to rotate instances within the grid</li>"
|
"<li>Use {scene-edit-secondary} to rotate instances within the grid</li>"
|
||||||
"<li>The center of the view acts as the axis of rotation</li>"
|
"<li>The center of the view acts as the axis of rotation</li>"
|
||||||
"</ul>"
|
"</ul>");
|
||||||
"<font color=Red>Grid rotate not implemented yet</font color>");
|
|
||||||
mSubMode->addButton (":scenetoolbar/transform-scale", "scale",
|
mSubMode->addButton (":scenetoolbar/transform-scale", "scale",
|
||||||
"Scale selected instances"
|
"Scale selected instances"
|
||||||
"<ul><li>Use {scene-edit-primary} to scale instances freely</li>"
|
"<ul><li>Use {scene-edit-primary} to scale instances freely</li>"
|
||||||
"<li>Use {scene-edit-secondary} to scale instances along the grid</li>"
|
"<li>Use {scene-edit-secondary} to scale instances along the grid</li>"
|
||||||
"<li>The scaling rate is based on how close the start of a drag is to the center of the screen</li>"
|
"<li>The scaling rate is based on how close the start of a drag is to the center of the screen</li>"
|
||||||
"</ul>"
|
"</ul>");
|
||||||
"<font color=Red>Grid scale not implemented yet</font color>");
|
|
||||||
|
|
||||||
mSubMode->setButton (mSubModeId);
|
mSubMode->setButton (mSubModeId);
|
||||||
|
|
||||||
@ -351,10 +354,81 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos)
|
|||||||
|
|
||||||
bool CSVRender::InstanceMode::secondaryEditStartDrag (const QPoint& pos)
|
bool CSVRender::InstanceMode::secondaryEditStartDrag (const QPoint& pos)
|
||||||
{
|
{
|
||||||
if (mLocked)
|
if (mDragMode != DragMode_None || mLocked)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return false;
|
WorldspaceHitResult hit = getWorldspaceWidget().mousePick(pos, getWorldspaceWidget().getInteractionMask());
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection(Mask_Reference);
|
||||||
|
if (selection.empty())
|
||||||
|
{
|
||||||
|
// Only change selection at the start of drag if no object is already selected
|
||||||
|
if (hit.tag && CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue())
|
||||||
|
{
|
||||||
|
getWorldspaceWidget().clearSelection(Mask_Reference);
|
||||||
|
if (CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*> (hit.tag.get()))
|
||||||
|
{
|
||||||
|
CSVRender::Object* object = objectTag->mObject;
|
||||||
|
object->setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selection = getWorldspaceWidget().getSelection(Mask_Reference);
|
||||||
|
if (selection.empty())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mObjectsAtDragStart.clear();
|
||||||
|
|
||||||
|
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 (mSubModeId == "move")
|
||||||
|
{
|
||||||
|
objectTag->mObject->setEdited(Object::Override_Position);
|
||||||
|
float x = objectTag->mObject->getPosition().pos[0];
|
||||||
|
float y = objectTag->mObject->getPosition().pos[1];
|
||||||
|
float z = objectTag->mObject->getPosition().pos[2];
|
||||||
|
osg::Vec3f thisPoint(x, y, z);
|
||||||
|
|
||||||
|
mDragStart = getMousePlaneCoords(pos, getProjectionSpaceCoords(thisPoint));
|
||||||
|
mObjectsAtDragStart.emplace_back(thisPoint);
|
||||||
|
mDragMode = DragMode_Move_Snap;
|
||||||
|
}
|
||||||
|
else if (mSubModeId == "rotate")
|
||||||
|
{
|
||||||
|
objectTag->mObject->setEdited(Object::Override_Rotation);
|
||||||
|
mDragMode = DragMode_Rotate_Snap;
|
||||||
|
}
|
||||||
|
else if (mSubModeId == "scale")
|
||||||
|
{
|
||||||
|
objectTag->mObject->setEdited(Object::Override_Scale);
|
||||||
|
mDragMode = DragMode_Scale_Snap;
|
||||||
|
|
||||||
|
// Calculate scale factor
|
||||||
|
std::vector<osg::ref_ptr<TagBase> > editedSelection = getWorldspaceWidget().getEdited(Mask_Reference);
|
||||||
|
osg::Vec3f center = getScreenCoords(getSelectionCenter(editedSelection));
|
||||||
|
|
||||||
|
int widgetHeight = getWorldspaceWidget().height();
|
||||||
|
|
||||||
|
float dx = pos.x() - center.x();
|
||||||
|
float dy = (widgetHeight - pos.y()) - center.y();
|
||||||
|
|
||||||
|
mUnitScaleDist = std::sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CSVRender::ObjectMarkerTag* objectTag = dynamic_cast<CSVRender::ObjectMarkerTag*> (hit.tag.get()))
|
||||||
|
{
|
||||||
|
mDragAxis = objectTag->mAxis;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mDragAxis = -1;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSVRender::InstanceMode::primarySelectStartDrag (const QPoint& pos)
|
bool CSVRender::InstanceMode::primarySelectStartDrag (const QPoint& pos)
|
||||||
@ -400,8 +474,8 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
|
|
||||||
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
|
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getEdited (Mask_Reference);
|
||||||
|
|
||||||
if (mDragMode == DragMode_Move) {}
|
if (mDragMode == DragMode_Move || mDragMode == DragMode_Move_Snap) {}
|
||||||
else if (mDragMode == DragMode_Rotate)
|
else if (mDragMode == DragMode_Rotate || mDragMode == DragMode_Rotate_Snap)
|
||||||
{
|
{
|
||||||
osg::Vec3f eye, centre, up;
|
osg::Vec3f eye, centre, up;
|
||||||
getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up);
|
getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up);
|
||||||
@ -465,7 +539,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
|
|
||||||
rotation = osg::Quat(angle, axis);
|
rotation = osg::Quat(angle, axis);
|
||||||
}
|
}
|
||||||
else if (mDragMode == DragMode_Scale)
|
else if (mDragMode == DragMode_Scale || mDragMode == DragMode_Scale_Snap)
|
||||||
{
|
{
|
||||||
osg::Vec3f center = getScreenCoords(getSelectionCenter(selection));
|
osg::Vec3f center = getScreenCoords(getSelectionCenter(selection));
|
||||||
|
|
||||||
@ -507,7 +581,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
{
|
{
|
||||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
|
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
|
||||||
{
|
{
|
||||||
if (mDragMode == DragMode_Move)
|
if (mDragMode == DragMode_Move || mDragMode == DragMode_Move_Snap)
|
||||||
{
|
{
|
||||||
ESM::Position position = objectTag->mObject->getPosition();
|
ESM::Position position = objectTag->mObject->getPosition();
|
||||||
osg::Vec3f mousePos = getMousePlaneCoords(pos, getProjectionSpaceCoords(mDragStart));
|
osg::Vec3f mousePos = getMousePlaneCoords(pos, getProjectionSpaceCoords(mDragStart));
|
||||||
@ -518,6 +592,14 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
position.pos[1] = mObjectsAtDragStart[i].y() + addToY;
|
position.pos[1] = mObjectsAtDragStart[i].y() + addToY;
|
||||||
position.pos[2] = mObjectsAtDragStart[i].z() + addToZ;
|
position.pos[2] = mObjectsAtDragStart[i].z() + addToZ;
|
||||||
|
|
||||||
|
if (mDragMode == DragMode_Move_Snap)
|
||||||
|
{
|
||||||
|
double snap = CSMPrefs::get()["3D Scene Editing"]["gridsnap-movement"].toDouble();
|
||||||
|
position.pos[0] = CSVRender::InstanceMode::roundFloatToMult(position.pos[0], snap);
|
||||||
|
position.pos[1] = CSVRender::InstanceMode::roundFloatToMult(position.pos[1], snap);
|
||||||
|
position.pos[2] = CSVRender::InstanceMode::roundFloatToMult(position.pos[2], snap);
|
||||||
|
}
|
||||||
|
|
||||||
// XYZ-locking
|
// XYZ-locking
|
||||||
if (mDragAxis != -1)
|
if (mDragAxis != -1)
|
||||||
{
|
{
|
||||||
@ -530,7 +612,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
|
|
||||||
objectTag->mObject->setPosition(position.pos);
|
objectTag->mObject->setPosition(position.pos);
|
||||||
}
|
}
|
||||||
else if (mDragMode == DragMode_Rotate)
|
else if (mDragMode == DragMode_Rotate || mDragMode == DragMode_Rotate_Snap)
|
||||||
{
|
{
|
||||||
ESM::Position position = objectTag->mObject->getPosition();
|
ESM::Position position = objectTag->mObject->getPosition();
|
||||||
|
|
||||||
@ -548,7 +630,7 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
|
|
||||||
objectTag->mObject->setRotation(position.rot);
|
objectTag->mObject->setRotation(position.rot);
|
||||||
}
|
}
|
||||||
else if (mDragMode == DragMode_Scale)
|
else if (mDragMode == DragMode_Scale || mDragMode == DragMode_Scale_Snap)
|
||||||
{
|
{
|
||||||
// Reset scale
|
// Reset scale
|
||||||
objectTag->mObject->setEdited(0);
|
objectTag->mObject->setEdited(0);
|
||||||
@ -557,6 +639,11 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou
|
|||||||
float scale = objectTag->mObject->getScale();
|
float scale = objectTag->mObject->getScale();
|
||||||
scale *= offset.x();
|
scale *= offset.x();
|
||||||
|
|
||||||
|
if (mDragMode == DragMode_Scale_Snap)
|
||||||
|
{
|
||||||
|
scale = CSVRender::InstanceMode::roundFloatToMult(scale, CSMPrefs::get()["3D Scene Editing"]["gridsnap-scale"].toDouble());
|
||||||
|
}
|
||||||
|
|
||||||
objectTag->mObject->setScale (scale);
|
objectTag->mObject->setScale (scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,7 +680,9 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
|||||||
handleSelectDrag(pos);
|
handleSelectDrag(pos);
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
case DragMode_Move_Snap: description = "Move Instances"; break;
|
||||||
|
case DragMode_Rotate_Snap: description = "Rotate Instances"; break;
|
||||||
|
case DragMode_Scale_Snap: description = "Scale Instances"; break;
|
||||||
case DragMode_None: break;
|
case DragMode_None: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,6 +694,17 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos)
|
|||||||
{
|
{
|
||||||
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
|
if (CSVRender::ObjectTag *objectTag = dynamic_cast<CSVRender::ObjectTag *> (iter->get()))
|
||||||
{
|
{
|
||||||
|
if (mDragMode == DragMode_Rotate_Snap)
|
||||||
|
{
|
||||||
|
ESM::Position position = objectTag->mObject->getPosition();
|
||||||
|
double snap = CSMPrefs::get()["3D Scene Editing"]["gridsnap-rotation"].toDouble();
|
||||||
|
position.rot[0] = CSVRender::InstanceMode::roundFloatToMult(position.rot[0], osg::DegreesToRadians(snap));
|
||||||
|
position.rot[1] = CSVRender::InstanceMode::roundFloatToMult(position.rot[1], osg::DegreesToRadians(snap));
|
||||||
|
position.rot[2] = CSVRender::InstanceMode::roundFloatToMult(position.rot[2], osg::DegreesToRadians(snap));
|
||||||
|
|
||||||
|
objectTag->mObject->setRotation(position.rot);
|
||||||
|
}
|
||||||
|
|
||||||
objectTag->mObject->apply (macro);
|
objectTag->mObject->apply (macro);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,7 +721,7 @@ void CSVRender::InstanceMode::dragAborted()
|
|||||||
|
|
||||||
void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
||||||
{
|
{
|
||||||
if (mDragMode==DragMode_Move)
|
if (mDragMode==DragMode_Move || mDragMode==DragMode_Move_Snap)
|
||||||
{
|
{
|
||||||
osg::Vec3f eye;
|
osg::Vec3f eye;
|
||||||
osg::Vec3f centre;
|
osg::Vec3f centre;
|
||||||
@ -646,6 +746,15 @@ void CSVRender::InstanceMode::dragWheel (int diff, double speedFactor)
|
|||||||
ESM::Position position = objectTag->mObject->getPosition();
|
ESM::Position position = objectTag->mObject->getPosition();
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
position.pos[i] += offset[i];
|
position.pos[i] += offset[i];
|
||||||
|
|
||||||
|
if (mDragMode == DragMode_Move_Snap)
|
||||||
|
{
|
||||||
|
double snap = CSMPrefs::get()["3D Scene Editing"]["gridsnap-movement"].toDouble();
|
||||||
|
position.pos[0] = CSVRender::InstanceMode::roundFloatToMult(position.pos[0], snap);
|
||||||
|
position.pos[1] = CSVRender::InstanceMode::roundFloatToMult(position.pos[1], snap);
|
||||||
|
position.pos[2] = CSVRender::InstanceMode::roundFloatToMult(position.pos[2], snap);
|
||||||
|
}
|
||||||
|
|
||||||
objectTag->mObject->setPosition (position.pos);
|
objectTag->mObject->setPosition (position.pos);
|
||||||
osg::Vec3f thisPoint(position.pos[0], position.pos[1], position.pos[2]);
|
osg::Vec3f thisPoint(position.pos[0], position.pos[1], position.pos[2]);
|
||||||
mDragStart = getMousePlaneCoords(getWorldspaceWidget().mapFromGlobal(QCursor::pos()), getProjectionSpaceCoords(thisPoint));
|
mDragStart = getMousePlaneCoords(getWorldspaceWidget().mapFromGlobal(QCursor::pos()), getProjectionSpaceCoords(thisPoint));
|
||||||
|
@ -53,6 +53,8 @@ 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;
|
||||||
|
|
||||||
|
float roundFloatToMult(const float val, const double mult) const;
|
||||||
|
|
||||||
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 getProjectionSpaceCoords(const osg::Vec3f& pos);
|
||||||
|
@ -6,7 +6,6 @@ CSVRender::InstanceMoveMode::InstanceMoveMode (QWidget *parent)
|
|||||||
"Move selected instances"
|
"Move selected instances"
|
||||||
"<ul><li>Use {scene-edit-primary} to move instances around freely</li>"
|
"<ul><li>Use {scene-edit-primary} to move instances around freely</li>"
|
||||||
"<li>Use {scene-edit-secondary} to move instances around within the grid</li>"
|
"<li>Use {scene-edit-secondary} to move instances around within the grid</li>"
|
||||||
"</ul>"
|
"</ul>",
|
||||||
"<font color=Red>Grid move not implemented yet</font color>",
|
|
||||||
parent)
|
parent)
|
||||||
{}
|
{}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user