1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26
27 #include <vcl/wrkwin.hxx>
28 #include <svx/svdogrp.hxx>
29 #include <svx/svdopath.hxx>
30 #include <tools/shl.hxx>
31 #include "svx/svditer.hxx"
32 #include <svx/svdpool.hxx>
33 #include <svx/svdorect.hxx>
34 #include <svx/svdmodel.hxx>
35 #include <svx/svdpagv.hxx>
36 #include <svx/svxids.hrc>
37 #include <editeng/colritem.hxx>
38 #include <svx/xtable.hxx>
39 #include <svx/svdview.hxx>
40 #include <svx/dialogs.hrc>
41 #include <svx/dialmgr.hxx>
42 #include "svx/globl3d.hxx"
43 #include <svx/obj3d.hxx>
44 #include <svx/lathe3d.hxx>
45 #include <svx/sphere3d.hxx>
46 #include <svx/extrud3d.hxx>
47 #include <svx/cube3d.hxx>
48 #include <svx/polysc3d.hxx>
49 #include "dragmt3d.hxx"
50 #include <svx/view3d.hxx>
51 #include <svx/svdundo.hxx>
52 #include <svx/xflclit.hxx>
53 #include <svx/xlnclit.hxx>
54 #include <svx/svdograf.hxx>
55 #include <svx/xbtmpit.hxx>
56 #include <svx/xflbmtit.hxx>
57 #include <basegfx/range/b2drange.hxx>
58 #include <basegfx/polygon/b2dpolygontools.hxx>
59 #include <basegfx/polygon/b2dpolypolygontools.hxx>
60 #include <svx/xlnwtit.hxx>
61 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
62 #include <svx/sdr/overlay/overlaymanager.hxx>
63 #include <svx/sdrpaintwindow.hxx>
64 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
65 #include <drawinglayer/geometry/viewinformation3d.hxx>
66 #include <svx/sdrpagewindow.hxx>
67 #include <svx/sdr/contact/displayinfo.hxx>
68 #include <svx/sdr/contact/objectcontact.hxx>
69 #include <svx/sdr/contact/viewobjectcontact.hxx>
70 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
71 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
72 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
73 #include <basegfx/matrix/b2dhommatrixtools.hxx>
74 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
75
76 #define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
77
78 TYPEINIT1(E3dView, SdrView);
79
80 ////////////////////////////////////////////////////////////////////////////////////////////////////
81 // Migrate Marking
82
83 class Impl3DMirrorConstructOverlay
84 {
85 // The OverlayObjects
86 ::sdr::overlay::OverlayObjectList maObjects;
87
88 // the view
89 const E3dView& mrView;
90
91 // the object count
92 sal_uInt32 mnCount;
93
94 // the unmirrored polygons
95 basegfx::B2DPolyPolygon* mpPolygons;
96
97 // the overlay geometry from selected objects
98 drawinglayer::primitive2d::Primitive2DSequence maFullOverlay;
99
100 public:
101 Impl3DMirrorConstructOverlay(const E3dView& rView);
102 ~Impl3DMirrorConstructOverlay();
103
104 void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB);
105 };
106
Impl3DMirrorConstructOverlay(const E3dView & rView)107 Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView)
108 : maObjects(),
109 mrView(rView),
110 mnCount(rView.GetMarkedObjectCount()),
111 mpPolygons(0),
112 maFullOverlay()
113 {
114 if(mnCount)
115 {
116 if(mrView.IsSolidDragging())
117 {
118 SdrPageView* pPV = rView.GetSdrPageView();
119
120 if(pPV && pPV->PageWindowCount())
121 {
122 sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
123 sdr::contact::DisplayInfo aDisplayInfo;
124
125 // Do not use the last ViewPort set at the OC at the last ProcessDisplay()
126 rOC.resetViewPort();
127
128 for(sal_uInt32 a(0);a < mnCount;a++)
129 {
130 SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
131
132 if(pObject)
133 {
134 sdr::contact::ViewContact& rVC = pObject->GetViewContact();
135 sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rOC);
136
137 const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo));
138 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay, aNewSequence);
139 }
140 }
141 }
142 }
143 else
144 {
145 mpPolygons = new basegfx::B2DPolyPolygon[mnCount];
146
147 for(sal_uInt32 a(0); a < mnCount; a++)
148 {
149 SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
150 mpPolygons[mnCount - (a + 1)] = pObject->TakeXorPoly();
151 }
152 }
153 }
154 }
155
~Impl3DMirrorConstructOverlay()156 Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
157 {
158 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
159 // That destructor calls clear() at the list which removes all objects from the
160 // OverlayManager and deletes them.
161 if(!mrView.IsSolidDragging())
162 {
163 delete[] mpPolygons;
164 }
165 }
166
SetMirrorAxis(Point aMirrorAxisA,Point aMirrorAxisB)167 void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
168 {
169 // get rid of old overlay objects
170 maObjects.clear();
171
172 // create new ones
173 for(sal_uInt32 a(0); a < mrView.PaintWindowCount(); a++)
174 {
175 SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a);
176 ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
177
178 if(pTargetOverlay)
179 {
180 // buld transfoprmation: translate and rotate so that given edge is
181 // on x axis, them mirror in y and translate back
182 const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y());
183 basegfx::B2DHomMatrix aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(
184 -aMirrorAxisA.X(), -aMirrorAxisA.Y()));
185 aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
186 aMatrixTransform.scale(1.0, -1.0);
187 aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX()));
188 aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y());
189
190 if(mrView.IsSolidDragging())
191 {
192 if(maFullOverlay.hasElements())
193 {
194 drawinglayer::primitive2d::Primitive2DSequence aContent(maFullOverlay);
195
196 if(!aMatrixTransform.isIdentity())
197 {
198 // embed in transformation group
199 drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform, aContent));
200 aContent = drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1);
201 }
202
203 // if we have full overlay from selected objects, embed with 50% transparence, the
204 // transformation is added to the OverlayPrimitive2DSequenceObject
205 drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aContent, 0.5));
206 aContent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1);
207
208 sdr::overlay::OverlayPrimitive2DSequenceObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent);
209
210 pTargetOverlay->add(*pNew);
211 maObjects.append(*pNew);
212 }
213 }
214 else
215 {
216 for(sal_uInt32 b(0); b < mnCount; b++)
217 {
218 // apply to polygon
219 basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]);
220 aPolyPolygon.transform(aMatrixTransform);
221
222 ::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
223 aPolyPolygon);
224 pTargetOverlay->add(*pNew);
225 maObjects.append(*pNew);
226 }
227 }
228 }
229 }
230 }
231
232 /*************************************************************************
233 |*
234 |* Konstruktor 1
235 |*
236 \************************************************************************/
237
E3dView(SdrModel * pModel,OutputDevice * pOut)238 E3dView::E3dView(SdrModel* pModel, OutputDevice* pOut) :
239 SdrView(pModel, pOut)
240 {
241 InitView ();
242 }
243
244 /*************************************************************************
245 |*
246 |* DrawMarkedObj ueberladen, da eventuell nur einzelne 3D-Objekte
247 |* gezeichnet werden sollen
248 |*
249 \************************************************************************/
250
DrawMarkedObj(OutputDevice & rOut) const251 void E3dView::DrawMarkedObj(OutputDevice& rOut) const
252 {
253 // Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
254 sal_Bool bSpecialHandling = sal_False;
255 E3dScene *pScene = NULL;
256
257 long nCnt = GetMarkedObjectCount();
258 for(long nObjs = 0;nObjs < nCnt;nObjs++)
259 {
260 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
261 if(pObj && pObj->ISA(E3dCompoundObject))
262 {
263 // zugehoerige Szene
264 pScene = ((E3dCompoundObject*)pObj)->GetScene();
265 if(pScene && !IsObjMarked(pScene))
266 bSpecialHandling = sal_True;
267 }
268 // Alle SelectionFlags zuruecksetzen
269 if(pObj && pObj->ISA(E3dObject))
270 {
271 pScene = ((E3dObject*)pObj)->GetScene();
272 if(pScene)
273 pScene->SetSelected(sal_False);
274 }
275 }
276
277 if(bSpecialHandling)
278 {
279 // SelectionFlag bei allen zu 3D Objekten gehoerigen
280 // Szenen und deren Objekten auf nicht selektiert setzen
281 long nObjs;
282 for(nObjs = 0;nObjs < nCnt;nObjs++)
283 {
284 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
285 if(pObj && pObj->ISA(E3dCompoundObject))
286 {
287 // zugehoerige Szene
288 pScene = ((E3dCompoundObject*)pObj)->GetScene();
289 if(pScene)
290 pScene->SetSelected(sal_False);
291 }
292 }
293
294 // bei allen direkt selektierten Objekten auf selektiert setzen
295 SdrMark* pM = NULL;
296
297 for(nObjs = 0;nObjs < nCnt;nObjs++)
298 {
299 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
300 if(pObj && pObj->ISA(E3dObject))
301 {
302 // Objekt markieren
303 E3dObject* p3DObj = (E3dObject*)pObj;
304 p3DObj->SetSelected(sal_True);
305 pScene = p3DObj->GetScene();
306 pM = GetSdrMarkByIndex(nObjs);
307 }
308 }
309
310 if(pScene)
311 {
312 // code from parent
313 SortMarkedObjects();
314
315 pScene->SetDrawOnlySelected(sal_True);
316 pScene->SingleObjectPainter(rOut); // #110094#-17
317 pScene->SetDrawOnlySelected(sal_False);
318 }
319
320 // SelectionFlag zuruecksetzen
321 for(nObjs = 0;nObjs < nCnt;nObjs++)
322 {
323 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
324 if(pObj && pObj->ISA(E3dCompoundObject))
325 {
326 // zugehoerige Szene
327 pScene = ((E3dCompoundObject*)pObj)->GetScene();
328 if(pScene)
329 pScene->SetSelected(sal_False);
330 }
331 }
332 }
333 else
334 {
335 // call parent
336 SdrExchangeView::DrawMarkedObj(rOut);
337 }
338 }
339
340 /*************************************************************************
341 |*
342 |* Model holen ueberladen, da bei einzelnen 3D Objekten noch eine Szene
343 |* untergeschoben werden muss
344 |*
345 \************************************************************************/
346
GetMarkedObjModel() const347 SdrModel* E3dView::GetMarkedObjModel() const
348 {
349 // Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
350 bool bSpecialHandling(false);
351 const sal_uInt32 nCount(GetMarkedObjectCount());
352 sal_uInt32 nObjs(0);
353 E3dScene *pScene = 0;
354
355 for(nObjs = 0; nObjs < nCount; nObjs++)
356 {
357 const SdrObject* pObj = GetMarkedObjectByIndex(nObjs);
358
359 if(!bSpecialHandling && pObj && pObj->ISA(E3dCompoundObject))
360 {
361 // if the object is selected, but it's scene not,
362 // we need special handling
363 pScene = ((E3dCompoundObject*)pObj)->GetScene();
364
365 if(pScene && !IsObjMarked(pScene))
366 {
367 bSpecialHandling = true;
368 }
369 }
370
371 if(pObj && pObj->ISA(E3dObject))
372 {
373 // reset all selection flags at 3D objects
374 pScene = ((E3dObject*)pObj)->GetScene();
375
376 if(pScene)
377 {
378 pScene->SetSelected(false);
379 }
380 }
381 }
382
383 if(!bSpecialHandling)
384 {
385 // call parent
386 return SdrView::GetMarkedObjModel();
387 }
388
389 SdrModel* pNewModel = 0;
390 Rectangle aSelectedSnapRect;
391
392 // set 3d selection flags at all directly selected objects
393 // and collect SnapRect of selected objects
394 for(nObjs = 0; nObjs < nCount; nObjs++)
395 {
396 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
397
398 if(pObj && pObj->ISA(E3dCompoundObject))
399 {
400 // mark object, but not scenes
401 E3dCompoundObject* p3DObj = (E3dCompoundObject*)pObj;
402 p3DObj->SetSelected(true);
403 aSelectedSnapRect.Union(p3DObj->GetSnapRect());
404 }
405 }
406
407 // create new mark list which contains all indirectly selected3d
408 // scenes as selected objects
409 SdrMarkList aOldML(GetMarkedObjectList());
410 SdrMarkList aNewML;
411 SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess();
412 rCurrentMarkList = aNewML;
413
414 for(nObjs = 0; nObjs < nCount; nObjs++)
415 {
416 SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj();
417
418 if(pObj && pObj->ISA(E3dObject))
419 {
420 pScene = ((E3dObject*)pObj)->GetScene();
421
422 if(pScene && !IsObjMarked(pScene) && GetSdrPageView())
423 {
424 ((E3dView*)this)->MarkObj(pScene, GetSdrPageView(), sal_False, sal_True);
425 }
426 }
427 }
428
429 // call parent. This will copy all scenes and the selection flags at the 3d objectss. So
430 // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes
431 pNewModel = SdrView::GetMarkedObjModel();
432
433 if(pNewModel)
434 {
435 for(sal_uInt16 nPg(0); nPg < pNewModel->GetPageCount(); nPg++)
436 {
437 const SdrPage* pSrcPg=pNewModel->GetPage(nPg);
438 const sal_uInt32 nObAnz(pSrcPg->GetObjCount());
439
440 for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
441 {
442 const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
443
444 if(pSrcOb->ISA(E3dScene))
445 {
446 pScene = (E3dScene*)pSrcOb;
447
448 // delete all not intentionally cloned 3d objects
449 pScene->removeAllNonSelectedObjects();
450
451 // reset select flags and set SnapRect of all selected objects
452 pScene->SetSelected(false);
453 pScene->SetSnapRect(aSelectedSnapRect);
454 }
455 }
456 }
457 }
458
459 // restore old selection
460 rCurrentMarkList = aOldML;
461
462 // model zurueckgeben
463 return pNewModel;
464 }
465
466 /*************************************************************************
467 |*
468 |* Bei Paste muss - falls in eine Scene eingefuegt wird - die
469 |* Objekte der Szene eingefuegt werden, die Szene selbst aber nicht
470 |*
471 \************************************************************************/
472
Paste(const SdrModel & rMod,const Point & rPos,SdrObjList * pLst,sal_uInt32 nOptions)473 sal_Bool E3dView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
474 {
475 sal_Bool bRetval = sal_False;
476
477 // Liste holen
478 Point aPos(rPos);
479 SdrObjList* pDstList = pLst;
480 ImpGetPasteObjList(aPos, pDstList);
481
482 if(!pDstList)
483 return sal_False;
484
485 // Owner der Liste holen
486 SdrObject* pOwner = pDstList->GetOwnerObj();
487 if(pOwner && pOwner->ISA(E3dScene))
488 {
489 E3dScene* pDstScene = (E3dScene*)pOwner;
490 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE));
491
492 // Alle Objekte aus E3dScenes kopieren und direkt einfuegen
493 for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++)
494 {
495 const SdrPage* pSrcPg=rMod.GetPage(nPg);
496 sal_uInt32 nObAnz(pSrcPg->GetObjCount());
497
498 // calculate offset for paste
499 Rectangle aR = pSrcPg->GetAllObjBoundRect();
500 Point aDist(aPos - aR.Center());
501
502 // Unterobjekte von Szenen einfuegen
503 for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
504 {
505 const SdrObject* pSrcOb = pSrcPg->GetObj(nOb);
506 if(pSrcOb->ISA(E3dScene))
507 {
508 E3dScene* pSrcScene = (E3dScene*)pSrcOb;
509 ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist);
510 }
511 }
512 }
513 EndUndo();
514 }
515 else
516 {
517 // call parent
518 bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions);
519 }
520
521 // und Rueckgabewert liefern
522 return bRetval;
523 }
524
525 // #83403# Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
ImpCloneAll3DObjectsToDestScene(E3dScene * pSrcScene,E3dScene * pDstScene,Point)526 sal_Bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point /*aOffset*/)
527 {
528 sal_Bool bRetval(sal_False);
529
530 if(pSrcScene && pDstScene)
531 {
532 const sdr::contact::ViewContactOfE3dScene& rVCSceneDst = static_cast< sdr::contact::ViewContactOfE3dScene& >(pDstScene->GetViewContact());
533 const drawinglayer::geometry::ViewInformation3D aViewInfo3DDst(rVCSceneDst.getViewInformation3D());
534 const sdr::contact::ViewContactOfE3dScene& rVCSceneSrc = static_cast< sdr::contact::ViewContactOfE3dScene& >(pSrcScene->GetViewContact());
535 const drawinglayer::geometry::ViewInformation3D aViewInfo3DSrc(rVCSceneSrc.getViewInformation3D());
536
537 for(sal_uInt32 i(0); i < pSrcScene->GetSubList()->GetObjCount(); i++)
538 {
539 E3dCompoundObject* pCompoundObj = dynamic_cast< E3dCompoundObject* >(pSrcScene->GetSubList()->GetObj(i));
540
541 if(pCompoundObj)
542 {
543 // #116235#
544 E3dCompoundObject* pNewCompoundObj = dynamic_cast< E3dCompoundObject* >(pCompoundObj->Clone());
545
546 if(pNewCompoundObj)
547 {
548 // get dest scene's current range in 3D world coordinates
549 const basegfx::B3DHomMatrix aSceneToWorldTrans(pDstScene->GetFullTransform());
550 basegfx::B3DRange aSceneRange(pDstScene->GetBoundVolume());
551 aSceneRange.transform(aSceneToWorldTrans);
552
553 // get new object's implied object transformation
554 const basegfx::B3DHomMatrix aNewObjectTrans(pNewCompoundObj->GetTransform());
555
556 // get new object's range in 3D world coordinates in dest scene
557 // as if it were already added
558 const basegfx::B3DHomMatrix aObjectToWorldTrans(aSceneToWorldTrans * aNewObjectTrans);
559 basegfx::B3DRange aObjectRange(pNewCompoundObj->GetBoundVolume());
560 aObjectRange.transform(aObjectToWorldTrans);
561
562 // get scale adaption
563 const basegfx::B3DVector aSceneScale(aSceneRange.getRange());
564 const basegfx::B3DVector aObjectScale(aObjectRange.getRange());
565 double fScale(1.0);
566
567 // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
568 // to not change the scene by the inserted object
569 const double fSizeFactor(0.5);
570
571 if(aObjectScale.getX() * fScale > aSceneScale.getX() * fSizeFactor)
572 {
573 const double fObjSize(aObjectScale.getX() * fScale);
574 const double fFactor((aSceneScale.getX() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
575 fScale *= fFactor;
576 }
577
578 if(aObjectScale.getY() * fScale > aSceneScale.getY() * fSizeFactor)
579 {
580 const double fObjSize(aObjectScale.getY() * fScale);
581 const double fFactor((aSceneScale.getY() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
582 fScale *= fFactor;
583 }
584
585 if(aObjectScale.getZ() * fScale > aSceneScale.getZ() * fSizeFactor)
586 {
587 const double fObjSize(aObjectScale.getZ() * fScale);
588 const double fFactor((aSceneScale.getZ() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
589 fScale *= fFactor;
590 }
591
592 // get translation adaption
593 const basegfx::B3DPoint aSceneCenter(aSceneRange.getCenter());
594 const basegfx::B3DPoint aObjectCenter(aObjectRange.getCenter());
595
596 // build full modification transform. The object's transformation
597 // shall be modified, so start at object coordinates; transform to 3d world coor
598 basegfx::B3DHomMatrix aModifyingTransform(aObjectToWorldTrans);
599
600 // translate to absolute center in 3d world coor
601 aModifyingTransform.translate(-aObjectCenter.getX(), -aObjectCenter.getY(), -aObjectCenter.getZ());
602
603 // scale to dest size in 3d world coor
604 aModifyingTransform.scale(fScale, fScale, fScale);
605
606 // translate to dest scene center in 3d world coor
607 aModifyingTransform.translate(aSceneCenter.getX(), aSceneCenter.getY(), aSceneCenter.getZ());
608
609 // transform from 3d world to dest object coordinates
610 basegfx::B3DHomMatrix aWorldToObject(aObjectToWorldTrans);
611 aWorldToObject.invert();
612 aModifyingTransform = aWorldToObject * aModifyingTransform;
613
614 // correct implied object transform by applying changing one in object coor
615 pNewCompoundObj->SetTransform(aModifyingTransform * aNewObjectTrans);
616
617 // fill and insert new object
618 pNewCompoundObj->SetModel(pDstScene->GetModel());
619 pNewCompoundObj->SetPage(pDstScene->GetPage());
620 pNewCompoundObj->NbcSetLayer(pCompoundObj->GetLayer());
621 pNewCompoundObj->NbcSetStyleSheet(pCompoundObj->GetStyleSheet(), sal_True);
622 pDstScene->Insert3DObj(pNewCompoundObj);
623 bRetval = sal_True;
624
625 // Undo anlegen
626 if( GetModel()->IsUndoEnabled() )
627 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj));
628 }
629 }
630 }
631 }
632
633 return bRetval;
634 }
635
636 /*************************************************************************
637 |*
638 |* 3D-Konvertierung moeglich?
639 |*
640 \************************************************************************/
641
IsConvertTo3DObjPossible() const642 sal_Bool E3dView::IsConvertTo3DObjPossible() const
643 {
644 sal_Bool bAny3D(sal_False);
645 sal_Bool bGroupSelected(sal_False);
646 sal_Bool bRetval(sal_True);
647
648 for(sal_uInt32 a=0;!bAny3D && a<GetMarkedObjectCount();a++)
649 {
650 SdrObject *pObj = GetMarkedObjectByIndex(a);
651 if(pObj)
652 {
653 ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected);
654 }
655 }
656
657 bRetval = !bAny3D
658 && (
659 IsConvertToPolyObjPossible(sal_False)
660 || IsConvertToPathObjPossible(sal_False)
661 || IsImportMtfPossible());
662 return bRetval;
663 }
664
ImpIsConvertTo3DPossible(SdrObject * pObj,sal_Bool & rAny3D,sal_Bool & rGroupSelected) const665 void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, sal_Bool& rAny3D,
666 sal_Bool& rGroupSelected) const
667 {
668 if(pObj)
669 {
670 if(pObj->ISA(E3dObject))
671 {
672 rAny3D = sal_True;
673 }
674 else
675 {
676 if(pObj->IsGroupObject())
677 {
678 SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS);
679 while(aIter.IsMore())
680 {
681 SdrObject* pNewObj = aIter.Next();
682 ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected);
683 }
684 rGroupSelected = sal_True;
685 }
686 }
687 }
688 }
689
690 /*************************************************************************
691 |*
692 |* 3D-Konvertierung zu Extrude ausfuehren
693 |*
694 \************************************************************************/
695 #include <editeng/eeitem.hxx>
696
ImpChangeSomeAttributesFor3DConversion(SdrObject * pObj)697 void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject* pObj)
698 {
699 if(pObj->ISA(SdrTextObj))
700 {
701 const SfxItemSet& rSet = pObj->GetMergedItemSet();
702 const SvxColorItem& rTextColorItem = (const SvxColorItem&)rSet.Get(EE_CHAR_COLOR);
703 if(rTextColorItem.GetValue() == RGB_Color(COL_BLACK))
704 {
705 // Bei schwarzen Textobjekten wird die Farbe auf grau gesetzt
706 if(pObj->GetPage())
707 {
708 // #84864# if black is only default attribute from
709 // pattern set it hard so that it is used in undo.
710 pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK), EE_CHAR_COLOR));
711
712 // add undo now
713 if( GetModel()->IsUndoEnabled() )
714 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
715 }
716
717 pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY), EE_CHAR_COLOR));
718 }
719 }
720 }
721
ImpChangeSomeAttributesFor3DConversion2(SdrObject * pObj)722 void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject* pObj)
723 {
724 if(pObj->ISA(SdrPathObj))
725 {
726 const SfxItemSet& rSet = pObj->GetMergedItemSet();
727 sal_Int32 nLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
728 XLineStyle eLineStyle = (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue();
729 XFillStyle eFillStyle = ITEMVALUE(rSet, XATTR_FILLSTYLE, XFillStyleItem);
730
731 if(((SdrPathObj*)pObj)->IsClosed()
732 && eLineStyle == XLINE_SOLID
733 && !nLineWidth
734 && eFillStyle != XFILL_NONE)
735 {
736 if(pObj->GetPage() && GetModel()->IsUndoEnabled() )
737 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
738 pObj->SetMergedItem(XLineStyleItem(XLINE_NONE));
739 pObj->SetMergedItem(XLineWidthItem(0L));
740 }
741 }
742 }
743
ImpCreateSingle3DObjectFlat(E3dScene * pScene,SdrObject * pObj,sal_Bool bExtrude,double fDepth,basegfx::B2DHomMatrix & rLatheMat)744 void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, sal_Bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
745 {
746 // Einzelnes PathObject, dieses umwanden
747 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
748
749 if(pPath)
750 {
751 E3dDefaultAttributes aDefault = Get3DDefaultAttributes();
752 if(bExtrude)
753 aDefault.SetDefaultExtrudeCharacterMode(sal_True);
754 else
755 aDefault.SetDefaultLatheCharacterMode(sal_True);
756
757 // ItemSet des Ursprungsobjektes holen
758 SfxItemSet aSet(pObj->GetMergedItemSet());
759
760 XFillStyle eFillStyle = ITEMVALUE(aSet, XATTR_FILLSTYLE, XFillStyleItem);
761
762 // Linienstil ausschalten
763 aSet.Put(XLineStyleItem(XLINE_NONE));
764
765 // Feststellen, ob ein FILL_Attribut gesetzt ist.
766 if(!pPath->IsClosed() || eFillStyle == XFILL_NONE)
767 {
768 // Das SdrPathObj ist nicht gefuellt, lasse die
769 // vordere und hintere Flaeche weg. Ausserdem ist
770 // eine beidseitige Darstellung notwendig.
771 aDefault.SetDefaultExtrudeCloseFront(sal_False);
772 aDefault.SetDefaultExtrudeCloseBack(sal_False);
773
774 aSet.Put(Svx3DDoubleSidedItem(sal_True));
775
776 // Fuellattribut setzen
777 aSet.Put(XFillStyleItem(XFILL_SOLID));
778
779 // Fuellfarbe muss auf Linienfarbe, da das Objekt vorher
780 // nur eine Linie war
781 Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue();
782 aSet.Put(XFillColorItem(String(), aColorLine));
783 }
784
785 // Neues Extrude-Objekt erzeugen
786 E3dObject* p3DObj = NULL;
787 if(bExtrude)
788 {
789 p3DObj = new E3dExtrudeObj(aDefault, pPath->GetPathPoly(), fDepth);
790 }
791 else
792 {
793 basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly());
794 aPolyPoly2D.transform(rLatheMat);
795 p3DObj = new E3dLatheObj(aDefault, aPolyPoly2D);
796 }
797
798 // Attribute setzen
799 if(p3DObj)
800 {
801 p3DObj->NbcSetLayer(pObj->GetLayer());
802
803 p3DObj->SetMergedItemSet(aSet);
804
805 p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True);
806
807 // Neues 3D-Objekt einfuegen
808 pScene->Insert3DObj(p3DObj);
809 }
810 }
811 }
812
ImpCreate3DObject(E3dScene * pScene,SdrObject * pObj,sal_Bool bExtrude,double fDepth,basegfx::B2DHomMatrix & rLatheMat)813 void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, sal_Bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
814 {
815 if(pObj)
816 {
817 // change text color attribute for not so dark colors
818 if(pObj->IsGroupObject())
819 {
820 SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
821 while(aIter.IsMore())
822 {
823 SdrObject* pGroupMember = aIter.Next();
824 ImpChangeSomeAttributesFor3DConversion(pGroupMember);
825 }
826 }
827 else
828 ImpChangeSomeAttributesFor3DConversion(pObj);
829
830 // convert completely to path objects
831 SdrObject* pNewObj1 = pObj->ConvertToPolyObj(sal_False, sal_False);
832
833 if(pNewObj1)
834 {
835 // change text color attribute for not so dark colors
836 if(pNewObj1->IsGroupObject())
837 {
838 SdrObjListIter aIter(*pNewObj1, IM_DEEPWITHGROUPS);
839 while(aIter.IsMore())
840 {
841 SdrObject* pGroupMember = aIter.Next();
842 ImpChangeSomeAttributesFor3DConversion2(pGroupMember);
843 }
844 }
845 else
846 ImpChangeSomeAttributesFor3DConversion2(pNewObj1);
847
848 // convert completely to path objects
849 SdrObject* pNewObj2 = pObj->ConvertToContourObj(pNewObj1, sal_True);
850
851 if(pNewObj2)
852 {
853 // add all to flat scene
854 if(pNewObj2->IsGroupObject())
855 {
856 SdrObjListIter aIter(*pNewObj2, IM_DEEPWITHGROUPS);
857 while(aIter.IsMore())
858 {
859 SdrObject* pGroupMember = aIter.Next();
860 ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat);
861 }
862 }
863 else
864 ImpCreateSingle3DObjectFlat(pScene, pNewObj2, bExtrude, fDepth, rLatheMat);
865
866 // delete zwi object
867 if(pNewObj2 != pObj && pNewObj2 != pNewObj1 && pNewObj2)
868 SdrObject::Free( pNewObj2 );
869 }
870
871 // delete zwi object
872 if(pNewObj1 != pObj && pNewObj1)
873 SdrObject::Free( pNewObj1 );
874 }
875 }
876 }
877
878 /*************************************************************************
879 |*
880 |* 3D-Konvertierung zu Extrude steuern
881 |*
882 \************************************************************************/
883
ConvertMarkedObjTo3D(sal_Bool bExtrude,basegfx::B2DPoint aPnt1,basegfx::B2DPoint aPnt2)884 void E3dView::ConvertMarkedObjTo3D(sal_Bool bExtrude, basegfx::B2DPoint aPnt1, basegfx::B2DPoint aPnt2)
885 {
886 if(AreObjectsMarked())
887 {
888 // Undo anlegen
889 if(bExtrude)
890 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE));
891 else
892 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE));
893
894 // Neue Szene fuer zu erzeugende 3D-Objekte anlegen
895 E3dScene* pScene = new E3dPolyScene(Get3DDefaultAttributes());
896
897 // Rechteck bestimmen und evtl. korrigieren
898 Rectangle aRect = GetAllMarkedRect();
899 if(aRect.GetWidth() <= 1)
900 aRect.SetSize(Size(500, aRect.GetHeight()));
901 if(aRect.GetHeight() <= 1)
902 aRect.SetSize(Size(aRect.GetWidth(), 500));
903
904 // Tiefe relativ zur Groesse der Selektion bestimmen
905 double fDepth = 0.0;
906 double fRot3D = 0.0;
907 basegfx::B2DHomMatrix aLatheMat;
908
909 if(bExtrude)
910 {
911 double fW = (double)aRect.GetWidth();
912 double fH = (double)aRect.GetHeight();
913 fDepth = sqrt(fW*fW + fH*fH) / 6.0;
914 }
915 if(!bExtrude)
916 {
917 // Transformation fuer Polygone Rotationskoerper erstellen
918 if(aPnt1 != aPnt2)
919 {
920 // Rotation um Kontrollpunkt1 mit eigestelltem Winkel
921 // fuer 3D Koordinaten
922 basegfx::B2DPoint aDiff(aPnt1 - aPnt2);
923 fRot3D = atan2(aDiff.getY(), aDiff.getX()) - F_PI2;
924
925 if(basegfx::fTools::equalZero(fabs(fRot3D)))
926 fRot3D = 0.0;
927
928 if(fRot3D != 0.0)
929 {
930 aLatheMat = basegfx::tools::createRotateAroundPoint(aPnt2, -fRot3D)
931 * aLatheMat;
932 }
933 }
934
935 if(aPnt2.getX() != 0.0)
936 {
937 // Translation auf Y=0 - Achse
938 aLatheMat.translate(-aPnt2.getX(), 0.0);
939 }
940 else
941 {
942 aLatheMat.translate((double)-aRect.Left(), 0.0);
943 }
944
945 // Inverse Matrix bilden, um die Zielausdehnung zu bestimmen
946 basegfx::B2DHomMatrix aInvLatheMat(aLatheMat);
947 aInvLatheMat.invert();
948
949 // SnapRect Ausdehnung mittels Spiegelung an der Rotationsachse
950 // erweitern
951 for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
952 {
953 SdrMark* pMark = GetSdrMarkByIndex(a);
954 SdrObject* pObj = pMark->GetMarkedSdrObj();
955 Rectangle aTurnRect = pObj->GetSnapRect();
956 basegfx::B2DPoint aRot;
957 Point aRotPnt;
958
959 aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top());
960 aRot *= aLatheMat;
961 aRot.setX(-aRot.getX());
962 aRot *= aInvLatheMat;
963 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
964 aRect.Union(Rectangle(aRotPnt, aRotPnt));
965
966 aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom());
967 aRot *= aLatheMat;
968 aRot.setX(-aRot.getX());
969 aRot *= aInvLatheMat;
970 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
971 aRect.Union(Rectangle(aRotPnt, aRotPnt));
972
973 aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top());
974 aRot *= aLatheMat;
975 aRot.setX(-aRot.getX());
976 aRot *= aInvLatheMat;
977 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
978 aRect.Union(Rectangle(aRotPnt, aRotPnt));
979
980 aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom());
981 aRot *= aLatheMat;
982 aRot.setX(-aRot.getX());
983 aRot *= aInvLatheMat;
984 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
985 aRect.Union(Rectangle(aRotPnt, aRotPnt));
986 }
987 }
988
989 // Ueber die Selektion gehen und in 3D wandeln, komplett mit
990 // Umwandeln in SdrPathObject, auch Schriften
991 for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
992 {
993 SdrMark* pMark = GetSdrMarkByIndex(a);
994 SdrObject* pObj = pMark->GetMarkedSdrObj();
995
996 ImpCreate3DObject(pScene, pObj, bExtrude, fDepth, aLatheMat);
997 }
998
999 if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0)
1000 {
1001 // Alle angelegten Objekte Tiefenarrangieren
1002 if(bExtrude)
1003 DoDepthArrange(pScene, fDepth);
1004
1005 // 3D-Objekte auf die Mitte des Gesamtrechtecks zentrieren
1006 basegfx::B3DPoint aCenter(pScene->GetBoundVolume().getCenter());
1007 basegfx::B3DHomMatrix aMatrix;
1008
1009 aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ());
1010 pScene->SetTransform(aMatrix * pScene->GetTransform()); // #112587#
1011
1012 // Szene initialisieren
1013 pScene->NbcSetSnapRect(aRect);
1014 basegfx::B3DRange aBoundVol = pScene->GetBoundVolume();
1015 InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth());
1016
1017 // Szene anstelle des ersten selektierten Objektes einfuegen
1018 // und alle alten Objekte weghauen
1019 SdrObject* pRepObj = GetMarkedObjectByIndex(0);
1020 SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0);
1021 MarkObj(pRepObj, pPV, sal_True);
1022 ReplaceObjectAtView(pRepObj, *pPV, pScene, sal_False);
1023 DeleteMarked();
1024 MarkObj(pScene, pPV);
1025
1026 // Rotationskoerper um Rotationsachse drehen
1027 basegfx::B3DHomMatrix aRotate;
1028
1029 if(!bExtrude && fRot3D != 0.0)
1030 {
1031 aRotate.rotate(0.0, 0.0, fRot3D);
1032 }
1033
1034 // Default-Rotation setzen
1035 {
1036 double XRotateDefault = 20;
1037 aRotate.rotate(DEG2RAD(XRotateDefault), 0.0, 0.0);
1038 }
1039
1040 if(!aRotate.isIdentity())
1041 {
1042 pScene->SetTransform(aRotate * pScene->GetTransform());
1043 }
1044
1045 // SnapRects der Objekte ungueltig
1046 pScene->SetSnapRect(aRect);
1047 }
1048 else
1049 {
1050 // Es wurden keine 3D Objekte erzeugt, schmeiss alles weg
1051 delete pScene;
1052 }
1053
1054 // Undo abschliessen
1055 EndUndo();
1056 }
1057 }
1058
1059 /*************************************************************************
1060 |*
1061 |* Alle enthaltenen Extrude-Objekte Tiefenarrangieren
1062 |*
1063 \************************************************************************/
1064
1065 struct E3dDepthNeighbour
1066 {
1067 E3dDepthNeighbour* mpNext;
1068 E3dExtrudeObj* mpObj;
1069 basegfx::B2DPolyPolygon maPreparedPolyPolygon;
1070
E3dDepthNeighbourE3dDepthNeighbour1071 E3dDepthNeighbour()
1072 : mpNext(0),
1073 mpObj(0),
1074 maPreparedPolyPolygon()
1075 {
1076 }
1077 };
1078
1079 struct E3dDepthLayer
1080 {
1081 E3dDepthLayer* mpDown;
1082 E3dDepthNeighbour* mpNext;
1083
E3dDepthLayerE3dDepthLayer1084 E3dDepthLayer()
1085 : mpDown(0),
1086 mpNext(0)
1087 {
1088 }
1089
~E3dDepthLayerE3dDepthLayer1090 ~E3dDepthLayer()
1091 {
1092 while(mpNext)
1093 {
1094 E3dDepthNeighbour* pSucc = mpNext->mpNext;
1095 delete mpNext;
1096 mpNext = pSucc;
1097 }
1098 }
1099 };
1100
DoDepthArrange(E3dScene * pScene,double fDepth)1101 void E3dView::DoDepthArrange(E3dScene* pScene, double fDepth)
1102 {
1103 if(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1)
1104 {
1105 SdrObjList* pSubList = pScene->GetSubList();
1106 SdrObjListIter aIter(*pSubList, IM_FLAT);
1107 E3dDepthLayer* pBaseLayer = NULL;
1108 E3dDepthLayer* pLayer = NULL;
1109 sal_Int32 nNumLayers = 0;
1110
1111 while(aIter.IsMore())
1112 {
1113 E3dExtrudeObj* pExtrudeObj = dynamic_cast< E3dExtrudeObj* >(aIter.Next());
1114
1115 if(pExtrudeObj)
1116 {
1117 const basegfx::B2DPolyPolygon aExtrudePoly(
1118 basegfx::tools::prepareForPolygonOperation(pExtrudeObj->GetExtrudePolygon()));
1119 const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet();
1120 const XFillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem);
1121 const Color aLocalColor = ((const XFillColorItem&)(rLocalSet.Get(XATTR_FILLCOLOR))).GetColorValue();
1122
1123 // sort in ExtrudeObj
1124 if(pLayer)
1125 {
1126 // do we have overlap with an object of this layer?
1127 bool bOverlap(false);
1128 E3dDepthNeighbour* pAct = pLayer->mpNext;
1129
1130 while(!bOverlap && pAct)
1131 {
1132 // do pAct->mpObj and pExtrudeObj overlap? Check by
1133 // using logical AND clipping
1134 const basegfx::B2DPolyPolygon aAndPolyPolygon(
1135 basegfx::tools::solvePolygonOperationAnd(
1136 aExtrudePoly,
1137 pAct->maPreparedPolyPolygon));
1138
1139 bOverlap = (0 != aAndPolyPolygon.count());
1140
1141 if(bOverlap)
1142 {
1143 // second ciriteria: is another fillstyle or color used?
1144 const SfxItemSet& rCompareSet = pAct->mpObj->GetMergedItemSet();
1145
1146 XFillStyle eCompareFillStyle = ITEMVALUE(rCompareSet, XATTR_FILLSTYLE, XFillStyleItem);
1147
1148 if(eLocalFillStyle == eCompareFillStyle)
1149 {
1150 if(eLocalFillStyle == XFILL_SOLID)
1151 {
1152 Color aCompareColor = ((const XFillColorItem&)(rCompareSet.Get(XATTR_FILLCOLOR))).GetColorValue();
1153
1154 if(aCompareColor == aLocalColor)
1155 {
1156 bOverlap = sal_False;
1157 }
1158 }
1159 else if(eLocalFillStyle == XFILL_NONE)
1160 {
1161 bOverlap = sal_False;
1162 }
1163 }
1164 }
1165
1166 pAct = pAct->mpNext;
1167 }
1168
1169 if(bOverlap)
1170 {
1171 // yes, start a new layer
1172 pLayer->mpDown = new E3dDepthLayer;
1173 pLayer = pLayer->mpDown;
1174 nNumLayers++;
1175 pLayer->mpNext = new E3dDepthNeighbour;
1176 pLayer->mpNext->mpObj = pExtrudeObj;
1177 pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly;
1178 }
1179 else
1180 {
1181 // no, add to current layer
1182 E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour;
1183 pNewNext->mpObj = pExtrudeObj;
1184 pNewNext->maPreparedPolyPolygon = aExtrudePoly;
1185 pNewNext->mpNext = pLayer->mpNext;
1186 pLayer->mpNext = pNewNext;
1187 }
1188 }
1189 else
1190 {
1191 // first layer ever
1192 pBaseLayer = new E3dDepthLayer;
1193 pLayer = pBaseLayer;
1194 nNumLayers++;
1195 pLayer->mpNext = new E3dDepthNeighbour;
1196 pLayer->mpNext->mpObj = pExtrudeObj;
1197 pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly;
1198 }
1199 }
1200 }
1201
1202 // number of layers is done
1203 if(nNumLayers > 1)
1204 {
1205 // need to be arranged
1206 double fMinDepth = fDepth * 0.8;
1207 double fStep = (fDepth - fMinDepth) / (double)nNumLayers;
1208 pLayer = pBaseLayer;
1209
1210 while(pLayer)
1211 {
1212 // move along layer
1213 E3dDepthNeighbour* pAct = pLayer->mpNext;
1214
1215 while(pAct)
1216 {
1217 // adapt extrude value
1218 pAct->mpObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5)));
1219
1220 // next
1221 pAct = pAct->mpNext;
1222 }
1223
1224 // next layer
1225 pLayer = pLayer->mpDown;
1226 fMinDepth += fStep;
1227 }
1228 }
1229
1230 // cleanup
1231 while(pBaseLayer)
1232 {
1233 pLayer = pBaseLayer->mpDown;
1234 delete pBaseLayer;
1235 pBaseLayer = pLayer;
1236 }
1237 }
1238 }
1239
1240 /*************************************************************************
1241 |*
1242 |* Drag beginnen, vorher ggf. Drag-Methode fuer 3D-Objekte erzeugen
1243 |*
1244 \************************************************************************/
1245
BegDragObj(const Point & rPnt,OutputDevice * pOut,SdrHdl * pHdl,short nMinMov,SdrDragMethod * pForcedMeth)1246 sal_Bool E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut,
1247 SdrHdl* pHdl, short nMinMov,
1248 SdrDragMethod* pForcedMeth)
1249 {
1250 if(Is3DRotationCreationActive() && GetMarkedObjectCount())
1251 {
1252 // bestimme alle selektierten Polygone und gebe die gespiegelte Hilfsfigur aus
1253 mpMirrorOverlay->SetMirrorAxis(aRef1, aRef2);
1254 }
1255 else
1256 {
1257 sal_Bool bOwnActionNecessary;
1258 if (pHdl == NULL)
1259 {
1260 bOwnActionNecessary = sal_True;
1261 }
1262 else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl())
1263 {
1264 bOwnActionNecessary = sal_True;
1265 }
1266 else
1267 {
1268 bOwnActionNecessary = sal_False;
1269 }
1270
1271 if(bOwnActionNecessary && GetMarkedObjectCount() >= 1)
1272 {
1273 E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ;
1274 sal_Bool bThereAreRootScenes = sal_False;
1275 sal_Bool bThereAre3DObjects = sal_False;
1276 long nCnt = GetMarkedObjectCount();
1277 for(long nObjs = 0;nObjs < nCnt;nObjs++)
1278 {
1279 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1280 if(pObj)
1281 {
1282 if(pObj->ISA(E3dScene) && ((E3dScene*)pObj)->GetScene() == pObj)
1283 bThereAreRootScenes = sal_True;
1284 if(pObj->ISA(E3dObject))
1285 bThereAre3DObjects = sal_True;
1286 }
1287 }
1288 if( bThereAre3DObjects )
1289 {
1290 eDragHdl = ( pHdl == NULL ? HDL_MOVE : pHdl->GetKind() );
1291 switch ( eDragMode )
1292 {
1293 case SDRDRAG_ROTATE:
1294 case SDRDRAG_SHEAR:
1295 {
1296 switch ( eDragHdl )
1297 {
1298 case HDL_LEFT:
1299 case HDL_RIGHT:
1300 {
1301 eConstraint = E3DDRAG_CONSTR_X;
1302 }
1303 break;
1304
1305 case HDL_UPPER:
1306 case HDL_LOWER:
1307 {
1308 eConstraint = E3DDRAG_CONSTR_Y;
1309 }
1310 break;
1311
1312 case HDL_UPLFT:
1313 case HDL_UPRGT:
1314 case HDL_LWLFT:
1315 case HDL_LWRGT:
1316 {
1317 eConstraint = E3DDRAG_CONSTR_Z;
1318 }
1319 break;
1320 default: break;
1321 }
1322
1323 // die nicht erlaubten Rotationen ausmaskieren
1324 eConstraint = E3dDragConstraint(eConstraint& eDragConstraint);
1325 pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint, IsSolidDragging());
1326 }
1327 break;
1328
1329 case SDRDRAG_MOVE:
1330 {
1331 if(!bThereAreRootScenes)
1332 {
1333 pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint, IsSolidDragging());
1334 }
1335 }
1336 break;
1337
1338 // spaeter mal
1339 case SDRDRAG_MIRROR:
1340 case SDRDRAG_CROOK:
1341 case SDRDRAG_DISTORT:
1342 case SDRDRAG_TRANSPARENCE:
1343 case SDRDRAG_GRADIENT:
1344 default:
1345 {
1346 }
1347 break;
1348 }
1349 }
1350 }
1351 }
1352 return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth);
1353 }
1354
1355 /*************************************************************************
1356 |*
1357 |* Pruefen, obj 3D-Szene markiert ist
1358 |*
1359 \************************************************************************/
1360
HasMarkedScene()1361 sal_Bool E3dView::HasMarkedScene()
1362 {
1363 return (GetMarkedScene() != NULL);
1364 }
1365
1366 /*************************************************************************
1367 |*
1368 |* Pruefen, obj 3D-Szene markiert ist
1369 |*
1370 \************************************************************************/
1371
GetMarkedScene()1372 E3dScene* E3dView::GetMarkedScene()
1373 {
1374 sal_uIntPtr nCnt = GetMarkedObjectCount();
1375
1376 for ( sal_uIntPtr i = 0; i < nCnt; i++ )
1377 if ( GetMarkedObjectByIndex(i)->ISA(E3dScene) )
1378 return (E3dScene*) GetMarkedObjectByIndex(i);
1379
1380 return NULL;
1381 }
1382
1383 /*************************************************************************
1384 |*
1385 |* aktuelles 3D-Zeichenobjekt setzen, dafuer Szene erzeugen
1386 |*
1387 \************************************************************************/
1388
SetCurrent3DObj(E3dObject * p3DObj)1389 E3dScene* E3dView::SetCurrent3DObj(E3dObject* p3DObj)
1390 {
1391 DBG_ASSERT(p3DObj != NULL, "Nana, wer steckt denn hier 'nen NULL-Zeiger rein?");
1392 E3dScene* pScene = NULL;
1393
1394 // get transformed BoundVolume of the object
1395 basegfx::B3DRange aVolume(p3DObj->GetBoundVolume());
1396 aVolume.transform(p3DObj->GetTransform());
1397 double fW(aVolume.getWidth());
1398 double fH(aVolume.getHeight());
1399
1400 Rectangle aRect(0,0, (long) fW, (long) fH);
1401
1402 pScene = new E3dPolyScene(Get3DDefaultAttributes());
1403
1404 InitScene(pScene, fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0));
1405
1406 pScene->Insert3DObj(p3DObj);
1407 pScene->NbcSetSnapRect(aRect);
1408
1409 return pScene;
1410 }
1411
1412 /*************************************************************************
1413 |*
1414 |* neu erzeugte Szene initialisieren
1415 |*
1416 \************************************************************************/
1417
InitScene(E3dScene * pScene,double fW,double fH,double fCamZ)1418 void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ)
1419 {
1420 Camera3D aCam(pScene->GetCamera());
1421
1422 aCam.SetAutoAdjustProjection(sal_False);
1423 aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1424 basegfx::B3DPoint aLookAt;
1425
1426 double fDefaultCamPosZ = GetDefaultCamPosZ();
1427 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1428
1429 aCam.SetPosAndLookAt(aCamPos, aLookAt);
1430 aCam.SetFocalLength(GetDefaultCamFocal());
1431 aCam.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, GetDefaultCamFocal());
1432 pScene->SetCamera(aCam);
1433 }
1434
1435 /*************************************************************************
1436 |*
1437 |* startsequenz fuer die erstellung eines 3D-Rotationskoerpers
1438 |*
1439 \************************************************************************/
1440
Start3DCreation()1441 void E3dView::Start3DCreation()
1442 {
1443 if (GetMarkedObjectCount())
1444 {
1445 // irgendwelche Markierungen ermitteln und ausschalten
1446 //HMHBOOL bVis = IsMarkHdlShown();
1447
1448 //HMHif (bVis) HideMarkHdl();
1449
1450 // bestimme die koordinaten fuer JOEs Mirrorachse
1451 // entgegen der normalen Achse wird diese an die linke Seite des Objektes
1452 // positioniert
1453 long nOutMin = 0;
1454 long nOutMax = 0;
1455 long nMinLen = 0;
1456 long nObjDst = 0;
1457 long nOutHgt = 0;
1458 OutputDevice* pOut = GetFirstOutputDevice(); //GetWin(0);
1459
1460 // erstmal Darstellungsgrenzen bestimmen
1461 if (pOut != NULL)
1462 {
1463 nMinLen = pOut->PixelToLogic(Size(0,50)).Height();
1464 nObjDst = pOut->PixelToLogic(Size(0,20)).Height();
1465
1466 long nDst = pOut->PixelToLogic(Size(0,10)).Height();
1467
1468 nOutMin = -pOut->GetMapMode().GetOrigin().Y();
1469 nOutMax = pOut->GetOutputSize().Height() - 1 + nOutMin;
1470 nOutMin += nDst;
1471 nOutMax -= nDst;
1472
1473 if (nOutMax - nOutMin < nDst)
1474 {
1475 nOutMin += nOutMax + 1;
1476 nOutMin /= 2;
1477 nOutMin -= (nDst + 1) / 2;
1478 nOutMax = nOutMin + nDst;
1479 }
1480
1481 nOutHgt = nOutMax - nOutMin;
1482
1483 long nTemp = nOutHgt / 4;
1484 if (nTemp > nMinLen) nMinLen = nTemp;
1485 }
1486
1487 // und dann die Markierungen oben und unten an das Objekt heften
1488 basegfx::B2DRange aR;
1489 for(sal_uInt32 nMark(0L); nMark < GetMarkedObjectCount(); nMark++)
1490 {
1491 SdrObject* pMark = GetMarkedObjectByIndex(nMark);
1492 basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly());
1493 aR.expand(basegfx::tools::getRange(aXPP));
1494 }
1495
1496 basegfx::B2DPoint aCenter(aR.getCenter());
1497 long nMarkHgt = basegfx::fround(aR.getHeight()) - 1;
1498 long nHgt = nMarkHgt + nObjDst * 2;
1499
1500 if (nHgt < nMinLen) nHgt = nMinLen;
1501
1502 long nY1 = basegfx::fround(aCenter.getY()) - (nHgt + 1) / 2;
1503 long nY2 = nY1 + nHgt;
1504
1505 if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt;
1506 if (pOut)
1507 {
1508 if (nY1 < nOutMin)
1509 {
1510 nY1 = nOutMin;
1511 if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen;
1512 }
1513 if (nY2 > nOutMax)
1514 {
1515 nY2 = nOutMax;
1516 if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen;
1517 }
1518 }
1519
1520 aRef1.X() = basegfx::fround(aR.getMinX()); // Initial Achse um 2/100mm nach links
1521 aRef1.Y() = nY1;
1522 aRef2.X() = aRef1.X();
1523 aRef2.Y() = nY2;
1524
1525 // Markierungen einschalten
1526 SetMarkHandles();
1527
1528 //HMHif (bVis) ShowMarkHdl();
1529 if (AreObjectsMarked()) MarkListHasChanged();
1530
1531 // SpiegelPolygone SOFORT zeigen
1532 const SdrHdlList &aHdlList = GetHdlList();
1533 mpMirrorOverlay = new Impl3DMirrorConstructOverlay(*this);
1534 mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(HDL_REF1)->GetPos(), aHdlList.GetHdl(HDL_REF2)->GetPos());
1535 //CreateMirrorPolygons ();
1536 //ShowMirrorPolygons (aHdlList.GetHdl (HDL_REF1)->GetPos (),
1537 // aHdlList.GetHdl (HDL_REF2)->GetPos ());
1538 }
1539 }
1540
1541 /*************************************************************************
1542 |*
1543 |* was passiert bei einer Mausbewegung, wenn das Objekt erstellt wird ?
1544 |*
1545 \************************************************************************/
1546
MovAction(const Point & rPnt)1547 void E3dView::MovAction(const Point& rPnt)
1548 {
1549 if(Is3DRotationCreationActive())
1550 {
1551 SdrHdl* pHdl = GetDragHdl();
1552
1553 if (pHdl)
1554 {
1555 SdrHdlKind eHdlKind = pHdl->GetKind();
1556
1557 // reagiere nur bei einer spiegelachse
1558 if ((eHdlKind == HDL_REF1) ||
1559 (eHdlKind == HDL_REF2) ||
1560 (eHdlKind == HDL_MIRX))
1561 {
1562 const SdrHdlList &aHdlList = GetHdlList ();
1563
1564 // loesche das gespiegelte Polygon, spiegele das Original und zeichne es neu
1565 //ShowMirrored ();
1566 SdrView::MovAction (rPnt);
1567 mpMirrorOverlay->SetMirrorAxis(
1568 aHdlList.GetHdl (HDL_REF1)->GetPos(),
1569 aHdlList.GetHdl (HDL_REF2)->GetPos());
1570 }
1571 }
1572 else
1573 {
1574 SdrView::MovAction (rPnt);
1575 }
1576 }
1577 else
1578 {
1579 SdrView::MovAction (rPnt);
1580 }
1581 }
1582
1583 /*************************************************************************
1584 |*
1585 |* Schluss. Objekt und evtl. Unterobjekte ueber ImpCreate3DLathe erstellen
1586 |* [FG] Mit dem Parameterwert sal_True (SDefault: sal_False) wird einfach ein
1587 |* Rotationskoerper erzeugt, ohne den Benutzer die Lage der
1588 |* Achse fetlegen zu lassen. Es reicht dieser Aufruf, falls
1589 |* ein Objekt selektiert ist. (keine Initialisierung noetig)
1590 |*
1591 \************************************************************************/
1592
End3DCreation(sal_Bool bUseDefaultValuesForMirrorAxes)1593 void E3dView::End3DCreation(sal_Bool bUseDefaultValuesForMirrorAxes)
1594 {
1595 ResetCreationActive();
1596
1597 if(AreObjectsMarked())
1598 {
1599 if(bUseDefaultValuesForMirrorAxes)
1600 {
1601 Rectangle aRect = GetAllMarkedRect();
1602 if(aRect.GetWidth() <= 1)
1603 aRect.SetSize(Size(500, aRect.GetHeight()));
1604 if(aRect.GetHeight() <= 1)
1605 aRect.SetSize(Size(aRect.GetWidth(), 500));
1606
1607 basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top());
1608 basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom());
1609
1610 ConvertMarkedObjTo3D(sal_False, aPnt1, aPnt2);
1611 }
1612 else
1613 {
1614 // Hilfsfigur ausschalten
1615 // bestimme aus den Handlepositionen und den Versatz der Punkte
1616 const SdrHdlList &aHdlList = GetHdlList();
1617 Point aMirrorRef1 = aHdlList.GetHdl(HDL_REF1)->GetPos();
1618 Point aMirrorRef2 = aHdlList.GetHdl(HDL_REF2)->GetPos();
1619
1620 basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y());
1621 basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y());
1622
1623 ConvertMarkedObjTo3D(sal_False, aPnt1, aPnt2);
1624 }
1625 }
1626 }
1627
1628 /*************************************************************************
1629 |*
1630 |* Destruktor
1631 |*
1632 \************************************************************************/
1633
~E3dView()1634 E3dView::~E3dView ()
1635 {
1636 }
1637
1638 /*************************************************************************
1639 |*
1640 |* beende das erzeugen und loesche die polygone
1641 |*
1642 \************************************************************************/
1643
ResetCreationActive()1644 void E3dView::ResetCreationActive ()
1645 {
1646 if(mpMirrorOverlay)
1647 {
1648 delete mpMirrorOverlay;
1649 mpMirrorOverlay = 0L;
1650 }
1651 }
1652
1653 /*************************************************************************
1654 |*
1655 |* Klasse initialisieren
1656 |*
1657 \************************************************************************/
1658
InitView()1659 void E3dView::InitView ()
1660 {
1661 eDragConstraint = E3DDRAG_CONSTR_XYZ;
1662 fDefaultScaleX =
1663 fDefaultScaleY =
1664 fDefaultScaleZ = 1.0;
1665 fDefaultRotateX =
1666 fDefaultRotateY =
1667 fDefaultRotateZ = 0.0;
1668 fDefaultExtrusionDeepth = 1000; // old: 2000;
1669 fDefaultLightIntensity = 0.8; // old: 0.6;
1670 fDefaultAmbientIntensity = 0.4;
1671 nHDefaultSegments = 12;
1672 nVDefaultSegments = 12;
1673 aDefaultLightColor = RGB_Color(COL_WHITE);
1674 aDefaultAmbientColor = RGB_Color(COL_BLACK);
1675 bDoubleSided = sal_False;
1676 mpMirrorOverlay = 0L;
1677 }
1678
1679 /*************************************************************************
1680 |*
1681 |* Koennen die selektierten Objekte aufgebrochen werden?
1682 |*
1683 \************************************************************************/
1684
IsBreak3DObjPossible() const1685 sal_Bool E3dView::IsBreak3DObjPossible() const
1686 {
1687 sal_uIntPtr nCount = GetMarkedObjectCount();
1688
1689 if (nCount > 0)
1690 {
1691 sal_uIntPtr i = 0;
1692
1693 while (i < nCount)
1694 {
1695 SdrObject* pObj = GetMarkedObjectByIndex(i);
1696
1697 if (pObj && pObj->ISA(E3dObject))
1698 {
1699 if(!(((E3dObject*)pObj)->IsBreakObjPossible()))
1700 return sal_False;
1701 }
1702 else
1703 {
1704 return sal_False;
1705 }
1706
1707 i++;
1708 }
1709 }
1710 else
1711 {
1712 return sal_False;
1713 }
1714
1715 return sal_True;
1716 }
1717
1718 /*************************************************************************
1719 |*
1720 |* Selektierte Lathe-Objekte aufbrechen
1721 |*
1722 \************************************************************************/
1723
Break3DObj()1724 void E3dView::Break3DObj()
1725 {
1726 if(IsBreak3DObjPossible())
1727 {
1728 // ALLE selektierten Objekte werden gewandelt
1729 sal_uInt32 nCount = GetMarkedObjectCount();
1730
1731 BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE)));
1732 for(sal_uInt32 a=0;a<nCount;a++)
1733 {
1734 E3dObject* pObj = (E3dObject*)GetMarkedObjectByIndex(a);
1735 BreakSingle3DObj(pObj);
1736 }
1737 DeleteMarked();
1738 EndUndo();
1739 }
1740 }
1741
BreakSingle3DObj(E3dObject * pObj)1742 void E3dView::BreakSingle3DObj(E3dObject* pObj)
1743 {
1744 if(pObj->ISA(E3dScene))
1745 {
1746 SdrObjList* pSubList = pObj->GetSubList();
1747 SdrObjListIter aIter(*pSubList, IM_FLAT);
1748
1749 while(aIter.IsMore())
1750 {
1751 E3dObject* pSubObj = (E3dObject*)aIter.Next();
1752 BreakSingle3DObj(pSubObj);
1753 }
1754 }
1755 else
1756 {
1757 SdrAttrObj* pNewObj = pObj->GetBreakObj();
1758 if(pNewObj)
1759 {
1760 InsertObjectAtView(pNewObj, *GetSdrPageView(), SDRINSERT_DONTMARK);
1761 pNewObj->SetChanged();
1762 pNewObj->BroadcastObjectChange();
1763 }
1764 }
1765 }
1766
1767 /*************************************************************************
1768 |*
1769 |* Szenen mischen
1770 |*
1771 \************************************************************************/
1772
MergeScenes()1773 void E3dView::MergeScenes ()
1774 {
1775 sal_uIntPtr nCount = GetMarkedObjectCount();
1776
1777 if (nCount > 0)
1778 {
1779 sal_uIntPtr nObj = 0;
1780 SdrObject *pObj = GetMarkedObjectByIndex(nObj);
1781 E3dScene *pScene = new E3dPolyScene(Get3DDefaultAttributes());
1782 basegfx::B3DRange aBoundVol;
1783 Rectangle aAllBoundRect (GetMarkedObjBoundRect ());
1784 Point aCenter (aAllBoundRect.Center());
1785
1786 while (pObj)
1787 {
1788 if (pObj->ISA(E3dScene))
1789 {
1790 /**********************************************************
1791 * Es ist eine 3D-Scene oder 3D-PolyScene
1792 **********************************************************/
1793 SdrObjList* pSubList = ((E3dObject*) pObj)->GetSubList();
1794
1795 SdrObjListIter aIter(*pSubList, IM_FLAT);
1796
1797 while (aIter.IsMore())
1798 {
1799 /******************************************************
1800 * LatheObjekte suchen
1801 ******************************************************/
1802 SdrObject* pSubObj = aIter.Next();
1803
1804 E3dObject *pNewObj = 0;
1805
1806 switch (pSubObj->GetObjIdentifier())
1807 {
1808 case E3D_CUBEOBJ_ID :
1809 pNewObj = new E3dCubeObj;
1810 *(E3dCubeObj*)pNewObj = *(E3dCubeObj*)pSubObj;
1811 break;
1812
1813 case E3D_SPHEREOBJ_ID:
1814 pNewObj = new E3dSphereObj;
1815 *(E3dSphereObj*)pNewObj = *(E3dSphereObj*)pSubObj;
1816 break;
1817
1818 case E3D_EXTRUDEOBJ_ID:
1819 pNewObj = new E3dExtrudeObj;
1820 *(E3dExtrudeObj*)pNewObj = *(E3dExtrudeObj*)pSubObj;
1821 break;
1822
1823 case E3D_LATHEOBJ_ID:
1824 pNewObj = new E3dLatheObj;
1825 *(E3dLatheObj*)pNewObj = *(E3dLatheObj*)pSubObj;
1826 break;
1827
1828 case E3D_COMPOUNDOBJ_ID:
1829 pNewObj = new E3dCompoundObject;
1830 *(E3dCompoundObject*)pNewObj = *(E3dCompoundObject*)pSubObj;
1831 break;
1832 }
1833
1834 Rectangle aBoundRect = pSubObj->GetCurrentBoundRect();
1835
1836 basegfx::B3DHomMatrix aMatrix;
1837 aMatrix.translate(aBoundRect.Left() - aCenter.getX(), aCenter.getY(), 0.0);
1838 pNewObj->SetTransform(aMatrix * pNewObj->GetTransform()); // #112587#
1839
1840 if (pNewObj) aBoundVol.expand(pNewObj->GetBoundVolume());
1841 pScene->Insert3DObj (pNewObj);
1842 }
1843 }
1844
1845 nObj++;
1846
1847 if (nObj < nCount)
1848 {
1849 pObj = GetMarkedObjectByIndex(nObj);
1850 }
1851 else
1852 {
1853 pObj = NULL;
1854 }
1855 }
1856
1857 double fW = aAllBoundRect.GetWidth();
1858 double fH = aAllBoundRect.GetHeight();
1859 Rectangle aRect(0,0, (long) fW, (long) fH);
1860
1861 InitScene(pScene, fW, fH, aBoundVol.getMaxZ() + + ((fW + fH) / 4.0));
1862 pScene->NbcSetSnapRect(aRect);
1863
1864 Camera3D &aCamera = (Camera3D&) pScene->GetCamera ();
1865 basegfx::B3DPoint aMinVec(aBoundVol.getMinimum());
1866 basegfx::B3DPoint aMaxVec(aBoundVol.getMaximum());
1867 double fDeepth(fabs(aMaxVec.getZ() - aMinVec.getZ()));
1868
1869 aCamera.SetPRP(basegfx::B3DPoint(0.0, 0.0, 1000.0));
1870 double fDefaultCamPosZ(GetDefaultCamPosZ());
1871 aCamera.SetPosition(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ + fDeepth / 2.0));
1872 aCamera.SetFocalLength(GetDefaultCamFocal());
1873 pScene->SetCamera (aCamera);
1874
1875 // SnapRects der Objekte ungueltig
1876 pScene->SetRectsDirty();
1877
1878 InsertObjectAtView(pScene, *(GetSdrPageViewOfMarkedByIndex(0)));
1879
1880 // SnapRects der Objekte ungueltig
1881 pScene->SetRectsDirty();
1882 }
1883 }
1884
1885 /*************************************************************************
1886 |*
1887 |* Possibilities, hauptsaechlich gruppieren/ungruppieren
1888 |*
1889 \************************************************************************/
CheckPossibilities()1890 void E3dView::CheckPossibilities()
1891 {
1892 // call parent
1893 SdrView::CheckPossibilities();
1894
1895 // Weitere Flags bewerten
1896 if(bGroupPossible || bUnGroupPossible || bGrpEnterPossible)
1897 {
1898 sal_Int32 nMarkCnt = GetMarkedObjectCount();
1899 sal_Bool bCoumpound = sal_False;
1900 sal_Bool b3DObject = sal_False;
1901 for(sal_Int32 nObjs = 0L; (nObjs < nMarkCnt) && !bCoumpound; nObjs++)
1902 {
1903 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1904 if(pObj && pObj->ISA(E3dCompoundObject))
1905 bCoumpound = sal_True;
1906 if(pObj && pObj->ISA(E3dObject))
1907 b3DObject = sal_True;
1908 }
1909
1910 // Bisher: Es sind ZWEI oder mehr beliebiger Objekte selektiert.
1911 // Nachsehen, ob CompoundObjects beteiligt sind. Falls ja,
1912 // das Gruppieren verbieten.
1913 if(bGroupPossible && bCoumpound)
1914 bGroupPossible = sal_False;
1915
1916 if(bUnGroupPossible && b3DObject)
1917 bUnGroupPossible = sal_False;
1918
1919 if(bGrpEnterPossible && bCoumpound)
1920 bGrpEnterPossible = sal_False;
1921 }
1922 }
1923
1924 // eof
1925