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