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