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 "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 <sdr/properties/e3dproperties.hxx>
62 : #include <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 16401 : TYPEINIT1(E3dObjList, SdrObjList);
87 :
88 5504 : E3dObjList::E3dObjList(SdrModel* pNewModel, SdrPage* pNewPage, E3dObjList* pNewUpList)
89 5504 : : SdrObjList(pNewModel, pNewPage, pNewUpList)
90 : {
91 5504 : }
92 :
93 0 : E3dObjList::E3dObjList(const E3dObjList& rSrcList)
94 0 : : SdrObjList(rSrcList)
95 : {
96 0 : }
97 :
98 5504 : E3dObjList::~E3dObjList()
99 : {
100 5504 : }
101 :
102 5467 : void E3dObjList::NbcInsertObject(SdrObject* pObj, size_t 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 5467 : if(pObj && pObj->ISA(E3dObject))
109 : {
110 : // Normal 3D object, insert means
111 : // call parent
112 5467 : 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 5467 : }
120 :
121 0 : void E3dObjList::InsertObject(SdrObject* pObj, size_t 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 = static_cast<E3dObject*>(GetOwnerObj())->GetScene();
129 0 : if(pScene)
130 : {
131 0 : pScene->Cleanup3DDepthMapper();
132 : }
133 0 : }
134 :
135 3828 : SdrObject* E3dObjList::NbcRemoveObject(size_t nObjNum)
136 : {
137 : DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "Remove 3D object from Parent != 3DObject");
138 :
139 : // call parent
140 3828 : SdrObject* pRetval = SdrObjList::NbcRemoveObject(nObjNum);
141 :
142 3828 : E3dScene* pScene = static_cast<E3dObject*>(GetOwnerObj())->GetScene();
143 3828 : if(pScene)
144 : {
145 3828 : pScene->Cleanup3DDepthMapper();
146 : }
147 :
148 3828 : return pRetval;
149 : }
150 :
151 0 : SdrObject* E3dObjList::RemoveObject(size_t 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 = static_cast<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 2285536 : TYPEINIT1(E3dObject, SdrAttrObj);
177 :
178 5504 : E3dObject::E3dObject()
179 : : maSubList(),
180 : maLocalBoundVol(),
181 : maTransformation(),
182 : maFullTransform(),
183 : mbTfHasChanged(true),
184 5504 : mbIsSelected(false)
185 : {
186 5504 : bIs3DObj = true;
187 5504 : maSubList.SetOwnerObj(this);
188 5504 : maSubList.SetListKind(SDROBJLIST_GROUPOBJ);
189 5504 : bClosedObj = true;
190 5504 : }
191 :
192 5504 : E3dObject::~E3dObject()
193 : {
194 5504 : }
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(size_t 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 : bool E3dObject::IsBreakObjPossible()
217 : {
218 0 : return 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 67816 : void E3dObject::SetRectsDirty(bool bNotMyself)
229 : {
230 : // call parent
231 67816 : SdrAttrObj::SetRectsDirty(bNotMyself);
232 :
233 108612 : for(size_t a = 0; a < maSubList.GetObjCount(); ++a)
234 : {
235 40796 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
236 :
237 40796 : if(pCandidate)
238 : {
239 40796 : pCandidate->SetRectsDirty(bNotMyself);
240 : }
241 : }
242 67816 : }
243 :
244 21768 : sal_uInt32 E3dObject::GetObjInventor() const
245 : {
246 21768 : 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 = true;
259 0 : rInfo.bResizePropAllowed = true;
260 0 : rInfo.bRotateFreeAllowed = true;
261 0 : rInfo.bRotate90Allowed = true;
262 0 : rInfo.bMirrorFreeAllowed = false;
263 0 : rInfo.bMirror45Allowed = false;
264 0 : rInfo.bMirror90Allowed = false;
265 0 : rInfo.bShearAllowed = false;
266 0 : rInfo.bEdgeRadiusAllowed = false;
267 0 : rInfo.bCanConvToPath = false;
268 :
269 : // no transparence for 3d objects
270 0 : rInfo.bTransparenceAllowed = false;
271 :
272 : // gradient depends on fillstyle
273 : // BM *** check if SetItem is NULL ***
274 0 : drawing::FillStyle eFillStyle = static_cast<const XFillStyleItem&>(GetMergedItem(XATTR_FILLSTYLE)).GetValue();
275 0 : rInfo.bGradientAllowed = (eFillStyle == drawing::FillStyle_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 = false;
283 0 : rInfo.bCanConvToContour = false;
284 0 : rInfo.bCanConvToPathLineToArea = false;
285 0 : rInfo.bCanConvToPolyLineToArea = false;
286 0 : }
287 :
288 0 : void E3dObject::NbcSetLayer(SdrLayerID nLayer)
289 : {
290 0 : SdrAttrObj::NbcSetLayer(nLayer);
291 :
292 0 : for(size_t 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 9332 : void E3dObject::SetObjList(SdrObjList* pNewObjList)
306 : {
307 9332 : SdrObject::SetObjList(pNewObjList);
308 9332 : maSubList.SetUpList(pNewObjList);
309 9332 : }
310 :
311 16028 : void E3dObject::SetPage(SdrPage* pNewPage)
312 : {
313 16028 : SdrAttrObj::SetPage(pNewPage);
314 16028 : maSubList.SetPage(pNewPage);
315 16028 : }
316 :
317 5541 : void E3dObject::SetModel(SdrModel* pNewModel)
318 : {
319 5541 : SdrAttrObj::SetModel(pNewModel);
320 5541 : maSubList.SetModel(pNewModel);
321 5541 : }
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 89609 : SdrObjList* E3dObject::GetSubList() const
427 : {
428 89609 : return &(const_cast< E3dObjList& >(maSubList));
429 : }
430 :
431 1369 : void E3dObject::RecalcSnapRect()
432 : {
433 1369 : maSnapRect = Rectangle();
434 :
435 1369 : for(size_t 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 1369 : }
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 110979 : void E3dObject::StructureChanged()
459 : {
460 110979 : if ( GetParentObj() )
461 : {
462 64032 : GetParentObj()->InvalidateBoundVolume();
463 64032 : GetParentObj()->StructureChanged();
464 : }
465 110979 : }
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 759590 : E3dObject* E3dObject::GetParentObj() const
494 : {
495 759590 : E3dObject* pRetval = NULL;
496 :
497 1519180 : if(GetObjList()
498 750613 : && GetObjList()->GetOwnerObj()
499 1510203 : && GetObjList()->GetOwnerObj()->ISA(E3dObject))
500 649546 : pRetval = static_cast<E3dObject*>(GetObjList()->GetOwnerObj());
501 759590 : return pRetval;
502 : }
503 :
504 : // Determine the top-level scene object
505 :
506 41225 : E3dScene* E3dObject::GetScene() const
507 : {
508 41225 : if(GetParentObj())
509 41225 : 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 size_t nObjCnt(maSubList.GetObjCount());
519 :
520 0 : if(nObjCnt)
521 : {
522 0 : for(size_t 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 68924 : void E3dObject::InvalidateBoundVolume()
571 : {
572 68924 : maLocalBoundVol.reset();
573 68924 : }
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(size_t 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 4705 : void E3dObject::SetTransformChanged()
595 : {
596 4705 : InvalidateBoundVolume();
597 4705 : mbTfHasChanged = true;
598 :
599 5878 : for(size_t a = 0; a < maSubList.GetObjCount(); ++a)
600 : {
601 1173 : E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
602 :
603 1173 : if(pCandidate)
604 : {
605 1173 : pCandidate->SetTransformChanged();
606 : }
607 : }
608 4705 : }
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 :
632 3532 : void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix)
633 : {
634 3532 : if(maTransformation != rMatrix)
635 : {
636 3532 : maTransformation = rMatrix;
637 3532 : SetTransformChanged();
638 3532 : StructureChanged();
639 : }
640 3532 : }
641 :
642 : // Set transformation matrix with repaint broadcast
643 :
644 3532 : void E3dObject::SetTransform(const basegfx::B3DHomMatrix& rMatrix)
645 : {
646 3532 : if(rMatrix != maTransformation)
647 : {
648 3532 : NbcSetTransform(rMatrix);
649 3532 : SetChanged();
650 3532 : BroadcastObjectChange();
651 3532 : if (pUserCall != NULL) pUserCall->Changed(*this, SDRUSERCALL_RESIZE, Rectangle());
652 : }
653 3532 : }
654 :
655 0 : basegfx::B3DPolyPolygon E3dObject::CreateWireframe() const
656 : {
657 0 : const basegfx::B3DRange aBoundVolume(GetBoundVolume());
658 0 : return basegfx::tools::createCubePolyPolygonFromB3DRange(aBoundVolume);
659 : }
660 :
661 : // Get the name of the object (singular)
662 :
663 0 : OUString E3dObject::TakeObjNameSingul() const
664 : {
665 0 : OUStringBuffer sName(ImpGetResStr(STR_ObjNameSingulObj3d));
666 :
667 0 : OUString aName(GetName());
668 0 : if (!aName.isEmpty())
669 : {
670 0 : sName.append(' ');
671 0 : sName.append('\'');
672 0 : sName.append(aName);
673 0 : sName.append('\'');
674 : }
675 0 : return sName.makeStringAndClear();
676 : }
677 :
678 : // Get the name of the object (plural)
679 :
680 0 : OUString E3dObject::TakeObjNamePlural() const
681 : {
682 0 : return ImpGetResStr(STR_ObjNamePluralObj3d);
683 : }
684 :
685 0 : E3dObject* E3dObject::Clone() const
686 : {
687 0 : return CloneHelper< E3dObject >();
688 : }
689 :
690 0 : E3dObject& E3dObject::operator=(const E3dObject& rObj)
691 : {
692 0 : if( this == &rObj )
693 0 : return *this;
694 0 : SdrObject::operator=(rObj);
695 :
696 0 : const E3dObject& r3DObj = (const E3dObject&) rObj;
697 0 : if (r3DObj.GetSubList())
698 : {
699 0 : maSubList.CopyObjects(*r3DObj.GetSubList());
700 : }
701 :
702 : // BoundVol can be copied since also the children are copied
703 0 : maLocalBoundVol = r3DObj.maLocalBoundVol;
704 0 : maTransformation = r3DObj.maTransformation;
705 :
706 : // Because the parent may have changed, definitely redefine the total
707 : // transformation next time
708 0 : SetTransformChanged();
709 :
710 : // Copy selection status
711 0 : mbIsSelected = r3DObj.mbIsSelected;
712 0 : return *this;
713 : }
714 :
715 0 : SdrObjGeoData *E3dObject::NewGeoData() const
716 : {
717 0 : return new E3DObjGeoData;
718 : }
719 :
720 0 : void E3dObject::SaveGeoData(SdrObjGeoData& rGeo) const
721 : {
722 0 : SdrAttrObj::SaveGeoData (rGeo);
723 :
724 0 : static_cast<E3DObjGeoData &>(rGeo).maLocalBoundVol = maLocalBoundVol;
725 0 : static_cast<E3DObjGeoData &>(rGeo).maTransformation = maTransformation;
726 0 : }
727 :
728 0 : void E3dObject::RestGeoData(const SdrObjGeoData& rGeo)
729 : {
730 0 : maLocalBoundVol = static_cast<const E3DObjGeoData &>(rGeo).maLocalBoundVol;
731 0 : E3DModifySceneSnapRectUpdater aUpdater(this);
732 0 : NbcSetTransform(static_cast<const E3DObjGeoData &>(rGeo).maTransformation);
733 0 : SdrAttrObj::RestGeoData (rGeo);
734 0 : }
735 :
736 : // 2D-rotation of a 3D-body, normally this is done by the scene itself.
737 : // This is however a correct implementation, because everything that has
738 : // happened is a rotation around the axis perpendicular to the screen and that
739 : // is regardless of how the scene has been rotated up until now.
740 :
741 0 : void E3dObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
742 : {
743 : // So currently the glue points are defined relative to the scene aOutRect.
744 : // Before turning the glue points are defined relative to the page. They
745 : // take no part in the rotation of the scene. To ensure this, there is the
746 : // SetGlueReallyAbsolute(sal_True);
747 :
748 0 : double fWinkelInRad = nWink/100.0 * F_PI180;
749 :
750 0 : basegfx::B3DHomMatrix aRotateZ;
751 0 : aRotateZ.rotate(0.0, 0.0, fWinkelInRad);
752 0 : NbcSetTransform(aRotateZ * GetTransform());
753 :
754 0 : SetRectsDirty(); // This forces a recalculation of all BoundRects
755 0 : NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotate the glue points (who still
756 : // have coordinates relative to the
757 : // original page)
758 0 : SetGlueReallyAbsolute(false); // from now they are again relative to BoundRect (that is defined as aOutRect)
759 0 : }
760 :
761 745 : sdr::properties::BaseProperties* E3dCompoundObject::CreateObjectSpecificProperties()
762 : {
763 745 : return new sdr::properties::E3dCompoundProperties(*this);
764 : }
765 :
766 :
767 :
768 280477 : TYPEINIT1(E3dCompoundObject, E3dObject);
769 :
770 4098 : E3dCompoundObject::E3dCompoundObject()
771 : : E3dObject(),
772 : aMaterialAmbientColor(),
773 : bCreateNormals(false),
774 4098 : bCreateTexture(false)
775 : {
776 : // Set defaults
777 4098 : E3dDefaultAttributes aDefault;
778 4098 : SetDefaultAttributes(aDefault);
779 4098 : }
780 :
781 0 : E3dCompoundObject::E3dCompoundObject(E3dDefaultAttributes& rDefault)
782 : : E3dObject(),
783 : aMaterialAmbientColor(),
784 : bCreateNormals(false),
785 0 : bCreateTexture(false)
786 : {
787 : // Set defaults
788 0 : SetDefaultAttributes(rDefault);
789 0 : }
790 :
791 4098 : void E3dCompoundObject::SetDefaultAttributes(E3dDefaultAttributes& rDefault)
792 : {
793 : // Set defaults
794 4098 : aMaterialAmbientColor = rDefault.GetDefaultAmbientColor();
795 :
796 4098 : bCreateNormals = rDefault.GetDefaultCreateNormals();
797 4098 : bCreateTexture = rDefault.GetDefaultCreateTexture();
798 4098 : }
799 :
800 4098 : E3dCompoundObject::~E3dCompoundObject ()
801 : {
802 4098 : }
803 :
804 0 : basegfx::B2DPolyPolygon E3dCompoundObject::TakeXorPoly() const
805 : {
806 0 : basegfx::B2DPolyPolygon aRetval;
807 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
808 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
809 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
810 :
811 0 : if(pRootScene)
812 : {
813 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
814 0 : const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe());
815 0 : aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon,
816 0 : aViewInfo3D.getObjectToView() * GetTransform());
817 0 : aRetval.transform(rVCScene.getObjectTransformation());
818 : }
819 :
820 0 : return aRetval;
821 : }
822 :
823 0 : sal_uInt32 E3dCompoundObject::GetHdlCount() const
824 : {
825 : // 8 corners + 1 E3dVolumeMarker (= Wireframe representation)
826 0 : return 9L;
827 : }
828 :
829 0 : void E3dCompoundObject::AddToHdlList(SdrHdlList& rHdlList) const
830 : {
831 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
832 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
833 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
834 :
835 0 : if(pRootScene)
836 : {
837 0 : const basegfx::B3DRange aBoundVolume(GetBoundVolume());
838 :
839 0 : if(!aBoundVolume.isEmpty())
840 : {
841 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
842 :
843 0 : for(sal_uInt32 a(0); a < 8; a++)
844 : {
845 0 : basegfx::B3DPoint aPos3D;
846 :
847 0 : switch(a)
848 : {
849 0 : case 0 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
850 0 : case 1 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
851 0 : case 2 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
852 0 : case 3 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
853 0 : case 4 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
854 0 : case 5 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
855 0 : case 6 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
856 0 : case 7 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
857 : }
858 :
859 : // to 3d view coor
860 0 : aPos3D *= aViewInfo3D.getObjectToView() * GetTransform();
861 :
862 : // create 2d relative scene
863 0 : basegfx::B2DPoint aPos2D(aPos3D.getX(), aPos3D.getY());
864 :
865 : // to 2d world coor
866 0 : aPos2D *= rVCScene.getObjectTransformation();
867 :
868 0 : rHdlList.AddHdl(new SdrHdl(Point(basegfx::fround(aPos2D.getX()), basegfx::fround(aPos2D.getY())), HDL_BWGT));
869 0 : }
870 : }
871 : }
872 :
873 0 : const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly());
874 :
875 0 : if(aPolyPolygon.count())
876 : {
877 0 : E3dVolumeMarker* pVolMarker = new E3dVolumeMarker(aPolyPolygon);
878 0 : rHdlList.AddHdl(pVolMarker);
879 0 : }
880 0 : }
881 :
882 0 : sal_uInt16 E3dCompoundObject::GetObjIdentifier() const
883 : {
884 0 : return E3D_COMPOUNDOBJ_ID;
885 : }
886 :
887 3319 : void E3dCompoundObject::RecalcSnapRect()
888 : {
889 3319 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
890 6638 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
891 3319 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
892 3319 : maSnapRect = Rectangle();
893 :
894 3319 : if(pRootScene)
895 : {
896 : // get VC of 3D candidate
897 3319 : const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact());
898 :
899 3319 : if(pVCOfE3D)
900 : {
901 : // get 3D primitive sequence
902 3319 : const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getViewIndependentPrimitive3DSequence());
903 :
904 3319 : if(xLocalSequence.hasElements())
905 : {
906 : // get BoundVolume
907 : basegfx::B3DRange aBoundVolume(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
908 3319 : xLocalSequence, aViewInfo3D));
909 :
910 : // transform bound volume to relative scene coordinates
911 3319 : aBoundVolume.transform(aViewInfo3D.getObjectToView());
912 :
913 : // build 2d relative scene range
914 : basegfx::B2DRange aSnapRange(
915 : aBoundVolume.getMinX(), aBoundVolume.getMinY(),
916 3319 : aBoundVolume.getMaxX(), aBoundVolume.getMaxY());
917 :
918 : // transform to 2D world coordiantes
919 3319 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
920 3319 : aSnapRange.transform(rVCScene.getObjectTransformation());
921 :
922 : // snap to integer
923 : maSnapRect = Rectangle(
924 6638 : sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())),
925 9957 : sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY())));
926 3319 : }
927 : }
928 3319 : }
929 3319 : }
930 :
931 0 : E3dCompoundObject* E3dCompoundObject::Clone() const
932 : {
933 0 : return CloneHelper< E3dCompoundObject >();
934 : }
935 :
936 : // convert given basegfx::B3DPolyPolygon to screen coor
937 :
938 0 : basegfx::B2DPolyPolygon E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon& rCandidate)
939 : {
940 0 : const uno::Sequence< beans::PropertyValue > aEmptyParameters;
941 0 : drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
942 0 : E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
943 0 : basegfx::B2DPolyPolygon aRetval;
944 :
945 0 : if(pRootScene)
946 : {
947 0 : aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate,
948 0 : aViewInfo3D.getObjectToView() * GetTransform());
949 0 : const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
950 0 : aRetval.transform(rVCScene.getObjectTransformation());
951 : }
952 :
953 0 : return aRetval;
954 : }
955 :
956 0 : bool E3dCompoundObject::IsAOrdNumRemapCandidate(E3dScene*& prScene) const
957 : {
958 0 : if(GetObjList()
959 0 : && GetObjList()->GetOwnerObj()
960 0 : && GetObjList()->GetOwnerObj()->ISA(E3dScene))
961 : {
962 0 : prScene = static_cast<E3dScene*>(GetObjList()->GetOwnerObj());
963 0 : return true;
964 : }
965 :
966 0 : return false;
967 651 : }
968 :
969 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|