summaryrefslogtreecommitdiffstats
path: root/svx/source/engine3d/dragmt3d.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /svx/source/engine3d/dragmt3d.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svx/source/engine3d/dragmt3d.cxx')
-rw-r--r--svx/source/engine3d/dragmt3d.cxx732
1 files changed, 732 insertions, 0 deletions
diff --git a/svx/source/engine3d/dragmt3d.cxx b/svx/source/engine3d/dragmt3d.cxx
new file mode 100644
index 000000000..c27d95598
--- /dev/null
+++ b/svx/source/engine3d/dragmt3d.cxx
@@ -0,0 +1,732 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <dragmt3d.hxx>
+#include <o3tl/numeric.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/svddrgmt.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/obj3d.hxx>
+#include <svx/e3dundo.hxx>
+#include <svx/strings.hrc>
+#include <svx/sdr/overlay/overlaypolypolygon.hxx>
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <svx/sdr/contact/viewcontactofe3dscene.hxx>
+#include <drawinglayer/geometry/viewinformation3d.hxx>
+#include <svx/e3dsceneupdater.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <comphelper/lok.hxx>
+
+
+E3dDragMethod::E3dDragMethod (
+ SdrDragView &_rView,
+ const SdrMarkList& rMark,
+ E3dDragConstraint eConstr,
+ bool bFull)
+: SdrDragMethod(_rView),
+ meConstraint(eConstr),
+ mbMoveFull(bFull),
+ mbMovedAtAll(false)
+{
+ // Create a unit for all the 3D objects present in the selection
+ const size_t nCnt(rMark.GetMarkCount());
+
+ if(mbMoveFull)
+ {
+ // for non-visible 3D objects fallback to wireframe interaction
+ for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
+ {
+ E3dObject* pE3dObj = dynamic_cast< E3dObject* >(rMark.GetMark(nObjs)->GetMarkedSdrObj());
+
+ if(pE3dObj)
+ {
+ if(!pE3dObj->HasFillStyle() && !pE3dObj->HasLineStyle())
+ {
+ mbMoveFull = false;
+ break;
+ }
+ }
+ }
+ }
+
+ for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
+ {
+ E3dObject* pE3dObj = dynamic_cast< E3dObject* >(rMark.GetMark(nObjs)->GetMarkedSdrObj());
+
+ if(pE3dObj)
+ {
+ // fill new interaction unit
+ E3dDragMethodUnit aNewUnit(*pE3dObj);
+
+ // get transformations
+ aNewUnit.maInitTransform = aNewUnit.maTransform = pE3dObj->GetTransform();
+
+ if(nullptr != pE3dObj->getParentE3dSceneFromE3dObject())
+ {
+ // get transform between object and world, normally scene transform
+ aNewUnit.maInvDisplayTransform = aNewUnit.maDisplayTransform = pE3dObj->getParentE3dSceneFromE3dObject()->GetFullTransform();
+ aNewUnit.maInvDisplayTransform.invert();
+ }
+
+ if(!mbMoveFull)
+ {
+ // create wireframe visualisation for parent coordinate system
+ aNewUnit.maWireframePoly.clear();
+ aNewUnit.maWireframePoly = pE3dObj->CreateWireframe();
+ aNewUnit.maWireframePoly.transform(aNewUnit.maTransform);
+ }
+
+ // Determine FullBound
+ maFullBound.Union(pE3dObj->GetSnapRect());
+
+ // Insert Unit
+ maGrp.push_back(aNewUnit);
+ }
+ }
+}
+
+OUString E3dDragMethod::GetSdrDragComment() const
+{
+ return OUString();
+}
+
+// Create the wireframe model for all actions
+
+bool E3dDragMethod::BeginSdrDrag()
+{
+ if(E3dDragConstraint::Z == meConstraint)
+ {
+ const sal_uInt32 nCnt(maGrp.size());
+ DragStat().SetRef1( maFullBound.Center() );
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ rCandidate.mnStartAngle = GetAngle(DragStat().GetStart() - DragStat().GetRef1());
+ rCandidate.mnLastAngle = 0_deg100;
+ }
+ }
+ else
+ {
+ maLastPos = DragStat().GetStart();
+ }
+
+ if(!mbMoveFull)
+ {
+ Show();
+ }
+
+ return true;
+}
+
+bool E3dDragMethod::EndSdrDrag(bool /*bCopy*/)
+{
+ const sal_uInt32 nCnt(maGrp.size());
+
+ if(!mbMoveFull)
+ {
+ // Hide wireframe
+ Hide();
+ }
+
+ // Apply all transformations and create undo's
+ if(mbMovedAtAll)
+ {
+ const bool bUndo = getSdrDragView().IsUndoEnabled();
+ if( bUndo )
+ getSdrDragView().BegUndo(SvxResId(RID_SVX_3D_UNDO_ROTATE));
+ sal_uInt32 nOb(0);
+
+ for(nOb=0;nOb<nCnt;nOb++)
+ {
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
+ rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
+ if( bUndo )
+ {
+ getSdrDragView().AddUndo(
+ std::make_unique<E3dRotateUndoAction>(
+ rCandidate.mr3DObj,
+ rCandidate.maInitTransform,
+ rCandidate.maTransform));
+ }
+ }
+ if( bUndo )
+ getSdrDragView().EndUndo();
+ }
+
+ return true;
+}
+
+void E3dDragMethod::CancelSdrDrag()
+{
+ if(mbMoveFull)
+ {
+ if(mbMovedAtAll)
+ {
+ const sal_uInt32 nCnt(maGrp.size());
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ // Restore transformation
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
+ rCandidate.mr3DObj.SetTransform(rCandidate.maInitTransform);
+ }
+ }
+ }
+ else
+ {
+ // Hide WireFrame
+ Hide();
+ }
+}
+
+// Common MoveSdrDrag()
+
+void E3dDragMethod::MoveSdrDrag(const Point& /*rPnt*/)
+{
+ mbMovedAtAll = true;
+}
+
+// Draw the wire frame model
+
+// for migration from XOR to overlay
+void E3dDragMethod::CreateOverlayGeometry(
+ sdr::overlay::OverlayManager& rOverlayManager,
+ const sdr::contact::ObjectContact& rObjectContact)
+{
+ // We do client-side object manipulation with the Kit API
+ if (comphelper::LibreOfficeKit::isActive())
+ return;
+
+ const sal_uInt32 nCnt(maGrp.size());
+ basegfx::B2DPolyPolygon aResult;
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ SdrPageView* pPV = getSdrDragView().GetSdrPageView();
+
+ if(pPV && pPV->HasMarkedObjPageView())
+ {
+ const basegfx::B3DPolyPolygon aCandidate(rCandidate.maWireframePoly);
+ const sal_uInt32 nPlyCnt(aCandidate.count());
+
+ if(nPlyCnt)
+ {
+ const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
+
+ if(nullptr != pScene)
+ {
+ const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
+ const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
+ const basegfx::B3DHomMatrix aWorldToView(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection() * aViewInfo3D.getOrientation());
+ const basegfx::B3DHomMatrix aTransform(aWorldToView * rCandidate.maDisplayTransform);
+
+ // transform to relative scene coordinates
+ basegfx::B2DPolyPolygon aPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aCandidate, aTransform));
+
+ // transform to 2D view coordinates
+ aPolyPolygon.transform(rVCScene.getObjectTransformation());
+
+ aResult.append(aPolyPolygon);
+ }
+ }
+ }
+ }
+
+ if(aResult.count())
+ {
+ std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(
+ new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
+ aResult));
+
+ insertNewlyCreatedOverlayObjectForSdrDragMethod(
+ std::move(pNew),
+ rObjectContact,
+ rOverlayManager);
+ }
+}
+
+
+E3dDragRotate::E3dDragRotate(SdrDragView &_rView,
+ const SdrMarkList& rMark,
+ E3dDragConstraint eConstr,
+ bool bFull)
+: E3dDragMethod(_rView, rMark, eConstr, bFull)
+{
+ // Get center of all selected objects in eye coordinates
+ const sal_uInt32 nCnt(maGrp.size());
+
+ if(!nCnt)
+ return;
+
+ const E3dScene* pScene(maGrp[0].mr3DObj.getRootE3dSceneFromE3dObject());
+
+ if(nullptr == pScene)
+ return;
+
+ const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
+ const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ basegfx::B3DPoint aObjCenter = rCandidate.mr3DObj.GetBoundVolume().getCenter();
+ const basegfx::B3DHomMatrix aTransform(aViewInfo3D.getOrientation() * rCandidate.maDisplayTransform * rCandidate.maInitTransform);
+
+ aObjCenter = aTransform * aObjCenter;
+ maGlobalCenter += aObjCenter;
+ }
+
+ // Divide by the number
+ if(nCnt > 1)
+ {
+ maGlobalCenter /= static_cast<double>(nCnt);
+ }
+
+ // get rotate center and transform to 3D eye coordinates
+ basegfx::B2DPoint aRotCenter2D(Ref1().X(), Ref1().Y());
+
+ // from world to relative scene using inverse getObjectTransformation()
+ basegfx::B2DHomMatrix aInverseObjectTransform(rVCScene.getObjectTransformation());
+ aInverseObjectTransform.invert();
+ aRotCenter2D = aInverseObjectTransform * aRotCenter2D;
+
+ // from 3D view to 3D eye
+ basegfx::B3DPoint aRotCenter3D(aRotCenter2D.getX(), aRotCenter2D.getY(), 0.0);
+ basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
+ aInverseViewToEye.invert();
+ aRotCenter3D = aInverseViewToEye * aRotCenter3D;
+
+// Use X,Y of the RotCenter and depth of the common object centre
+// as rotation point in the space
+ maGlobalCenter.setX(aRotCenter3D.getX());
+ maGlobalCenter.setY(aRotCenter3D.getY());
+}
+
+
+//The object is moved, determine the angle
+
+void E3dDragRotate::MoveSdrDrag(const Point& rPnt)
+{
+ // call parent
+ E3dDragMethod::MoveSdrDrag(rPnt);
+
+ if(!DragStat().CheckMinMoved(rPnt))
+ return;
+
+ // Get modifier
+ sal_uInt16 nModifier = 0;
+ if(auto pDragView = dynamic_cast<const E3dView*>(&getSdrDragView()))
+ {
+ const MouseEvent& rLastMouse = pDragView->GetMouseEvent();
+ nModifier = rLastMouse.GetModifier();
+ }
+
+ // Rotate all objects
+ const sal_uInt32 nCnt(maGrp.size());
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ // Determine rotation angle
+ double fWAngle, fHAngle;
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+
+ if(E3dDragConstraint::Z == meConstraint)
+ {
+ Degree100 lastAngle = NormAngle36000(GetAngle(rPnt - DragStat().GetRef1()) -
+ rCandidate.mnStartAngle) - rCandidate.mnLastAngle;
+ rCandidate.mnLastAngle = lastAngle + rCandidate.mnLastAngle;
+ fWAngle = toDegrees(lastAngle);
+ fHAngle = 0.0;
+ }
+ else
+ {
+ if ((maFullBound.GetWidth() == 0) || (maFullBound.GetHeight() == 0))
+ throw o3tl::divide_by_zero();
+ fWAngle = 90.0 * static_cast<double>(rPnt.X() - maLastPos.X())
+ / static_cast<double>(maFullBound.GetWidth());
+ fHAngle = 90.0 * static_cast<double>(rPnt.Y() - maLastPos.Y())
+ / static_cast<double>(maFullBound.GetHeight());
+ }
+ tools::Long nSnap = 0;
+
+ if(!getSdrDragView().IsRotateAllowed())
+ nSnap = 90;
+
+ if(nSnap != 0)
+ {
+ fWAngle = static_cast<double>((static_cast<tools::Long>(fWAngle) + nSnap/2) / nSnap * nSnap);
+ fHAngle = static_cast<double>((static_cast<tools::Long>(fHAngle) + nSnap/2) / nSnap * nSnap);
+ }
+
+ // to radians
+ fWAngle = basegfx::deg2rad(fWAngle);
+ fHAngle = basegfx::deg2rad(fHAngle);
+
+ // Determine transformation
+ basegfx::B3DHomMatrix aRotMat;
+ if(E3dDragConstraint::Y & meConstraint)
+ {
+ if(nModifier & KEY_MOD2)
+ aRotMat.rotate(0.0, 0.0, fWAngle);
+ else
+ aRotMat.rotate(0.0, fWAngle, 0.0);
+ }
+ else if(E3dDragConstraint::Z & meConstraint)
+ {
+ if(nModifier & KEY_MOD2)
+ aRotMat.rotate(0.0, fWAngle, 0.0);
+ else
+ aRotMat.rotate(0.0, 0.0, fWAngle);
+ }
+ if(E3dDragConstraint::X & meConstraint)
+ {
+ aRotMat.rotate(fHAngle, 0.0, 0.0);
+ }
+
+ const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
+
+ if(nullptr != pScene)
+ {
+ // Transformation in eye coordinates, there rotate then and back
+ const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
+ const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
+ basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
+ aInverseOrientation.invert();
+
+ basegfx::B3DHomMatrix aTransMat(rCandidate.maDisplayTransform);
+ aTransMat *= aViewInfo3D.getOrientation();
+ aTransMat.translate(-maGlobalCenter.getX(), -maGlobalCenter.getY(), -maGlobalCenter.getZ());
+ aTransMat *= aRotMat;
+ aTransMat.translate(maGlobalCenter.getX(), maGlobalCenter.getY(), maGlobalCenter.getZ());
+ aTransMat *= aInverseOrientation;
+ aTransMat *= rCandidate.maInvDisplayTransform;
+
+ // ...and apply
+ rCandidate.maTransform *= aTransMat;
+
+ if(mbMoveFull)
+ {
+ E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
+ rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
+ }
+ else
+ {
+ Hide();
+ rCandidate.maWireframePoly.transform(aTransMat);
+ Show();
+ }
+ }
+ }
+ maLastPos = rPnt;
+ DragStat().NextMove(rPnt);
+}
+
+PointerStyle E3dDragRotate::GetSdrDragPointer() const
+{
+ return PointerStyle::Rotate;
+}
+
+// E3dDragMove. This drag method is only required for translations inside
+// 3D scenes. If a 3D-scene itself moved, then this drag method will drag
+// not be used.
+
+
+E3dDragMove::E3dDragMove(SdrDragView &_rView,
+ const SdrMarkList& rMark,
+ SdrHdlKind eDrgHdl,
+ E3dDragConstraint eConstr,
+ bool bFull)
+: E3dDragMethod(_rView, rMark, eConstr, bFull),
+ meWhatDragHdl(eDrgHdl)
+{
+ switch(meWhatDragHdl)
+ {
+ case SdrHdlKind::Left:
+ maScaleFixPos = maFullBound.RightCenter();
+ break;
+ case SdrHdlKind::Right:
+ maScaleFixPos = maFullBound.LeftCenter();
+ break;
+ case SdrHdlKind::Upper:
+ maScaleFixPos = maFullBound.BottomCenter();
+ break;
+ case SdrHdlKind::Lower:
+ maScaleFixPos = maFullBound.TopCenter();
+ break;
+ case SdrHdlKind::UpperLeft:
+ maScaleFixPos = maFullBound.BottomRight();
+ break;
+ case SdrHdlKind::UpperRight:
+ maScaleFixPos = maFullBound.BottomLeft();
+ break;
+ case SdrHdlKind::LowerLeft:
+ maScaleFixPos = maFullBound.TopRight();
+ break;
+ case SdrHdlKind::LowerRight:
+ maScaleFixPos = maFullBound.TopLeft();
+ break;
+ default:
+ // Moving the object, SdrHdlKind::Move
+ break;
+ }
+
+ // Override when IsResizeAtCenter()
+ if(getSdrDragView().IsResizeAtCenter())
+ {
+ meWhatDragHdl = SdrHdlKind::User;
+ maScaleFixPos = maFullBound.Center();
+ }
+}
+
+// The object is moved, determine the translations
+
+void E3dDragMove::MoveSdrDrag(const Point& rPnt)
+{
+ // call parent
+ E3dDragMethod::MoveSdrDrag(rPnt);
+
+ if(!DragStat().CheckMinMoved(rPnt))
+ return;
+
+ if(SdrHdlKind::Move == meWhatDragHdl)
+ {
+ // Translation
+ // Determine the motion vector
+ const sal_uInt32 nCnt(maGrp.size());
+
+ // Get modifier
+ sal_uInt16 nModifier(0);
+
+ if(auto pDragView = dynamic_cast<const E3dView*>(&getSdrDragView()))
+ {
+ const MouseEvent& rLastMouse = pDragView->GetMouseEvent();
+ nModifier = rLastMouse.GetModifier();
+ }
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
+
+ if(nullptr != pScene)
+ {
+ const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
+ const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
+
+ // move coor from 2d world to 3d Eye
+ basegfx::B2DPoint aGlobalMoveHead2D(static_cast<double>(rPnt.X() - maLastPos.X()), static_cast<double>(rPnt.Y() - maLastPos.Y()));
+ basegfx::B2DPoint aGlobalMoveTail2D(0.0, 0.0);
+ basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
+
+ aInverseSceneTransform.invert();
+ aGlobalMoveHead2D = aInverseSceneTransform * aGlobalMoveHead2D;
+ aGlobalMoveTail2D = aInverseSceneTransform * aGlobalMoveTail2D;
+
+ basegfx::B3DPoint aMoveHead3D(aGlobalMoveHead2D.getX(), aGlobalMoveHead2D.getY(), 0.5);
+ basegfx::B3DPoint aMoveTail3D(aGlobalMoveTail2D.getX(), aGlobalMoveTail2D.getY(), 0.5);
+ basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
+ aInverseViewToEye.invert();
+
+ aMoveHead3D = aInverseViewToEye * aMoveHead3D;
+ aMoveTail3D = aInverseViewToEye * aMoveTail3D;
+
+ // eventually switch movement from XY to XZ plane
+ if(nModifier & KEY_MOD2)
+ {
+ double fZwi = aMoveHead3D.getY();
+ aMoveHead3D.setY(aMoveHead3D.getZ());
+ aMoveHead3D.setZ(fZwi);
+
+ fZwi = aMoveTail3D.getY();
+ aMoveTail3D.setY(aMoveTail3D.getZ());
+ aMoveTail3D.setZ(fZwi);
+ }
+
+ // Motion vector from eye coordinates to parent coordinates
+ basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
+ aInverseOrientation.invert();
+ basegfx::B3DHomMatrix aCompleteTrans(rCandidate.maInvDisplayTransform * aInverseOrientation);
+
+ aMoveHead3D = aCompleteTrans * aMoveHead3D;
+ aMoveTail3D = aCompleteTrans* aMoveTail3D;
+
+ // build transformation
+ basegfx::B3DHomMatrix aTransMat;
+ basegfx::B3DPoint aTranslate(aMoveHead3D - aMoveTail3D);
+ aTransMat.translate(aTranslate.getX(), aTranslate.getY(), aTranslate.getZ());
+
+ // ...and apply
+ rCandidate.maTransform *= aTransMat;
+
+ if(mbMoveFull)
+ {
+ E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
+ rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
+ }
+ else
+ {
+ Hide();
+ rCandidate.maWireframePoly.transform(aTransMat);
+ Show();
+ }
+ }
+ }
+ }
+ else
+ {
+ // Scaling
+ // Determine scaling vector
+ Point aStartPos = DragStat().GetStart();
+ const sal_uInt32 nCnt(maGrp.size());
+
+ for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
+ {
+ E3dDragMethodUnit& rCandidate = maGrp[nOb];
+ const basegfx::B3DPoint aObjectCenter(rCandidate.mr3DObj.GetBoundVolume().getCenter());
+ const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
+
+ if(nullptr != pScene)
+ {
+ // transform from 2D world view to 3D eye
+ const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
+ const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
+
+ basegfx::B2DPoint aGlobalScaleStart2D(static_cast<double>(aStartPos.X()), static_cast<double>(aStartPos.Y()));
+ basegfx::B2DPoint aGlobalScaleNext2D(static_cast<double>(rPnt.X()), static_cast<double>(rPnt.Y()));
+ basegfx::B2DPoint aGlobalScaleFixPos2D(static_cast<double>(maScaleFixPos.X()), static_cast<double>(maScaleFixPos.Y()));
+ basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
+
+ aInverseSceneTransform.invert();
+ aGlobalScaleStart2D = aInverseSceneTransform * aGlobalScaleStart2D;
+ aGlobalScaleNext2D = aInverseSceneTransform * aGlobalScaleNext2D;
+ aGlobalScaleFixPos2D = aInverseSceneTransform * aGlobalScaleFixPos2D;
+
+ basegfx::B3DPoint aGlobalScaleStart3D(aGlobalScaleStart2D.getX(), aGlobalScaleStart2D.getY(), aObjectCenter.getZ());
+ basegfx::B3DPoint aGlobalScaleNext3D(aGlobalScaleNext2D.getX(), aGlobalScaleNext2D.getY(), aObjectCenter.getZ());
+ basegfx::B3DPoint aGlobalScaleFixPos3D(aGlobalScaleFixPos2D.getX(), aGlobalScaleFixPos2D.getY(), aObjectCenter.getZ());
+ basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
+
+ aInverseViewToEye.invert();
+ basegfx::B3DPoint aScStart(aInverseViewToEye * aGlobalScaleStart3D);
+ basegfx::B3DPoint aScNext(aInverseViewToEye * aGlobalScaleNext3D);
+ basegfx::B3DPoint aScFixPos(aInverseViewToEye * aGlobalScaleFixPos3D);
+
+ // constraints?
+ switch(meWhatDragHdl)
+ {
+ case SdrHdlKind::Left:
+ case SdrHdlKind::Right:
+ // to constrain on X -> Y equal
+ aScNext.setY(aScFixPos.getY());
+ break;
+ case SdrHdlKind::Upper:
+ case SdrHdlKind::Lower:
+ // constrain to Y -> X equal
+ aScNext.setX(aScFixPos.getX());
+ break;
+ default:
+ break;
+ }
+
+ // get scale vector in eye coordinates
+ basegfx::B3DPoint aScaleVec(aScStart - aScFixPos);
+ aScaleVec.setZ(1.0);
+
+ if(aScaleVec.getX() != 0.0)
+ {
+ aScaleVec.setX((aScNext.getX() - aScFixPos.getX()) / aScaleVec.getX());
+ }
+ else
+ {
+ aScaleVec.setX(1.0);
+ }
+
+ if(aScaleVec.getY() != 0.0)
+ {
+ aScaleVec.setY((aScNext.getY() - aScFixPos.getY()) / aScaleVec.getY());
+ }
+ else
+ {
+ aScaleVec.setY(1.0);
+ }
+
+ // SHIFT-key used?
+ if(getSdrDragView().IsOrtho())
+ {
+ if(fabs(aScaleVec.getX()) > fabs(aScaleVec.getY()))
+ {
+ // X is biggest
+ aScaleVec.setY(aScaleVec.getX());
+ }
+ else
+ {
+ // Y is biggest
+ aScaleVec.setX(aScaleVec.getY());
+ }
+ }
+
+ // build transformation
+ basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
+ aInverseOrientation.invert();
+
+ basegfx::B3DHomMatrix aNewTrans = rCandidate.maInitTransform;
+ aNewTrans *= rCandidate.maDisplayTransform;
+ aNewTrans *= aViewInfo3D.getOrientation();
+ aNewTrans.translate(-aScFixPos.getX(), -aScFixPos.getY(), -aScFixPos.getZ());
+ aNewTrans.scale(aScaleVec.getX(), aScaleVec.getY(), aScaleVec.getZ());
+ aNewTrans.translate(aScFixPos.getX(), aScFixPos.getY(), aScFixPos.getZ());
+ aNewTrans *= aInverseOrientation;
+ aNewTrans *= rCandidate.maInvDisplayTransform;
+
+ // ...and apply
+ rCandidate.maTransform = aNewTrans;
+
+ if(mbMoveFull)
+ {
+ E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
+ rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
+ }
+ else
+ {
+ Hide();
+ rCandidate.maWireframePoly.clear();
+ rCandidate.maWireframePoly = rCandidate.mr3DObj.CreateWireframe();
+ rCandidate.maWireframePoly.transform(rCandidate.maTransform);
+ Show();
+ }
+ }
+ }
+ }
+ maLastPos = rPnt;
+ DragStat().NextMove(rPnt);
+}
+
+PointerStyle E3dDragMove::GetSdrDragPointer() const
+{
+ return PointerStyle::Move;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */