xref: /AOO41X/main/svx/source/engine3d/view3d.cxx (revision 47148b3bc50811ceb41802e4cc50a5db21535900)
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