xref: /aoo41x/main/svx/source/engine3d/dragmt3d.cxx (revision f6e50924)
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 
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 
140 void E3dDragMethod::TakeSdrDragComment(XubString& /*rStr*/) const
141 {
142 }
143 
144 /*************************************************************************
145 |*
146 |* Erstelle das Drahtgittermodel fuer alle Aktionen
147 |*
148 \************************************************************************/
149 
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 
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 
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 
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
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::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(aResult);
304 		rOverlayManager.add(*pNew);
305 		addToOverlayObjectList(*pNew);
306 	}
307 }
308 
309 /*************************************************************************
310 
311 								E3dDragRotate
312 
313 *************************************************************************/
314 
315 TYPEINIT1(E3dDragRotate, E3dDragMethod);
316 
317 E3dDragRotate::E3dDragRotate(SdrDragView &_rView,
318 	const SdrMarkList& rMark,
319 	E3dDragConstraint eConstr,
320 	sal_Bool bFull)
321 :	E3dDragMethod(_rView, rMark, eConstr, bFull)
322 {
323 	// Zentrum aller selektierten Objekte in Augkoordinaten holen
324 	const sal_uInt32 nCnt(maGrp.size());
325 
326 	if(nCnt)
327 	{
328 		const E3dScene *pScene = maGrp[0].mp3DObj->GetScene();
329 
330 		if(pScene)
331 		{
332 			const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
333 			const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
334 
335 			for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
336 			{
337 				E3dDragMethodUnit& rCandidate = maGrp[nOb];
338 				basegfx::B3DPoint aObjCenter = rCandidate.mp3DObj->GetBoundVolume().getCenter();
339 				const basegfx::B3DHomMatrix aTransform(aViewInfo3D.getOrientation() * rCandidate.maDisplayTransform * rCandidate.maInitTransform);
340 
341 				aObjCenter = aTransform * aObjCenter;
342 				maGlobalCenter += aObjCenter;
343 			}
344 
345 			// Teilen durch Anzahl
346 			if(nCnt > 1)
347 			{
348 				maGlobalCenter /= (double)nCnt;
349 			}
350 
351 			// get rotate center and transform to 3D eye coordinates
352 			basegfx::B2DPoint aRotCenter2D(Ref1().X(), Ref1().Y());
353 
354 			// from world to relative scene using inverse getObjectTransformation()
355 			basegfx::B2DHomMatrix aInverseObjectTransform(rVCScene.getObjectTransformation());
356 			aInverseObjectTransform.invert();
357 			aRotCenter2D = aInverseObjectTransform * aRotCenter2D;
358 
359 			// from 3D view to 3D eye
360 			basegfx::B3DPoint aRotCenter3D(aRotCenter2D.getX(), aRotCenter2D.getY(), 0.0);
361 			basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
362 			aInverseViewToEye.invert();
363 			aRotCenter3D = aInverseViewToEye * aRotCenter3D;
364 
365 		// X,Y des RotCenter und Tiefe der gemeinsamen Objektmitte aus
366 		// Rotationspunkt im Raum benutzen
367 			maGlobalCenter.setX(aRotCenter3D.getX());
368 			maGlobalCenter.setY(aRotCenter3D.getY());
369 		}
370 	}
371 }
372 
373 /*************************************************************************
374 |*
375 |* Das Objekt wird bewegt, bestimme die Winkel
376 |*
377 \************************************************************************/
378 
379 void E3dDragRotate::MoveSdrDrag(const Point& rPnt)
380 {
381 	// call parent
382 	E3dDragMethod::MoveSdrDrag(rPnt);
383 
384 	if(DragStat().CheckMinMoved(rPnt))
385 	{
386 		// Modifier holen
387 		sal_uInt16 nModifier = 0;
388 		if(getSdrDragView().ISA(E3dView))
389 		{
390 			const MouseEvent& rLastMouse = ((E3dView&)getSdrDragView()).GetMouseEvent();
391 			nModifier = rLastMouse.GetModifier();
392 		}
393 
394 		// Alle Objekte rotieren
395 		const sal_uInt32 nCnt(maGrp.size());
396 
397 		for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
398 		{
399 			// Rotationswinkel bestimmen
400 			double fWAngle, fHAngle;
401 			E3dDragMethodUnit& rCandidate = maGrp[nOb];
402 
403 			if(E3DDRAG_CONSTR_Z == meConstraint)
404 			{
405 				fWAngle = NormAngle360(GetAngle(rPnt - DragStat().GetRef1()) -
406 					rCandidate.mnStartAngle) - rCandidate.mnLastAngle;
407 				rCandidate.mnLastAngle = (long)fWAngle + rCandidate.mnLastAngle;
408 				fWAngle /= 100.0;
409 				fHAngle = 0.0;
410 			}
411 			else
412 			{
413 				fWAngle = 90.0 * (double)(rPnt.X() - maLastPos.X())
414 					/ (double)maFullBound.GetWidth();
415 				fHAngle = 90.0 * (double)(rPnt.Y() - maLastPos.Y())
416 					/ (double)maFullBound.GetHeight();
417 			}
418 			long nSnap = 0;
419 
420 			if(!getSdrDragView().IsRotateAllowed(sal_False))
421 				nSnap = 90;
422 
423 			if(nSnap != 0)
424 			{
425 				fWAngle = (double)(((long) fWAngle + nSnap/2) / nSnap * nSnap);
426 				fHAngle = (double)(((long) fHAngle + nSnap/2) / nSnap * nSnap);
427 			}
428 
429 			// nach radiant
430 			fWAngle *= F_PI180;
431 			fHAngle *= F_PI180;
432 
433 			// Transformation bestimmen
434 			basegfx::B3DHomMatrix aRotMat;
435 			if(E3DDRAG_CONSTR_Y & meConstraint)
436 			{
437 				if(nModifier & KEY_MOD2)
438 					aRotMat.rotate(0.0, 0.0, fWAngle);
439 				else
440 					aRotMat.rotate(0.0, fWAngle, 0.0);
441 			}
442 			else if(E3DDRAG_CONSTR_Z & meConstraint)
443 			{
444 				if(nModifier & KEY_MOD2)
445 					aRotMat.rotate(0.0, fWAngle, 0.0);
446 				else
447 					aRotMat.rotate(0.0, 0.0, fWAngle);
448 			}
449 			if(E3DDRAG_CONSTR_X & meConstraint)
450 			{
451 				aRotMat.rotate(fHAngle, 0.0, 0.0);
452 			}
453 
454 			// Transformation in Eye-Koordinaten, dort rotieren
455 			// und zurueck
456 			const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
457 			const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
458 			basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
459 			aInverseOrientation.invert();
460 
461 			basegfx::B3DHomMatrix aTransMat(rCandidate.maDisplayTransform);
462 			aTransMat *= aViewInfo3D.getOrientation();
463 			aTransMat.translate(-maGlobalCenter.getX(), -maGlobalCenter.getY(), -maGlobalCenter.getZ());
464 			aTransMat *= aRotMat;
465 			aTransMat.translate(maGlobalCenter.getX(), maGlobalCenter.getY(), maGlobalCenter.getZ());
466 			aTransMat *= aInverseOrientation;
467 			aTransMat *= rCandidate.maInvDisplayTransform;
468 
469 			// ...und anwenden
470 			rCandidate.maTransform *= aTransMat;
471 
472 			if(mbMoveFull)
473 			{
474         		E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
475 				rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
476 			}
477 			else
478 			{
479 				Hide();
480 				rCandidate.maWireframePoly.transform(aTransMat);
481 				Show();
482 			}
483 		}
484 		maLastPos = rPnt;
485 		DragStat().NextMove(rPnt);
486 	}
487 }
488 
489 /*************************************************************************
490 |*
491 \************************************************************************/
492 
493 Pointer E3dDragRotate::GetSdrDragPointer() const
494 {
495 	return Pointer(POINTER_ROTATE);
496 }
497 
498 /*************************************************************************
499 |*
500 |* E3dDragMove
501 |* Diese DragMethod wird nur bei Translationen innerhalb von 3D-Scenen
502 |* benoetigt. Wird eine 3D-Scene selbst verschoben, so wird diese DragMethod
503 |* nicht verwendet.
504 |*
505 \************************************************************************/
506 
507 TYPEINIT1(E3dDragMove, E3dDragMethod);
508 
509 E3dDragMove::E3dDragMove(SdrDragView &_rView,
510 	const SdrMarkList& rMark,
511 	SdrHdlKind eDrgHdl,
512 	E3dDragConstraint eConstr,
513 	sal_Bool bFull)
514 :	E3dDragMethod(_rView, rMark, eConstr, bFull),
515 	meWhatDragHdl(eDrgHdl)
516 {
517 	switch(meWhatDragHdl)
518 	{
519 		case HDL_LEFT:
520 			maScaleFixPos = maFullBound.RightCenter();
521 			break;
522 		case HDL_RIGHT:
523 			maScaleFixPos = maFullBound.LeftCenter();
524 			break;
525 		case HDL_UPPER:
526 			maScaleFixPos = maFullBound.BottomCenter();
527 			break;
528 		case HDL_LOWER:
529 			maScaleFixPos = maFullBound.TopCenter();
530 			break;
531 		case HDL_UPLFT:
532 			maScaleFixPos = maFullBound.BottomRight();
533 			break;
534 		case HDL_UPRGT:
535 			maScaleFixPos = maFullBound.BottomLeft();
536 			break;
537 		case HDL_LWLFT:
538 			maScaleFixPos = maFullBound.TopRight();
539 			break;
540 		case HDL_LWRGT:
541 			maScaleFixPos = maFullBound.TopLeft();
542 			break;
543 		default:
544 			// Bewegen des Objektes, HDL_MOVE
545 			break;
546 	}
547 
548 	// Override wenn IsResizeAtCenter()
549 	if(getSdrDragView().IsResizeAtCenter())
550 	{
551 		meWhatDragHdl = HDL_USER;
552 		maScaleFixPos = maFullBound.Center();
553 	}
554 }
555 
556 /*************************************************************************
557 |*
558 |* Das Objekt wird bewegt, bestimme die Translation
559 |*
560 \************************************************************************/
561 
562 void E3dDragMove::MoveSdrDrag(const Point& rPnt)
563 {
564 	// call parent
565 	E3dDragMethod::MoveSdrDrag(rPnt);
566 
567 	if(DragStat().CheckMinMoved(rPnt))
568 	{
569 		if(HDL_MOVE == meWhatDragHdl)
570 		{
571 			// Translation
572 			// Bewegungsvektor bestimmen
573 			basegfx::B3DPoint aGlobalMoveHead((double)(rPnt.X() - maLastPos.X()), (double)(rPnt.Y() - maLastPos.Y()), 32768.0);
574 			basegfx::B3DPoint aGlobalMoveTail(0.0, 0.0, 32768.0);
575 			const sal_uInt32 nCnt(maGrp.size());
576 
577 			// Modifier holen
578 			sal_uInt16 nModifier(0);
579 
580 			if(getSdrDragView().ISA(E3dView))
581 			{
582 				const MouseEvent& rLastMouse = ((E3dView&)getSdrDragView()).GetMouseEvent();
583 				nModifier = rLastMouse.GetModifier();
584 			}
585 
586 			for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
587 			{
588 				E3dDragMethodUnit& rCandidate = maGrp[nOb];
589 				const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
590 				const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
591 
592 				// move coor from 2d world to 3d Eye
593 				basegfx::B2DPoint aGlobalMoveHead2D((double)(rPnt.X() - maLastPos.X()), (double)(rPnt.Y() - maLastPos.Y()));
594 				basegfx::B2DPoint aGlobalMoveTail2D(0.0, 0.0);
595 				basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
596 
597 				aInverseSceneTransform.invert();
598 				aGlobalMoveHead2D = aInverseSceneTransform * aGlobalMoveHead2D;
599 				aGlobalMoveTail2D = aInverseSceneTransform * aGlobalMoveTail2D;
600 
601 				basegfx::B3DPoint aMoveHead3D(aGlobalMoveHead2D.getX(), aGlobalMoveHead2D.getY(), 0.5);
602 				basegfx::B3DPoint aMoveTail3D(aGlobalMoveTail2D.getX(), aGlobalMoveTail2D.getY(), 0.5);
603 				basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
604 				aInverseViewToEye.invert();
605 
606 				aMoveHead3D = aInverseViewToEye * aMoveHead3D;
607 				aMoveTail3D = aInverseViewToEye * aMoveTail3D;
608 
609 				// eventually switch movement from XY to XZ plane
610 				if(nModifier & KEY_MOD2)
611 				{
612 					double fZwi = aMoveHead3D.getY();
613 					aMoveHead3D.setY(aMoveHead3D.getZ());
614 					aMoveHead3D.setZ(fZwi);
615 
616 					fZwi = aMoveTail3D.getY();
617 					aMoveTail3D.setY(aMoveTail3D.getZ());
618 					aMoveTail3D.setZ(fZwi);
619 				}
620 
621 				// Bewegungsvektor von Aug-Koordinaten nach Parent-Koordinaten
622 				basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
623 				aInverseOrientation.invert();
624 				basegfx::B3DHomMatrix aCompleteTrans(rCandidate.maInvDisplayTransform * aInverseOrientation);
625 
626 				aMoveHead3D = aCompleteTrans * aMoveHead3D;
627 				aMoveTail3D = aCompleteTrans* aMoveTail3D;
628 
629 				// build transformation
630 				basegfx::B3DHomMatrix aTransMat;
631 				basegfx::B3DPoint aTranslate(aMoveHead3D - aMoveTail3D);
632 				aTransMat.translate(aTranslate.getX(), aTranslate.getY(), aTranslate.getZ());
633 
634 				// ...and apply
635 				rCandidate.maTransform *= aTransMat;
636 
637 				if(mbMoveFull)
638 				{
639         			E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
640 					rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
641 				}
642 				else
643 				{
644 					Hide();
645 					rCandidate.maWireframePoly.transform(aTransMat);
646 					Show();
647 				}
648 			}
649 		}
650 		else
651 		{
652 			// Skalierung
653 			// Skalierungsvektor bestimmen
654 			Point aStartPos = DragStat().GetStart();
655 			const sal_uInt32 nCnt(maGrp.size());
656 
657 			for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
658 			{
659 				E3dDragMethodUnit& rCandidate = maGrp[nOb];
660 				const basegfx::B3DPoint aObjectCenter(rCandidate.mp3DObj->GetBoundVolume().getCenter());
661 
662 				// transform from 2D world view to 3D eye
663 				const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
664 				const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
665 
666 				basegfx::B2DPoint aGlobalScaleStart2D((double)(aStartPos.X()), (double)(aStartPos.Y()));
667 				basegfx::B2DPoint aGlobalScaleNext2D((double)(rPnt.X()), (double)(rPnt.Y()));
668 				basegfx::B2DPoint aGlobalScaleFixPos2D((double)(maScaleFixPos.X()), (double)(maScaleFixPos.Y()));
669 				basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
670 
671 				aInverseSceneTransform.invert();
672 				aGlobalScaleStart2D = aInverseSceneTransform * aGlobalScaleStart2D;
673 				aGlobalScaleNext2D = aInverseSceneTransform * aGlobalScaleNext2D;
674 				aGlobalScaleFixPos2D = aInverseSceneTransform * aGlobalScaleFixPos2D;
675 
676 				basegfx::B3DPoint aGlobalScaleStart3D(aGlobalScaleStart2D.getX(), aGlobalScaleStart2D.getY(), aObjectCenter.getZ());
677 				basegfx::B3DPoint aGlobalScaleNext3D(aGlobalScaleNext2D.getX(), aGlobalScaleNext2D.getY(), aObjectCenter.getZ());
678 				basegfx::B3DPoint aGlobalScaleFixPos3D(aGlobalScaleFixPos2D.getX(), aGlobalScaleFixPos2D.getY(), aObjectCenter.getZ());
679 				basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
680 
681 				aInverseViewToEye.invert();
682 				basegfx::B3DPoint aScStart(aInverseViewToEye * aGlobalScaleStart3D);
683 				basegfx::B3DPoint aScNext(aInverseViewToEye * aGlobalScaleNext3D);
684 				basegfx::B3DPoint aScFixPos(aInverseViewToEye * aGlobalScaleFixPos3D);
685 
686 				// constraints?
687 				switch(meWhatDragHdl)
688 				{
689 					case HDL_LEFT:
690 					case HDL_RIGHT:
691 						// constrain to auf X -> Y equal
692 						aScNext.setY(aScFixPos.getY());
693 						break;
694 					case HDL_UPPER:
695 					case HDL_LOWER:
696 						// constrain to auf Y -> X equal
697 						aScNext.setX(aScFixPos.getX());
698 						break;
699 					default:
700 						break;
701 				}
702 
703 				// get scale vector in eye coordinates
704 				basegfx::B3DPoint aScaleVec(aScStart - aScFixPos);
705 				aScaleVec.setZ(1.0);
706 
707 				if(aScaleVec.getX() != 0.0)
708 				{
709 					aScaleVec.setX((aScNext.getX() - aScFixPos.getX()) / aScaleVec.getX());
710 				}
711 				else
712 				{
713 					aScaleVec.setX(1.0);
714 				}
715 
716 				if(aScaleVec.getY() != 0.0)
717 				{
718 					aScaleVec.setY((aScNext.getY() - aScFixPos.getY()) / aScaleVec.getY());
719 				}
720 				else
721 				{
722 					aScaleVec.setY(1.0);
723 				}
724 
725 				// SHIFT-key used?
726 				if(getSdrDragView().IsOrtho())
727 				{
728 					if(fabs(aScaleVec.getX()) > fabs(aScaleVec.getY()))
729 					{
730 						// X is biggest
731 						aScaleVec.setY(aScaleVec.getX());
732 					}
733 					else
734 					{
735 						// Y is biggest
736 						aScaleVec.setX(aScaleVec.getY());
737 					}
738 				}
739 
740 				// build transformation
741 				basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
742 				aInverseOrientation.invert();
743 
744 				basegfx::B3DHomMatrix aNewTrans = rCandidate.maInitTransform;
745 				aNewTrans *= rCandidate.maDisplayTransform;
746 				aNewTrans *= aViewInfo3D.getOrientation();
747 				aNewTrans.translate(-aScFixPos.getX(), -aScFixPos.getY(), -aScFixPos.getZ());
748 				aNewTrans.scale(aScaleVec.getX(), aScaleVec.getY(), aScaleVec.getZ());
749 				aNewTrans.translate(aScFixPos.getX(), aScFixPos.getY(), aScFixPos.getZ());
750 				aNewTrans *= aInverseOrientation;
751 				aNewTrans *= rCandidate.maInvDisplayTransform;
752 
753 				// ...und anwenden
754 				rCandidate.maTransform = aNewTrans;
755 
756 				if(mbMoveFull)
757 				{
758         			E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
759 					rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
760 				}
761 				else
762 				{
763 					Hide();
764 					rCandidate.maWireframePoly.clear();
765 					rCandidate.maWireframePoly = rCandidate.mp3DObj->CreateWireframe();
766 					rCandidate.maWireframePoly.transform(rCandidate.maTransform);
767 					Show();
768 				}
769 			}
770 		}
771 		maLastPos = rPnt;
772 		DragStat().NextMove(rPnt);
773 	}
774 }
775 
776 /*************************************************************************
777 |*
778 \************************************************************************/
779 
780 Pointer E3dDragMove::GetSdrDragPointer() const
781 {
782 	return Pointer(POINTER_MOVE);
783 }
784 
785 // eof
786