From 388917df891fe164035c6b30f74b272630f38def Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Wed, 10 Aug 2016 19:31:34 -0400 Subject: [PATCH 01/22] Base editor rotate/scale commit. --- apps/opencs/view/render/instancemode.cpp | 233 ++++++++++++++++++----- apps/opencs/view/render/instancemode.hpp | 11 +- apps/opencs/view/render/object.cpp | 133 +++++++++++-- apps/opencs/view/render/object.hpp | 10 +- 4 files changed, 323 insertions(+), 64 deletions(-) diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 4eb9ea388..80687359e 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -27,6 +27,38 @@ int CSVRender::InstanceMode::getSubModeFromId (const std::string& id) const return id=="move" ? 0 : (id=="rotate" ? 1 : 2); } +osg::Vec3f CSVRender::InstanceMode::quatToEuler(const osg::Quat& rot) const +{ + const float Pi = 3.14159265f; + + float x, y, z; + float test = 2 * (rot.w() * rot.y() + rot.x() * rot.z()); + + if (std::abs(test) >= 1.f) + { + x = atan2(rot.x(), rot.w()); + y = (test > 0) ? (Pi / 2) : (-Pi / 2); + z = 0; + } + else + { + x = std::atan2(2 * (rot.w() * rot.x() - rot.y() * rot.z()), 1 - 2 * (rot.x() * rot.x() + rot.y() * rot.y())); + y = std::asin(test); + z = std::atan2(2 * (rot.w() * rot.z() - rot.x() * rot.y()), 1 - 2 * (rot.y() * rot.y() + rot.z() * rot.z())); + } + + return osg::Vec3f(-x, -y, -z); +} + +osg::Quat CSVRender::InstanceMode::eulerToQuat(const osg::Vec3f& euler) const +{ + osg::Quat xr = osg::Quat(-euler[0], osg::Vec3f(1,0,0)); + osg::Quat yr = osg::Quat(-euler[1], osg::Vec3f(0,1,0)); + osg::Quat zr = osg::Quat(-euler[2], osg::Vec3f(0,0,1)); + + return zr * yr * xr; +} + CSVRender::InstanceMode::InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) : EditMode (worldspaceWidget, QIcon (":placeholder"), Mask_Reference, "Instance editing", parent), mSubMode (0), mSubModeId ("move"), mSelectionMode (0), mDragMode (DragMode_None), @@ -44,14 +76,16 @@ void CSVRender::InstanceMode::activate (CSVWidget::SceneToolbar *toolbar) "Rotate selected instances" "" - "Not implemented yet"); + "Grid rotate not implemented yet"); mSubMode->addButton (":placeholder", "scale", "Scale selected instances" "" - "Not implemented yet"); + "Grid scale not implemented yet"); mSubMode->setButton (mSubModeId); @@ -151,6 +185,7 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos) if (mDragMode!=DragMode_None || mLocked) return false; + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); if (hit.tag && CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue()) { @@ -173,12 +208,33 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos) { if (CSVRender::ObjectTag *objectTag = dynamic_cast (iter->get())) { - objectTag->mObject->setEdited (Object::Override_Position); + if (mSubModeId == "move") + { + objectTag->mObject->setEdited (Object::Override_Position); + mDragMode = DragMode_Move; + } + else if (mSubModeId == "rotate") + { + objectTag->mObject->setEdited (Object::Override_Rotation); + mDragMode = DragMode_Rotate; + } + else if (mSubModeId == "scale") + { + objectTag->mObject->setEdited (Object::Override_Scale); + mDragMode = DragMode_Scale; + + // Calculate scale + int widgetWidth = getWorldspaceWidget().width(); + int widgetHeight = getWorldspaceWidget().height(); + + int x = pos.x() - widgetWidth / 2; + int y = pos.y() - widgetHeight / 2; + + mUnitScaleDist = std::sqrt(x * x + y * y); + } } } - // \todo check for sub-mode - if (CSVRender::ObjectMarkerTag *objectTag = dynamic_cast (hit.tag.get())) { mDragAxis = objectTag->mAxis; @@ -186,8 +242,6 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos) else mDragAxis = -1; - mDragMode = DragMode_Move; - return true; } @@ -201,48 +255,139 @@ bool CSVRender::InstanceMode::secondaryEditStartDrag (const QPoint& pos) void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) { - osg::Vec3f eye; - osg::Vec3f centre; - osg::Vec3f up; - - getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up); - osg::Vec3f offset; + osg::Quat rotation; - if (diffY) - offset += up * diffY * speedFactor; - - if (diffX) - offset += ((centre-eye) ^ up) * diffX * speedFactor; - - switch (mDragMode) + if (mDragMode == DragMode_Move) { - case DragMode_Move: + osg::Vec3f eye, centre, up; + getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up); + + if (diffY) { - if (mDragAxis!=-1) - for (int i=0; i<3; ++i) - if (i!=mDragAxis) - offset[i] = 0; - - std::vector > selection = - getWorldspaceWidget().getEdited (Mask_Reference); - - for (std::vector >::iterator iter (selection.begin()); - iter!=selection.end(); ++iter) - { - if (CSVRender::ObjectTag *objectTag = dynamic_cast (iter->get())) - { - ESM::Position position = objectTag->mObject->getPosition(); - for (int i=0; i<3; ++i) - position.pos[i] += offset[i]; - objectTag->mObject->setPosition (position.pos); - } - } - - break; + offset += up * diffY * speedFactor; + } + if (diffX) + { + offset += ((centre-eye) ^ up) * diffX * speedFactor; } - case DragMode_None: break; + if (mDragAxis!=-1) + { + for (int i=0; i<3; ++i) + { + if (i!=mDragAxis) + offset[i] = 0; + } + } + } + else if (mDragMode == DragMode_Rotate) + { + osg::Vec3f eye, centre, up; + getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up); + + osg::Vec3f camBack = eye - centre; + + // Convert coordinate system + int widgetWidth = getWorldspaceWidget().width(); + int widgetHeight = getWorldspaceWidget().height(); + + int newX = pos.x() - widgetWidth / 2; + int newY = -pos.y() + widgetHeight / 2; + + int oldX = newX - diffX; + int oldY = newY - diffY; // diffY appears to already be flipped + + osg::Vec3f oldVec = osg::Vec3f(oldX, oldY, 0); + oldVec.normalize(); + + osg::Vec3f newVec = osg::Vec3f(newX, newY, 0); + newVec.normalize(); + + // Find angle and axis of rotation + float angle = std::acos(oldVec * newVec) * speedFactor; + if (((oldVec ^ newVec) * camBack < 0) ^ (camBack.z() < 0)) + angle *= -1; + + osg::Vec3f axis; + if (mDragAxis != -1) + { + for (int i = 0; i < 3; ++i) + { + if (i == mDragAxis) + axis[i] = 1; + else + axis[i] = 0; + } + + if (camBack * axis < 0) + axis *= -1; + } + else + axis = camBack; + + rotation = osg::Quat(angle, axis); + } + else if (mDragMode == DragMode_Scale) + { + int widgetWidth = getWorldspaceWidget().width(); + int widgetHeight = getWorldspaceWidget().height(); + + int x = pos.x() - widgetWidth / 2; + int y = pos.y() - widgetHeight / 2; + + float dist = std::sqrt(x * x + y * y); + float scale = dist / mUnitScaleDist; + + // Only uniform scaling is currently supported + offset = osg::Vec3f(scale, scale, scale); + } + + std::vector > selection = getWorldspaceWidget().getEdited (Mask_Reference); + for (std::vector >::iterator iter (selection.begin()); iter!=selection.end(); ++iter) + { + if (CSVRender::ObjectTag *objectTag = dynamic_cast (iter->get())) + { + if (mDragMode == DragMode_Move) + { + ESM::Position position = objectTag->mObject->getPosition(); + for (int i=0; i<3; ++i) + { + position.pos[i] += offset[i]; + } + + objectTag->mObject->setPosition(position.pos); + } + else if (mDragMode == DragMode_Rotate) + { + ESM::Position position = objectTag->mObject->getPosition(); + + osg::Quat currentRot = eulerToQuat(osg::Vec3f(position.rot[0], position.rot[1], position.rot[2])); + osg::Quat combined = currentRot * rotation; + + osg::Vec3f euler = quatToEuler(combined); + // There appears to be a very rare rounding error that can cause asin to return NaN + if (!euler.isNaN()) + { + position.rot[0] = euler.x(); + position.rot[1] = euler.y(); + position.rot[2] = euler.z(); + } + + objectTag->mObject->setRotation(position.rot); + } + else if (mDragMode == DragMode_Scale) + { + // Reset scale + objectTag->mObject->setEdited(0); + objectTag->mObject->setEdited(Object::Override_Scale); + + float scale = objectTag->mObject->getScale(); + scale *= offset.x(); + + objectTag->mObject->setScale (scale); + } + } } } @@ -258,6 +403,8 @@ void CSVRender::InstanceMode::dragCompleted(const QPoint& pos) switch (mDragMode) { case DragMode_Move: description = "Move Instances"; break; + case DragMode_Rotate: description = "Rotate Instances"; break; + case DragMode_Scale: description = "Scale Instances"; break; case DragMode_None: break; } diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index 4f7937b51..dd2755237 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -1,6 +1,9 @@ #ifndef CSV_RENDER_INSTANCEMODE_H #define CSV_RENDER_INSTANCEMODE_H +#include +#include + #include "editmode.hpp" namespace CSVWidget @@ -19,7 +22,9 @@ namespace CSVRender enum DragMode { DragMode_None, - DragMode_Move + DragMode_Move, + DragMode_Rotate, + DragMode_Scale }; CSVWidget::SceneToolMode *mSubMode; @@ -28,9 +33,13 @@ namespace CSVRender DragMode mDragMode; int mDragAxis; bool mLocked; + float mUnitScaleDist; int getSubModeFromId (const std::string& id) const; + osg::Vec3f quatToEuler(const osg::Quat& quat) const; + osg::Quat eulerToQuat(const osg::Vec3f& euler) const; + public: InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index cc151ead9..3a6640c54 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -29,6 +29,13 @@ #include "mask.hpp" + +const float CSVRender::Object::MarkerShaftWidth = 30; +const float CSVRender::Object::MarkerShaftBaseLength = 70; +const float CSVRender::Object::MarkerHeadWidth = 50; +const float CSVRender::Object::MarkerHeadLength = 50; + + namespace { @@ -179,7 +186,21 @@ void CSVRender::Object::updateMarker() { if (mSubMode==0) { - mMarker[i] = makeMarker (i); + mMarker[i] = makeMoveOrScaleMarker (i); + mMarker[i]->setUserData(new ObjectMarkerTag (this, i)); + + mRootNode->addChild (mMarker[i]); + } + else if (mSubMode==1) + { + mMarker[i] = makeRotateMarker (i); + mMarker[i]->setUserData(new ObjectMarkerTag (this, i)); + + mRootNode->addChild (mMarker[i]); + } + else if (mSubMode==2) + { + mMarker[i] = makeMoveOrScaleMarker (i); mMarker[i]->setUserData(new ObjectMarkerTag (this, i)); mRootNode->addChild (mMarker[i]); @@ -188,16 +209,11 @@ void CSVRender::Object::updateMarker() } } -osg::ref_ptr CSVRender::Object::makeMarker (int axis) +osg::ref_ptr CSVRender::Object::makeMoveOrScaleMarker (int axis) { osg::ref_ptr geometry (new osg::Geometry); - const float shaftWidth = 10; - const float shaftBaseLength = 50; - const float headWidth = 30; - const float headLength = 30; - - float shaftLength = shaftBaseLength + mBaseNode->getBound().radius(); + float shaftLength = MarkerShaftBaseLength + mBaseNode->getBound().radius(); // shaft osg::Vec3Array *vertices = new osg::Vec3Array; @@ -206,20 +222,20 @@ osg::ref_ptr CSVRender::Object::makeMarker (int axis) { float length = i ? shaftLength : 0; - vertices->push_back (getMarkerPosition (-shaftWidth/2, -shaftWidth/2, length, axis)); - vertices->push_back (getMarkerPosition (-shaftWidth/2, shaftWidth/2, length, axis)); - vertices->push_back (getMarkerPosition (shaftWidth/2, shaftWidth/2, length, axis)); - vertices->push_back (getMarkerPosition (shaftWidth/2, -shaftWidth/2, length, axis)); + vertices->push_back (getMarkerPosition (-MarkerShaftWidth/2, -MarkerShaftWidth/2, length, axis)); + vertices->push_back (getMarkerPosition (-MarkerShaftWidth/2, MarkerShaftWidth/2, length, axis)); + vertices->push_back (getMarkerPosition (MarkerShaftWidth/2, MarkerShaftWidth/2, length, axis)); + vertices->push_back (getMarkerPosition (MarkerShaftWidth/2, -MarkerShaftWidth/2, length, axis)); } // head backside - vertices->push_back (getMarkerPosition (-headWidth/2, -headWidth/2, shaftLength, axis)); - vertices->push_back (getMarkerPosition (-headWidth/2, headWidth/2, shaftLength, axis)); - vertices->push_back (getMarkerPosition (headWidth/2, headWidth/2, shaftLength, axis)); - vertices->push_back (getMarkerPosition (headWidth/2, -headWidth/2, shaftLength, axis)); + vertices->push_back (getMarkerPosition (-MarkerHeadWidth/2, -MarkerHeadWidth/2, shaftLength, axis)); + vertices->push_back (getMarkerPosition (-MarkerHeadWidth/2, MarkerHeadWidth/2, shaftLength, axis)); + vertices->push_back (getMarkerPosition (MarkerHeadWidth/2, MarkerHeadWidth/2, shaftLength, axis)); + vertices->push_back (getMarkerPosition (MarkerHeadWidth/2, -MarkerHeadWidth/2, shaftLength, axis)); // head - vertices->push_back (getMarkerPosition (0, 0, shaftLength+headLength, axis)); + vertices->push_back (getMarkerPosition (0, 0, shaftLength+MarkerHeadLength, axis)); geometry->setVertexArray (vertices); @@ -285,6 +301,87 @@ osg::ref_ptr CSVRender::Object::makeMarker (int axis) return geode; } +osg::ref_ptr CSVRender::Object::makeRotateMarker (int axis) +{ + const float Pi = 3.14159265f; + + const float InnerRadius = mBaseNode->getBound().radius(); + const float OuterRadius = InnerRadius + MarkerShaftWidth; + + const float SegmentDistance = 100.f; + const size_t SegmentCount = std::min(64, std::max(8, (int)(OuterRadius * 2 * Pi / SegmentDistance))); + const size_t VerticesPerSegment = 4; + const size_t IndicesPerSegment = 24; + + const size_t VertexCount = SegmentCount * VerticesPerSegment; + const size_t IndexCount = SegmentCount * IndicesPerSegment; + + const float Angle = 2 * Pi / SegmentCount; + + const unsigned short IndexPattern[IndicesPerSegment] = + { + 0, 4, 5, 0, 5, 1, + 2, 6, 4, 2, 4, 0, + 3, 7, 6, 3, 6, 2, + 1, 5, 7, 1, 7, 3 + }; + + + osg::ref_ptr geometry = new osg::Geometry(); + + osg::ref_ptr vertices = new osg::Vec3Array(VertexCount); + osg::ref_ptr colors = new osg::Vec4Array(1); + osg::ref_ptr primitives = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, + IndexCount); + + for (size_t i = 0; i < SegmentCount; ++i) + { + size_t index = i * VerticesPerSegment; + + float innerX = InnerRadius * std::cos(i * Angle); + float innerY = InnerRadius * std::sin(i * Angle); + + float outerX = OuterRadius * std::cos(i * Angle); + float outerY = OuterRadius * std::sin(i * Angle); + + vertices->at(index++) = getMarkerPosition(innerX, innerY, MarkerShaftWidth / 2, axis); + vertices->at(index++) = getMarkerPosition(innerX, innerY, -MarkerShaftWidth / 2, axis); + vertices->at(index++) = getMarkerPosition(outerX, outerY, MarkerShaftWidth / 2, axis); + vertices->at(index++) = getMarkerPosition(outerX, outerY, -MarkerShaftWidth / 2, axis); + } + + colors->at(0) = osg::Vec4f (axis==0 ? 1.0f : 0.2f, axis==1 ? 1.0f : 0.2f, axis==2 ? 1.0f : 0.2f, 1.0f); + + for (size_t i = 0; i < SegmentCount; ++i) + { + size_t indices[IndicesPerSegment]; + for (size_t j = 0; j < IndicesPerSegment; ++j) + { + indices[j] = i * VerticesPerSegment + j; + + if (indices[j] >= VertexCount) + indices[j] -= VertexCount; + } + + size_t offset = i * IndicesPerSegment; + for (size_t j = 0; j < IndicesPerSegment; ++j) + { + primitives->setElement(offset++, indices[IndexPattern[j]]); + } + } + + geometry->setVertexArray(vertices); + geometry->setColorArray(colors, osg::Array::BIND_OVERALL); + geometry->addPrimitiveSet(primitives); + + geometry->getOrCreateStateSet()->setMode (GL_LIGHTING, osg::StateAttribute::OFF); + + osg::ref_ptr geode = new osg::Geode(); + geode->addDrawable (geometry); + + return geode; +} + osg::Vec3f CSVRender::Object::getMarkerPosition (float x, float y, float z, int axis) { switch (axis) @@ -494,7 +591,7 @@ ESM::Position CSVRender::Object::getPosition() const float CSVRender::Object::getScale() const { - return mOverrideFlags & Override_Scale ? mScaleOverride : getReference().mScale; + return (mOverrideFlags & Override_Scale) ? mScaleOverride : getReference().mScale; } void CSVRender::Object::setPosition (const float position[3]) diff --git a/apps/opencs/view/render/object.hpp b/apps/opencs/view/render/object.hpp index 54a284fa3..d3cba6c55 100644 --- a/apps/opencs/view/render/object.hpp +++ b/apps/opencs/view/render/object.hpp @@ -78,6 +78,11 @@ namespace CSVRender private: + static const float MarkerShaftWidth; + static const float MarkerShaftBaseLength; + static const float MarkerHeadWidth; + static const float MarkerHeadLength; + CSMWorld::Data& mData; std::string mReferenceId; std::string mReferenceableId; @@ -89,7 +94,7 @@ namespace CSVRender Resource::ResourceSystem* mResourceSystem; bool mForceBaseToZero; ESM::Position mPositionOverride; - int mScaleOverride; + float mScaleOverride; int mOverrideFlags; osg::ref_ptr mMarker[3]; int mSubMode; @@ -115,7 +120,8 @@ namespace CSVRender void updateMarker(); - osg::ref_ptr makeMarker (int axis); + osg::ref_ptr makeMoveOrScaleMarker (int axis); + osg::ref_ptr makeRotateMarker (int axis); osg::Vec3f getMarkerPosition (float x, float y, float z, int axis); From 571969cd6534772ab22daf3bcf87a2ac7ecb51c4 Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Fri, 12 Aug 2016 17:11:37 -0400 Subject: [PATCH 02/22] Scale from center of selection. --- apps/opencs/view/render/instancemode.cpp | 56 +++++++++++++++++++----- apps/opencs/view/render/instancemode.hpp | 5 +++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 80687359e..5b5edef9e 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -59,6 +59,36 @@ osg::Quat CSVRender::InstanceMode::eulerToQuat(const osg::Vec3f& euler) const return zr * yr * xr; } +osg::Vec3f CSVRender::InstanceMode::getSelectionCenter(const std::vector >& selection) const +{ + osg::Vec3f center = osg::Vec3f(0, 0, 0); + int objectCount = 0; + + for (std::vector >::const_iterator iter (selection.begin()); iter!=selection.end(); ++iter) + { + if (CSVRender::ObjectTag *objectTag = dynamic_cast (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) : EditMode (worldspaceWidget, QIcon (":placeholder"), Mask_Reference, "Instance editing", 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); mDragMode = DragMode_Scale; - // Calculate scale - int widgetWidth = getWorldspaceWidget().width(); + // Calculate scale factor + std::vector > selection = getWorldspaceWidget().getEdited (Mask_Reference); + osg::Vec3f center = getScreenCoords(getSelectionCenter(selection)); + int widgetHeight = getWorldspaceWidget().height(); - int x = pos.x() - widgetWidth / 2; - int y = pos.y() - widgetHeight / 2; + float dx = pos.x() - center.x(); + 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::Quat rotation; + std::vector > selection = getWorldspaceWidget().getEdited (Mask_Reference); + if (mDragMode == DragMode_Move) { 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) { - int widgetWidth = getWorldspaceWidget().width(); + osg::Vec3f center = getScreenCoords(getSelectionCenter(selection)); + + // Calculate scaling distance/rate int widgetHeight = getWorldspaceWidget().height(); - int x = pos.x() - widgetWidth / 2; - int y = pos.y() - widgetHeight / 2; + float dx = pos.x() - center.x(); + 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; // Only uniform scaling is currently supported offset = osg::Vec3f(scale, scale, scale); } - std::vector > selection = getWorldspaceWidget().getEdited (Mask_Reference); + // Apply for (std::vector >::iterator iter (selection.begin()); iter!=selection.end(); ++iter) { if (CSVRender::ObjectTag *objectTag = dynamic_cast (iter->get())) diff --git a/apps/opencs/view/render/instancemode.hpp b/apps/opencs/view/render/instancemode.hpp index dd2755237..933cae529 100644 --- a/apps/opencs/view/render/instancemode.hpp +++ b/apps/opencs/view/render/instancemode.hpp @@ -1,6 +1,7 @@ #ifndef CSV_RENDER_INSTANCEMODE_H #define CSV_RENDER_INSTANCEMODE_H +#include #include #include @@ -13,6 +14,7 @@ namespace CSVWidget namespace CSVRender { + class TagBase; class InstanceSelectionMode; class InstanceMode : public EditMode @@ -40,6 +42,9 @@ namespace CSVRender osg::Vec3f quatToEuler(const osg::Quat& quat) const; osg::Quat eulerToQuat(const osg::Vec3f& euler) const; + osg::Vec3f getSelectionCenter(const std::vector >& selection) const; + osg::Vec3f getScreenCoords(const osg::Vec3f& pos); + public: InstanceMode (WorldspaceWidget *worldspaceWidget, QWidget *parent = 0); From 101c3cc90d375a1ac20db52a8325ff356c93206a Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Fri, 12 Aug 2016 17:12:10 -0400 Subject: [PATCH 03/22] Rotate around center of selection. --- apps/opencs/view/render/instancemode.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index 5b5edef9e..feca6fa6a 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -323,14 +323,15 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou osg::Vec3f camBack = eye - centre; // Convert coordinate system - int widgetWidth = getWorldspaceWidget().width(); + osg::Vec3f screenCenter = getScreenCoords(getSelectionCenter(selection)); + int widgetHeight = getWorldspaceWidget().height(); - int newX = pos.x() - widgetWidth / 2; - int newY = -pos.y() + widgetHeight / 2; + float newX = pos.x() - screenCenter.x(); + float newY = (widgetHeight - pos.y()) - screenCenter.y(); - int oldX = newX - diffX; - int oldY = newY - diffY; // diffY appears to already be flipped + float oldX = newX - diffX; + float oldY = newY - diffY; // diffY appears to already be flipped osg::Vec3f oldVec = osg::Vec3f(oldX, oldY, 0); oldVec.normalize(); From 3e4ac0c6625a86ca1b3d0b5e98ebdda8f191ca02 Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Sun, 14 Aug 2016 14:43:29 -0400 Subject: [PATCH 04/22] Potential fix for context sensitive select mode issues. --- apps/opencs/view/render/instancemode.cpp | 31 +++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index feca6fa6a..aa6408fef 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -215,23 +215,26 @@ bool CSVRender::InstanceMode::primaryEditStartDrag (const QPoint& pos) if (mDragMode!=DragMode_None || mLocked) return false; - WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); - if (hit.tag && CSMPrefs::get()["3D Scene Input"]["context-select"].isTrue()) - { - getWorldspaceWidget().clearSelection (Mask_Reference); - if (CSVRender::ObjectTag *objectTag = dynamic_cast (hit.tag.get())) - { - CSVRender::Object* object = objectTag->mObject; - object->setSelected (true); - } - } - - std::vector > selection = - getWorldspaceWidget().getSelection (Mask_Reference); + std::vector > selection = getWorldspaceWidget().getSelection (Mask_Reference); if (selection.empty()) - return false; + { + // 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 (hit.tag.get())) + { + CSVRender::Object* object = objectTag->mObject; + object->setSelected (true); + } + } + + selection = getWorldspaceWidget().getSelection (Mask_Reference); + if (selection.empty()) + return false; + } for (std::vector >::iterator iter (selection.begin()); iter!=selection.end(); ++iter) From 2b860e260058c19be4dc84ce347317e448583ae7 Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Mon, 15 Aug 2016 16:29:01 +0300 Subject: [PATCH 05/22] Reduce the number of if conditions in Travis config --- .travis.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 839dbccd4..2ab0a006e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,12 +33,8 @@ matrix: allow_failures: - env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 " -before_install: - - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi - - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_install.osx.sh; fi -before_script: - - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_script.linux.sh; fi - - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi +before_install: ./CI/before_install.${TRAVIS_OS_NAME}.sh +before_script: ./CI/before_script.${TRAVIS_OS_NAME}.sh script: - cd ./build - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j3; fi From f4f81a14c97c7cc6ac90f14799e442704d2fc16c Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Mon, 15 Aug 2016 17:04:29 +0300 Subject: [PATCH 06/22] Use Travis addons.apt.packages to install packages --- .travis.yml | 20 ++++++++++++++++++++ CI/before_install.linux.sh | 14 +------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2ab0a006e..3641459de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,26 @@ env: # via the "travis encrypt" command using the project repo's public key - secure: "jybGzAdUbqt9vWR/GEnRd96BgAi/7Zd1+2HK68j/i/8+/1YH2XxLOy4Jv/DUBhBlJIkxs/Xv8dRcUlFOclZDHX1d/9Qnsqd3oUVkD7k1y7cTOWy9TBQaE/v/kZo3LpzA3xPwwthrb0BvqIbOfIELi5fS5s8ba85WFRg3AX70wWE=" addons: + apt: + sources: + - sourceline: 'ppa:openmw/openmw' + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 + packages: [ + # Dev + clang-3.6, libunshield-dev, libtinyxml-dev, + # Tests + libgtest-dev, google-mock, + # Boost + libboost-filesystem-dev, libboost-program-options-dev, libboost-system-dev, libboost-thread-dev, + # FFmpeg + libavcodec-dev, libavformat-dev, libavutil-dev, libswscale-dev, + # Audio & Video + libsdl2-dev, libqt4-dev, libopenal-dev, + # The other from OpenMW ppa + libbullet-dev, libswresample-dev, libopenscenegraph-dev, libmygui-dev + ] + coverity_scan: project: name: "OpenMW/openmw" diff --git a/CI/before_install.linux.sh b/CI/before_install.linux.sh index 1c02bc8d9..cbc293dab 100755 --- a/CI/before_install.linux.sh +++ b/CI/before_install.linux.sh @@ -1,18 +1,6 @@ #!/bin/sh -if [ "${ANALYZE}" ]; then - echo "yes" | sudo add-apt-repository "deb http://llvm.org/apt/`lsb_release -sc`/ llvm-toolchain-`lsb_release -sc`-3.6 main" - wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add - -fi - -echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" -echo "yes" | sudo apt-add-repository ppa:openmw/openmw -sudo apt-get update -qq -sudo apt-get install -qq libgtest-dev google-mock -sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev -sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev -sudo apt-get install -qq libbullet-dev libopenscenegraph-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev -if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi +# build libgtest & libgtest_main sudo mkdir /usr/src/gtest/build cd /usr/src/gtest/build sudo cmake .. -DBUILD_SHARED_LIBS=1 From 6163c7bb03f1ec38b449788745caeb42f25f5200 Mon Sep 17 00:00:00 2001 From: Allofich Date: Tue, 16 Aug 2016 01:15:26 +0900 Subject: [PATCH 07/22] Use loopfallback for idle animation groups --- apps/openmw/mwmechanics/character.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index e65195531..14b235cd8 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -2023,9 +2023,10 @@ bool CharacterController::playGroup(const std::string &groupname, int mode, int mCurrentIdle.clear(); mIdleState = CharState_SpecialIdle; + bool loopfallback = (entry.mGroup.compare(0,4,"idle") == 0); mAnimation->play(groupname, Priority_Default, MWRender::Animation::BlendMask_All, false, 1.0f, - ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1); + ((mode==2) ? "loop start" : "start"), "stop", 0.0f, count-1, loopfallback); } else if(mode == 0) { From c05782581e3c224c092865b03a871a9f8dbb2753 Mon Sep 17 00:00:00 2001 From: Allofich Date: Tue, 16 Aug 2016 02:47:37 +0900 Subject: [PATCH 08/22] Account for all instances of play() --- apps/openmw/mwmechanics/character.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 14b235cd8..c92530259 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1542,9 +1542,10 @@ void CharacterController::update(float duration) mAnimation->disable(mAnimQueue.front().mGroup); mAnimQueue.pop_front(); + bool loopfallback = (mAnimQueue.front().mGroup.compare(0,4,"idle") == 0); mAnimation->play(mAnimQueue.front().mGroup, Priority_Default, MWRender::Animation::BlendMask_All, false, - 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount); + 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback); } } } @@ -1822,9 +1823,10 @@ void CharacterController::update(float duration) mAnimation->disable(mAnimQueue.front().mGroup); mAnimQueue.pop_front(); + bool loopfallback = (mAnimQueue.front().mGroup.compare(0,4,"idle") == 0); mAnimation->play(mAnimQueue.front().mGroup, Priority_Default, MWRender::Animation::BlendMask_All, false, - 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount); + 1.0f, "start", "stop", 0.0f, mAnimQueue.front().mLoopCount, loopfallback); } } From 712577564868e0ad0b637fc6769b447a48856890 Mon Sep 17 00:00:00 2001 From: Aesylwinn Date: Mon, 15 Aug 2016 15:07:43 -0400 Subject: [PATCH 09/22] Change free axis rotation. --- apps/opencs/model/prefs/state.cpp | 1 + apps/opencs/view/render/instancemode.cpp | 70 +++++++++++++++--------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 718d9a107..b8d6102ac 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -188,6 +188,7 @@ void CSMPrefs::State::declare() "Shift-acceleration factor during drag operations", 4.0). setTooltip ("Acceleration factor during drag operations while holding down shift"). setRange (0.001, 100.0); + declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1); declareCategory ("Tooltips"); declareBool ("scene", "Show Tooltips in 3D scenes", true); diff --git a/apps/opencs/view/render/instancemode.cpp b/apps/opencs/view/render/instancemode.cpp index aa6408fef..4932e6ca9 100644 --- a/apps/opencs/view/render/instancemode.cpp +++ b/apps/opencs/view/render/instancemode.cpp @@ -323,33 +323,28 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou osg::Vec3f eye, centre, up; getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, centre, up); - osg::Vec3f camBack = eye - centre; - - // Convert coordinate system - osg::Vec3f screenCenter = getScreenCoords(getSelectionCenter(selection)); - - int widgetHeight = getWorldspaceWidget().height(); - - float newX = pos.x() - screenCenter.x(); - float newY = (widgetHeight - pos.y()) - screenCenter.y(); - - float oldX = newX - diffX; - float oldY = newY - diffY; // diffY appears to already be flipped - - osg::Vec3f oldVec = osg::Vec3f(oldX, oldY, 0); - oldVec.normalize(); - - osg::Vec3f newVec = osg::Vec3f(newX, newY, 0); - newVec.normalize(); - - // Find angle and axis of rotation - float angle = std::acos(oldVec * newVec) * speedFactor; - if (((oldVec ^ newVec) * camBack < 0) ^ (camBack.z() < 0)) - angle *= -1; - + float angle; osg::Vec3f axis; - if (mDragAxis != -1) + + if (mDragAxis == -1) { + // Free rotate + float rotationFactor = CSMPrefs::get()["3D Scene Input"]["rotate-factor"].toDouble() * speedFactor; + + osg::Quat cameraRotation = getWorldspaceWidget().getCamera()->getInverseViewMatrix().getRotate(); + + osg::Vec3f camForward = centre - eye; + osg::Vec3f screenDir = cameraRotation * osg::Vec3f(diffX, diffY, 0); + screenDir.normalize(); + + angle = std::sqrt(diffX*diffX + diffY*diffY) * rotationFactor; + axis = screenDir ^ camForward; + } + else + { + // Global axis rotation + osg::Vec3f camBack = eye - centre; + for (int i = 0; i < 3; ++i) { if (i == mDragAxis) @@ -358,11 +353,32 @@ void CSVRender::InstanceMode::drag (const QPoint& pos, int diffX, int diffY, dou axis[i] = 0; } + // Flip axis if facing opposite side if (camBack * axis < 0) axis *= -1; + + // Convert coordinate system + osg::Vec3f screenCenter = getScreenCoords(getSelectionCenter(selection)); + + int widgetHeight = getWorldspaceWidget().height(); + + float newX = pos.x() - screenCenter.x(); + float newY = (widgetHeight - pos.y()) - screenCenter.y(); + + float oldX = newX - diffX; + float oldY = newY - diffY; // diffY appears to already be flipped + + osg::Vec3f oldVec = osg::Vec3f(oldX, oldY, 0); + oldVec.normalize(); + + osg::Vec3f newVec = osg::Vec3f(newX, newY, 0); + newVec.normalize(); + + // Find angle and axis of rotation + angle = std::acos(oldVec * newVec) * speedFactor; + if (((oldVec ^ newVec) * camBack < 0) ^ (camBack.z() < 0)) + angle *= -1; } - else - axis = camBack; rotation = osg::Quat(angle, axis); } From 2311969f05f648e94182caf0e8cca98492ef9811 Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Mon, 15 Aug 2016 20:25:34 +0300 Subject: [PATCH 10/22] Reduce the number of copypaste in FindSphinx.cmake --- cmake/FindSphinx.cmake | 173 +++++++++++++---------------------------- 1 file changed, 56 insertions(+), 117 deletions(-) diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake index 4607f7806..331598006 100644 --- a/cmake/FindSphinx.cmake +++ b/cmake/FindSphinx.cmake @@ -2,44 +2,36 @@ # Find the Sphinx documentation generator # # This modules defines -# SPHINX_EXECUTABLE -# SPHINX_FOUND - -find_program(SPHINX_EXECUTABLE - NAMES sphinx-build - PATHS - /usr/bin - /usr/local/bin - /opt/local/bin - DOC "Sphinx documentation generator" -) - -if( NOT SPHINX_EXECUTABLE ) - set(_Python_VERSIONS - 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0 1.6 1.5 - ) - - foreach( _version ${_Python_VERSIONS} ) - set( _sphinx_NAMES sphinx-build-${_version} ) - - find_program( SPHINX_EXECUTABLE - NAMES ${_sphinx_NAMES} - PATHS - /usr/bin - /usr/local/bin - /opt/loca/bin - DOC "Sphinx documentation generator" - ) - endforeach() -endif() +# Sphinx_EXECUTABLE +# Sphinx_FOUND +# function Sphinx_add_target +# function Sphinx_add_targets +# include(FindPackageHandleStandardArgs) +include(CMakeParseArguments) -find_package_handle_standard_args(Sphinx DEFAULT_MSG - SPHINX_EXECUTABLE +set(_sphinx_names sphinx-build) +foreach(_version 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0 1.6 1.5) + list(APPEND _sphinx_names sphinx-build-${_version}) +endforeach() + +find_program(Sphinx_EXECUTABLE + NAMES ${_sphinx_names} + PATHS + /usr/bin + /usr/local/bin + /opt/local/bin + DOC "Sphinx documentation generator" ) +mark_as_advanced(Sphinx_EXECUTABLE) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Sphinx + FOUND_VAR Sphinx_FOUND + REQUIRED_VARS Sphinx_EXECUTABLE +) + option( SPHINX_HTML_OUTPUT "Build a single HTML with the whole content." ON ) option( SPHINX_DIRHTML_OUTPUT "Build HTML pages, but with a single directory per document." OFF ) option( SPHINX_HTMLHELP_OUTPUT "Build HTML pages with additional information for building a documentation collection in htmlhelp." OFF ) @@ -50,96 +42,43 @@ option( SPHINX_LATEX_OUTPUT "Build LaTeX sources that can be compiled to a PDF d option( SPHINX_MAN_OUTPUT "Build manual pages in groff format for UNIX systems." OFF ) option( SPHINX_TEXT_OUTPUT "Build plain text files." OFF ) - -mark_as_advanced( - SPHINX_EXECUTABLE - SPHINX_HTML_OUTPUT - SPHINX_DIRHTML_OUTPUT - SPHINX_HTMLHELP_OUTPUT - SPHINX_QTHELP_OUTPUT - SPHINX_DEVHELP_OUTPUT - SPHINX_EPUB_OUTPUT - SPHINX_LATEX_OUTPUT - SPHINX_MAN_OUTPUT - SPHINX_TEXT_OUTPUT -) - -function( Sphinx_add_target target_name builder conf source destination ) - add_custom_target( ${target_name} ALL - COMMAND ${SPHINX_EXECUTABLE} -b ${builder} - -c ${conf} - ${source} - ${destination} - COMMENT "Generating sphinx documentation: ${builder}" +function(Sphinx_add_target target_name builder conf source destination) + add_custom_target( ${target_name} ALL + COMMAND ${Sphinx_EXECUTABLE} -b ${builder} -c ${conf} ${source} ${destination} + DEPENDS ${conf}/conf.py + COMMENT "Generating sphinx documentation: ${builder}" ) - set_property( - DIRECTORY APPEND PROPERTY - ADDITIONAL_MAKE_CLEAN_FILES - ${destination} + set_property(DIRECTORY APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES ${destination} ) endfunction() -# Target dependencies can be optionally listed at the end. -function( Sphinx_add_targets target_base_name conf source base_destination ) +# Usage: +# +# Sphinx_add_targets(NAME +# SRC_DIR / +# DST_DIR / +# CONFIG_DIR / +# [DEPENDENCIES dep1 dep2 dep3 ...] +# ) +function(Sphinx_add_targets) + set(options ) + set(one_value_keywords NAME SRC_DIR DST_DIR CONFIG_DIR) + set(multi_value_keywords DEPENDENCIES) + CMAKE_PARSE_ARGUMENTS(OPT "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN}) - set( _dependencies ) + if (NOT OPT_NAME OR NOT OPT_SRC_DIR OR NOT OPT_DST_DIR OR NOT OPT_CONFIG_DIR) + message(FATAL_ERROR "Arguments NAME, SRC_DIR, DST_DIR, CONFIG_DIR are required!") + endif() - foreach( arg IN LISTS ARGN ) - set( _dependencies ${_dependencies} ${arg} ) - endforeach() - - if( ${SPHINX_HTML_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_html html ${conf} ${source} ${base_destination}/html ) - - add_dependencies( ${target_base_name}_html ${_dependencies} ) - endif() - - if( ${SPHINX_DIRHTML_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_dirhtml dirhtml ${conf} ${source} ${base_destination}/dirhtml ) - - add_dependencies( ${target_base_name}_dirhtml ${_dependencies} ) - endif() - - if( ${SPHINX_QTHELP_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_qthelp qthelp ${conf} ${source} ${base_destination}/qthelp ) - - add_dependencies( ${target_base_name}_qthelp ${_dependencies} ) - endif() - - if( ${SPHINX_DEVHELP_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_devhelp devhelp ${conf} ${source} ${base_destination}/devhelp ) - - add_dependencies( ${target_base_name}_devhelp ${_dependencies} ) - endif() - - if( ${SPHINX_EPUB_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_epub epub ${conf} ${source} ${base_destination}/epub ) - - add_dependencies( ${target_base_name}_epub ${_dependencies} ) - endif() - - if( ${SPHINX_LATEX_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_latex latex ${conf} ${source} ${base_destination}/latex ) - - add_dependencies( ${target_base_name}_latex ${_dependencies} ) - endif() - - if( ${SPHINX_MAN_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_man man ${conf} ${source} ${base_destination}/man ) - - add_dependencies( ${target_base_name}_man ${_dependencies} ) - endif() - - if( ${SPHINX_TEXT_OUTPUT} ) - Sphinx_add_target( ${target_base_name}_text text ${conf} ${source} ${base_destination}/text ) - - add_dependencies( ${target_base_name}_text ${_dependencies} ) - endif() - - if( ${BUILD_TESTING} ) - sphinx_add_target( ${target_base_name}_linkcheck linkcheck ${conf} ${source} ${base_destination}/linkcheck ) - - add_dependencies( ${target_base_name}_linkcheck ${_dependencies} ) - endif() + foreach(_generator html dirhtml qthelp devhelp epub latex man text linkcheck) + string(TOUPPER ${_generator} _generator_uc) + if (SPHINX_${_generator_uc}_OUTPUT) + Sphinx_add_target(${OPT_NAME}_${_generator} ${_generator} ${OPT_CONFIG_DIR} ${OPT_SRC_DIR} ${OPT_DST_DIR}/${_generator}/) + if (OPT_DEPENDENCIES) + add_dependencies(${OPT_NAME}_${_generator} ${OPT_DEPENDENCIES}) + endif() + endif() + endforeach() endfunction() From 9d51e1966f5b3ffd77e88eaee8a88748dd458495 Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Mon, 15 Aug 2016 22:11:12 +0300 Subject: [PATCH 11/22] Rename SDL_SDK -> SDL2DIR as it is said in FindSDL2 documentation --- CI/before_script.msvc.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 6cd39fd0e..6ed4365a4 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -557,12 +557,9 @@ printf "SDL 2.0.3... " eval 7z x -y SDL2-2.0.3.zip $STRIP fi - SDL_SDK="`real_pwd`/SDL2-2.0.3" - add_cmake_opts -DSDL2_INCLUDE_DIR="$SDL_SDK/include" \ - -DSDL2MAIN_LIBRARY="$SDL_SDK/lib/x$ARCHSUFFIX/SDL2main.lib" \ - -DSDL2_LIBRARY_PATH="$SDL_SDK/lib/x$ARCHSUFFIX/SDL2.lib" + export SDL2DIR="`real_pwd`/SDL2-2.0.3" - add_runtime_dlls `pwd`/SDL2-2.0.3/lib/x$ARCHSUFFIX/SDL2.dll + add_runtime_dlls $SDL2DIR/lib/x$ARCHSUFFIX/SDL2.dll echo Done. } From 3df57b183374cc941824a31758c5a43ab899faa4 Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Mon, 15 Aug 2016 21:59:24 +0300 Subject: [PATCH 12/22] Fixes LibFindMacros for libfind_process --- cmake/LibFindMacros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake index 56b39a1ad..2be27c5fc 100644 --- a/cmake/LibFindMacros.cmake +++ b/cmake/LibFindMacros.cmake @@ -322,7 +322,7 @@ function (libfind_process PREFIX) set(val ${${i}}) if ("${val}" STREQUAL "${i}-NOTFOUND") set (val "") - elseif (val AND NOT EXISTS ${val}) + elseif (val AND NOT EXISTS "${val}") set (val "${val} (does not exist)") else() set(some_files TRUE) From ed2c2170f088bc9ab4a7a1318412a5c8455c48d1 Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Mon, 15 Aug 2016 21:41:51 +0300 Subject: [PATCH 13/22] Rewrites FindSDL2 using LibFindMacros --- cmake/FindSDL2.cmake | 179 ++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 123 deletions(-) diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake index 163abf463..25105f1e2 100644 --- a/cmake/FindSDL2.cmake +++ b/cmake/FindSDL2.cmake @@ -1,16 +1,20 @@ # Locate SDL2 library # This module defines -# SDL2_LIBRARY, the name of the library to link against +# SDL2_LIBRARY, the SDL2 library, with no other libraries +# SDL2_LIBRARIES, the SDL library and required components with compiler flags # SDL2_FOUND, if false, do not try to link to SDL2 # SDL2_INCLUDE_DIR, where to find SDL.h +# SDL2_VERSION, the version of the found library # +# This module accepts the following env variables +# SDL2DIR - Can be set to ./configure --prefix=$SDL2DIR used in building SDL2. l.e.galup 9-20-02 # This module responds to the the flag: # SDL2_BUILDING_LIBRARY # If this is defined, then no SDL2_main will be linked in because # only applications need main(). # Otherwise, it is assumed you are building an application and this # module will attempt to locate and set the the proper link flags -# as part of the returned SDL2_LIBRARY variable. +# as part of the returned SDL2_LIBRARIES variable. # # Don't forget to include SDL2main.h and SDL2main.m your project for the # OS X framework based version. (Other versions link to -lSDL2main which @@ -18,20 +22,6 @@ # module will automatically add the -framework Cocoa on your behalf. # # -# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration -# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library -# (SDL2.dll, libsdl2.so, SDL2.framework, etc). -# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. -# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value -# as appropriate. These values are used to generate the final SDL2_LIBRARY -# variable, but when these values are unset, SDL2_LIBRARY does not get created. -# -# -# $SDL2DIR is an environment variable that would -# correspond to the ./configure --prefix=$SDL2DIR -# used in building SDL2. -# l.e.galup 9-20-02 -# # Modified by Eric Wing. # Added code to assist with automated building by using environmental variables # and providing a more controlled/consistent search behavior. @@ -71,126 +61,69 @@ # License text for the above reference.) -FIND_PATH(SDL2_INCLUDE_DIR SDL.h - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES include/SDL2 include - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local/include/SDL2 - /usr/include/SDL2 - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_sdl_lib_suffix lib/x64) +else() + set(_sdl_lib_suffix lib/x86) +endif() + +libfind_pkg_detect(SDL2 sdl2 + FIND_PATH SDL.h + HINTS $ENV{SDL2DIR} + PATH_SUFFIXES include SDL2 + FIND_LIBRARY SDL2 + HINTS $ENV{SDL2DIR} + PATH_SUFFIXES ${_sdl_lib_suffix} ) -#MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}") +libfind_version_n_header(SDL2 NAMES SDL_version.h DEFINES SDL_MAJOR_VERSION SDL_MINOR_VERSION SDL_PATCHLEVEL) -FIND_LIBRARY(SDL2_LIBRARY_PATH - NAMES SDL2 - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES lib64 lib - PATHS - /sw - /opt/local - /opt/csw - /opt -) - -set(SDL2_LIBRARY_ONLY ${SDL2_LIBRARY_PATH} CACHE STRING "The SDL2 library, with no other libraries.") -set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_PATH}) - -#MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}") - -IF(NOT SDL2_BUILDING_LIBRARY) - IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") +IF(NOT SDL2_BUILDING_LIBRARY AND NOT APPLE) # Non-OS X framework versions expect you to also dynamically link to # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms # seem to provide SDL2main for compatibility even though they don't # necessarily need it. - FIND_LIBRARY(SDL2MAIN_LIBRARY - NAMES SDL2main - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES lib64 lib - PATHS - /sw - /opt/local - /opt/csw - /opt + libfind_pkg_detect(SDL2MAIN sdl2 + FIND_LIBRARY SDL2main + HINTS $ENV{SDL2DIR} + PATH_SUFFIXES ${_sdl_lib_suffix} ) - ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") -ENDIF(NOT SDL2_BUILDING_LIBRARY) + set(SDL2MAIN_FIND_QUIETLY TRUE) + libfind_process(SDL2MAIN) + list(APPEND SDL2_PROCESS_LIBS SDL2MAIN_LIBRARY) +ENDIF() -# SDL2 may require threads on your system. -# The Apple build may not need an explicit flag because one of the -# frameworks may already provide it. -# But for non-OSX systems, I will use the CMake Threads package. -IF(NOT APPLE) - FIND_PACKAGE(Threads) -ENDIF(NOT APPLE) + +set(SDL2_TARGET_SPECIFIC) + +if (APPLE) + # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. + list(APPEND SDL2_TARGET_SPECIFIC "-framework Cocoa") +else() + # SDL2 may require threads on your system. + # The Apple build may not need an explicit flag because one of the + # frameworks may already provide it. + # But for non-OSX systems, I will use the CMake Threads package. + libfind_package(SDL2 Threads) + list(APPEND SDL2_TARGET_SPECIFIC ${CMAKE_THREAD_LIBS_INIT}) +endif() # MinGW needs an additional library, mwindows # It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows # (Actually on second look, I think it only needs one of the m* libraries.) -IF(MINGW) - SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") -ENDIF(MINGW) +if(MINGW) + list(APPEND SDL2_TARGET_SPECIFIC mingw32) +endif() -SET(SDL2_FOUND "NO") -IF(SDL2_LIBRARY_TEMP) - # For SDL2main - IF(NOT SDL2_BUILDING_LIBRARY) - IF(SDL2MAIN_LIBRARY) - SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) - ENDIF(SDL2MAIN_LIBRARY) - ENDIF(NOT SDL2_BUILDING_LIBRARY) +if(WIN32) + list(APPEND SDL2_TARGET_SPECIFIC winmm imm32 version msimg32) +endif() - # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. - # CMake doesn't display the -framework Cocoa string in the UI even - # though it actually is there if I modify a pre-used variable. - # I think it has something to do with the CACHE STRING. - # So I use a temporary variable until the end so I can set the - # "real" variable in one-shot. - IF(APPLE) - SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") - ENDIF(APPLE) +set(SDL2_PROCESS_LIBS SDL2_TARGET_SPECIFIC) - # For threads, as mentioned Apple doesn't need this. - # In fact, there seems to be a problem if I used the Threads package - # and try using this line, so I'm just skipping it entirely for OS X. - IF(NOT APPLE) - SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) - ENDIF(NOT APPLE) +libfind_process(SDL2) - # For MinGW library - IF(MINGW) - SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) - ENDIF(MINGW) - - IF(WIN32) - SET(SDL2_LIBRARY_TEMP winmm imm32 version msimg32 ${SDL2_LIBRARY_TEMP}) - ENDIF(WIN32) - - # Set the final string here so the GUI reflects the final state. - SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") - # Set the temp variable to INTERNAL so it is not seen in the CMake GUI - SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") - - SET(SDL2_FOUND "YES") -ENDIF(SDL2_LIBRARY_TEMP) - -INCLUDE(FindPackageHandleStandardArgs) - -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 - REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) - -IF(SDL2_STATIC) - if (UNIX AND NOT APPLE) - EXECUTE_PROCESS(COMMAND sdl2-config --static-libs OUTPUT_VARIABLE SDL2_LINK_FLAGS) - STRING(REGEX REPLACE "(\r?\n)+$" "" SDL2_LINK_FLAGS "${SDL2_LINK_FLAGS}") - SET(SDL2_LIBRARY ${SDL2_LINK_FLAGS}) - ENDIF() -ENDIF(SDL2_STATIC) +if (SDL2_STATIC AND UNIX AND NOT APPLE) + execute_process(COMMAND sdl2-config --static-libs OUTPUT_VARIABLE SDL2_STATIC_FLAGS) + string(REGEX REPLACE "(\r?\n)+$" "" SDL2_STATIC_FLAGS "${SDL2_STATIC_FLAGS}") + set(SDL2_LIBRARIES ${SDL2_STATIC_FLAGS}) +endif() From 95dc1258d647375225d75184a17a6ed029c2b2d2 Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Tue, 16 Aug 2016 02:23:04 +0300 Subject: [PATCH 14/22] Rewrites find_package for OpenSceneGraph plugins using LibFindMacros and osg_find_library --- CI/before_script.osx.sh | 1 - CMakeLists.txt | 58 ++++++++------------------------------ cmake/FindOSGPlugins.cmake | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 48 deletions(-) create mode 100644 cmake/FindOSGPlugins.cmake diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index 164208f49..c3822291d 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -17,7 +17,6 @@ cmake \ -D CMAKE_BUILD_TYPE=Debug \ -D OPENMW_OSX_DEPLOYMENT=TRUE \ -D DESIRED_QT_VERSION=5 \ --D OSG_PLUGIN_LIB_SEARCH_PATH="$DEPENDENCIES_ROOT/lib/osgPlugins-3.4.0" \ -D BUILD_ESMTOOL=FALSE \ -D BUILD_MYGUI_PLUGIN=FALSE \ -G"Unix Makefiles" \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d73644b4..77ff2416d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,55 +221,16 @@ IF(BOOST_STATIC) endif() find_package(OpenSceneGraph 3.3.4 REQUIRED osgDB osgViewer osgText osgGA osgAnimation osgParticle osgUtil osgFX) - include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}) +get_filename_component(OSG_LIB_DIR ${OSGDB_LIBRARY} DIRECTORY) +set(OSGPlugins_LIB_DIR "${OSG_LIB_DIR}/osgPlugins-${OPENSCENEGRAPH_VERSION}") + if(OSG_STATIC) - macro(use_static_osg_plugin_library PLUGIN_NAME) - set(PLUGIN_NAME_DBG ${PLUGIN_NAME}d ${PLUGIN_NAME}D ${PLUGIN_NAME}_d ${PLUGIN_NAME}_D ${PLUGIN_NAME}_debug ${PLUGIN_NAME}) + add_definitions(-DOSG_LIBRARY_STATIC) - # For now, users wishing to do a static build will need to pass the path to where the plugins reside - # More clever logic would need to deduce the path, probably installed under /lib/osgPlugins- - include(FindPkgMacros) - find_library(${PLUGIN_NAME}_LIBRARY_REL NAMES ${PLUGIN_NAME} HINTS ${OSG_PLUGIN_LIB_SEARCH_PATH}) - find_library(${PLUGIN_NAME}_LIBRARY_DBG NAMES ${PLUGIN_NAME_DBG} HINTS ${OSG_PLUGIN_LIB_SEARCH_PATH}) - make_library_set(${PLUGIN_NAME}_LIBRARY) - - if("${${PLUGIN_NAME}_LIBRARY}" STREQUAL "") - message(FATAL_ERROR "Unable to find static OpenSceneGraph plugin: ${PLUGIN_NAME}") - endif() - - set(OPENSCENEGRAPH_LIBRARIES ${OPENSCENEGRAPH_LIBRARIES} ${${PLUGIN_NAME}_LIBRARY}) - endmacro() - - add_definitions(-DOSG_LIBRARY_STATIC) - - set(PLUGIN_LIST - osgdb_png # depends on libpng, zlib - osgdb_tga - osgdb_dds - osgdb_jpeg # depends on libjpeg - ) - - foreach(PLUGIN ${PLUGIN_LIST}) - use_static_osg_plugin_library(${PLUGIN}) - endforeach() - - # OSG static plugins need to linked against their respective dependencies - set(PLUGIN_DEPS_LIST - PNG # needed by osgdb_png - ZLIB # needed by osgdb_png - JPEG # needed by osgdb_jpeg - ) - - macro(use_static_osg_plugin_dep DEPENDENCY) - find_package(${DEPENDENCY} REQUIRED) - - set(OPENSCENEGRAPH_LIBRARIES ${OPENSCENEGRAPH_LIBRARIES} ${${DEPENDENCY}_LIBRARIES}) - endmacro() - foreach(DEPENDENCY ${PLUGIN_DEPS_LIST}) - use_static_osg_plugin_dep(${DEPENDENCY}) - endforeach() + find_package(OSGPlugins REQUIRED COMPONENTS osgdb_png osgdb_tga osgdb_dds osgdb_jpeg) + list(APPEND OPENSCENEGRAPH_LIBRARIES ${OSGPlugins_LIBRARIES}) endif() if(QT_STATIC) @@ -764,11 +725,14 @@ if (APPLE) ) foreach (PLUGIN_NAME ${USED_OSG_PLUGINS}) - set(PLUGIN_ABS "${OSG_PLUGIN_LIB_SEARCH_PATH}/${PLUGIN_NAME}.so") + set(PLUGIN_ABS "${OSGPlugins_LIB_DIR}/${PLUGIN_NAME}.so") set(ABSOLUTE_PLUGINS ${PLUGIN_ABS} ${ABSOLUTE_PLUGINS}) endforeach () - get_filename_component(OSG_PLUGIN_PREFIX_DIR "${OSG_PLUGIN_LIB_SEARCH_PATH}" NAME) + get_filename_component(OSG_PLUGIN_PREFIX_DIR "${OSGPlugins_LIB_DIR}" NAME) + if (NOT OSG_PLUGIN_PREFIX_DIR) + message(FATAL_ERROR "Can't get directory name for OSG plugins from '${OSGPlugins_LIB_DIR}'") + endif() # installs used plugins in bundle at given path (bundle_path must be relative to ${CMAKE_INSTALL_PREFIX}) # and returns list of install paths for all installed plugins diff --git a/cmake/FindOSGPlugins.cmake b/cmake/FindOSGPlugins.cmake new file mode 100644 index 000000000..8220f33d4 --- /dev/null +++ b/cmake/FindOSGPlugins.cmake @@ -0,0 +1,50 @@ +# This module accepts the following env variable +# OSGPlugins_LIB_DIR - /lib/osgPlugins- , path to search plugins +# +# Once done this will define +# OSGPlugins_FOUND - System has the all required components. +# OSGPlugins_LIBRARIES - Link these to use the required osg plugins components. +# +# Components: +# - osgdb_png +# - osgdb_tga +# - osgdb_dds +# - osgdb_jpeg + +include(LibFindMacros) +include(Findosg_functions) + +if (NOT OSGPlugins_LIB_DIR) + set(_mode WARNING) + if (OSGPlugins_FIND_REQUIRED) + set(_mode FATAL_ERROR) + endif() + message(${_mode} "OSGPlugins_LIB_DIR variable must be set") +endif() + +foreach(_library ${OSGPlugins_FIND_COMPONENTS}) + string(TOUPPER ${_library} _library_uc) + set(_component OSGPlugins_${_library}) + + set(${_library_uc}_DIR ${OSGPlugins_LIB_DIR}) # to help function osg_find_library + set(_saved_lib_prefix ${CMAKE_FIND_LIBRARY_PREFIXES}) # save CMAKE_FIND_LIBRARY_PREFIXES + set(CMAKE_FIND_LIBRARY_PREFIXES "") # search libraries with no prefix + osg_find_library(${_library_uc} ${_library}) # find it into ${_library_uc}_LIBRARIES + set(CMAKE_FIND_LIBRARY_PREFIXES ${_saved_lib_prefix}) # restore prefix + + if (${_library_uc}_LIBRARIES) + set(${_component}_LIBRARY ${${_library_uc}_LIBRARIES}) # fake as if we call find_library + else() + set(${_component}_LIBRARY ${_component}_LIBRARY-NOTFOUND) + endif() + + list(APPEND OSGPlugins_PROCESS_LIBS ${_component}_LIBRARY) +endforeach() + +foreach(_dependency PNG ZLIB JPEG) # needed by osgdb_png or osgdb_jpeg + libfind_package(OSGPlugins ${_dependency}) + set(${_dependency}_LIBRARY_OPTS ${_dependency}_LIBRARY) + #list(APPEND OSGPlugins_PROCESS_LIBS ${_dependency}_LIBRARY) +endforeach() + +libfind_process(OSGPlugins) From 0d83121a6f01f40a76179317f986687e1525718a Mon Sep 17 00:00:00 2001 From: Roman Proskuryakov Date: Tue, 16 Aug 2016 03:41:15 +0300 Subject: [PATCH 15/22] Removes unused FindPkgMacros --- cmake/FindPkgMacros.cmake | 161 -------------------------------------- 1 file changed, 161 deletions(-) delete mode 100644 cmake/FindPkgMacros.cmake diff --git a/cmake/FindPkgMacros.cmake b/cmake/FindPkgMacros.cmake deleted file mode 100644 index 473b27b2a..000000000 --- a/cmake/FindPkgMacros.cmake +++ /dev/null @@ -1,161 +0,0 @@ -#------------------------------------------------------------------- -# This file is part of the CMake build system for OGRE -# (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ -# -# The contents of this file are placed in the public domain. Feel -# free to make use of it in any way you like. -#------------------------------------------------------------------- - -################################################################## -# Provides some common functionality for the FindPackage modules -################################################################## - -# Begin processing of package -macro(findpkg_begin PREFIX) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Looking for ${PREFIX}...") - endif () -endmacro(findpkg_begin) - -# Display a status message unless FIND_QUIETLY is set -macro(pkg_message PREFIX) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS ${ARGN}) - endif () -endmacro(pkg_message) - -# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes -macro(getenv_path VAR) - set(ENV_${VAR} $ENV{${VAR}}) - # replace won't work if var is blank - if (ENV_${VAR}) - string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) - endif () -endmacro(getenv_path) - -# Construct search paths for includes and libraries from a PREFIX_PATH -macro(create_search_paths PREFIX) - foreach(dir ${${PREFIX}_PREFIX_PATH}) - set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} - ${dir}/include ${dir}/Include ${dir}/include/${PREFIX} ${dir}/Headers) - set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} - ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX} ${dir}/Libs) - set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH} - ${dir}/bin) - endforeach(dir) - set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) -endmacro(create_search_paths) - -# clear cache variables if a certain variable changed -macro(clear_if_changed TESTVAR) - # test against internal check variable - # HACK: Apparently, adding a variable to the cache cleans up the list - # a bit. We need to also remove any empty strings from the list, but - # at the same time ensure that we are actually dealing with a list. - list(APPEND ${TESTVAR} "") - list(REMOVE_ITEM ${TESTVAR} "") - if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") - message(STATUS "${TESTVAR} changed.") - foreach(var ${ARGN}) - set(${var} "NOTFOUND" CACHE STRING "x" FORCE) - endforeach(var) - endif () - set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) -endmacro(clear_if_changed) - -# Try to get some hints from pkg-config, if available -macro(use_pkgconfig PREFIX PKGNAME) - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(${PREFIX} ${PKGNAME}) - endif () -endmacro (use_pkgconfig) - -# Couple a set of release AND debug libraries (or frameworks) -macro(make_library_set PREFIX) - if (${PREFIX}_FWK) - set(${PREFIX} ${${PREFIX}_FWK}) - elseif (${PREFIX}_REL AND ${PREFIX}_DBG) - set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) - elseif (${PREFIX}_REL) - set(${PREFIX} ${${PREFIX}_REL}) - elseif (${PREFIX}_DBG) - set(${PREFIX} ${${PREFIX}_DBG}) - endif () -endmacro(make_library_set) - -# Generate debug names from given release names -macro(get_debug_names PREFIX) - foreach(i ${${PREFIX}}) - set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) - endforeach(i) -endmacro(get_debug_names) - -# Add the parent dir from DIR to VAR -macro(add_parent_dir VAR DIR) - get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) - set(${VAR} ${${VAR}} ${${DIR}_TEMP}) -endmacro(add_parent_dir) - -# Do the final processing for the package find. -macro(findpkg_finish PREFIX) - # skip if already processed during this run - if (NOT ${PREFIX}_FOUND) - if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) - set(${PREFIX}_FOUND TRUE) - set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) - set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") - endif () - else () - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Could not locate ${PREFIX}") - endif () - if (${PREFIX}_FIND_REQUIRED) - message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") - endif () - endif () - - mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) - endif () -endmacro(findpkg_finish) - - -# Slightly customised framework finder -MACRO(findpkg_framework fwk) - IF(APPLE) - SET(${fwk}_FRAMEWORK_PATH - ${${fwk}_FRAMEWORK_SEARCH_PATH} - ${CMAKE_FRAMEWORK_PATH} - ~/Library/Frameworks - /Library/Frameworks - /System/Library/Frameworks - /Network/Library/Frameworks - /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/ - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Release - ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug - ) - # These could be arrays of paths, add each individually to the search paths - foreach(i ${OGRE_PREFIX_PATH}) - set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/Release ${i}/lib/Debug) - endforeach(i) - - foreach(i ${OGRE_PREFIX_BUILD}) - set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/Release ${i}/lib/Debug) - endforeach(i) - - FOREACH(dir ${${fwk}_FRAMEWORK_PATH}) - SET(fwkpath ${dir}/${fwk}.framework) - IF(EXISTS ${fwkpath}) - SET(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} - ${fwkpath}/Headers ${fwkpath}/PrivateHeaders) - SET(${fwk}_FRAMEWORK_PATH ${dir}) - if (NOT ${fwk}_LIBRARY_FWK) - SET(${fwk}_LIBRARY_FWK "-framework ${fwk}") - endif () - ENDIF(EXISTS ${fwkpath}) - ENDFOREACH(dir) - ENDIF(APPLE) -ENDMACRO(findpkg_framework) From 8a4722cb8412c8dc7967831e02bbe858317ab737 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 17:42:07 +0200 Subject: [PATCH 16/22] Revert "animateCollisionShape checks if the shape is really animated" This reverts commit cbf344663fc0914098d2c0d0b1679baa81ea1019. Doesn't work correctly because the Animation delays the assignment of the UpdateCallbacks until the animation starts. The commit broke the animation of in_dagoth_bridge00 --- apps/openmw/mwphysics/physicssystem.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 95de8430d..82397e406 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -591,7 +591,7 @@ namespace MWPhysics btCompoundShape* compound = static_cast(mShapeInstance->getCollisionShape()); - for (std::map::iterator it = mShapeInstance->mAnimatedShapes.begin(); it != mShapeInstance->mAnimatedShapes.end();) + for (std::map::const_iterator it = mShapeInstance->mAnimatedShapes.begin(); it != mShapeInstance->mAnimatedShapes.end(); ++it) { int recIndex = it->first; int shapeIndex = it->second; @@ -606,24 +606,6 @@ namespace MWPhysics osg::NodePath path = visitor.mFoundPath; path.erase(path.begin()); - - // Attempt to remove "animated" shapes that are not actually animated - // We may get these because the BulletNifLoader does not know if a .kf file with additional controllers will be attached later on. - // On the first animateCollisionShapes call, we'll consider the graph completely loaded (with extra controllers and what not), - // so now we can better decide if the shape is really animated. - bool animated = false; - for (osg::NodePath::iterator nodePathIt = path.begin(); nodePathIt != path.end(); ++nodePathIt) - { - osg::Node* node = *nodePathIt; - if (node->getUpdateCallback()) - animated = true; - } - if (!animated) - { - mShapeInstance->mAnimatedShapes.erase(it++); - break; - } - osg::Matrixf matrix = osg::computeLocalToWorld(path); osg::Vec3f scale = matrix.getScale(); matrix.orthoNormalize(matrix); @@ -636,8 +618,6 @@ namespace MWPhysics compound->getChildShape(shapeIndex)->setLocalScaling(compound->getLocalScaling() * toBullet(scale)); compound->updateChildTransform(shapeIndex, transform); - - ++it; } collisionWorld->updateSingleAabb(mCollisionObject.get()); From 4751e0e9538dd968451d5b52fd94fc541b117362 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 17:49:47 +0200 Subject: [PATCH 17/22] Improve performance of animateCollisionShapes by caching the node path --- apps/openmw/mwphysics/physicssystem.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 82397e406..ef9e0245a 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -596,17 +596,23 @@ namespace MWPhysics int recIndex = it->first; int shapeIndex = it->second; - NifOsg::FindGroupByRecIndex visitor(recIndex); - mPtr.getRefData().getBaseNode()->accept(visitor); - if (!visitor.mFound) + std::map::iterator nodePathFound = mRecIndexToNodePath.find(recIndex); + if (nodePathFound == mRecIndexToNodePath.end()) { - std::cerr << "animateCollisionShapes: Can't find node " << recIndex << std::endl; - return; + NifOsg::FindGroupByRecIndex visitor(recIndex); + mPtr.getRefData().getBaseNode()->accept(visitor); + if (!visitor.mFound) + { + std::cerr << "animateCollisionShapes: Can't find node " << recIndex << std::endl; + return; + } + osg::NodePath nodePath = visitor.mFoundPath; + nodePath.erase(nodePath.begin()); + nodePathFound = mRecIndexToNodePath.insert(std::make_pair(recIndex, nodePath)).first; } - osg::NodePath path = visitor.mFoundPath; - path.erase(path.begin()); - osg::Matrixf matrix = osg::computeLocalToWorld(path); + osg::NodePath& nodePath = nodePathFound->second; + osg::Matrixf matrix = osg::computeLocalToWorld(nodePath); osg::Vec3f scale = matrix.getScale(); matrix.orthoNormalize(matrix); @@ -626,6 +632,7 @@ namespace MWPhysics private: std::auto_ptr mCollisionObject; osg::ref_ptr mShapeInstance; + std::map mRecIndexToNodePath; bool mSolid; }; From 0209c705836511e66733a3cf5bd0a3c9d8df225c Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 17:50:16 +0200 Subject: [PATCH 18/22] Improve performance by skipping update if transform is unchanged --- apps/openmw/mwphysics/physicssystem.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index ef9e0245a..954d195dd 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -622,8 +622,10 @@ namespace MWPhysics for (int j=0; j<3; ++j) transform.getBasis()[i][j] = matrix(j,i); // NB column/row major difference - compound->getChildShape(shapeIndex)->setLocalScaling(compound->getLocalScaling() * toBullet(scale)); - compound->updateChildTransform(shapeIndex, transform); + if (compound->getLocalScaling() * toBullet(scale) != compound->getChildShape(shapeIndex)->getLocalScaling()) + compound->getChildShape(shapeIndex)->setLocalScaling(compound->getLocalScaling() * toBullet(scale)); + if (!(transform == compound->getChildTransform(shapeIndex))) + compound->updateChildTransform(shapeIndex, transform); } collisionWorld->updateSingleAabb(mCollisionObject.get()); From b2ae45f0eb2cd287e311683ea13b8974c2b3b10d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 19:33:09 +0200 Subject: [PATCH 19/22] Remove unneeded setGraphicsContext() calls --- apps/openmw/mwrender/characterpreview.cpp | 1 - apps/openmw/mwrender/localmap.cpp | 1 - apps/openmw/mwrender/renderingmanager.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 566a8d6ba..84f60c82d 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -93,7 +93,6 @@ namespace MWRender mCamera->setViewport(0, 0, sizeX, sizeY); mCamera->setRenderOrder(osg::Camera::PRE_RENDER); mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture); - mCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext()); mCamera->setNodeMask(Mask_RenderToTexture); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 833e2717b..489257ab3 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -208,7 +208,6 @@ osg::ref_ptr LocalMap::createOrthographicCamera(float x, float y, f camera->addChild(lightSource); camera->setStateSet(stateset); - camera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext()); camera->setViewport(0, 0, mMapResolution, mMapResolution); camera->setUpdateCallback(new CameraLocalUpdateCallback(this)); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 8f73036e9..d74bac0b3 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -620,7 +620,6 @@ namespace MWRender mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); rttCamera->removeChildren(0, rttCamera->getNumChildren()); - rttCamera->setGraphicsContext(NULL); mRootNode->removeChild(rttCamera); } From 8bfcf259a3a658156878e64be221b0d7f711eed8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 22:37:44 +0200 Subject: [PATCH 20/22] LocalMap no longer depends on osgViewer --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- apps/openmw/mwrender/localmap.cpp | 11 ++++------- apps/openmw/mwrender/localmap.hpp | 9 +-------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 54fd31acd..2426dc3e1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -282,7 +282,7 @@ namespace MWGui mRecharge = new Recharge(); mMenu = new MainMenu(w, h, mResourceSystem->getVFS(), mVersionDescription); - mLocalMapRender = new MWRender::LocalMap(mViewer); + mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup()); mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender); trackWindow(mMap, "map"); mStatsWindow = new StatsWindow(mDragAndDrop); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 489257ab3..3b45a3c60 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -7,11 +7,10 @@ #include #include #include +#include #include -#include - #include #include #include @@ -68,16 +67,14 @@ namespace namespace MWRender { -LocalMap::LocalMap(osgViewer::Viewer* viewer) - : mViewer(viewer) +LocalMap::LocalMap(osg::Group* root) + : mRoot(root) , mMapResolution(Settings::Manager::getInt("local map resolution", "Map")) , mMapWorldSize(8192.f) , mCellDistance(Settings::Manager::getInt("local map cell distance", "Map")) , mAngle(0.f) , mInterior(false) { - mRoot = mViewer->getSceneData()->asGroup(); - SceneUtil::FindByNameVisitor find("Scene Root"); mRoot->accept(find); mSceneRoot = find.mFoundNode; @@ -310,7 +307,7 @@ void LocalMap::requestExteriorMap(const MWWorld::CellStore* cell) int x = cell->getCell()->getGridX(); int y = cell->getCell()->getGridY(); - osg::BoundingSphere bound = mViewer->getSceneData()->getBound(); + osg::BoundingSphere bound = mSceneRoot->getBound(); float zmin = bound.center().z() - bound.radius(); float zmax = bound.center().z() + bound.radius(); diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 2516c063e..1928871ca 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -19,11 +19,6 @@ namespace ESM struct FogTexture; } -namespace osgViewer -{ - class Viewer; -} - namespace osg { class Texture2D; @@ -41,7 +36,7 @@ namespace MWRender class LocalMap { public: - LocalMap(osgViewer::Viewer* viewer); + LocalMap(osg::Group* root); ~LocalMap(); /** @@ -106,8 +101,6 @@ namespace MWRender osg::Group* getRoot(); private: - osg::ref_ptr mViewer; - osg::ref_ptr mRoot; osg::ref_ptr mSceneRoot; From dda5bfbc9f9abf0d2f43eb21e5e61f39b4a60dd2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 22:47:45 +0200 Subject: [PATCH 21/22] CharacterPreview no longer depends on osgViewer --- apps/openmw/mwgui/charactercreation.cpp | 6 +++--- apps/openmw/mwgui/charactercreation.hpp | 8 ++++---- apps/openmw/mwgui/inventorywindow.cpp | 4 ++-- apps/openmw/mwgui/inventorywindow.hpp | 6 +++--- apps/openmw/mwgui/race.cpp | 6 +++--- apps/openmw/mwgui/race.hpp | 8 ++++---- apps/openmw/mwgui/windowmanagerimp.cpp | 6 +++--- apps/openmw/mwrender/characterpreview.cpp | 18 +++++++++--------- apps/openmw/mwrender/characterpreview.hpp | 14 +++++--------- components/resource/imagemanager.hpp | 5 ----- 10 files changed, 36 insertions(+), 45 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index a880bca45..9a1b43678 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -62,8 +62,8 @@ namespace namespace MWGui { - CharacterCreation::CharacterCreation(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem) - : mViewer(viewer) + CharacterCreation::CharacterCreation(osg::Group* parent, Resource::ResourceSystem* resourceSystem) + : mParent(parent) , mResourceSystem(resourceSystem) , mNameDialog(0) , mRaceDialog(0) @@ -152,7 +152,7 @@ namespace MWGui case GM_Race: MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog); mRaceDialog = 0; - mRaceDialog = new RaceDialog(mViewer, mResourceSystem); + mRaceDialog = new RaceDialog(mParent, mResourceSystem); mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen); mRaceDialog->setRaceId(mPlayerRaceId); mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone); diff --git a/apps/openmw/mwgui/charactercreation.hpp b/apps/openmw/mwgui/charactercreation.hpp index 7fb67caf6..75f3a7016 100644 --- a/apps/openmw/mwgui/charactercreation.hpp +++ b/apps/openmw/mwgui/charactercreation.hpp @@ -8,9 +8,9 @@ #include "../mwmechanics/stat.hpp" -namespace osgViewer +namespace osg { - class Viewer; + class Group; } namespace Resource @@ -39,7 +39,7 @@ namespace MWGui public: typedef std::vector SkillList; - CharacterCreation(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem); + CharacterCreation(osg::Group* parent, Resource::ResourceSystem* resourceSystem); ~CharacterCreation(); //Show a dialog @@ -51,7 +51,7 @@ namespace MWGui void configureSkills (const SkillList& major, const SkillList& minor); private: - osgViewer::Viewer* mViewer; + osg::Group* mParent; Resource::ResourceSystem* mResourceSystem; //Dialogs diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 4599132e3..bd864b45b 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -56,7 +56,7 @@ namespace namespace MWGui { - InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop, osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem) + InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem) : WindowPinnableBase("openmw_inventory_window.layout") , mDragAndDrop(dragAndDrop) , mSelectedItem(-1) @@ -65,7 +65,7 @@ namespace MWGui , mGuiMode(GM_Inventory) , mLastXSize(0) , mLastYSize(0) - , mPreview(new MWRender::InventoryPreview(viewer, resourceSystem, MWMechanics::getPlayer())) + , mPreview(new MWRender::InventoryPreview(parent, resourceSystem, MWMechanics::getPlayer())) , mTrading(false) { mPreviewTexture.reset(new osgMyGUI::OSGTexture(mPreview->getTexture())); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index b7ae067ac..651bda590 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -6,9 +6,9 @@ #include "../mwworld/ptr.hpp" -namespace osgViewer +namespace osg { - class Viewer; + class Group; } namespace Resource @@ -37,7 +37,7 @@ namespace MWGui class InventoryWindow : public WindowPinnableBase { public: - InventoryWindow(DragAndDrop* dragAndDrop, osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem); + InventoryWindow(DragAndDrop* dragAndDrop, osg::Group* parent, Resource::ResourceSystem* resourceSystem); virtual void open(); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 6c08f7dc1..daa07d5c4 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -41,9 +41,9 @@ namespace namespace MWGui { - RaceDialog::RaceDialog(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem) + RaceDialog::RaceDialog(osg::Group* parent, Resource::ResourceSystem* resourceSystem) : WindowModal("openmw_chargen_race.layout") - , mViewer(viewer) + , mParent(parent) , mResourceSystem(resourceSystem) , mGenderIndex(0) , mFaceIndex(0) @@ -136,7 +136,7 @@ namespace MWGui mPreview.reset(NULL); mPreviewTexture.reset(NULL); - mPreview.reset(new MWRender::RaceSelectionPreview(mViewer, mResourceSystem)); + mPreview.reset(new MWRender::RaceSelectionPreview(mParent, mResourceSystem)); mPreview->rebuild(); mPreview->setAngle (mCurrentAngle); diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index b3de9bef0..42e758983 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -19,9 +19,9 @@ namespace ESM struct NPC; } -namespace osgViewer +namespace osg { - class Viewer; + class Group; } namespace Resource @@ -34,7 +34,7 @@ namespace MWGui class RaceDialog : public WindowModal { public: - RaceDialog(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem); + RaceDialog(osg::Group* parent, Resource::ResourceSystem* resourceSystem); enum Gender { @@ -93,7 +93,7 @@ namespace MWGui void getBodyParts (int part, std::vector& out); - osgViewer::Viewer* mViewer; + osg::Group* mParent; Resource::ResourceSystem* mResourceSystem; std::vector mAvailableHeads; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2426dc3e1..09b72ad3d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -293,7 +293,7 @@ namespace MWGui bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds"); mJournal = JournalWindow::create(JournalViewModel::create (), questList); mMessageBoxManager = new MessageBoxManager(mStore->get().find("fMessageTimePerChar")->getFloat()); - mInventoryWindow = new InventoryWindow(mDragAndDrop, mViewer, mResourceSystem); + mInventoryWindow = new InventoryWindow(mDragAndDrop, mViewer->getSceneData()->asGroup(), mResourceSystem); mTradeWindow = new TradeWindow(); trackWindow(mTradeWindow, "barter"); mSpellBuyingWindow = new SpellBuyingWindow(); @@ -350,7 +350,7 @@ namespace MWGui mHud->setVisible(mHudEnabled); - mCharGen = new CharacterCreation(mViewer, mResourceSystem); + mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); // Setup player stats for (int i = 0; i < ESM::Attribute::Length; ++i) @@ -384,7 +384,7 @@ namespace MWGui { disallowAll(); delete mCharGen; - mCharGen = new CharacterCreation(mViewer, mResourceSystem); + mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); mGuiModes.clear(); MWBase::Environment::get().getInputManager()->changeInputMode(false); mHud->unsetSelectedWeapon(); diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 84f60c82d..ed61334bb 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include #include @@ -65,9 +65,9 @@ namespace MWRender unsigned int mLastRenderedFrame; }; - CharacterPreview::CharacterPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, + CharacterPreview::CharacterPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character, int sizeX, int sizeY, const osg::Vec3f& position, const osg::Vec3f& lookAt) - : mViewer(viewer) + : mParent(parent) , mResourceSystem(resourceSystem) , mPosition(position) , mLookAt(lookAt) @@ -139,7 +139,7 @@ namespace MWRender mDrawOnceCallback = new DrawOnceCallback; mCamera->addUpdateCallback(mDrawOnceCallback); - mViewer->getSceneData()->asGroup()->addChild(mCamera); + mParent->addChild(mCamera); mCharacter.mCell = NULL; } @@ -147,7 +147,7 @@ namespace MWRender CharacterPreview::~CharacterPreview () { mCamera->removeChildren(0, mCamera->getNumChildren()); - mViewer->getSceneData()->asGroup()->removeChild(mCamera); + mParent->removeChild(mCamera); } int CharacterPreview::getTextureWidth() const @@ -190,8 +190,8 @@ namespace MWRender // -------------------------------------------------------------------------------------------------- - InventoryPreview::InventoryPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character) - : CharacterPreview(viewer, resourceSystem, character, 512, 1024, osg::Vec3f(0, 700, 71), osg::Vec3f(0,0,71)) + InventoryPreview::InventoryPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character) + : CharacterPreview(parent, resourceSystem, character, 512, 1024, osg::Vec3f(0, 700, 71), osg::Vec3f(0,0,71)) { } @@ -319,8 +319,8 @@ namespace MWRender // -------------------------------------------------------------------------------------------------- - RaceSelectionPreview::RaceSelectionPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem) - : CharacterPreview(viewer, resourceSystem, MWMechanics::getPlayer(), + RaceSelectionPreview::RaceSelectionPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem) + : CharacterPreview(parent, resourceSystem, MWMechanics::getPlayer(), 512, 512, osg::Vec3f(0, 125, 8), osg::Vec3f(0,0,8)) , mBase (*mCharacter.get()->mBase) , mRef(&mBase) diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index 2b7984b00..2a4ef9877 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -16,11 +16,7 @@ namespace osg { class Texture2D; class Camera; -} - -namespace osgViewer -{ - class Viewer; + class Group; } namespace MWRender @@ -32,7 +28,7 @@ namespace MWRender class CharacterPreview { public: - CharacterPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character, int sizeX, int sizeY, + CharacterPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character, int sizeX, int sizeY, const osg::Vec3f& position, const osg::Vec3f& lookAt); virtual ~CharacterPreview(); @@ -53,7 +49,7 @@ namespace MWRender virtual bool renderHeadOnly() { return false; } virtual void onSetup(); - osg::ref_ptr mViewer; + osg::ref_ptr mParent; Resource::ResourceSystem* mResourceSystem; osg::ref_ptr mTexture; osg::ref_ptr mCamera; @@ -76,7 +72,7 @@ namespace MWRender { public: - InventoryPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character); + InventoryPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem, MWWorld::Ptr character); void updatePtr(const MWWorld::Ptr& ptr); @@ -102,7 +98,7 @@ namespace MWRender virtual void onSetup(); public: - RaceSelectionPreview(osgViewer::Viewer* viewer, Resource::ResourceSystem* resourceSystem); + RaceSelectionPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem); virtual ~RaceSelectionPreview(); void setAngle(float angleRadians); diff --git a/components/resource/imagemanager.hpp b/components/resource/imagemanager.hpp index 8d9ad2c32..2ef601e6b 100644 --- a/components/resource/imagemanager.hpp +++ b/components/resource/imagemanager.hpp @@ -10,11 +10,6 @@ #include "resourcemanager.hpp" -namespace osgViewer -{ - class Viewer; -} - namespace osgDB { class Options; From 341e3846c0727d70a0dae3226b00cfa9c76fd0a8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 16 Aug 2016 23:28:03 +0200 Subject: [PATCH 22/22] Use initial particle state to compute the initial bounding box (Fixes #3500) --- components/nifosg/nifloader.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 309dac88b..8a50c2c92 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -868,6 +868,8 @@ namespace NifOsg else return; + osg::BoundingBox box; + int i=0; for (std::vector::const_iterator it = partctrl->particles.begin(); iactiveCount && it != partctrl->particles.end(); ++it, ++i) @@ -882,7 +884,8 @@ namespace NifOsg // Note this position and velocity is not correct for a particle system with absolute reference frame, // which can not be done in this loader since we are not attached to the scene yet. Will be fixed up post-load in the SceneManager. created->setVelocity(particle.velocity); - created->setPosition(particledata->vertices->at(particle.vertex)); + const osg::Vec3f& position = particledata->vertices->at(particle.vertex); + created->setPosition(position); osg::Vec4f partcolor (1.f,1.f,1.f,1.f); if (particle.vertex < int(particledata->colors->size())) @@ -891,10 +894,12 @@ namespace NifOsg float size = particledata->sizes.at(particle.vertex) * partctrl->size; created->setSizeRange(osgParticle::rangef(size, size)); + box.expandBy(osg::BoundingSphere(position, size)); } - osg::BoundingBox box; + // radius may be used to force a larger bounding box box.expandBy(osg::BoundingSphere(osg::Vec3(0,0,0), particledata->radius)); + partsys->setInitialBound(box); }