Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <dragmt3d.hxx>
22 : #include <tools/shl.hxx>
23 : #include <svx/svdpagv.hxx>
24 : #include <svx/dialmgr.hxx>
25 : #include <svx/svddrgmt.hxx>
26 : #include <svx/svdtrans.hxx>
27 : #include <svx/obj3d.hxx>
28 : #include <svx/polysc3d.hxx>
29 : #include <svx/e3dundo.hxx>
30 : #include <svx/dialogs.hrc>
31 : #include <svx/sdr/overlay/overlaypolypolygon.hxx>
32 : #include <svx/sdr/overlay/overlaymanager.hxx>
33 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
34 : #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
35 : #include <drawinglayer/geometry/viewinformation3d.hxx>
36 : #include <svx/e3dsceneupdater.hxx>
37 :
38 0 : TYPEINIT1(E3dDragMethod, SdrDragMethod);
39 :
40 0 : E3dDragMethod::E3dDragMethod (
41 : SdrDragView &_rView,
42 : const SdrMarkList& rMark,
43 : E3dDragConstraint eConstr,
44 : sal_Bool bFull)
45 : : SdrDragMethod(_rView),
46 : meConstraint(eConstr),
47 : mbMoveFull(bFull),
48 0 : mbMovedAtAll(false)
49 : {
50 : // Create a unit for all the 3D objects present in the selection
51 0 : const long nCnt(rMark.GetMarkCount());
52 : static bool bDoInvalidate(false);
53 0 : long nObjs(0);
54 :
55 0 : if(mbMoveFull)
56 : {
57 : // for non-visible 3D objects fallback to wireframe interaction
58 0 : bool bInvisibleObjects(false);
59 :
60 0 : for(nObjs = 0;!bInvisibleObjects && nObjs < nCnt;nObjs++)
61 : {
62 0 : E3dObject* pE3dObj = dynamic_cast< E3dObject* >(rMark.GetMark(nObjs)->GetMarkedSdrObj());
63 :
64 0 : if(pE3dObj)
65 : {
66 0 : if(!pE3dObj->HasFillStyle() && !pE3dObj->HasLineStyle())
67 : {
68 0 : bInvisibleObjects = true;
69 : }
70 : }
71 : }
72 :
73 0 : if(bInvisibleObjects)
74 : {
75 0 : mbMoveFull = false;
76 : }
77 : }
78 :
79 0 : for(nObjs = 0;nObjs < nCnt;nObjs++)
80 : {
81 0 : E3dObject* pE3dObj = dynamic_cast< E3dObject* >(rMark.GetMark(nObjs)->GetMarkedSdrObj());
82 :
83 0 : if(pE3dObj)
84 : {
85 : // fill new interaction unit
86 0 : E3dDragMethodUnit aNewUnit;
87 0 : aNewUnit.mp3DObj = pE3dObj;
88 :
89 : // get transformations
90 0 : aNewUnit.maInitTransform = aNewUnit.maTransform = pE3dObj->GetTransform();
91 :
92 0 : if(pE3dObj->GetParentObj())
93 : {
94 : // get transform between object and world, normally scene transform
95 0 : aNewUnit.maInvDisplayTransform = aNewUnit.maDisplayTransform = pE3dObj->GetParentObj()->GetFullTransform();
96 0 : aNewUnit.maInvDisplayTransform.invert();
97 : }
98 :
99 : // Invalidate SnapRects of the objects involved, to force a
100 : // recalculation for setting the marker
101 0 : if(bDoInvalidate)
102 : {
103 0 : pE3dObj->SetRectsDirty();
104 : }
105 :
106 0 : if(!mbMoveFull)
107 : {
108 : // create wireframe visualisation for parent coordinate system
109 0 : aNewUnit.maWireframePoly.clear();
110 0 : aNewUnit.maWireframePoly = pE3dObj->CreateWireframe();
111 0 : aNewUnit.maWireframePoly.transform(aNewUnit.maTransform);
112 : }
113 :
114 : // Determine FullBound
115 0 : maFullBound.Union(pE3dObj->GetSnapRect());
116 :
117 : // Insert Unit
118 0 : maGrp.push_back(aNewUnit);
119 : }
120 : }
121 0 : }
122 :
123 0 : void E3dDragMethod::TakeSdrDragComment(OUString& /*rStr*/) const
124 : {
125 0 : }
126 :
127 : // Create the wireframe model for all actions
128 :
129 0 : bool E3dDragMethod::BeginSdrDrag()
130 : {
131 0 : if(E3DDRAG_CONSTR_Z == meConstraint)
132 : {
133 0 : const sal_uInt32 nCnt(maGrp.size());
134 0 : DragStat().Ref1() = maFullBound.Center();
135 :
136 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
137 : {
138 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
139 0 : rCandidate.mnStartAngle = GetAngle(DragStat().GetStart() - DragStat().GetRef1());
140 0 : rCandidate.mnLastAngle = 0;
141 : }
142 : }
143 : else
144 : {
145 0 : maLastPos = DragStat().GetStart();
146 : }
147 :
148 0 : if(!mbMoveFull)
149 : {
150 0 : Show();
151 : }
152 :
153 0 : return true;
154 : }
155 :
156 0 : bool E3dDragMethod::EndSdrDrag(bool /*bCopy*/)
157 : {
158 0 : const sal_uInt32 nCnt(maGrp.size());
159 :
160 0 : if(!mbMoveFull)
161 : {
162 : // Hide wireframe
163 0 : Hide();
164 : }
165 :
166 : // Apply all transformations and create undo's
167 0 : if(mbMovedAtAll)
168 : {
169 0 : const bool bUndo = getSdrDragView().IsUndoEnabled();
170 0 : if( bUndo )
171 0 : getSdrDragView().BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_ROTATE));
172 0 : sal_uInt32 nOb(0);
173 :
174 0 : for(nOb=0;nOb<nCnt;nOb++)
175 : {
176 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
177 0 : E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
178 0 : rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
179 0 : if( bUndo )
180 : {
181 0 : getSdrDragView().AddUndo(new E3dRotateUndoAction(rCandidate.mp3DObj->GetModel(),
182 : rCandidate.mp3DObj, rCandidate.maInitTransform,
183 0 : rCandidate.maTransform));
184 : }
185 0 : }
186 0 : if( bUndo )
187 0 : getSdrDragView().EndUndo();
188 : }
189 :
190 0 : return true;
191 : }
192 :
193 0 : void E3dDragMethod::CancelSdrDrag()
194 : {
195 0 : if(mbMoveFull)
196 : {
197 0 : if(mbMovedAtAll)
198 : {
199 0 : const sal_uInt32 nCnt(maGrp.size());
200 :
201 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
202 : {
203 : // Restore transformation
204 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
205 0 : E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
206 0 : rCandidate.mp3DObj->SetTransform(rCandidate.maInitTransform);
207 0 : }
208 : }
209 : }
210 : else
211 : {
212 : // Hide WireFrame
213 0 : Hide();
214 : }
215 0 : }
216 :
217 : // Common MoveSdrDrag()
218 :
219 0 : void E3dDragMethod::MoveSdrDrag(const Point& /*rPnt*/)
220 : {
221 0 : mbMovedAtAll = true;
222 0 : }
223 :
224 : // Draw the wire frame model
225 :
226 : // for migration from XOR to overlay
227 0 : void E3dDragMethod::CreateOverlayGeometry(::sdr::overlay::OverlayManager& rOverlayManager)
228 : {
229 0 : const sal_uInt32 nCnt(maGrp.size());
230 0 : basegfx::B2DPolyPolygon aResult;
231 :
232 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
233 : {
234 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
235 0 : SdrPageView* pPV = getSdrDragView().GetSdrPageView();
236 :
237 0 : if(pPV && pPV->HasMarkedObjPageView())
238 : {
239 0 : const basegfx::B3DPolyPolygon aCandidate(rCandidate.maWireframePoly);
240 0 : const sal_uInt32 nPlyCnt(aCandidate.count());
241 :
242 0 : if(nPlyCnt)
243 : {
244 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
245 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
246 0 : const basegfx::B3DHomMatrix aWorldToView(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection() * aViewInfo3D.getOrientation());
247 0 : const basegfx::B3DHomMatrix aTransform(aWorldToView * rCandidate.maDisplayTransform);
248 :
249 : // transform to relative scene coordinates
250 0 : basegfx::B2DPolyPolygon aPolyPolygon(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCandidate, aTransform));
251 :
252 : // transform to 2D view coordinates
253 0 : aPolyPolygon.transform(rVCScene.getObjectTransformation());
254 :
255 0 : aResult.append(aPolyPolygon);
256 0 : }
257 : }
258 : }
259 :
260 0 : if(aResult.count())
261 : {
262 : ::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
263 0 : aResult);
264 0 : rOverlayManager.add(*pNew);
265 0 : addToOverlayObjectList(*pNew);
266 0 : }
267 0 : }
268 :
269 : /*************************************************************************
270 :
271 : E3dDragRotate
272 :
273 : *************************************************************************/
274 :
275 0 : TYPEINIT1(E3dDragRotate, E3dDragMethod);
276 :
277 0 : E3dDragRotate::E3dDragRotate(SdrDragView &_rView,
278 : const SdrMarkList& rMark,
279 : E3dDragConstraint eConstr,
280 : sal_Bool bFull)
281 0 : : E3dDragMethod(_rView, rMark, eConstr, bFull)
282 : {
283 : // Get center of all selected objects in eye coordinates
284 0 : const sal_uInt32 nCnt(maGrp.size());
285 :
286 0 : if(nCnt)
287 : {
288 0 : const E3dScene *pScene = maGrp[0].mp3DObj->GetScene();
289 :
290 0 : if(pScene)
291 : {
292 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
293 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
294 :
295 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
296 : {
297 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
298 0 : basegfx::B3DPoint aObjCenter = rCandidate.mp3DObj->GetBoundVolume().getCenter();
299 0 : const basegfx::B3DHomMatrix aTransform(aViewInfo3D.getOrientation() * rCandidate.maDisplayTransform * rCandidate.maInitTransform);
300 :
301 0 : aObjCenter = aTransform * aObjCenter;
302 0 : maGlobalCenter += aObjCenter;
303 0 : }
304 :
305 : // Divide by the number
306 0 : if(nCnt > 1)
307 : {
308 0 : maGlobalCenter /= (double)nCnt;
309 : }
310 :
311 : // get rotate center and transform to 3D eye coordinates
312 0 : basegfx::B2DPoint aRotCenter2D(Ref1().X(), Ref1().Y());
313 :
314 : // from world to relative scene using inverse getObjectTransformation()
315 0 : basegfx::B2DHomMatrix aInverseObjectTransform(rVCScene.getObjectTransformation());
316 0 : aInverseObjectTransform.invert();
317 0 : aRotCenter2D = aInverseObjectTransform * aRotCenter2D;
318 :
319 : // from 3D view to 3D eye
320 0 : basegfx::B3DPoint aRotCenter3D(aRotCenter2D.getX(), aRotCenter2D.getY(), 0.0);
321 0 : basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
322 0 : aInverseViewToEye.invert();
323 0 : aRotCenter3D = aInverseViewToEye * aRotCenter3D;
324 :
325 : // Use X,Y of the RotCenter and depth of the common object centre
326 : // as rotation point in the space
327 0 : maGlobalCenter.setX(aRotCenter3D.getX());
328 0 : maGlobalCenter.setY(aRotCenter3D.getY());
329 : }
330 : }
331 0 : }
332 :
333 :
334 : //The object is moved, determine the angle
335 :
336 0 : void E3dDragRotate::MoveSdrDrag(const Point& rPnt)
337 : {
338 : // call parent
339 0 : E3dDragMethod::MoveSdrDrag(rPnt);
340 :
341 0 : if(DragStat().CheckMinMoved(rPnt))
342 : {
343 : // Get modifier
344 0 : sal_uInt16 nModifier = 0;
345 0 : if(getSdrDragView().ISA(E3dView))
346 : {
347 0 : const MouseEvent& rLastMouse = ((E3dView&)getSdrDragView()).GetMouseEvent();
348 0 : nModifier = rLastMouse.GetModifier();
349 : }
350 :
351 : // Rotate all objects
352 0 : const sal_uInt32 nCnt(maGrp.size());
353 :
354 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
355 : {
356 : // Determine rotation angle
357 : double fWAngle, fHAngle;
358 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
359 :
360 0 : if(E3DDRAG_CONSTR_Z == meConstraint)
361 : {
362 0 : fWAngle = NormAngle360(GetAngle(rPnt - DragStat().GetRef1()) -
363 0 : rCandidate.mnStartAngle) - rCandidate.mnLastAngle;
364 0 : rCandidate.mnLastAngle = (long)fWAngle + rCandidate.mnLastAngle;
365 0 : fWAngle /= 100.0;
366 0 : fHAngle = 0.0;
367 : }
368 : else
369 : {
370 0 : fWAngle = 90.0 * (double)(rPnt.X() - maLastPos.X())
371 0 : / (double)maFullBound.GetWidth();
372 0 : fHAngle = 90.0 * (double)(rPnt.Y() - maLastPos.Y())
373 0 : / (double)maFullBound.GetHeight();
374 : }
375 0 : long nSnap = 0;
376 :
377 0 : if(!getSdrDragView().IsRotateAllowed(false))
378 0 : nSnap = 90;
379 :
380 0 : if(nSnap != 0)
381 : {
382 0 : fWAngle = (double)(((long) fWAngle + nSnap/2) / nSnap * nSnap);
383 0 : fHAngle = (double)(((long) fHAngle + nSnap/2) / nSnap * nSnap);
384 : }
385 :
386 : // to radians
387 0 : fWAngle *= F_PI180;
388 0 : fHAngle *= F_PI180;
389 :
390 : // Determine transformation
391 0 : basegfx::B3DHomMatrix aRotMat;
392 0 : if(E3DDRAG_CONSTR_Y & meConstraint)
393 : {
394 0 : if(nModifier & KEY_MOD2)
395 0 : aRotMat.rotate(0.0, 0.0, fWAngle);
396 : else
397 0 : aRotMat.rotate(0.0, fWAngle, 0.0);
398 : }
399 0 : else if(E3DDRAG_CONSTR_Z & meConstraint)
400 : {
401 0 : if(nModifier & KEY_MOD2)
402 0 : aRotMat.rotate(0.0, fWAngle, 0.0);
403 : else
404 0 : aRotMat.rotate(0.0, 0.0, fWAngle);
405 : }
406 0 : if(E3DDRAG_CONSTR_X & meConstraint)
407 : {
408 0 : aRotMat.rotate(fHAngle, 0.0, 0.0);
409 : }
410 :
411 : // Transformation in eye coordinates, there rotate then and back
412 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
413 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
414 0 : basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
415 0 : aInverseOrientation.invert();
416 :
417 0 : basegfx::B3DHomMatrix aTransMat(rCandidate.maDisplayTransform);
418 0 : aTransMat *= aViewInfo3D.getOrientation();
419 0 : aTransMat.translate(-maGlobalCenter.getX(), -maGlobalCenter.getY(), -maGlobalCenter.getZ());
420 0 : aTransMat *= aRotMat;
421 0 : aTransMat.translate(maGlobalCenter.getX(), maGlobalCenter.getY(), maGlobalCenter.getZ());
422 0 : aTransMat *= aInverseOrientation;
423 0 : aTransMat *= rCandidate.maInvDisplayTransform;
424 :
425 : // ...and apply
426 0 : rCandidate.maTransform *= aTransMat;
427 :
428 0 : if(mbMoveFull)
429 : {
430 0 : E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
431 0 : rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
432 : }
433 : else
434 : {
435 0 : Hide();
436 0 : rCandidate.maWireframePoly.transform(aTransMat);
437 0 : Show();
438 : }
439 0 : }
440 0 : maLastPos = rPnt;
441 0 : DragStat().NextMove(rPnt);
442 : }
443 0 : }
444 :
445 0 : Pointer E3dDragRotate::GetSdrDragPointer() const
446 : {
447 0 : return Pointer(POINTER_ROTATE);
448 : }
449 :
450 : // E3dDragMove. This drag method is only required for translations inside
451 : // 3D scenes. If a 3D-scene itself moved, then this drag method will drag
452 : // not be used.
453 :
454 0 : TYPEINIT1(E3dDragMove, E3dDragMethod);
455 :
456 0 : E3dDragMove::E3dDragMove(SdrDragView &_rView,
457 : const SdrMarkList& rMark,
458 : SdrHdlKind eDrgHdl,
459 : E3dDragConstraint eConstr,
460 : sal_Bool bFull)
461 : : E3dDragMethod(_rView, rMark, eConstr, bFull),
462 0 : meWhatDragHdl(eDrgHdl)
463 : {
464 0 : switch(meWhatDragHdl)
465 : {
466 : case HDL_LEFT:
467 0 : maScaleFixPos = maFullBound.RightCenter();
468 0 : break;
469 : case HDL_RIGHT:
470 0 : maScaleFixPos = maFullBound.LeftCenter();
471 0 : break;
472 : case HDL_UPPER:
473 0 : maScaleFixPos = maFullBound.BottomCenter();
474 0 : break;
475 : case HDL_LOWER:
476 0 : maScaleFixPos = maFullBound.TopCenter();
477 0 : break;
478 : case HDL_UPLFT:
479 0 : maScaleFixPos = maFullBound.BottomRight();
480 0 : break;
481 : case HDL_UPRGT:
482 0 : maScaleFixPos = maFullBound.BottomLeft();
483 0 : break;
484 : case HDL_LWLFT:
485 0 : maScaleFixPos = maFullBound.TopRight();
486 0 : break;
487 : case HDL_LWRGT:
488 0 : maScaleFixPos = maFullBound.TopLeft();
489 0 : break;
490 : default:
491 : // Moving the object, HDL_MOVE
492 0 : break;
493 : }
494 :
495 : // Override when IsResizeAtCenter()
496 0 : if(getSdrDragView().IsResizeAtCenter())
497 : {
498 0 : meWhatDragHdl = HDL_USER;
499 0 : maScaleFixPos = maFullBound.Center();
500 : }
501 0 : }
502 :
503 : // The object is moved, determine the translations
504 :
505 0 : void E3dDragMove::MoveSdrDrag(const Point& rPnt)
506 : {
507 : // call parent
508 0 : E3dDragMethod::MoveSdrDrag(rPnt);
509 :
510 0 : if(DragStat().CheckMinMoved(rPnt))
511 : {
512 0 : if(HDL_MOVE == meWhatDragHdl)
513 : {
514 : // Translation
515 : // Determine the motion vector
516 0 : const sal_uInt32 nCnt(maGrp.size());
517 :
518 : // Get modifier
519 0 : sal_uInt16 nModifier(0);
520 :
521 0 : if(getSdrDragView().ISA(E3dView))
522 : {
523 0 : const MouseEvent& rLastMouse = ((E3dView&)getSdrDragView()).GetMouseEvent();
524 0 : nModifier = rLastMouse.GetModifier();
525 : }
526 :
527 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
528 : {
529 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
530 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
531 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
532 :
533 : // move coor from 2d world to 3d Eye
534 0 : basegfx::B2DPoint aGlobalMoveHead2D((double)(rPnt.X() - maLastPos.X()), (double)(rPnt.Y() - maLastPos.Y()));
535 0 : basegfx::B2DPoint aGlobalMoveTail2D(0.0, 0.0);
536 0 : basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
537 :
538 0 : aInverseSceneTransform.invert();
539 0 : aGlobalMoveHead2D = aInverseSceneTransform * aGlobalMoveHead2D;
540 0 : aGlobalMoveTail2D = aInverseSceneTransform * aGlobalMoveTail2D;
541 :
542 0 : basegfx::B3DPoint aMoveHead3D(aGlobalMoveHead2D.getX(), aGlobalMoveHead2D.getY(), 0.5);
543 0 : basegfx::B3DPoint aMoveTail3D(aGlobalMoveTail2D.getX(), aGlobalMoveTail2D.getY(), 0.5);
544 0 : basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
545 0 : aInverseViewToEye.invert();
546 :
547 0 : aMoveHead3D = aInverseViewToEye * aMoveHead3D;
548 0 : aMoveTail3D = aInverseViewToEye * aMoveTail3D;
549 :
550 : // eventually switch movement from XY to XZ plane
551 0 : if(nModifier & KEY_MOD2)
552 : {
553 0 : double fZwi = aMoveHead3D.getY();
554 0 : aMoveHead3D.setY(aMoveHead3D.getZ());
555 0 : aMoveHead3D.setZ(fZwi);
556 :
557 0 : fZwi = aMoveTail3D.getY();
558 0 : aMoveTail3D.setY(aMoveTail3D.getZ());
559 0 : aMoveTail3D.setZ(fZwi);
560 : }
561 :
562 : // Motion vector from eye coordinates to parent coordinates
563 0 : basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
564 0 : aInverseOrientation.invert();
565 0 : basegfx::B3DHomMatrix aCompleteTrans(rCandidate.maInvDisplayTransform * aInverseOrientation);
566 :
567 0 : aMoveHead3D = aCompleteTrans * aMoveHead3D;
568 0 : aMoveTail3D = aCompleteTrans* aMoveTail3D;
569 :
570 : // build transformation
571 0 : basegfx::B3DHomMatrix aTransMat;
572 0 : basegfx::B3DPoint aTranslate(aMoveHead3D - aMoveTail3D);
573 0 : aTransMat.translate(aTranslate.getX(), aTranslate.getY(), aTranslate.getZ());
574 :
575 : // ...and apply
576 0 : rCandidate.maTransform *= aTransMat;
577 :
578 0 : if(mbMoveFull)
579 : {
580 0 : E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
581 0 : rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
582 : }
583 : else
584 : {
585 0 : Hide();
586 0 : rCandidate.maWireframePoly.transform(aTransMat);
587 0 : Show();
588 : }
589 0 : }
590 : }
591 : else
592 : {
593 : // Scaling
594 : // Determine scaling vector
595 0 : Point aStartPos = DragStat().GetStart();
596 0 : const sal_uInt32 nCnt(maGrp.size());
597 :
598 0 : for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
599 : {
600 0 : E3dDragMethodUnit& rCandidate = maGrp[nOb];
601 0 : const basegfx::B3DPoint aObjectCenter(rCandidate.mp3DObj->GetBoundVolume().getCenter());
602 :
603 : // transform from 2D world view to 3D eye
604 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(rCandidate.mp3DObj->GetScene()->GetViewContact());
605 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
606 :
607 0 : basegfx::B2DPoint aGlobalScaleStart2D((double)(aStartPos.X()), (double)(aStartPos.Y()));
608 0 : basegfx::B2DPoint aGlobalScaleNext2D((double)(rPnt.X()), (double)(rPnt.Y()));
609 0 : basegfx::B2DPoint aGlobalScaleFixPos2D((double)(maScaleFixPos.X()), (double)(maScaleFixPos.Y()));
610 0 : basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
611 :
612 0 : aInverseSceneTransform.invert();
613 0 : aGlobalScaleStart2D = aInverseSceneTransform * aGlobalScaleStart2D;
614 0 : aGlobalScaleNext2D = aInverseSceneTransform * aGlobalScaleNext2D;
615 0 : aGlobalScaleFixPos2D = aInverseSceneTransform * aGlobalScaleFixPos2D;
616 :
617 0 : basegfx::B3DPoint aGlobalScaleStart3D(aGlobalScaleStart2D.getX(), aGlobalScaleStart2D.getY(), aObjectCenter.getZ());
618 0 : basegfx::B3DPoint aGlobalScaleNext3D(aGlobalScaleNext2D.getX(), aGlobalScaleNext2D.getY(), aObjectCenter.getZ());
619 0 : basegfx::B3DPoint aGlobalScaleFixPos3D(aGlobalScaleFixPos2D.getX(), aGlobalScaleFixPos2D.getY(), aObjectCenter.getZ());
620 0 : basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
621 :
622 0 : aInverseViewToEye.invert();
623 0 : basegfx::B3DPoint aScStart(aInverseViewToEye * aGlobalScaleStart3D);
624 0 : basegfx::B3DPoint aScNext(aInverseViewToEye * aGlobalScaleNext3D);
625 0 : basegfx::B3DPoint aScFixPos(aInverseViewToEye * aGlobalScaleFixPos3D);
626 :
627 : // constraints?
628 0 : switch(meWhatDragHdl)
629 : {
630 : case HDL_LEFT:
631 : case HDL_RIGHT:
632 : // to constrain on X -> Y equal
633 0 : aScNext.setY(aScFixPos.getY());
634 0 : break;
635 : case HDL_UPPER:
636 : case HDL_LOWER:
637 : // constrain to auf Y -> X equal
638 0 : aScNext.setX(aScFixPos.getX());
639 0 : break;
640 : default:
641 0 : break;
642 : }
643 :
644 : // get scale vector in eye coordinates
645 0 : basegfx::B3DPoint aScaleVec(aScStart - aScFixPos);
646 0 : aScaleVec.setZ(1.0);
647 :
648 0 : if(aScaleVec.getX() != 0.0)
649 : {
650 0 : aScaleVec.setX((aScNext.getX() - aScFixPos.getX()) / aScaleVec.getX());
651 : }
652 : else
653 : {
654 0 : aScaleVec.setX(1.0);
655 : }
656 :
657 0 : if(aScaleVec.getY() != 0.0)
658 : {
659 0 : aScaleVec.setY((aScNext.getY() - aScFixPos.getY()) / aScaleVec.getY());
660 : }
661 : else
662 : {
663 0 : aScaleVec.setY(1.0);
664 : }
665 :
666 : // SHIFT-key used?
667 0 : if(getSdrDragView().IsOrtho())
668 : {
669 0 : if(fabs(aScaleVec.getX()) > fabs(aScaleVec.getY()))
670 : {
671 : // X is biggest
672 0 : aScaleVec.setY(aScaleVec.getX());
673 : }
674 : else
675 : {
676 : // Y is biggest
677 0 : aScaleVec.setX(aScaleVec.getY());
678 : }
679 : }
680 :
681 : // build transformation
682 0 : basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
683 0 : aInverseOrientation.invert();
684 :
685 0 : basegfx::B3DHomMatrix aNewTrans = rCandidate.maInitTransform;
686 0 : aNewTrans *= rCandidate.maDisplayTransform;
687 0 : aNewTrans *= aViewInfo3D.getOrientation();
688 0 : aNewTrans.translate(-aScFixPos.getX(), -aScFixPos.getY(), -aScFixPos.getZ());
689 0 : aNewTrans.scale(aScaleVec.getX(), aScaleVec.getY(), aScaleVec.getZ());
690 0 : aNewTrans.translate(aScFixPos.getX(), aScFixPos.getY(), aScFixPos.getZ());
691 0 : aNewTrans *= aInverseOrientation;
692 0 : aNewTrans *= rCandidate.maInvDisplayTransform;
693 :
694 : // ...and apply
695 0 : rCandidate.maTransform = aNewTrans;
696 :
697 0 : if(mbMoveFull)
698 : {
699 0 : E3DModifySceneSnapRectUpdater aUpdater(rCandidate.mp3DObj);
700 0 : rCandidate.mp3DObj->SetTransform(rCandidate.maTransform);
701 : }
702 : else
703 : {
704 0 : Hide();
705 0 : rCandidate.maWireframePoly.clear();
706 0 : rCandidate.maWireframePoly = rCandidate.mp3DObj->CreateWireframe();
707 0 : rCandidate.maWireframePoly.transform(rCandidate.maTransform);
708 0 : Show();
709 : }
710 0 : }
711 : }
712 0 : maLastPos = rPnt;
713 0 : DragStat().NextMove(rPnt);
714 : }
715 0 : }
716 :
717 0 : Pointer E3dDragMove::GetSdrDragPointer() const
718 : {
719 0 : return Pointer(POINTER_MOVE);
720 : }
721 :
722 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|