xref: /AOO41X/main/svx/source/engine3d/dragmt3d.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <dragmt3d.hxx>
28 #include <tools/shl.hxx>
29 #include <svx/svdpagv.hxx>
30 #include <svx/dialmgr.hxx>
31 #include <svx/svddrgmt.hxx>
32 #include <svx/svdtrans.hxx>
33 #include <svx/obj3d.hxx>
34 #include <svx/polysc3d.hxx>
35 #include <svx/e3dundo.hxx>
36 #include <svx/dialogs.hrc>
37 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
38 #include <svx/sdr/overlay/overlaymanager.hxx>
39 #include <basegfx/polygon/b2dpolypolygontools.hxx>
40 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
41 #include <drawinglayer/geometry/viewinformation3d.hxx>
42 #include <svx/e3dsceneupdater.hxx>
43 
44 TYPEINIT1(E3dDragMethod, SdrDragMethod);
45 
46 /*************************************************************************
47 |*
48 |* Konstruktor aller 3D-DragMethoden
49 |*
50 \************************************************************************/
51 
E3dDragMethod(SdrDragView & _rView,const SdrMarkList & rMark,E3dDragConstraint eConstr,sal_Bool bFull)52 E3dDragMethod::E3dDragMethod (
53     SdrDragView &_rView,
54     const SdrMarkList& rMark,
55     E3dDragConstraint eConstr,
56     sal_Bool bFull)
57 :   SdrDragMethod(_rView),
58     meConstraint(eConstr),
59     mbMoveFull(bFull),
60     mbMovedAtAll(sal_False)
61 {
62     // Fuer alle in der selektion befindlichen 3D-Objekte
63     // eine Unit anlegen
64     const long nCnt(rMark.GetMarkCount());
65     static bool bDoInvalidate(false);
66     long nObjs(0);
67 
68     if(mbMoveFull)
69     {
70         // for non-visible 3D objects fallback to wireframe interaction
71         bool bInvisibleObjects(false);
72 
73         for(nObjs = 0;!bInvisibleObjects && nObjs < nCnt;nObjs++)
74         {
75             E3dObject* pE3dObj = dynamic_cast< E3dObject* >(rMark.GetMark(nObjs)->GetMarkedSdrObj());
76 
77             if(pE3dObj)
78             {
79                 if(!pE3dObj->HasFillStyle() && !pE3dObj->HasLineStyle())
80                 {
81                     bInvisibleObjects = true;
82                 }
83             }
84         }
85 
86         if(bInvisibleObjects)
87         {
88             mbMoveFull = false;
89         }
90     }
91 
92     for(nObjs = 0;nObjs < nCnt;nObjs++)
93     {
94         E3dObject* pE3dObj = dynamic_cast< E3dObject* >(rMark.GetMark(nObjs)->GetMarkedSdrObj());
95 
96         if(pE3dObj)
97         {
98             // fill new interaction unit
99             E3dDragMethodUnit aNewUnit;
100             aNewUnit.mp3DObj = pE3dObj;
101 
102             // get transformations
103             aNewUnit.maInitTransform = aNewUnit.maTransform = pE3dObj->GetTransform();
104 
105             if(pE3dObj->GetParentObj())
106             {
107                 // get transform between object and world, normally scene transform
108                 aNewUnit.maInvDisplayTransform = aNewUnit.maDisplayTransform = pE3dObj->GetParentObj()->GetFullTransform();
109                 aNewUnit.maInvDisplayTransform.invert();
110             }
111 
112             // SnapRects der beteiligten Objekte invalidieren, um eine
113             // Neuberechnung beim Setzen der Marker zu erzwingen
114             if(bDoInvalidate)
115             {
116                 pE3dObj->SetRectsDirty();
117             }
118 
119             if(!mbMoveFull)
120             {
121                 // create wireframe visualisation for parent coordinate system
122                 aNewUnit.maWireframePoly.clear();
123                 aNewUnit.maWireframePoly = pE3dObj->CreateWireframe();
124                 aNewUnit.maWireframePoly.transform(aNewUnit.maTransform);
125             }
126 
127             // FullBound ermitteln
128             maFullBound.Union(pE3dObj->GetSnapRect());
129 
130             // Unit einfuegen
131             maGrp.push_back(aNewUnit);
132         }
133     }
134 }
135 
136 /*************************************************************************
137 |*
138 \************************************************************************/
139 
TakeSdrDragComment(XubString &) const140 void E3dDragMethod::TakeSdrDragComment(XubString& /*rStr*/) const
141 {
142 }
143 
144 /*************************************************************************
145 |*
146 |* Erstelle das Drahtgittermodel fuer alle Aktionen
147 |*
148 \************************************************************************/
149 
BeginSdrDrag()150 bool E3dDragMethod::BeginSdrDrag()
151 {
152     if(E3DDRAG_CONSTR_Z == meConstraint)
153     {
154         const sal_uInt32 nCnt(maGrp.size());
155         DragStat().Ref1() = maFullBound.Center();
156 
157         for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
158         {
159             E3dDragMethodUnit& rCandidate = maGrp[nOb];
160             rCandidate.mnStartAngle = GetAngle(DragStat().GetStart() - DragStat().GetRef1());
161             rCandidate.mnLastAngle = 0;
162         }
163     }
164     else
165     {
166         maLastPos = DragStat().GetStart();
167     }
168 
169     if(!mbMoveFull)
170     {
171         Show();
172     }
173 
174     return sal_True;
175 }
176 
177 /*************************************************************************
178 |*
179 |* Schluss
180 |*
181 \************************************************************************/
182 
EndSdrDrag(bool)183 bool E3dDragMethod::EndSdrDrag(bool /*bCopy*/)
184 {
185     const sal_uInt32 nCnt(maGrp.size());
186 
187     if(!mbMoveFull)
188     {
189         // WireFrame ausblenden
190         Hide();
191     }
192 
193     // Alle Transformationen anwenden und UnDo's anlegen
194     if(mbMovedAtAll)
195     {
196         const bool bUndo = getSdrDragView().IsUndoEnabled();
197         if( bUndo )
198             getSdrDragView().BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_ROTATE));
199         sal_uInt32 nOb(0);
200 
201         for(nOb=0;nOb<nCnt;nOb++)
202         {
203             E3dDragMethodUnit& rCandidate = maGrp[nOb];
204             E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
205             rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
206             if( bUndo )
207             {
208                 getSdrDragView().AddUndo(new E3dRotateUndoAction(rCandidate.mp3DObj->GetModel(),
209                     rCandidate.mp3DObj, rCandidate.maInitTransform,
210                     rCandidate.maTransform));
211             }
212         }
213         if( bUndo )
214             getSdrDragView().EndUndo();
215     }
216 
217     return sal_True;
218 }
219 
220 /*************************************************************************
221 |*
222 |* Abbruch
223 |*
224 \************************************************************************/
225 
CancelSdrDrag()226 void E3dDragMethod::CancelSdrDrag()
227 {
228     if(mbMoveFull)
229     {
230         if(mbMovedAtAll)
231         {
232             const sal_uInt32 nCnt(maGrp.size());
233 
234             for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
235             {
236                 // Transformation restaurieren
237                 E3dDragMethodUnit& rCandidate = maGrp[nOb];
238                 E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
239                 rCandidate.mp3DObj->SetTransform(rCandidate.maInitTransform);
240             }
241         }
242     }
243     else
244     {
245         // WireFrame ausblenden
246         Hide();
247     }
248 }
249 
250 /*************************************************************************
251 |*
252 |* Gemeinsames MoveSdrDrag()
253 |*
254 \************************************************************************/
255 
MoveSdrDrag(const Point &)256 void E3dDragMethod::MoveSdrDrag(const Point& /*rPnt*/)
257 {
258     mbMovedAtAll = true;
259 }
260 
261 /*************************************************************************
262 |*
263 |* Zeichne das Drahtgittermodel
264 |*
265 \************************************************************************/
266 
267 // for migration from XOR to overlay
CreateOverlayGeometry(::sdr::overlay::OverlayManager & rOverlayManager)268 void E3dDragMethod::CreateOverlayGeometry(::sdr::overlay::OverlayManager& rOverlayManager)
269 {
270     const sal_uInt32 nCnt(maGrp.size());
271     basegfx::B2DPolyPolygon aResult;
272 
273     for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
274     {
275         E3dDragMethodUnit& rCandidate = maGrp[nOb];
276         SdrPageView* pPV = getSdrDragView().GetSdrPageView();
277 
278         if(pPV && pPV->HasMarkedObjPageView())
279         {
280             const basegfx::B3DPolyPolygon aCandidate(rCandidate.maWireframePoly);
281             const sal_uInt32 nPlyCnt(aCandidate.count());
282 
283             if(nPlyCnt)
284             {
285                 const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
286                 const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
287                 const basegfx::B3DHomMatrix aWorldToView(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection() * aViewInfo3D.getOrientation());
288                 const basegfx::B3DHomMatrix aTransform(aWorldToView * rCandidate.maDisplayTransform);
289 
290                 // transform to relative scene coordinates
291                 basegfx::B2DPolyPolygon aPolyPolygon(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCandidate, aTransform));
292 
293                 // transform to 2D view coordinates
294                 aPolyPolygon.transform(rVCScene.getObjectTransformation());
295 
296                 aResult.append(aPolyPolygon);
297             }
298         }
299     }
300 
301     if(aResult.count())
302     {
303         ::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
304             aResult);
305         rOverlayManager.add(*pNew);
306         addToOverlayObjectList(*pNew);
307     }
308 }
309 
310 /*************************************************************************
311 
312                                 E3dDragRotate
313 
314 *************************************************************************/
315 
316 TYPEINIT1(E3dDragRotate, E3dDragMethod);
317 
E3dDragRotate(SdrDragView & _rView,const SdrMarkList & rMark,E3dDragConstraint eConstr,sal_Bool bFull)318 E3dDragRotate::E3dDragRotate(SdrDragView &_rView,
319     const SdrMarkList& rMark,
320     E3dDragConstraint eConstr,
321     sal_Bool bFull)
322 :   E3dDragMethod(_rView, rMark, eConstr, bFull)
323 {
324     // Zentrum aller selektierten Objekte in Augkoordinaten holen
325     const sal_uInt32 nCnt(maGrp.size());
326 
327     if(nCnt)
328     {
329         const E3dScene *pScene = maGrp[0].mp3DObj->GetScene();
330 
331         if(pScene)
332         {
333             const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
334             const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
335 
336             for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
337             {
338                 E3dDragMethodUnit& rCandidate = maGrp[nOb];
339                 basegfx::B3DPoint aObjCenter = rCandidate.mp3DObj->GetBoundVolume().getCenter();
340                 const basegfx::B3DHomMatrix aTransform(aViewInfo3D.getOrientation() * rCandidate.maDisplayTransform * rCandidate.maInitTransform);
341 
342                 aObjCenter = aTransform * aObjCenter;
343                 maGlobalCenter += aObjCenter;
344             }
345 
346             // Teilen durch Anzahl
347             if(nCnt > 1)
348             {
349                 maGlobalCenter /= (double)nCnt;
350             }
351 
352             // get rotate center and transform to 3D eye coordinates
353             basegfx::B2DPoint aRotCenter2D(Ref1().X(), Ref1().Y());
354 
355             // from world to relative scene using inverse getObjectTransformation()
356             basegfx::B2DHomMatrix aInverseObjectTransform(rVCScene.getObjectTransformation());
357             aInverseObjectTransform.invert();
358             aRotCenter2D = aInverseObjectTransform * aRotCenter2D;
359 
360             // from 3D view to 3D eye
361             basegfx::B3DPoint aRotCenter3D(aRotCenter2D.getX(), aRotCenter2D.getY(), 0.0);
362             basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
363             aInverseViewToEye.invert();
364             aRotCenter3D = aInverseViewToEye * aRotCenter3D;
365 
366         // X,Y des RotCenter und Tiefe der gemeinsamen Objektmitte aus
367         // Rotationspunkt im Raum benutzen
368             maGlobalCenter.setX(aRotCenter3D.getX());
369             maGlobalCenter.setY(aRotCenter3D.getY());
370         }
371     }
372 }
373 
374 /*************************************************************************
375 |*
376 |* Das Objekt wird bewegt, bestimme die Winkel
377 |*
378 \************************************************************************/
379 
MoveSdrDrag(const Point & rPnt)380 void E3dDragRotate::MoveSdrDrag(const Point& rPnt)
381 {
382     // call parent
383     E3dDragMethod::MoveSdrDrag(rPnt);
384 
385     if(DragStat().CheckMinMoved(rPnt))
386     {
387         // Modifier holen
388         sal_uInt16 nModifier = 0;
389         if(getSdrDragView().ISA(E3dView))
390         {
391             const MouseEvent& rLastMouse = ((E3dView&)getSdrDragView()).GetMouseEvent();
392             nModifier = rLastMouse.GetModifier();
393         }
394 
395         // Alle Objekte rotieren
396         const sal_uInt32 nCnt(maGrp.size());
397 
398         for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
399         {
400             // Rotationswinkel bestimmen
401             double fWAngle, fHAngle;
402             E3dDragMethodUnit& rCandidate = maGrp[nOb];
403 
404             if(E3DDRAG_CONSTR_Z == meConstraint)
405             {
406                 fWAngle = NormAngle360(GetAngle(rPnt - DragStat().GetRef1()) -
407                     rCandidate.mnStartAngle) - rCandidate.mnLastAngle;
408                 rCandidate.mnLastAngle = (long)fWAngle + rCandidate.mnLastAngle;
409                 fWAngle /= 100.0;
410                 fHAngle = 0.0;
411             }
412             else
413             {
414                 fWAngle = 90.0 * (double)(rPnt.X() - maLastPos.X())
415                     / (double)maFullBound.GetWidth();
416                 fHAngle = 90.0 * (double)(rPnt.Y() - maLastPos.Y())
417                     / (double)maFullBound.GetHeight();
418             }
419             long nSnap = 0;
420 
421             if(!getSdrDragView().IsRotateAllowed(sal_False))
422                 nSnap = 90;
423 
424             if(nSnap != 0)
425             {
426                 fWAngle = (double)(((long) fWAngle + nSnap/2) / nSnap * nSnap);
427                 fHAngle = (double)(((long) fHAngle + nSnap/2) / nSnap * nSnap);
428             }
429 
430             // nach radiant
431             fWAngle *= F_PI180;
432             fHAngle *= F_PI180;
433 
434             // Transformation bestimmen
435             basegfx::B3DHomMatrix aRotMat;
436             if(E3DDRAG_CONSTR_Y & meConstraint)
437             {
438                 if(nModifier & KEY_MOD2)
439                     aRotMat.rotate(0.0, 0.0, fWAngle);
440                 else
441                     aRotMat.rotate(0.0, fWAngle, 0.0);
442             }
443             else if(E3DDRAG_CONSTR_Z & meConstraint)
444             {
445                 if(nModifier & KEY_MOD2)
446                     aRotMat.rotate(0.0, fWAngle, 0.0);
447                 else
448                     aRotMat.rotate(0.0, 0.0, fWAngle);
449             }
450             if(E3DDRAG_CONSTR_X & meConstraint)
451             {
452                 aRotMat.rotate(fHAngle, 0.0, 0.0);
453             }
454 
455             // Transformation in Eye-Koordinaten, dort rotieren
456             // und zurueck
457             const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
458             const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
459             basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
460             aInverseOrientation.invert();
461 
462             basegfx::B3DHomMatrix aTransMat(rCandidate.maDisplayTransform);
463             aTransMat *= aViewInfo3D.getOrientation();
464             aTransMat.translate(-maGlobalCenter.getX(), -maGlobalCenter.getY(), -maGlobalCenter.getZ());
465             aTransMat *= aRotMat;
466             aTransMat.translate(maGlobalCenter.getX(), maGlobalCenter.getY(), maGlobalCenter.getZ());
467             aTransMat *= aInverseOrientation;
468             aTransMat *= rCandidate.maInvDisplayTransform;
469 
470             // ...und anwenden
471             rCandidate.maTransform *= aTransMat;
472 
473             if(mbMoveFull)
474             {
475                 E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
476                 rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
477             }
478             else
479             {
480                 Hide();
481                 rCandidate.maWireframePoly.transform(aTransMat);
482                 Show();
483             }
484         }
485         maLastPos = rPnt;
486         DragStat().NextMove(rPnt);
487     }
488 }
489 
490 /*************************************************************************
491 |*
492 \************************************************************************/
493 
GetSdrDragPointer() const494 Pointer E3dDragRotate::GetSdrDragPointer() const
495 {
496     return Pointer(POINTER_ROTATE);
497 }
498 
499 /*************************************************************************
500 |*
501 |* E3dDragMove
502 |* Diese DragMethod wird nur bei Translationen innerhalb von 3D-Scenen
503 |* benoetigt. Wird eine 3D-Scene selbst verschoben, so wird diese DragMethod
504 |* nicht verwendet.
505 |*
506 \************************************************************************/
507 
508 TYPEINIT1(E3dDragMove, E3dDragMethod);
509 
E3dDragMove(SdrDragView & _rView,const SdrMarkList & rMark,SdrHdlKind eDrgHdl,E3dDragConstraint eConstr,sal_Bool bFull)510 E3dDragMove::E3dDragMove(SdrDragView &_rView,
511     const SdrMarkList& rMark,
512     SdrHdlKind eDrgHdl,
513     E3dDragConstraint eConstr,
514     sal_Bool bFull)
515 :   E3dDragMethod(_rView, rMark, eConstr, bFull),
516     meWhatDragHdl(eDrgHdl)
517 {
518     switch(meWhatDragHdl)
519     {
520         case HDL_LEFT:
521             maScaleFixPos = maFullBound.RightCenter();
522             break;
523         case HDL_RIGHT:
524             maScaleFixPos = maFullBound.LeftCenter();
525             break;
526         case HDL_UPPER:
527             maScaleFixPos = maFullBound.BottomCenter();
528             break;
529         case HDL_LOWER:
530             maScaleFixPos = maFullBound.TopCenter();
531             break;
532         case HDL_UPLFT:
533             maScaleFixPos = maFullBound.BottomRight();
534             break;
535         case HDL_UPRGT:
536             maScaleFixPos = maFullBound.BottomLeft();
537             break;
538         case HDL_LWLFT:
539             maScaleFixPos = maFullBound.TopRight();
540             break;
541         case HDL_LWRGT:
542             maScaleFixPos = maFullBound.TopLeft();
543             break;
544         default:
545             // Bewegen des Objektes, HDL_MOVE
546             break;
547     }
548 
549     // Override wenn IsResizeAtCenter()
550     if(getSdrDragView().IsResizeAtCenter())
551     {
552         meWhatDragHdl = HDL_USER;
553         maScaleFixPos = maFullBound.Center();
554     }
555 }
556 
557 /*************************************************************************
558 |*
559 |* Das Objekt wird bewegt, bestimme die Translation
560 |*
561 \************************************************************************/
562 
MoveSdrDrag(const Point & rPnt)563 void E3dDragMove::MoveSdrDrag(const Point& rPnt)
564 {
565     // call parent
566     E3dDragMethod::MoveSdrDrag(rPnt);
567 
568     if(DragStat().CheckMinMoved(rPnt))
569     {
570         if(HDL_MOVE == meWhatDragHdl)
571         {
572             // Translation
573             // Bewegungsvektor bestimmen
574             basegfx::B3DPoint aGlobalMoveHead((double)(rPnt.X() - maLastPos.X()), (double)(rPnt.Y() - maLastPos.Y()), 32768.0);
575             basegfx::B3DPoint aGlobalMoveTail(0.0, 0.0, 32768.0);
576             const sal_uInt32 nCnt(maGrp.size());
577 
578             // Modifier holen
579             sal_uInt16 nModifier(0);
580 
581             if(getSdrDragView().ISA(E3dView))
582             {
583                 const MouseEvent& rLastMouse = ((E3dView&)getSdrDragView()).GetMouseEvent();
584                 nModifier = rLastMouse.GetModifier();
585             }
586 
587             for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
588             {
589                 E3dDragMethodUnit& rCandidate = maGrp[nOb];
590                 const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
591                 const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
592 
593                 // move coor from 2d world to 3d Eye
594                 basegfx::B2DPoint aGlobalMoveHead2D((double)(rPnt.X() - maLastPos.X()), (double)(rPnt.Y() - maLastPos.Y()));
595                 basegfx::B2DPoint aGlobalMoveTail2D(0.0, 0.0);
596                 basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
597 
598                 aInverseSceneTransform.invert();
599                 aGlobalMoveHead2D = aInverseSceneTransform * aGlobalMoveHead2D;
600                 aGlobalMoveTail2D = aInverseSceneTransform * aGlobalMoveTail2D;
601 
602                 basegfx::B3DPoint aMoveHead3D(aGlobalMoveHead2D.getX(), aGlobalMoveHead2D.getY(), 0.5);
603                 basegfx::B3DPoint aMoveTail3D(aGlobalMoveTail2D.getX(), aGlobalMoveTail2D.getY(), 0.5);
604                 basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
605                 aInverseViewToEye.invert();
606 
607                 aMoveHead3D = aInverseViewToEye * aMoveHead3D;
608                 aMoveTail3D = aInverseViewToEye * aMoveTail3D;
609 
610                 // eventually switch movement from XY to XZ plane
611                 if(nModifier & KEY_MOD2)
612                 {
613                     double fZwi = aMoveHead3D.getY();
614                     aMoveHead3D.setY(aMoveHead3D.getZ());
615                     aMoveHead3D.setZ(fZwi);
616 
617                     fZwi = aMoveTail3D.getY();
618                     aMoveTail3D.setY(aMoveTail3D.getZ());
619                     aMoveTail3D.setZ(fZwi);
620                 }
621 
622                 // Bewegungsvektor von Aug-Koordinaten nach Parent-Koordinaten
623                 basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
624                 aInverseOrientation.invert();
625                 basegfx::B3DHomMatrix aCompleteTrans(rCandidate.maInvDisplayTransform * aInverseOrientation);
626 
627                 aMoveHead3D = aCompleteTrans * aMoveHead3D;
628                 aMoveTail3D = aCompleteTrans* aMoveTail3D;
629 
630                 // build transformation
631                 basegfx::B3DHomMatrix aTransMat;
632                 basegfx::B3DPoint aTranslate(aMoveHead3D - aMoveTail3D);
633                 aTransMat.translate(aTranslate.getX(), aTranslate.getY(), aTranslate.getZ());
634 
635                 // ...and apply
636                 rCandidate.maTransform *= aTransMat;
637 
638                 if(mbMoveFull)
639                 {
640                     E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
641                     rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
642                 }
643                 else
644                 {
645                     Hide();
646                     rCandidate.maWireframePoly.transform(aTransMat);
647                     Show();
648                 }
649             }
650         }
651         else
652         {
653             // Skalierung
654             // Skalierungsvektor bestimmen
655             Point aStartPos = DragStat().GetStart();
656             const sal_uInt32 nCnt(maGrp.size());
657 
658             for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
659             {
660                 E3dDragMethodUnit& rCandidate = maGrp[nOb];
661                 const basegfx::B3DPoint aObjectCenter(rCandidate.mp3DObj->GetBoundVolume().getCenter());
662 
663                 // transform from 2D world view to 3D eye
664                 const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
665                 const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
666 
667                 basegfx::B2DPoint aGlobalScaleStart2D((double)(aStartPos.X()), (double)(aStartPos.Y()));
668                 basegfx::B2DPoint aGlobalScaleNext2D((double)(rPnt.X()), (double)(rPnt.Y()));
669                 basegfx::B2DPoint aGlobalScaleFixPos2D((double)(maScaleFixPos.X()), (double)(maScaleFixPos.Y()));
670                 basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
671 
672                 aInverseSceneTransform.invert();
673                 aGlobalScaleStart2D = aInverseSceneTransform * aGlobalScaleStart2D;
674                 aGlobalScaleNext2D = aInverseSceneTransform * aGlobalScaleNext2D;
675                 aGlobalScaleFixPos2D = aInverseSceneTransform * aGlobalScaleFixPos2D;
676 
677                 basegfx::B3DPoint aGlobalScaleStart3D(aGlobalScaleStart2D.getX(), aGlobalScaleStart2D.getY(), aObjectCenter.getZ());
678                 basegfx::B3DPoint aGlobalScaleNext3D(aGlobalScaleNext2D.getX(), aGlobalScaleNext2D.getY(), aObjectCenter.getZ());
679                 basegfx::B3DPoint aGlobalScaleFixPos3D(aGlobalScaleFixPos2D.getX(), aGlobalScaleFixPos2D.getY(), aObjectCenter.getZ());
680                 basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
681 
682                 aInverseViewToEye.invert();
683                 basegfx::B3DPoint aScStart(aInverseViewToEye * aGlobalScaleStart3D);
684                 basegfx::B3DPoint aScNext(aInverseViewToEye * aGlobalScaleNext3D);
685                 basegfx::B3DPoint aScFixPos(aInverseViewToEye * aGlobalScaleFixPos3D);
686 
687                 // constraints?
688                 switch(meWhatDragHdl)
689                 {
690                     case HDL_LEFT:
691                     case HDL_RIGHT:
692                         // constrain to auf X -> Y equal
693                         aScNext.setY(aScFixPos.getY());
694                         break;
695                     case HDL_UPPER:
696                     case HDL_LOWER:
697                         // constrain to auf Y -> X equal
698                         aScNext.setX(aScFixPos.getX());
699                         break;
700                     default:
701                         break;
702                 }
703 
704                 // get scale vector in eye coordinates
705                 basegfx::B3DPoint aScaleVec(aScStart - aScFixPos);
706                 aScaleVec.setZ(1.0);
707 
708                 if(aScaleVec.getX() != 0.0)
709                 {
710                     aScaleVec.setX((aScNext.getX() - aScFixPos.getX()) / aScaleVec.getX());
711                 }
712                 else
713                 {
714                     aScaleVec.setX(1.0);
715                 }
716 
717                 if(aScaleVec.getY() != 0.0)
718                 {
719                     aScaleVec.setY((aScNext.getY() - aScFixPos.getY()) / aScaleVec.getY());
720                 }
721                 else
722                 {
723                     aScaleVec.setY(1.0);
724                 }
725 
726                 // SHIFT-key used?
727                 if(getSdrDragView().IsOrtho())
728                 {
729                     if(fabs(aScaleVec.getX()) > fabs(aScaleVec.getY()))
730                     {
731                         // X is biggest
732                         aScaleVec.setY(aScaleVec.getX());
733                     }
734                     else
735                     {
736                         // Y is biggest
737                         aScaleVec.setX(aScaleVec.getY());
738                     }
739                 }
740 
741                 // build transformation
742                 basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
743                 aInverseOrientation.invert();
744 
745                 basegfx::B3DHomMatrix aNewTrans = rCandidate.maInitTransform;
746                 aNewTrans *= rCandidate.maDisplayTransform;
747                 aNewTrans *= aViewInfo3D.getOrientation();
748                 aNewTrans.translate(-aScFixPos.getX(), -aScFixPos.getY(), -aScFixPos.getZ());
749                 aNewTrans.scale(aScaleVec.getX(), aScaleVec.getY(), aScaleVec.getZ());
750                 aNewTrans.translate(aScFixPos.getX(), aScFixPos.getY(), aScFixPos.getZ());
751                 aNewTrans *= aInverseOrientation;
752                 aNewTrans *= rCandidate.maInvDisplayTransform;
753 
754                 // ...und anwenden
755                 rCandidate.maTransform = aNewTrans;
756 
757                 if(mbMoveFull)
758                 {
759                     E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
760                     rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
761                 }
762                 else
763                 {
764                     Hide();
765                     rCandidate.maWireframePoly.clear();
766                     rCandidate.maWireframePoly = rCandidate.mp3DObj->CreateWireframe();
767                     rCandidate.maWireframePoly.transform(rCandidate.maTransform);
768                     Show();
769                 }
770             }
771         }
772         maLastPos = rPnt;
773         DragStat().NextMove(rPnt);
774     }
775 }
776 
777 /*************************************************************************
778 |*
779 \************************************************************************/
780 
GetSdrDragPointer() const781 Pointer E3dDragMove::GetSdrDragPointer() const
782 {
783     return Pointer(POINTER_MOVE);
784 }
785 
786 // eof
787