Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "svx/svdstr.hrc"
31 : : #include "svx/svdglob.hxx"
32 : : #include "svx/svditer.hxx"
33 : :
34 : : #include <stdlib.h>
35 : : #include <svx/globl3d.hxx>
36 : : #include <svx/svdpage.hxx>
37 : : #include <svl/style.hxx>
38 : : #include <svx/scene3d.hxx>
39 : : #include <svx/e3dundo.hxx>
40 : : #include <svx/svdtrans.hxx>
41 : : #include <svx/svxids.hrc>
42 : : #include <editeng/colritem.hxx>
43 : : #include <svx/e3ditem.hxx>
44 : : #include <svx/xlntrit.hxx>
45 : : #include <svx/xfltrit.hxx>
46 : : #include <svx/svx3ditems.hxx>
47 : : #include <svl/whiter.hxx>
48 : : #include <svx/xflftrit.hxx>
49 : : #include <svx/sdr/properties/e3dsceneproperties.hxx>
50 : : #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
51 : : #include <svx/svddrag.hxx>
52 : : #include <helperminimaldepth3d.hxx>
53 : : #include <algorithm>
54 : : #include <drawinglayer/geometry/viewinformation3d.hxx>
55 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
56 : : #include <svx/e3dsceneupdater.hxx>
57 : :
58 : : //////////////////////////////////////////////////////////////////////////////
59 : :
60 : : class ImpRemap3DDepth
61 : : {
62 : : sal_uInt32 mnOrdNum;
63 : : double mfMinimalDepth;
64 : :
65 : : // bit field
66 : : unsigned mbIsScene : 1;
67 : :
68 : : public:
69 : : ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth);
70 : : ImpRemap3DDepth(sal_uInt32 nOrdNum);
71 : : ~ImpRemap3DDepth();
72 : :
73 : : // for ::std::sort
74 : : bool operator<(const ImpRemap3DDepth& rComp) const;
75 : :
76 : 0 : sal_uInt32 GetOrdNum() const { return mnOrdNum; }
77 : 0 : sal_Bool IsScene() const { return mbIsScene; }
78 : : };
79 : :
80 : 0 : ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth)
81 : : : mnOrdNum(nOrdNum),
82 : : mfMinimalDepth(fMinimalDepth),
83 : 0 : mbIsScene(sal_False)
84 : : {
85 : 0 : }
86 : :
87 : 0 : ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum)
88 : : : mnOrdNum(nOrdNum),
89 : : mfMinimalDepth(0.0),
90 : 0 : mbIsScene(sal_True)
91 : : {
92 : 0 : }
93 : :
94 : 0 : ImpRemap3DDepth::~ImpRemap3DDepth()
95 : : {
96 : 0 : }
97 : :
98 : 0 : bool ImpRemap3DDepth::operator<(const ImpRemap3DDepth& rComp) const
99 : : {
100 [ # # ]: 0 : if(IsScene())
101 : : {
102 : 0 : return sal_False;
103 : : }
104 : : else
105 : : {
106 [ # # ]: 0 : if(rComp.IsScene())
107 : : {
108 : 0 : return sal_True;
109 : : }
110 : : else
111 : : {
112 : 0 : return mfMinimalDepth < rComp.mfMinimalDepth;
113 : : }
114 : : }
115 : : }
116 : :
117 : : // typedefs for a vector of ImpRemap3DDepths
118 : : typedef ::std::vector< ImpRemap3DDepth > ImpRemap3DDepthVector;
119 : :
120 : : //////////////////////////////////////////////////////////////////////////////
121 : :
122 : : class Imp3DDepthRemapper
123 : : {
124 : : ImpRemap3DDepthVector maVector;
125 : :
126 : : public:
127 : : Imp3DDepthRemapper(E3dScene& rScene);
128 : : ~Imp3DDepthRemapper();
129 : :
130 : : sal_uInt32 RemapOrdNum(sal_uInt32 nOrdNum) const;
131 : : };
132 : :
133 : 0 : Imp3DDepthRemapper::Imp3DDepthRemapper(E3dScene& rScene)
134 : : {
135 : : // only called when rScene.GetSubList() and nObjCount > 1L
136 [ # # ]: 0 : SdrObjList* pList = rScene.GetSubList();
137 [ # # ]: 0 : const sal_uInt32 nObjCount(pList->GetObjCount());
138 : :
139 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nObjCount; a++)
140 : : {
141 [ # # ]: 0 : SdrObject* pCandidate = pList->GetObj(a);
142 : :
143 [ # # ]: 0 : if(pCandidate)
144 : : {
145 [ # # ][ # # ]: 0 : if(pCandidate->ISA(E3dCompoundObject))
[ # # ]
146 : : {
147 : : // single 3d object, calc depth
148 [ # # ]: 0 : const double fMinimalDepth(getMinimalDepthInViewCoordinates(static_cast< const E3dCompoundObject& >(*pCandidate)));
149 : 0 : ImpRemap3DDepth aEntry(a, fMinimalDepth);
150 [ # # ]: 0 : maVector.push_back(aEntry);
151 : : }
152 : : else
153 : : {
154 : : // scene, use standard entry for scene
155 : 0 : ImpRemap3DDepth aEntry(a);
156 [ # # ]: 0 : maVector.push_back(aEntry);
157 : : }
158 : : }
159 : : }
160 : :
161 : : // now, we need to sort the maVector by it's members minimal depth. The
162 : : // smaller, the nearer to the viewer.
163 [ # # ]: 0 : ::std::sort(maVector.begin(), maVector.end());
164 : 0 : }
165 : :
166 : 0 : Imp3DDepthRemapper::~Imp3DDepthRemapper()
167 : : {
168 : 0 : }
169 : :
170 : 0 : sal_uInt32 Imp3DDepthRemapper::RemapOrdNum(sal_uInt32 nOrdNum) const
171 : : {
172 [ # # ]: 0 : if(nOrdNum < maVector.size())
173 : : {
174 : 0 : nOrdNum = maVector[(maVector.size() - 1) - nOrdNum].GetOrdNum();
175 : : }
176 : :
177 : 0 : return nOrdNum;
178 : : }
179 : :
180 : : //////////////////////////////////////////////////////////////////////////////
181 : : // BaseProperties section
182 : :
183 : 736 : sdr::properties::BaseProperties* E3dScene::CreateObjectSpecificProperties()
184 : : {
185 [ + - ]: 736 : return new sdr::properties::E3dSceneProperties(*this);
186 : : }
187 : :
188 : : //////////////////////////////////////////////////////////////////////////////
189 : : // DrawContact section
190 : :
191 : 736 : sdr::contact::ViewContact* E3dScene::CreateObjectSpecificViewContact()
192 : : {
193 [ + - ]: 736 : return new sdr::contact::ViewContactOfE3dScene(*this);
194 : : }
195 : :
196 : : //////////////////////////////////////////////////////////////////////////////
197 : :
198 [ + + ][ + + ]: 10246734 : TYPEINIT1(E3dScene, E3dObject);
199 : :
200 : 736 : E3dScene::E3dScene()
201 : : : E3dObject(),
202 : : aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()),
203 : : mp3DDepthRemapper(0L),
204 [ + - ][ + - ]: 736 : bDrawOnlySelected(false)
205 : : {
206 : : // Set defaults
207 [ + - ]: 736 : E3dDefaultAttributes aDefault;
208 [ + - ][ + - ]: 736 : SetDefaultAttributes(aDefault);
209 : 736 : }
210 : :
211 : 0 : E3dScene::E3dScene(E3dDefaultAttributes& rDefault)
212 : : : E3dObject(),
213 : : aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()),
214 : : mp3DDepthRemapper(0L),
215 [ # # ][ # # ]: 0 : bDrawOnlySelected(false)
216 : : {
217 : : // Set defaults
218 [ # # ]: 0 : SetDefaultAttributes(rDefault);
219 : 0 : }
220 : :
221 : 736 : void E3dScene::SetDefaultAttributes(E3dDefaultAttributes& /*rDefault*/)
222 : : {
223 : : // For WIN95/NT turn off the FP-Exceptions
224 : : #if defined(WNT)
225 : : _control87( _MCW_EM, _MCW_EM );
226 : : #endif
227 : :
228 : : // Set defaults
229 [ + - ]: 736 : aCamera.SetViewWindow(-2, -2, 4, 4);
230 [ + - ]: 736 : aCameraSet.SetDeviceRectangle(-2, 2, -2, 2);
231 [ + - ][ + - ]: 736 : aCamera.SetDeviceWindow(Rectangle(0, 0, 10, 10));
232 [ + - ]: 736 : Rectangle aRect(0, 0, 10, 10);
233 [ + - ]: 736 : aCameraSet.SetViewportRectangle(aRect);
234 : :
235 : : // set defaults for Camera from ItemPool
236 [ + - ]: 736 : aCamera.SetProjection(GetPerspective());
237 : 736 : basegfx::B3DPoint aActualPosition(aCamera.GetPosition());
238 [ + - ]: 736 : double fNew = GetDistance();
239 : :
240 [ + - ]: 736 : if(fabs(fNew - aActualPosition.getZ()) > 1.0)
241 : : {
242 [ + - ]: 736 : aCamera.SetPosition( basegfx::B3DPoint( aActualPosition.getX(), aActualPosition.getY(), fNew) );
243 : : }
244 : :
245 [ + - ]: 736 : fNew = GetFocalLength() / 100.0;
246 [ + - ]: 736 : aCamera.SetFocalLength(fNew);
247 : 736 : }
248 : :
249 [ + - ][ + - ]: 736 : E3dScene::~E3dScene()
250 : : {
251 [ + - ]: 736 : ImpCleanup3DDepthMapper();
252 [ - + ]: 736 : }
253 : :
254 : 0 : basegfx::B2DPolyPolygon E3dScene::TakeXorPoly() const
255 : : {
256 [ # # ]: 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(GetViewContact());
257 [ # # ][ # # ]: 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
258 [ # # ]: 0 : const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe());
259 : :
260 : : basegfx::B2DPolyPolygon aRetval(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon,
261 [ # # ][ # # ]: 0 : aViewInfo3D.getObjectToView()));
262 [ # # ][ # # ]: 0 : aRetval.transform(rVCScene.getObjectTransformation());
263 : :
264 [ # # ][ # # ]: 0 : return aRetval;
265 : : }
266 : :
267 : 50097 : void E3dScene::ImpCleanup3DDepthMapper()
268 : : {
269 [ - + ]: 50097 : if(mp3DDepthRemapper)
270 : : {
271 [ # # ]: 0 : delete mp3DDepthRemapper;
272 : 0 : mp3DDepthRemapper = 0L;
273 : : }
274 : 50097 : }
275 : :
276 : 0 : sal_uInt32 E3dScene::RemapOrdNum(sal_uInt32 nNewOrdNum) const
277 : : {
278 [ # # ]: 0 : if(!mp3DDepthRemapper)
279 : : {
280 [ # # ]: 0 : const sal_uInt32 nObjCount(GetSubList() ? GetSubList()->GetObjCount() : 0L);
281 : :
282 [ # # ]: 0 : if(nObjCount > 1L)
283 : : {
284 [ # # ]: 0 : ((E3dScene*)this)->mp3DDepthRemapper = new Imp3DDepthRemapper((E3dScene&)(*this));
285 : : }
286 : : }
287 : :
288 [ # # ]: 0 : if(mp3DDepthRemapper)
289 : : {
290 : 0 : return mp3DDepthRemapper->RemapOrdNum(nNewOrdNum);
291 : : }
292 : :
293 : 0 : return nNewOrdNum;
294 : : }
295 : :
296 : 0 : sal_uInt16 E3dScene::GetObjIdentifier() const
297 : : {
298 : 0 : return E3D_SCENE_ID;
299 : : }
300 : :
301 : 658344 : void E3dScene::SetBoundRectDirty()
302 : : {
303 : 658344 : E3dScene* pScene = GetScene();
304 : :
305 [ + + ]: 658344 : if(pScene == this)
306 : : {
307 : : // avoid resetting aOutRect which in case of a 3D scene used as 2d object
308 : : // is model data,not re-creatable view data
309 : : }
310 : : else
311 : : {
312 : : // if not the outmost scene it is used as group in 3d, call parent
313 : 633320 : E3dObject::SetBoundRectDirty();
314 : : }
315 : 658344 : }
316 : :
317 : 1629 : void E3dScene::NbcSetSnapRect(const Rectangle& rRect)
318 : : {
319 : 1629 : SetRectsDirty();
320 : 1629 : E3dObject::NbcSetSnapRect(rRect);
321 : 1629 : aCamera.SetDeviceWindow(rRect);
322 : 1629 : aCameraSet.SetViewportRectangle((Rectangle&)rRect);
323 : :
324 : 1629 : ImpCleanup3DDepthMapper();
325 : 1629 : }
326 : :
327 : 47 : void E3dScene::NbcMove(const Size& rSize)
328 : : {
329 [ + - ]: 47 : Rectangle aNewSnapRect = GetSnapRect();
330 [ + - ]: 47 : MoveRect(aNewSnapRect, rSize);
331 [ + - ]: 47 : NbcSetSnapRect(aNewSnapRect);
332 : 47 : }
333 : :
334 : 0 : void E3dScene::NbcResize(const Point& rRef, const Fraction& rXFact,
335 : : const Fraction& rYFact)
336 : : {
337 [ # # ]: 0 : Rectangle aNewSnapRect = GetSnapRect();
338 [ # # ]: 0 : ResizeRect(aNewSnapRect, rRef, rXFact, rYFact);
339 [ # # ]: 0 : NbcSetSnapRect(aNewSnapRect);
340 : 0 : }
341 : :
342 : : // Set new camera, and thus mark the scene and if possible the bound volume
343 : : // as changed
344 : :
345 : 761 : void E3dScene::SetCamera(const Camera3D& rNewCamera)
346 : : {
347 : : // Set old camera
348 [ + - ]: 761 : aCamera = rNewCamera;
349 [ + - ][ + - ]: 761 : ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
350 : :
351 [ + - ]: 761 : SetRectsDirty();
352 : :
353 : : // Fill new camera from old
354 : 761 : Camera3D& rCam = (Camera3D&)GetCamera();
355 : :
356 : : // Turn off ratio
357 [ + - ]: 761 : if(rCam.GetAspectMapping() == AS_NO_MAPPING)
358 [ + - ]: 761 : GetCameraSet().SetRatio(0.0);
359 : :
360 : : // Set Imaging geometry
361 [ + - ]: 761 : basegfx::B3DPoint aVRP(rCam.GetViewPoint());
362 : 761 : basegfx::B3DVector aVPN(aVRP - rCam.GetVRP());
363 : 761 : basegfx::B3DVector aVUV(rCam.GetVUV());
364 : :
365 : : // use SetViewportValues() to set VRP, VPN and VUV as vectors, too.
366 : : // Else these values would not be exported/imported correctly.
367 [ + - ]: 761 : GetCameraSet().SetViewportValues(aVRP, aVPN, aVUV);
368 : :
369 : : // Set perspective
370 [ + - ]: 761 : GetCameraSet().SetPerspective(rCam.GetProjection() == PR_PERSPECTIVE);
371 [ + - ]: 761 : GetCameraSet().SetViewportRectangle((Rectangle&)rCam.GetDeviceWindow());
372 : :
373 [ + - ]: 761 : ImpCleanup3DDepthMapper();
374 : 761 : }
375 : :
376 : 0 : void E3dScene::NewObjectInserted(const E3dObject* p3DObj)
377 : : {
378 : 0 : E3dObject::NewObjectInserted(p3DObj);
379 : :
380 [ # # ]: 0 : if ( p3DObj == this )
381 : 0 : return;
382 : :
383 : 0 : ImpCleanup3DDepthMapper();
384 : : }
385 : :
386 : : // Inform parent of changes of a child
387 : :
388 : 45077 : void E3dScene::StructureChanged()
389 : : {
390 : 45077 : E3dObject::StructureChanged();
391 : 45077 : SetRectsDirty();
392 : :
393 : 45077 : ImpCleanup3DDepthMapper();
394 : 45077 : }
395 : :
396 : : // Determine the overall scene object
397 : :
398 : 3168123 : E3dScene* E3dScene::GetScene() const
399 : : {
400 [ + + ]: 3168123 : if(GetParentObj())
401 : 2475763 : return GetParentObj()->GetScene();
402 : : else
403 : 3168123 : return (E3dScene*)this;
404 : : }
405 : :
406 : 0 : void E3dScene::removeAllNonSelectedObjects()
407 : : {
408 [ # # ]: 0 : E3DModifySceneSnapRectUpdater aUpdater(this);
409 : :
410 [ # # ][ # # ]: 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
411 : : {
412 [ # # ]: 0 : SdrObject* pObj = maSubList.GetObj(a);
413 : :
414 [ # # ]: 0 : if(pObj)
415 : : {
416 : 0 : bool bRemoveObject(false);
417 : :
418 [ # # ][ # # ]: 0 : if(pObj->ISA(E3dScene))
[ # # ]
419 : : {
420 : 0 : E3dScene* pScene = (E3dScene*)pObj;
421 : :
422 : : // iterate over this sub-scene
423 [ # # ]: 0 : pScene->removeAllNonSelectedObjects();
424 : :
425 : : // check object count. Empty scenes can be deleted
426 [ # # ][ # # ]: 0 : const sal_uInt32 nObjCount(pScene->GetSubList() ? pScene->GetSubList()->GetObjCount() : 0);
[ # # ][ # # ]
427 : :
428 [ # # ]: 0 : if(!nObjCount)
429 : : {
430 : : // all objects removed, scene can be removed, too
431 : 0 : bRemoveObject = true;
432 : : }
433 : : }
434 [ # # ][ # # ]: 0 : else if(pObj->ISA(E3dCompoundObject))
[ # # ]
435 : : {
436 : 0 : E3dCompoundObject* pCompound = (E3dCompoundObject*)pObj;
437 : :
438 [ # # ]: 0 : if(!pCompound->GetSelected())
439 : : {
440 : 0 : bRemoveObject = true;
441 : : }
442 : : }
443 : :
444 [ # # ]: 0 : if(bRemoveObject)
445 : : {
446 [ # # ][ # # ]: 0 : maSubList.NbcRemoveObject(pObj->GetOrdNum());
447 : 0 : a--;
448 [ # # ]: 0 : SdrObject::Free(pObj);
449 : : }
450 : : }
451 [ # # ]: 0 : }
452 : 0 : }
453 : :
454 : 0 : E3dScene* E3dScene::Clone() const
455 : : {
456 : 0 : return CloneHelper< E3dScene >();
457 : : }
458 : :
459 : 0 : E3dScene& E3dScene::operator=(const E3dScene& rObj)
460 : : {
461 [ # # ]: 0 : if( this == &rObj )
462 : 0 : return *this;
463 : 0 : E3dObject::operator=(rObj);
464 : :
465 : 0 : const E3dScene& r3DObj = (const E3dScene&) rObj;
466 : 0 : aCamera = r3DObj.aCamera;
467 : :
468 : 0 : aCameraSet = r3DObj.aCameraSet;
469 : 0 : ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
470 : :
471 : 0 : InvalidateBoundVolume();
472 : 0 : RebuildLists();
473 : 0 : SetRectsDirty();
474 : :
475 : 0 : ImpCleanup3DDepthMapper();
476 : :
477 : : // #i101941#
478 : : // After a Scene as model object is cloned, the used
479 : : // ViewContactOfE3dScene is created and partially used
480 : : // to calculate Bound/SnapRects, but - since quite some
481 : : // values are buffered at the VC - not really well
482 : : // initialized. It would be possible to always watch for
483 : : // preconditions of buffered data, but this would be expensive
484 : : // and would create a lot of short living data structures.
485 : : // It is currently better to flush that data, e.g. by using
486 : : // ActionChanged at the VC which will for this class
487 : : // flush that cached data and initalize it's valid reconstruction
488 : 0 : GetViewContact().ActionChanged();
489 : 0 : return *this;
490 : : }
491 : :
492 : : // Rebuild Light- and label- object lists rebuild (after loading, allocation)
493 : :
494 : 0 : void E3dScene::RebuildLists()
495 : : {
496 : : // first delete
497 [ # # ]: 0 : SdrLayerID nCurrLayerID = GetLayer();
498 : :
499 [ # # ]: 0 : SdrObjListIter a3DIterator(maSubList, IM_FLAT);
500 : :
501 : : // then examine all the objects in the scene
502 [ # # ]: 0 : while ( a3DIterator.IsMore() )
503 : : {
504 [ # # ]: 0 : E3dObject* p3DObj = (E3dObject*) a3DIterator.Next();
505 [ # # ]: 0 : p3DObj->NbcSetLayer(nCurrLayerID);
506 [ # # ]: 0 : NewObjectInserted(p3DObj);
507 : 0 : }
508 : 0 : }
509 : :
510 : 0 : SdrObjGeoData *E3dScene::NewGeoData() const
511 : : {
512 [ # # ]: 0 : return new E3DSceneGeoData;
513 : : }
514 : :
515 : 0 : void E3dScene::SaveGeoData(SdrObjGeoData& rGeo) const
516 : : {
517 : 0 : E3dObject::SaveGeoData (rGeo);
518 : :
519 : 0 : ((E3DSceneGeoData &) rGeo).aCamera = aCamera;
520 : 0 : }
521 : :
522 : 0 : void E3dScene::RestGeoData(const SdrObjGeoData& rGeo)
523 : : {
524 : : // #i94832# removed E3DModifySceneSnapRectUpdater here.
525 : : // It should not be needed, is already part of E3dObject::RestGeoData
526 : 0 : E3dObject::RestGeoData (rGeo);
527 : 0 : SetCamera (((E3DSceneGeoData &) rGeo).aCamera);
528 : 0 : }
529 : :
530 : : // Something was changed in the style sheet, so change scene
531 : :
532 : 0 : void E3dScene::Notify(SfxBroadcaster &rBC, const SfxHint &rHint)
533 : : {
534 : 0 : SetRectsDirty();
535 : 0 : E3dObject::Notify(rBC, rHint);
536 : 0 : }
537 : :
538 : 0 : void E3dScene::RotateScene (const Point& rRef, long /*nWink*/, double sn, double cs)
539 : : {
540 : 0 : Point UpperLeft, LowerRight, Center, NewCenter;
541 : :
542 : 0 : UpperLeft = aOutRect.TopLeft();
543 [ # # ]: 0 : LowerRight = aOutRect.BottomRight();
544 : :
545 : 0 : long dxOutRectHalf = labs(UpperLeft.X() - LowerRight.X());
546 : 0 : dxOutRectHalf /= 2;
547 : 0 : long dyOutRectHalf = labs(UpperLeft.Y() - LowerRight.Y());
548 : 0 : dyOutRectHalf /= 2;
549 : :
550 : : // Only the center is moved. The corners are moved by NbcMove. For the
551 : : // rotation a cartesian coordinate system is used in which the pivot
552 : : // point is the origin, and the y-axis increases upward, the X-axis to
553 : : // the right. This must be especially noted for the Y-values.
554 : : // (When considering a flat piece of paper the Y-axis pointing downwards
555 : 0 : Center.X() = (UpperLeft.X() + dxOutRectHalf) - rRef.X();
556 : 0 : Center.Y() = -((UpperLeft.Y() + dyOutRectHalf) - rRef.Y());
557 : : // A few special cases has to be dealt with first (n * 90 degrees n integer)
558 [ # # ][ # # ]: 0 : if (sn==1.0 && cs==0.0) { // 90deg
559 : 0 : NewCenter.X() = -Center.Y();
560 : 0 : NewCenter.Y() = -Center.X();
561 [ # # ][ # # ]: 0 : } else if (sn==0.0 && cs==-1.0) { // 180deg
562 : 0 : NewCenter.X() = -Center.X();
563 : 0 : NewCenter.Y() = -Center.Y();
564 [ # # ][ # # ]: 0 : } else if (sn==-1.0 && cs==0.0) { // 270deg
565 : 0 : NewCenter.X() = Center.Y();
566 : 0 : NewCenter.Y() = -Center.X();
567 : : }
568 : : else // Here it is rotated to any angle in the mathematically
569 : : // positive direction!
570 : : { // xnew = x * cos(alpha) - y * sin(alpha)
571 : : // ynew = x * sin(alpha) + y * cos(alpha)
572 : : // Bottom Right is not rotated: the pages of aOutRect must
573 : : // remain parallel to the coordinate axes.
574 : 0 : NewCenter.X() = (long) (Center.X() * cs - Center.Y() * sn);
575 : 0 : NewCenter.Y() = (long) (Center.X() * sn + Center.Y() * cs);
576 : : }
577 : :
578 : 0 : Size Differenz;
579 : 0 : Point DiffPoint = (NewCenter - Center);
580 : 0 : Differenz.Width() = DiffPoint.X();
581 : 0 : Differenz.Height() = -DiffPoint.Y(); // Note that the Y-axis is counted ad positive downward.
582 [ # # ]: 0 : NbcMove (Differenz); // Actually executes the coordinate transformation.
583 : 0 : }
584 : :
585 : 0 : void E3dScene::TakeObjNameSingul(XubString& rName) const
586 : : {
587 [ # # ][ # # ]: 0 : rName=ImpGetResStr(STR_ObjNameSingulScene3d);
[ # # ]
588 : :
589 [ # # ][ # # ]: 0 : String aName( GetName() );
590 [ # # ]: 0 : if(aName.Len())
591 : : {
592 [ # # ]: 0 : rName += sal_Unicode(' ');
593 [ # # ]: 0 : rName += sal_Unicode('\'');
594 [ # # ]: 0 : rName += aName;
595 [ # # ]: 0 : rName += sal_Unicode('\'');
596 [ # # ]: 0 : }
597 : 0 : }
598 : :
599 : 0 : void E3dScene::TakeObjNamePlural(XubString& rName) const
600 : : {
601 [ # # ]: 0 : rName=ImpGetResStr(STR_ObjNamePluralScene3d);
602 : 0 : }
603 : :
604 : : // The NbcRotate routine overloads the one of the SdrObject. The idea is
605 : : // to be able to rotate the scene relative to the position of the scene
606 : : // and then the objects in the scene
607 : :
608 : 75 : void E3dScene::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix)
609 : : {
610 [ + - ]: 75 : if(maTransformation != rMatrix)
611 : : {
612 : : // call parent
613 : 75 : E3dObject::NbcSetTransform(rMatrix);
614 : : }
615 : 75 : }
616 : :
617 : 797 : void E3dScene::SetTransform(const basegfx::B3DHomMatrix& rMatrix)
618 : : {
619 [ + + ]: 797 : if(rMatrix != maTransformation)
620 : : {
621 : : // call parent
622 : 75 : E3dObject::SetTransform(rMatrix);
623 : : }
624 : 797 : }
625 : :
626 : 0 : void E3dScene::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
627 : : {
628 : : // So currently the glue points are defined relative to the scene aOutRect.
629 : : // Before turning the glue points are defined relative to the page. They
630 : : // take no part in the rotation of the scene. To ensure this, there is the
631 : : // SetGlueReallyAbsolute(sal_True);
632 : :
633 : : // So that was the scene, now the objects used in the scene
634 : : // 3D objects, if there is only one it can still have multiple surfaces but
635 : : // the surfaces do not hve to be connected. This allows you to access child
636 : : // objects. So going through the entire list and rotate around the Z axis
637 : : // through the enter of aOutRect's (Steiner's theorem), so RotateZ
638 : :
639 [ # # ]: 0 : RotateScene (rRef, nWink, sn, cs); // Rotates the scene
640 : 0 : double fWinkelInRad = nWink/100 * F_PI180;
641 : :
642 [ # # ]: 0 : basegfx::B3DHomMatrix aRotation;
643 [ # # ]: 0 : aRotation.rotate(0.0, 0.0, fWinkelInRad);
644 [ # # ][ # # ]: 0 : NbcSetTransform(aRotation * GetTransform());
[ # # ][ # # ]
645 : :
646 [ # # ]: 0 : SetRectsDirty(); // This forces a recalculation of all BoundRects
647 [ # # ]: 0 : NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotate the glue points (who still
648 : : // have coordinates relative to the
649 : : // original page)
650 [ # # ]: 0 : SetGlueReallyAbsolute(sal_False); // from now they are again relative to BoundRect (that is defined as aOutRect)
651 [ # # ][ # # ]: 0 : SetRectsDirty();
652 : 0 : }
653 : :
654 : 1443 : void E3dScene::RecalcSnapRect()
655 : : {
656 : 1443 : E3dScene* pScene = GetScene();
657 : :
658 [ + + ]: 1443 : if(pScene == this)
659 : : {
660 : : // The Scene is used as a 2D-Objekt, take the SnapRect from the
661 : : // 2D Display settings
662 : 721 : Camera3D& rCam = (Camera3D&)pScene->GetCamera();
663 : 721 : maSnapRect = rCam.GetDeviceWindow();
664 : : }
665 : : else
666 : : {
667 : : // The Scene itself is a member of another scene, get the SnapRect
668 : : // as a composite object
669 : 722 : E3dObject::RecalcSnapRect();
670 : : }
671 : 1443 : }
672 : :
673 : 0 : sal_Bool E3dScene::IsBreakObjPossible()
674 : : {
675 : : // Break scene, if all members are able to break
676 [ # # ]: 0 : SdrObjListIter a3DIterator(maSubList, IM_DEEPWITHGROUPS);
677 : :
678 [ # # ]: 0 : while ( a3DIterator.IsMore() )
679 : : {
680 [ # # ]: 0 : E3dObject* pObj = (E3dObject*) a3DIterator.Next();
681 : : DBG_ASSERT(pObj->ISA(E3dObject), "only 3D objects are allowed in scenes!");
682 [ # # ][ # # ]: 0 : if(!pObj->IsBreakObjPossible())
683 : 0 : return sal_False;
684 : : }
685 : :
686 : 0 : return sal_True;
687 : : }
688 : :
689 : 0 : basegfx::B2DPolyPolygon E3dScene::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
690 : : {
691 : 0 : return TakeXorPoly();
692 : : }
693 : :
694 : 0 : bool E3dScene::BegCreate(SdrDragStat& rStat)
695 : : {
696 : 0 : rStat.SetOrtho4Possible();
697 [ # # ][ # # ]: 0 : Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
[ # # ]
698 [ # # ]: 0 : aRect1.Justify();
699 : 0 : rStat.SetActionRect(aRect1);
700 [ # # ]: 0 : NbcSetSnapRect(aRect1);
701 : 0 : return sal_True;
702 : : }
703 : :
704 : 0 : bool E3dScene::MovCreate(SdrDragStat& rStat)
705 : : {
706 [ # # ]: 0 : Rectangle aRect1;
707 [ # # ]: 0 : rStat.TakeCreateRect(aRect1);
708 [ # # ]: 0 : aRect1.Justify();
709 : 0 : rStat.SetActionRect(aRect1);
710 [ # # ]: 0 : NbcSetSnapRect(aRect1);
711 [ # # ]: 0 : SetBoundRectDirty();
712 : 0 : bSnapRectDirty=sal_True;
713 : 0 : return sal_True;
714 : : }
715 : :
716 : 0 : bool E3dScene::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
717 : : {
718 [ # # ]: 0 : Rectangle aRect1;
719 [ # # ]: 0 : rStat.TakeCreateRect(aRect1);
720 [ # # ]: 0 : aRect1.Justify();
721 [ # # ]: 0 : NbcSetSnapRect(aRect1);
722 [ # # ]: 0 : SetRectsDirty();
723 [ # # ][ # # ]: 0 : return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
724 : : }
725 : :
726 : 0 : bool E3dScene::BckCreate(SdrDragStat& /*rStat*/)
727 : : {
728 : 0 : return sal_False;
729 : : }
730 : :
731 : 0 : void E3dScene::BrkCreate(SdrDragStat& /*rStat*/)
732 : : {
733 : 0 : }
734 : :
735 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|