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 "svx/svdstr.hrc"
22 : #include "svx/svdglob.hxx"
23 : #include <svx/svdview.hxx>
24 : #include <svx/svdattr.hxx>
25 : #include <svx/svdpage.hxx>
26 : #include <svx/svdmodel.hxx>
27 : #include "svx/svditer.hxx"
28 : #include "svx/globl3d.hxx"
29 : #include <svx/camera3d.hxx>
30 : #include <svx/scene3d.hxx>
31 : #include <svx/polysc3d.hxx>
32 : #include <svx/cube3d.hxx>
33 : #include <svx/lathe3d.hxx>
34 : #include <svx/sphere3d.hxx>
35 : #include <svx/extrud3d.hxx>
36 : #include <svx/obj3d.hxx>
37 : #include <svx/xtable.hxx>
38 : #include <svx/xflclit.hxx>
39 : #include <vcl/svapp.hxx>
40 : #include <vcl/settings.hxx>
41 : #include <svx/xlnclit.hxx>
42 : #include <svl/metitem.hxx>
43 : #include <svx/xfillit.hxx>
44 : #include <svx/xlnwtit.hxx>
45 : #include <vcl/virdev.hxx>
46 : #include <tools/poly.hxx>
47 : #include <tools/b3dtrans.hxx>
48 : #include <svx/svxids.hrc>
49 : #include <editeng/colritem.hxx>
50 : #include <svx/e3ditem.hxx>
51 : #include <svx/xlntrit.hxx>
52 : #include <svx/xfltrit.hxx>
53 : #include <svx/svdpagv.hxx>
54 : #include <vcl/gradient.hxx>
55 : #include <vcl/metaact.hxx>
56 : #include <svx/svx3ditems.hxx>
57 : #include <svl/whiter.hxx>
58 : #include <svtools/colorcfg.hxx>
59 : #include <editeng/eeitem.hxx>
60 : #include <svx/xgrscit.hxx>
61 : #include <svx/sdr/properties/e3dproperties.hxx>
62 : #include <svx/sdr/properties/e3dcompoundproperties.hxx>
63 : #include <basegfx/polygon/b3dpolypolygontools.hxx>
64 : #include <basegfx/point/b3dpoint.hxx>
65 : #include <basegfx/vector/b3dvector.hxx>
66 : #include <svx/xlndsit.hxx>
67 : #include <basegfx/matrix/b3dhommatrix.hxx>
68 : #include <basegfx/polygon/b3dpolygon.hxx>
69 : #include <basegfx/matrix/b2dhommatrix.hxx>
70 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
71 : #include <basegfx/polygon/b3dpolygontools.hxx>
72 : #include <svx/helperhittest3d.hxx>
73 : #include <svx/sdr/contact/viewcontactofe3d.hxx>
74 : #include <drawinglayer/geometry/viewinformation3d.hxx>
75 : #include <com/sun/star/uno/Sequence.h>
76 : #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
77 : #include <svx/e3dsceneupdater.hxx>
78 :
79 : //////////////////////////////////////////////////////////////////////////////
80 :
81 : using namespace com::sun::star;
82 :
83 :
84 : // List for 3D-Objects
85 :
86 0 : TYPEINIT1(E3dObjList, SdrObjList);
87 :
88 0 : E3dObjList::E3dObjList(SdrModel* pNewModel, SdrPage* pNewPage, E3dObjList* pNewUpList)
89 0 : : SdrObjList(pNewModel, pNewPage, pNewUpList)
90 : {
91 0 : }
92 :
93 0 : E3dObjList::E3dObjList(const E3dObjList& rSrcList)
94 0 : : SdrObjList(rSrcList)
95 : {
96 0 : }
97 :
98 0 : E3dObjList::~E3dObjList()
99 : {
100 0 : }
101 :
102 0 : void E3dObjList::NbcInsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason)
103 : {
104 : // Get owner
105 : DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "Insert 3D object in parent != 3DObject");
106 :
107 : // Is it even a 3D object?
108 0 : if(pObj && pObj->ISA(E3dObject))
109 : {
110 : // Normal 3D object, insert means
111 : // call parent
112 0 : SdrObjList::NbcInsertObject(pObj, nPos, pReason);
113 : }
114 : else
115 : {
116 : // No 3D object, inserted a page in place in a scene ...
117 0 : GetOwnerObj()->GetPage()->InsertObject(pObj, nPos);
118 : }
119 0 : }
120 :
121 0 : void E3dObjList::InsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason)
122 : {
123 : OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "Insert 3D object in non-3D Parent");
124 :
125 : // call parent
126 0 : SdrObjList::InsertObject(pObj, nPos, pReason);
127 :
128 0 : E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene();
129 0 : if(pScene)
130 : {
131 0 : pScene->Cleanup3DDepthMapper();
132 : }
133 0 : }
134 :
135 0 : SdrObject* E3dObjList::NbcRemoveObject(sal_uIntPtr nObjNum)
136 : {
137 : DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "Remove 3D object from Parent != 3DObject");
138 :
139 : // call parent
140 0 : SdrObject* pRetval = SdrObjList::NbcRemoveObject(nObjNum);
141 :
142 0 : E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene();
143 0 : if(pScene)
144 : {
145 0 : pScene->Cleanup3DDepthMapper();
146 : }
147 :
148 0 : return pRetval;
149 : }
150 :
151 0 : SdrObject* E3dObjList::RemoveObject(sal_uIntPtr nObjNum)
152 : {
153 : OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "3D object is removed from non-3D Parent");
154 :
155 : // call parent
156 0 : SdrObject* pRetval = SdrObjList::RemoveObject(nObjNum);
157 :
158 0 : E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene();
159 0 : if(pScene)
160 : {
161 0 : pScene->Cleanup3DDepthMapper();
162 : }
163 :
164 0 : return pRetval;
165 : }
166 :
167 : //////////////////////////////////////////////////////////////////////////////
168 :
169 0 : sdr::properties::BaseProperties* E3dObject::CreateObjectSpecificProperties()
170 : {
171 0 : return new sdr::properties::E3dProperties(*this);
172 : }
173 :
174 : //////////////////////////////////////////////////////////////////////////////
175 :
176 68 : TYPEINIT1(E3dObject, SdrAttrObj);
177 :
178 0 : E3dObject::E3dObject()
179 : : maSubList(),
180 : maLocalBoundVol(),
181 : maTransformation(),
182 : maFullTransform(),
183 : mbTfHasChanged(true),
184 0 : mbIsSelected(false)
185 : {
186 0 : bIs3DObj = true;
187 0 : maSubList.SetOwnerObj(this);
188 0 : maSubList.SetListKind(SDROBJLIST_GROUPOBJ);
189 0 : bClosedObj = true;
190 0 : }
191 :
192 0 : E3dObject::~E3dObject()
193 : {
194 0 : }
195 :
196 0 : void E3dObject::SetSelected(bool bNew)
197 : {
198 0 : if((bool)mbIsSelected != bNew)
199 : {
200 0 : mbIsSelected = bNew;
201 : }
202 :
203 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
204 : {
205 0 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
206 :
207 0 : if(pCandidate)
208 : {
209 0 : pCandidate->SetSelected(bNew);
210 : }
211 : }
212 0 : }
213 :
214 : // Break, default implementations
215 :
216 0 : sal_Bool E3dObject::IsBreakObjPossible()
217 : {
218 0 : return sal_False;
219 : }
220 :
221 0 : SdrAttrObj* E3dObject::GetBreakObj()
222 : {
223 0 : return 0L;
224 : }
225 :
226 : // SetRectsDirty must be done through the local SdrSubList
227 :
228 0 : void E3dObject::SetRectsDirty(sal_Bool bNotMyself)
229 : {
230 : // call parent
231 0 : SdrAttrObj::SetRectsDirty(bNotMyself);
232 :
233 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
234 : {
235 0 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
236 :
237 0 : if(pCandidate)
238 : {
239 0 : pCandidate->SetRectsDirty(bNotMyself);
240 : }
241 : }
242 0 : }
243 :
244 0 : sal_uInt32 E3dObject::GetObjInventor() const
245 : {
246 0 : return E3dInventor;
247 : }
248 :
249 0 : sal_uInt16 E3dObject::GetObjIdentifier() const
250 : {
251 0 : return E3D_OBJECT_ID;
252 : }
253 :
254 : // Determine the capabilities of the object
255 :
256 0 : void E3dObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
257 : {
258 0 : rInfo.bResizeFreeAllowed = sal_True;
259 0 : rInfo.bResizePropAllowed = sal_True;
260 0 : rInfo.bRotateFreeAllowed = sal_True;
261 0 : rInfo.bRotate90Allowed = sal_True;
262 0 : rInfo.bMirrorFreeAllowed = sal_False;
263 0 : rInfo.bMirror45Allowed = sal_False;
264 0 : rInfo.bMirror90Allowed = sal_False;
265 0 : rInfo.bShearAllowed = sal_False;
266 0 : rInfo.bEdgeRadiusAllowed = sal_False;
267 0 : rInfo.bCanConvToPath = sal_False;
268 :
269 : // no transparence for 3d objects
270 0 : rInfo.bTransparenceAllowed = sal_False;
271 :
272 : // gradient depends on fillstyle
273 : // BM *** check if SetItem is NULL ***
274 0 : XFillStyle eFillStyle = ((XFillStyleItem&)(GetMergedItem(XATTR_FILLSTYLE))).GetValue();
275 0 : rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
276 :
277 : // Convert 3D objects in a group of polygons:
278 : // At first not only possible, because the creation of a group of
279 : // 2D polygons would be required which need to be sorted by depth,
280 : // ie at intersections be cut relative to each other. Also the texture
281 : // coorinates were an unsolved problem.
282 0 : rInfo.bCanConvToPoly = sal_False;
283 0 : rInfo.bCanConvToContour = sal_False;
284 0 : rInfo.bCanConvToPathLineToArea = sal_False;
285 0 : rInfo.bCanConvToPolyLineToArea = sal_False;
286 0 : }
287 :
288 0 : void E3dObject::NbcSetLayer(SdrLayerID nLayer)
289 : {
290 0 : SdrAttrObj::NbcSetLayer(nLayer);
291 :
292 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
293 : {
294 0 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
295 :
296 0 : if(pCandidate)
297 : {
298 0 : pCandidate->NbcSetLayer(nLayer);
299 : }
300 : }
301 0 : }
302 :
303 : // Set ObjList also on SubList
304 :
305 0 : void E3dObject::SetObjList(SdrObjList* pNewObjList)
306 : {
307 0 : SdrObject::SetObjList(pNewObjList);
308 0 : maSubList.SetUpList(pNewObjList);
309 0 : }
310 :
311 0 : void E3dObject::SetPage(SdrPage* pNewPage)
312 : {
313 0 : SdrAttrObj::SetPage(pNewPage);
314 0 : maSubList.SetPage(pNewPage);
315 0 : }
316 :
317 0 : void E3dObject::SetModel(SdrModel* pNewModel)
318 : {
319 0 : SdrAttrObj::SetModel(pNewModel);
320 0 : maSubList.SetModel(pNewModel);
321 0 : }
322 :
323 : // resize object, used from old 2d interfaces, e.g. in Move/Scale dialog (F4)
324 :
325 0 : void E3dObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
326 : {
327 : // Movement in X, Y in the eye coordinate system
328 0 : E3dScene* pScene = GetScene();
329 :
330 0 : if(pScene)
331 : {
332 : // transform pos from 2D world to 3D eye
333 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
334 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
335 0 : basegfx::B2DPoint aScaleCenter2D((double)rRef.X(), (double)rRef.Y());
336 0 : basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
337 :
338 0 : aInverseSceneTransform.invert();
339 0 : aScaleCenter2D = aInverseSceneTransform * aScaleCenter2D;
340 :
341 0 : basegfx::B3DPoint aScaleCenter3D(aScaleCenter2D.getX(), aScaleCenter2D.getY(), 0.5);
342 0 : basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
343 :
344 0 : aInverseViewToEye.invert();
345 0 : aScaleCenter3D = aInverseViewToEye * aScaleCenter3D;
346 :
347 : // Get scale factors
348 0 : double fScaleX(xFact);
349 0 : double fScaleY(yFact);
350 :
351 : // build transform
352 0 : basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
353 0 : aInverseOrientation.invert();
354 0 : basegfx::B3DHomMatrix mFullTransform(GetFullTransform());
355 0 : basegfx::B3DHomMatrix mTrans(mFullTransform);
356 :
357 0 : mTrans *= aViewInfo3D.getOrientation();
358 0 : mTrans.translate(-aScaleCenter3D.getX(), -aScaleCenter3D.getY(), -aScaleCenter3D.getZ());
359 0 : mTrans.scale(fScaleX, fScaleY, 1.0);
360 0 : mTrans.translate(aScaleCenter3D.getX(), aScaleCenter3D.getY(), aScaleCenter3D.getZ());
361 0 : mTrans *= aInverseOrientation;
362 0 : mFullTransform.invert();
363 0 : mTrans *= mFullTransform;
364 :
365 : // Apply
366 0 : basegfx::B3DHomMatrix mObjTrans(GetTransform());
367 0 : mObjTrans *= mTrans;
368 :
369 0 : E3DModifySceneSnapRectUpdater aUpdater(this);
370 0 : SetTransform(mObjTrans);
371 : }
372 0 : }
373 :
374 :
375 : // Move object in 2D is needed when using cursor keys
376 :
377 0 : void E3dObject::NbcMove(const Size& rSize)
378 : {
379 : // Movement in X, Y in the eye coordinate system
380 0 : E3dScene* pScene = GetScene();
381 :
382 0 : if(pScene)
383 : {
384 : //Dimensions of the scene in 3D and 2D for comparison
385 0 : Rectangle aRect = pScene->GetSnapRect();
386 :
387 0 : basegfx::B3DHomMatrix mInvDispTransform;
388 0 : if(GetParentObj())
389 : {
390 0 : mInvDispTransform = GetParentObj()->GetFullTransform();
391 0 : mInvDispTransform.invert();
392 : }
393 :
394 : // BoundVolume from 3d world to 3d eye
395 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
396 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
397 0 : basegfx::B3DRange aEyeVol(pScene->GetBoundVolume());
398 0 : aEyeVol.transform(aViewInfo3D.getOrientation());
399 :
400 : // build relative movement vector in eye coordinates
401 : basegfx::B3DPoint aMove(
402 0 : (double)rSize.Width() * aEyeVol.getWidth() / (double)aRect.GetWidth(),
403 0 : (double)-rSize.Height() * aEyeVol.getHeight() / (double)aRect.GetHeight(),
404 0 : 0.0);
405 0 : basegfx::B3DPoint aPos(0.0, 0.0, 0.0);
406 :
407 : // movement vector to local coordinates of objects' parent
408 0 : basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
409 0 : aInverseOrientation.invert();
410 0 : basegfx::B3DHomMatrix aCompleteTrans(mInvDispTransform * aInverseOrientation);
411 :
412 0 : aMove = aCompleteTrans * aMove;
413 0 : aPos = aCompleteTrans * aPos;
414 :
415 : // build transformation and apply
416 0 : basegfx::B3DHomMatrix aTranslate;
417 0 : aTranslate.translate(aMove.getX() - aPos.getX(), aMove.getY() - aPos.getY(), aMove.getZ() - aPos.getZ());
418 :
419 0 : E3DModifySceneSnapRectUpdater aUpdater(pScene);
420 0 : SetTransform(aTranslate * GetTransform());
421 : }
422 0 : }
423 :
424 : // Return the sublist, but only if it contains objects!
425 :
426 0 : SdrObjList* E3dObject::GetSubList() const
427 : {
428 0 : return &(const_cast< E3dObjList& >(maSubList));
429 : }
430 :
431 0 : void E3dObject::RecalcSnapRect()
432 : {
433 0 : maSnapRect = Rectangle();
434 :
435 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
436 : {
437 0 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
438 :
439 0 : if(pCandidate)
440 : {
441 0 : maSnapRect.Union(pCandidate->GetSnapRect());
442 : }
443 : }
444 0 : }
445 :
446 : // Inform the parent about insertion of a 3D object, so that the parent is able
447 : // treat the particualar objects in a special way (eg Light / Label in E3dScene)
448 :
449 0 : void E3dObject::NewObjectInserted(const E3dObject* p3DObj)
450 : {
451 0 : if(GetParentObj())
452 0 : GetParentObj()->NewObjectInserted(p3DObj);
453 0 : }
454 :
455 : // Inform parent of changes in the structure (eg by transformation), in this
456 : // process the object in which the change has occurred is returned.
457 :
458 0 : void E3dObject::StructureChanged()
459 : {
460 0 : if ( GetParentObj() )
461 : {
462 0 : GetParentObj()->InvalidateBoundVolume();
463 0 : GetParentObj()->StructureChanged();
464 : }
465 0 : }
466 :
467 0 : void E3dObject::Insert3DObj(E3dObject* p3DObj)
468 : {
469 : DBG_ASSERT(p3DObj, "Insert3DObj with NULL-pointer!");
470 0 : SdrPage* pPg = pPage;
471 0 : maSubList.InsertObject(p3DObj);
472 0 : pPage = pPg;
473 0 : InvalidateBoundVolume();
474 0 : NewObjectInserted(p3DObj);
475 0 : StructureChanged();
476 0 : }
477 :
478 0 : void E3dObject::Remove3DObj(E3dObject* p3DObj)
479 : {
480 : DBG_ASSERT(p3DObj, "Remove3DObj with NULL-pointer!");
481 :
482 0 : if(p3DObj->GetParentObj() == this)
483 : {
484 0 : SdrPage* pPg = pPage;
485 0 : maSubList.RemoveObject(p3DObj->GetOrdNum());
486 0 : pPage = pPg;
487 :
488 0 : InvalidateBoundVolume();
489 0 : StructureChanged();
490 : }
491 0 : }
492 :
493 0 : E3dObject* E3dObject::GetParentObj() const
494 : {
495 0 : E3dObject* pRetval = NULL;
496 :
497 0 : if(GetObjList()
498 0 : && GetObjList()->GetOwnerObj()
499 0 : && GetObjList()->GetOwnerObj()->ISA(E3dObject))
500 0 : pRetval = ((E3dObject*)GetObjList()->GetOwnerObj());
501 0 : return pRetval;
502 : }
503 :
504 : // Determine the top-level scene object
505 :
506 0 : E3dScene* E3dObject::GetScene() const
507 : {
508 0 : if(GetParentObj())
509 0 : return GetParentObj()->GetScene();
510 0 : return NULL;
511 : }
512 :
513 : // Calculate enclosed volume, including all child objects
514 :
515 0 : basegfx::B3DRange E3dObject::RecalcBoundVolume() const
516 : {
517 0 : basegfx::B3DRange aRetval;
518 0 : const sal_uInt32 nObjCnt(maSubList.GetObjCount());
519 :
520 0 : if(nObjCnt)
521 : {
522 0 : for(sal_uInt32 a(0); a < nObjCnt; a++)
523 : {
524 0 : const E3dObject* p3DObject = dynamic_cast< const E3dObject* >(maSubList.GetObj(a));
525 :
526 0 : if(p3DObject)
527 : {
528 0 : basegfx::B3DRange aLocalRange(p3DObject->GetBoundVolume());
529 0 : aLocalRange.transform(p3DObject->GetTransform());
530 0 : aRetval.expand(aLocalRange);
531 : }
532 : }
533 : }
534 : else
535 : {
536 : // single 3D object
537 0 : const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact());
538 :
539 0 : if(pVCOfE3D)
540 : {
541 : // BoundVolume is without 3D object transformation, use correct sequence
542 0 : const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getVIP3DSWithoutObjectTransform());
543 :
544 0 : if(xLocalSequence.hasElements())
545 : {
546 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
547 0 : const drawinglayer::geometry::ViewInformation3D aLocalViewInformation3D(aEmptyParameters);
548 :
549 : aRetval = drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
550 0 : xLocalSequence, aLocalViewInformation3D);
551 0 : }
552 : }
553 : }
554 :
555 0 : return aRetval;
556 : }
557 :
558 : // Get enclosed volume and possibly recalculate it
559 :
560 0 : const basegfx::B3DRange& E3dObject::GetBoundVolume() const
561 : {
562 0 : if(maLocalBoundVol.isEmpty())
563 : {
564 0 : const_cast< E3dObject* >(this)->maLocalBoundVol = RecalcBoundVolume();
565 : }
566 :
567 0 : return maLocalBoundVol;
568 : }
569 :
570 0 : void E3dObject::InvalidateBoundVolume()
571 : {
572 0 : maLocalBoundVol.reset();
573 0 : }
574 :
575 : // Pass on the changes of the BoundVolumes to all child objects
576 :
577 0 : void E3dObject::SetBoundVolInvalid()
578 : {
579 0 : InvalidateBoundVolume();
580 :
581 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
582 : {
583 0 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
584 :
585 0 : if(pCandidate)
586 : {
587 0 : pCandidate->SetBoundVolInvalid();
588 : }
589 : }
590 0 : }
591 :
592 : // Pass on the changes in transformation to all child objects
593 :
594 0 : void E3dObject::SetTransformChanged()
595 : {
596 0 : InvalidateBoundVolume();
597 0 : mbTfHasChanged = true;
598 :
599 0 : for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
600 : {
601 0 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
602 :
603 0 : if(pCandidate)
604 : {
605 0 : pCandidate->SetTransformChanged();
606 : }
607 : }
608 0 : }
609 :
610 : // Define the hierarchical transformation over all Parents, store in
611 : // maFullTransform and return them
612 :
613 0 : const basegfx::B3DHomMatrix& E3dObject::GetFullTransform() const
614 : {
615 0 : if(mbTfHasChanged)
616 : {
617 0 : basegfx::B3DHomMatrix aNewFullTransformation(maTransformation);
618 :
619 0 : if ( GetParentObj() )
620 : {
621 0 : aNewFullTransformation = GetParentObj()->GetFullTransform() * aNewFullTransformation;
622 : }
623 :
624 0 : const_cast< E3dObject* >(this)->maFullTransform = aNewFullTransformation;
625 0 : const_cast< E3dObject* >(this)->mbTfHasChanged = false;
626 : }
627 :
628 0 : return maFullTransform;
629 : }
630 :
631 0 : const basegfx::B3DHomMatrix& E3dObject::GetTransform() const
632 : {
633 0 : return maTransformation;
634 : }
635 :
636 0 : void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix)
637 : {
638 0 : if(maTransformation != rMatrix)
639 : {
640 0 : maTransformation = rMatrix;
641 0 : SetTransformChanged();
642 0 : StructureChanged();
643 : }
644 0 : }
645 :
646 : // Set transformation matrix with repaint broadcast
647 :
648 0 : void E3dObject::SetTransform(const basegfx::B3DHomMatrix& rMatrix)
649 : {
650 0 : if(rMatrix != maTransformation)
651 : {
652 0 : NbcSetTransform(rMatrix);
653 0 : SetChanged();
654 0 : BroadcastObjectChange();
655 0 : if (pUserCall != NULL) pUserCall->Changed(*this, SDRUSERCALL_RESIZE, Rectangle());
656 : }
657 0 : }
658 :
659 0 : basegfx::B3DPolyPolygon E3dObject::CreateWireframe() const
660 : {
661 0 : const basegfx::B3DRange aBoundVolume(GetBoundVolume());
662 0 : return basegfx::tools::createCubePolyPolygonFromB3DRange(aBoundVolume);
663 : }
664 :
665 : // Get the name of the object (singular)
666 :
667 0 : void E3dObject::TakeObjNameSingul(XubString& rName) const
668 : {
669 0 : rName=ImpGetResStr(STR_ObjNameSingulObj3d);
670 :
671 0 : String aName( GetName() );
672 0 : if(aName.Len())
673 : {
674 0 : rName += sal_Unicode(' ');
675 0 : rName += sal_Unicode('\'');
676 0 : rName += aName;
677 0 : rName += sal_Unicode('\'');
678 0 : }
679 0 : }
680 :
681 : // Get the name of the object (plural)
682 :
683 0 : void E3dObject::TakeObjNamePlural(XubString& rName) const
684 : {
685 0 : rName=ImpGetResStr(STR_ObjNamePluralObj3d);
686 0 : }
687 :
688 0 : E3dObject* E3dObject::Clone() const
689 : {
690 0 : return CloneHelper< E3dObject >();
691 : }
692 :
693 0 : E3dObject& E3dObject::operator=(const E3dObject& rObj)
694 : {
695 0 : if( this == &rObj )
696 0 : return *this;
697 0 : SdrObject::operator=(rObj);
698 :
699 0 : const E3dObject& r3DObj = (const E3dObject&) rObj;
700 0 : if (r3DObj.GetSubList())
701 : {
702 0 : maSubList.CopyObjects(*r3DObj.GetSubList());
703 : }
704 :
705 : // BoundVol can be copied since also the children are copied
706 0 : maLocalBoundVol = r3DObj.maLocalBoundVol;
707 0 : maTransformation = r3DObj.maTransformation;
708 :
709 : // Because the parent may have changed, definitely redefine the total
710 : // transformation next time
711 0 : SetTransformChanged();
712 :
713 : // Copy selection status
714 0 : mbIsSelected = r3DObj.mbIsSelected;
715 0 : return *this;
716 : }
717 :
718 0 : SdrObjGeoData *E3dObject::NewGeoData() const
719 : {
720 0 : return new E3DObjGeoData;
721 : }
722 :
723 0 : void E3dObject::SaveGeoData(SdrObjGeoData& rGeo) const
724 : {
725 0 : SdrAttrObj::SaveGeoData (rGeo);
726 :
727 0 : ((E3DObjGeoData &) rGeo).maLocalBoundVol = maLocalBoundVol;
728 0 : ((E3DObjGeoData &) rGeo).maTransformation = maTransformation;
729 0 : }
730 :
731 0 : void E3dObject::RestGeoData(const SdrObjGeoData& rGeo)
732 : {
733 0 : maLocalBoundVol = ((E3DObjGeoData &) rGeo).maLocalBoundVol;
734 0 : E3DModifySceneSnapRectUpdater aUpdater(this);
735 0 : NbcSetTransform(((E3DObjGeoData &) rGeo).maTransformation);
736 0 : SdrAttrObj::RestGeoData (rGeo);
737 0 : }
738 :
739 : // 2D-rotation of a 3D-body, normally this is done by the scene itself.
740 : // This is however a correct implementation, because everything that has
741 : // happened is a rotation around the axis perpendicular to the screen and that
742 : // is regardless of how the scene has been rotated up until now.
743 :
744 0 : void E3dObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
745 : {
746 : // So currently the glue points are defined relative to the scene aOutRect.
747 : // Before turning the glue points are defined relative to the page. They
748 : // take no part in the rotation of the scene. To ensure this, there is the
749 : // SetGlueReallyAbsolute(sal_True);
750 :
751 0 : double fWinkelInRad = nWink/100 * F_PI180;
752 :
753 0 : basegfx::B3DHomMatrix aRotateZ;
754 0 : aRotateZ.rotate(0.0, 0.0, fWinkelInRad);
755 0 : NbcSetTransform(aRotateZ * GetTransform());
756 :
757 0 : SetRectsDirty(); // This forces a recalculation of all BoundRects
758 0 : NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotate the glue points (who still
759 : // have coordinates relative to the
760 : // original page)
761 0 : SetGlueReallyAbsolute(sal_False); // from now they are again relative to BoundRect (that is defined as aOutRect)
762 0 : }
763 :
764 : /*************************************************************************/
765 :
766 : //////////////////////////////////////////////////////////////////////////////
767 :
768 0 : sdr::properties::BaseProperties* E3dCompoundObject::CreateObjectSpecificProperties()
769 : {
770 0 : return new sdr::properties::E3dCompoundProperties(*this);
771 : }
772 :
773 : //////////////////////////////////////////////////////////////////////////////
774 :
775 5633 : TYPEINIT1(E3dCompoundObject, E3dObject);
776 :
777 0 : E3dCompoundObject::E3dCompoundObject()
778 : : E3dObject(),
779 : aMaterialAmbientColor(),
780 : bCreateNormals(false),
781 0 : bCreateTexture(false)
782 : {
783 : // Set defaults
784 0 : E3dDefaultAttributes aDefault;
785 0 : SetDefaultAttributes(aDefault);
786 0 : }
787 :
788 0 : E3dCompoundObject::E3dCompoundObject(E3dDefaultAttributes& rDefault)
789 : : E3dObject(),
790 : aMaterialAmbientColor(),
791 : bCreateNormals(false),
792 0 : bCreateTexture(false)
793 : {
794 : // Set defaults
795 0 : SetDefaultAttributes(rDefault);
796 0 : }
797 :
798 0 : void E3dCompoundObject::SetDefaultAttributes(E3dDefaultAttributes& rDefault)
799 : {
800 : // Set defaults
801 0 : aMaterialAmbientColor = rDefault.GetDefaultAmbientColor();
802 :
803 0 : bCreateNormals = rDefault.GetDefaultCreateNormals();
804 0 : bCreateTexture = rDefault.GetDefaultCreateTexture();
805 0 : }
806 :
807 0 : E3dCompoundObject::~E3dCompoundObject ()
808 : {
809 0 : }
810 :
811 0 : basegfx::B2DPolyPolygon E3dCompoundObject::TakeXorPoly() const
812 : {
813 0 : basegfx::B2DPolyPolygon aRetval;
814 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
815 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
816 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
817 :
818 0 : if(pRootScene)
819 : {
820 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
821 0 : const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe());
822 : aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon,
823 0 : aViewInfo3D.getObjectToView() * GetTransform());
824 0 : aRetval.transform(rVCScene.getObjectTransformation());
825 : }
826 :
827 0 : return aRetval;
828 : }
829 :
830 0 : sal_uInt32 E3dCompoundObject::GetHdlCount() const
831 : {
832 : // 8 corners + 1 E3dVolumeMarker (= Wireframe representation)
833 0 : return 9L;
834 : }
835 :
836 0 : void E3dCompoundObject::AddToHdlList(SdrHdlList& rHdlList) const
837 : {
838 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
839 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
840 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
841 :
842 0 : if(pRootScene)
843 : {
844 0 : const basegfx::B3DRange aBoundVolume(GetBoundVolume());
845 :
846 0 : if(!aBoundVolume.isEmpty())
847 : {
848 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
849 :
850 0 : for(sal_uInt32 a(0); a < 8; a++)
851 : {
852 0 : basegfx::B3DPoint aPos3D;
853 :
854 0 : switch(a)
855 : {
856 0 : case 0 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
857 0 : case 1 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
858 0 : case 2 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
859 0 : case 3 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
860 0 : case 4 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
861 0 : case 5 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
862 0 : case 6 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
863 0 : case 7 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
864 : }
865 :
866 : // to 3d view coor
867 0 : aPos3D *= aViewInfo3D.getObjectToView() * GetTransform();
868 :
869 : // create 2d relative scene
870 0 : basegfx::B2DPoint aPos2D(aPos3D.getX(), aPos3D.getY());
871 :
872 : // to 2d world coor
873 0 : aPos2D *= rVCScene.getObjectTransformation();
874 :
875 0 : rHdlList.AddHdl(new SdrHdl(Point(basegfx::fround(aPos2D.getX()), basegfx::fround(aPos2D.getY())), HDL_BWGT));
876 0 : }
877 : }
878 : }
879 :
880 0 : const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly());
881 :
882 0 : if(aPolyPolygon.count())
883 : {
884 0 : E3dVolumeMarker* pVolMarker = new E3dVolumeMarker(aPolyPolygon);
885 0 : rHdlList.AddHdl(pVolMarker);
886 0 : }
887 0 : }
888 :
889 0 : sal_uInt16 E3dCompoundObject::GetObjIdentifier() const
890 : {
891 0 : return E3D_COMPOUNDOBJ_ID;
892 : }
893 :
894 0 : void E3dCompoundObject::RecalcSnapRect()
895 : {
896 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
897 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
898 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
899 0 : maSnapRect = Rectangle();
900 :
901 0 : if(pRootScene)
902 : {
903 : // get VC of 3D candidate
904 0 : const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact());
905 :
906 0 : if(pVCOfE3D)
907 : {
908 : // get 3D primitive sequence
909 0 : const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getViewIndependentPrimitive3DSequence());
910 :
911 0 : if(xLocalSequence.hasElements())
912 : {
913 : // get BoundVolume
914 : basegfx::B3DRange aBoundVolume(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
915 0 : xLocalSequence, aViewInfo3D));
916 :
917 : // transform bound volume to relative scene coordinates
918 0 : aBoundVolume.transform(aViewInfo3D.getObjectToView());
919 :
920 : // build 2d relative scene range
921 : basegfx::B2DRange aSnapRange(
922 : aBoundVolume.getMinX(), aBoundVolume.getMinY(),
923 0 : aBoundVolume.getMaxX(), aBoundVolume.getMaxY());
924 :
925 : // transform to 2D world coordiantes
926 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
927 0 : aSnapRange.transform(rVCScene.getObjectTransformation());
928 :
929 : // snap to integer
930 : maSnapRect = Rectangle(
931 0 : sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())),
932 0 : sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY())));
933 0 : }
934 : }
935 0 : }
936 0 : }
937 :
938 0 : E3dCompoundObject* E3dCompoundObject::Clone() const
939 : {
940 0 : return CloneHelper< E3dCompoundObject >();
941 : }
942 :
943 : // convert given basegfx::B3DPolyPolygon to screen coor
944 :
945 0 : basegfx::B2DPolyPolygon E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon& rCandidate)
946 : {
947 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
948 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
949 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
950 0 : basegfx::B2DPolyPolygon aRetval;
951 :
952 0 : if(pRootScene)
953 : {
954 : aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate,
955 0 : aViewInfo3D.getObjectToView() * GetTransform());
956 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
957 0 : aRetval.transform(rVCScene.getObjectTransformation());
958 : }
959 :
960 0 : return aRetval;
961 : }
962 :
963 0 : sal_Bool E3dCompoundObject::IsAOrdNumRemapCandidate(E3dScene*& prScene) const
964 : {
965 0 : if(GetObjList()
966 0 : && GetObjList()->GetOwnerObj()
967 0 : && GetObjList()->GetOwnerObj()->ISA(E3dScene))
968 : {
969 0 : prScene = (E3dScene*)GetObjList()->GetOwnerObj();
970 0 : return sal_True;
971 : }
972 :
973 0 : return sal_False;
974 : }
975 :
976 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|