xref: /aoo41x/main/svx/source/engine3d/dragmt3d.cxx (revision cdf0e10c)
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