merge the formfield patch from ooo-build
[ooovba.git] / svx / source / engine3d / view3d.cxx
blob06eb51299663f59b68da330c7b5517709c9691ee
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: view3d.cxx,v $
10 * $Revision: 1.32.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <vcl/wrkwin.hxx>
35 #include <svx/svdogrp.hxx>
36 #include <svx/svdopath.hxx>
37 #include <tools/shl.hxx>
38 #include "svditer.hxx"
39 #include <svx/svdpool.hxx>
40 #include <svx/svdorect.hxx>
41 #include <svx/svdmodel.hxx>
42 #include <svx/svdpagv.hxx>
43 #include <svx/svxids.hrc>
44 #include <svx/colritem.hxx>
45 #include <svx/xtable.hxx>
46 #include <svx/svdview.hxx>
47 #include <svx/dialogs.hrc>
48 #include <svx/dialmgr.hxx>
49 #include "globl3d.hxx"
50 #include <svx/obj3d.hxx>
51 #include <svx/lathe3d.hxx>
52 #include <svx/sphere3d.hxx>
53 #include <svx/extrud3d.hxx>
54 #include <svx/cube3d.hxx>
55 #include <svx/polysc3d.hxx>
56 #include "dragmt3d.hxx"
57 #include <svx/view3d.hxx>
58 #include <svx/svdundo.hxx>
59 #include <svx/xflclit.hxx>
60 #include <svx/xlnclit.hxx>
61 #include <svx/svdograf.hxx>
62 #include <svx/xbtmpit.hxx>
63 #include <svx/xflbmtit.hxx>
64 #include <basegfx/range/b2drange.hxx>
65 #include <basegfx/polygon/b2dpolygontools.hxx>
66 #include <basegfx/polygon/b2dpolypolygontools.hxx>
67 #include <svx/xlnwtit.hxx>
68 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
69 #include <svx/sdr/overlay/overlaymanager.hxx>
70 #include <sdrpaintwindow.hxx>
71 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
72 #include <drawinglayer/geometry/viewinformation3d.hxx>
73 #include <svx/sdrpagewindow.hxx>
74 #include <svx/sdr/contact/displayinfo.hxx>
75 #include <svx/sdr/contact/objectcontact.hxx>
76 #include <svx/sdr/contact/viewobjectcontact.hxx>
77 #include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
78 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
79 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
81 #define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
83 TYPEINIT1(E3dView, SdrView);
85 ////////////////////////////////////////////////////////////////////////////////////////////////////
86 // Migrate Marking
88 class Impl3DMirrorConstructOverlay
90 // The OverlayObjects
91 ::sdr::overlay::OverlayObjectList maObjects;
93 // the view
94 const E3dView& mrView;
96 // the object count
97 sal_uInt32 mnCount;
99 // the unmirrored polygons
100 basegfx::B2DPolyPolygon* mpPolygons;
102 // the overlay geometry from selected objects
103 drawinglayer::primitive2d::Primitive2DSequence maFullOverlay;
105 public:
106 Impl3DMirrorConstructOverlay(const E3dView& rView);
107 ~Impl3DMirrorConstructOverlay();
109 void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB);
112 Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView)
113 : maObjects(),
114 mrView(rView),
115 mnCount(rView.GetMarkedObjectCount()),
116 mpPolygons(0),
117 maFullOverlay()
119 if(mnCount)
121 if(mrView.IsSolidDragging())
123 SdrPageView* pPV = rView.GetSdrPageView();
125 if(pPV && pPV->PageWindowCount())
127 sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
128 sdr::contact::DisplayInfo aDisplayInfo;
130 // Do not use the last ViewPort set at the OC at the last ProcessDisplay()
131 rOC.resetViewPort();
133 for(sal_uInt32 a(0);a < mnCount;a++)
135 SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
137 if(pObject)
139 sdr::contact::ViewContact& rVC = pObject->GetViewContact();
140 sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rOC);
142 const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo));
143 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay, aNewSequence);
148 else
150 mpPolygons = new basegfx::B2DPolyPolygon[mnCount];
152 for(sal_uInt32 a(0); a < mnCount; a++)
154 SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
155 mpPolygons[mnCount - (a + 1)] = pObject->TakeXorPoly();
161 Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
163 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
164 // That destructor calls clear() at the list which removes all objects from the
165 // OverlayManager and deletes them.
166 if(!mrView.IsSolidDragging())
168 delete[] mpPolygons;
172 void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
174 // get rid of old overlay objects
175 maObjects.clear();
177 // create new ones
178 for(sal_uInt32 a(0); a < mrView.PaintWindowCount(); a++)
180 SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a);
181 ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
183 if(pTargetOverlay)
185 // buld transfoprmation: translate and rotate so that given edge is
186 // on x axis, them mirror in y and translate back
187 const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y());
188 basegfx::B2DHomMatrix aMatrixTransform;
190 aMatrixTransform.translate(-aMirrorAxisA.X(), -aMirrorAxisA.Y());
191 aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
192 aMatrixTransform.scale(1.0, -1.0);
193 aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX()));
194 aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y());
196 if(mrView.IsSolidDragging())
198 if(maFullOverlay.hasElements())
200 drawinglayer::primitive2d::Primitive2DSequence aContent(maFullOverlay);
202 if(!aMatrixTransform.isIdentity())
204 // embed in transformation group
205 drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform, aContent));
206 aContent = drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1);
209 // if we have full overlay from selected objects, embed with 50% transparence, the
210 // transformation is added to the OverlayPrimitive2DSequenceObject
211 drawinglayer::primitive2d::Primitive2DReference aUnifiedAlphaPrimitive2D(new drawinglayer::primitive2d::UnifiedAlphaPrimitive2D(aContent, 0.5));
212 aContent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedAlphaPrimitive2D, 1);
214 sdr::overlay::OverlayPrimitive2DSequenceObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent);
216 pTargetOverlay->add(*pNew);
217 maObjects.append(*pNew);
220 else
222 for(sal_uInt32 b(0); b < mnCount; b++)
224 // apply to polygon
225 basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]);
226 aPolyPolygon.transform(aMatrixTransform);
228 ::sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(aPolyPolygon);
229 pTargetOverlay->add(*pNew);
230 maObjects.append(*pNew);
237 /*************************************************************************
239 |* Konstruktor 1
241 \************************************************************************/
243 E3dView::E3dView(SdrModel* pModel, OutputDevice* pOut) :
244 SdrView(pModel, pOut)
246 InitView ();
249 /*************************************************************************
251 |* DrawMarkedObj ueberladen, da eventuell nur einzelne 3D-Objekte
252 |* gezeichnet werden sollen
254 \************************************************************************/
256 void E3dView::DrawMarkedObj(OutputDevice& rOut) const
258 // Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
259 BOOL bSpecialHandling = FALSE;
260 E3dScene *pScene = NULL;
262 long nCnt = GetMarkedObjectCount();
263 for(long nObjs = 0;nObjs < nCnt;nObjs++)
265 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
266 if(pObj && pObj->ISA(E3dCompoundObject))
268 // zugehoerige Szene
269 pScene = ((E3dCompoundObject*)pObj)->GetScene();
270 if(pScene && !IsObjMarked(pScene))
271 bSpecialHandling = TRUE;
273 // Alle SelectionFlags zuruecksetzen
274 if(pObj && pObj->ISA(E3dObject))
276 pScene = ((E3dObject*)pObj)->GetScene();
277 if(pScene)
278 pScene->SetSelected(FALSE);
282 if(bSpecialHandling)
284 // SelectionFlag bei allen zu 3D Objekten gehoerigen
285 // Szenen und deren Objekten auf nicht selektiert setzen
286 long nObjs;
287 for(nObjs = 0;nObjs < nCnt;nObjs++)
289 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
290 if(pObj && pObj->ISA(E3dCompoundObject))
292 // zugehoerige Szene
293 pScene = ((E3dCompoundObject*)pObj)->GetScene();
294 if(pScene)
295 pScene->SetSelected(FALSE);
299 // bei allen direkt selektierten Objekten auf selektiert setzen
300 SdrMark* pM = NULL;
302 for(nObjs = 0;nObjs < nCnt;nObjs++)
304 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
305 if(pObj && pObj->ISA(E3dObject))
307 // Objekt markieren
308 E3dObject* p3DObj = (E3dObject*)pObj;
309 p3DObj->SetSelected(TRUE);
310 pScene = p3DObj->GetScene();
311 pM = GetSdrMarkByIndex(nObjs);
315 if(pScene)
317 // code from parent
318 SortMarkedObjects();
320 pScene->SetDrawOnlySelected(TRUE);
321 pScene->SingleObjectPainter(rOut); // #110094#-17
322 pScene->SetDrawOnlySelected(FALSE);
325 // SelectionFlag zuruecksetzen
326 for(nObjs = 0;nObjs < nCnt;nObjs++)
328 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
329 if(pObj && pObj->ISA(E3dCompoundObject))
331 // zugehoerige Szene
332 pScene = ((E3dCompoundObject*)pObj)->GetScene();
333 if(pScene)
334 pScene->SetSelected(FALSE);
338 else
340 // call parent
341 SdrExchangeView::DrawMarkedObj(rOut);
345 /*************************************************************************
347 |* Model holen ueberladen, da bei einzelnen 3D Objekten noch eine Szene
348 |* untergeschoben werden muss
350 \************************************************************************/
352 SdrModel* E3dView::GetMarkedObjModel() const
354 // Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
355 bool bSpecialHandling(false);
356 const sal_uInt32 nCount(GetMarkedObjectCount());
357 sal_uInt32 nObjs(0);
358 E3dScene *pScene = 0;
360 for(nObjs = 0; nObjs < nCount; nObjs++)
362 const SdrObject* pObj = GetMarkedObjectByIndex(nObjs);
364 if(!bSpecialHandling && pObj && pObj->ISA(E3dCompoundObject))
366 // if the object is selected, but it's scene not,
367 // we need special handling
368 pScene = ((E3dCompoundObject*)pObj)->GetScene();
370 if(pScene && !IsObjMarked(pScene))
372 bSpecialHandling = true;
376 if(pObj && pObj->ISA(E3dObject))
378 // reset all selection flags at 3D objects
379 pScene = ((E3dObject*)pObj)->GetScene();
381 if(pScene)
383 pScene->SetSelected(false);
388 if(!bSpecialHandling)
390 // call parent
391 return SdrView::GetMarkedObjModel();
394 SdrModel* pNewModel = 0;
395 Rectangle aSelectedSnapRect;
397 // set 3d selection flags at all directly selected objects
398 // and collect SnapRect of selected objects
399 for(nObjs = 0; nObjs < nCount; nObjs++)
401 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
403 if(pObj && pObj->ISA(E3dCompoundObject))
405 // mark object, but not scenes
406 E3dCompoundObject* p3DObj = (E3dCompoundObject*)pObj;
407 p3DObj->SetSelected(true);
408 aSelectedSnapRect.Union(p3DObj->GetSnapRect());
412 // create new mark list which contains all indirectly selected3d
413 // scenes as selected objects
414 SdrMarkList aOldML(GetMarkedObjectList());
415 SdrMarkList aNewML;
416 SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess();
417 rCurrentMarkList = aNewML;
419 for(nObjs = 0; nObjs < nCount; nObjs++)
421 SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj();
423 if(pObj && pObj->ISA(E3dObject))
425 pScene = ((E3dObject*)pObj)->GetScene();
427 if(pScene && !IsObjMarked(pScene) && GetSdrPageView())
429 ((E3dView*)this)->MarkObj(pScene, GetSdrPageView(), FALSE, TRUE);
434 // call parent. This will copy all scenes and the selection flags at the 3d objectss. So
435 // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes
436 pNewModel = SdrView::GetMarkedObjModel();
438 if(pNewModel)
440 for(sal_uInt16 nPg(0); nPg < pNewModel->GetPageCount(); nPg++)
442 const SdrPage* pSrcPg=pNewModel->GetPage(nPg);
443 const sal_uInt32 nObAnz(pSrcPg->GetObjCount());
445 for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
447 const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
449 if(pSrcOb->ISA(E3dScene))
451 pScene = (E3dScene*)pSrcOb;
453 // delete all not intentionally cloned 3d objects
454 pScene->removeAllNonSelectedObjects();
456 // reset select flags and set SnapRect of all selected objects
457 pScene->SetSelected(false);
458 pScene->SetSnapRect(aSelectedSnapRect);
464 // restore old selection
465 rCurrentMarkList = aOldML;
467 // model zurueckgeben
468 return pNewModel;
471 /*************************************************************************
473 |* Bei Paste muss - falls in eine Scene eingefuegt wird - die
474 |* Objekte der Szene eingefuegt werden, die Szene selbst aber nicht
476 \************************************************************************/
478 BOOL E3dView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, UINT32 nOptions)
480 BOOL bRetval = FALSE;
482 // Liste holen
483 Point aPos(rPos);
484 SdrObjList* pDstList = pLst;
485 ImpGetPasteObjList(aPos, pDstList);
487 if(!pDstList)
488 return FALSE;
490 // Owner der Liste holen
491 SdrObject* pOwner = pDstList->GetOwnerObj();
492 if(pOwner && pOwner->ISA(E3dScene))
494 E3dScene* pDstScene = (E3dScene*)pOwner;
495 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE));
497 // Alle Objekte aus E3dScenes kopieren und direkt einfuegen
498 for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++)
500 const SdrPage* pSrcPg=rMod.GetPage(nPg);
501 sal_uInt32 nObAnz(pSrcPg->GetObjCount());
503 // calculate offset for paste
504 Rectangle aR = pSrcPg->GetAllObjBoundRect();
505 Point aDist(aPos - aR.Center());
507 // Unterobjekte von Szenen einfuegen
508 for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
510 const SdrObject* pSrcOb = pSrcPg->GetObj(nOb);
511 if(pSrcOb->ISA(E3dScene))
513 E3dScene* pSrcScene = (E3dScene*)pSrcOb;
514 ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist);
518 EndUndo();
520 else
522 // call parent
523 bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions);
526 // und Rueckgabewert liefern
527 return bRetval;
530 // #83403# Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
531 BOOL E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point /*aOffset*/)
533 BOOL bRetval(FALSE);
535 if(pSrcScene && pDstScene)
537 const sdr::contact::ViewContactOfE3dScene& rVCSceneDst = static_cast< sdr::contact::ViewContactOfE3dScene& >(pDstScene->GetViewContact());
538 const drawinglayer::geometry::ViewInformation3D aViewInfo3DDst(rVCSceneDst.getViewInformation3D());
539 const sdr::contact::ViewContactOfE3dScene& rVCSceneSrc = static_cast< sdr::contact::ViewContactOfE3dScene& >(pSrcScene->GetViewContact());
540 const drawinglayer::geometry::ViewInformation3D aViewInfo3DSrc(rVCSceneSrc.getViewInformation3D());
542 for(sal_uInt32 i(0); i < pSrcScene->GetSubList()->GetObjCount(); i++)
544 E3dCompoundObject* pCompoundObj = dynamic_cast< E3dCompoundObject* >(pSrcScene->GetSubList()->GetObj(i));
546 if(pCompoundObj)
548 // #116235#
549 E3dCompoundObject* pNewCompoundObj = dynamic_cast< E3dCompoundObject* >(pCompoundObj->Clone());
551 if(pNewCompoundObj)
553 // get dest scene's current range in 3D world coordinates
554 const basegfx::B3DHomMatrix aSceneToWorldTrans(pDstScene->GetFullTransform());
555 basegfx::B3DRange aSceneRange(pDstScene->GetBoundVolume());
556 aSceneRange.transform(aSceneToWorldTrans);
558 // get new object's implied object transformation
559 const basegfx::B3DHomMatrix aNewObjectTrans(pNewCompoundObj->GetTransform());
561 // get new object's range in 3D world coordinates in dest scene
562 // as if it were already added
563 const basegfx::B3DHomMatrix aObjectToWorldTrans(aSceneToWorldTrans * aNewObjectTrans);
564 basegfx::B3DRange aObjectRange(pNewCompoundObj->GetBoundVolume());
565 aObjectRange.transform(aObjectToWorldTrans);
567 // get scale adaption
568 const basegfx::B3DVector aSceneScale(aSceneRange.getRange());
569 const basegfx::B3DVector aObjectScale(aObjectRange.getRange());
570 double fScale(1.0);
572 // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
573 // to not change the scene by the inserted object
574 const double fSizeFactor(0.5);
576 if(aObjectScale.getX() * fScale > aSceneScale.getX() * fSizeFactor)
578 const double fObjSize(aObjectScale.getX() * fScale);
579 const double fFactor((aSceneScale.getX() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
580 fScale *= fFactor;
583 if(aObjectScale.getY() * fScale > aSceneScale.getY() * fSizeFactor)
585 const double fObjSize(aObjectScale.getY() * fScale);
586 const double fFactor((aSceneScale.getY() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
587 fScale *= fFactor;
590 if(aObjectScale.getZ() * fScale > aSceneScale.getZ() * fSizeFactor)
592 const double fObjSize(aObjectScale.getZ() * fScale);
593 const double fFactor((aSceneScale.getZ() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
594 fScale *= fFactor;
597 // get translation adaption
598 const basegfx::B3DPoint aSceneCenter(aSceneRange.getCenter());
599 const basegfx::B3DPoint aObjectCenter(aObjectRange.getCenter());
601 // build full modification transform. The object's transformation
602 // shall be modified, so start at object coordinates; transform to 3d world coor
603 basegfx::B3DHomMatrix aModifyingTransform(aObjectToWorldTrans);
605 // translate to absolute center in 3d world coor
606 aModifyingTransform.translate(-aObjectCenter.getX(), -aObjectCenter.getY(), -aObjectCenter.getZ());
608 // scale to dest size in 3d world coor
609 aModifyingTransform.scale(fScale, fScale, fScale);
611 // translate to dest scene center in 3d world coor
612 aModifyingTransform.translate(aSceneCenter.getX(), aSceneCenter.getY(), aSceneCenter.getZ());
614 // transform from 3d world to dest object coordinates
615 basegfx::B3DHomMatrix aWorldToObject(aObjectToWorldTrans);
616 aWorldToObject.invert();
617 aModifyingTransform = aWorldToObject * aModifyingTransform;
619 // correct implied object transform by applying changing one in object coor
620 pNewCompoundObj->SetTransform(aModifyingTransform * aNewObjectTrans);
622 // fill and insert new object
623 pNewCompoundObj->SetModel(pDstScene->GetModel());
624 pNewCompoundObj->SetPage(pDstScene->GetPage());
625 pNewCompoundObj->NbcSetLayer(pCompoundObj->GetLayer());
626 pNewCompoundObj->NbcSetStyleSheet(pCompoundObj->GetStyleSheet(), sal_True);
627 pDstScene->Insert3DObj(pNewCompoundObj);
628 bRetval = TRUE;
630 // Undo anlegen
631 if( GetModel()->IsUndoEnabled() )
632 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj));
638 return bRetval;
641 /*************************************************************************
643 |* 3D-Konvertierung moeglich?
645 \************************************************************************/
647 BOOL E3dView::IsConvertTo3DObjPossible() const
649 BOOL bAny3D(FALSE);
650 BOOL bGroupSelected(FALSE);
651 BOOL bRetval(TRUE);
653 for(sal_uInt32 a=0;!bAny3D && a<GetMarkedObjectCount();a++)
655 SdrObject *pObj = GetMarkedObjectByIndex(a);
656 if(pObj)
658 ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected);
662 bRetval = !bAny3D
663 && (
664 IsConvertToPolyObjPossible(FALSE)
665 || IsConvertToPathObjPossible(FALSE)
666 || IsImportMtfPossible());
667 return bRetval;
670 void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, BOOL& rAny3D,
671 BOOL& rGroupSelected) const
673 if(pObj)
675 if(pObj->ISA(E3dObject))
677 rAny3D = TRUE;
679 else
681 if(pObj->IsGroupObject())
683 SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS);
684 while(aIter.IsMore())
686 SdrObject* pNewObj = aIter.Next();
687 ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected);
689 rGroupSelected = TRUE;
695 /*************************************************************************
697 |* 3D-Konvertierung zu Extrude ausfuehren
699 \************************************************************************/
700 #include <svx/eeitem.hxx>
702 void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject* pObj)
704 if(pObj->ISA(SdrTextObj))
706 const SfxItemSet& rSet = pObj->GetMergedItemSet();
707 const SvxColorItem& rTextColorItem = (const SvxColorItem&)rSet.Get(EE_CHAR_COLOR);
708 if(rTextColorItem.GetValue() == RGB_Color(COL_BLACK))
710 // Bei schwarzen Textobjekten wird die Farbe auf grau gesetzt
711 if(pObj->GetPage())
713 // #84864# if black is only default attribute from
714 // pattern set it hard so that it is used in undo.
715 pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK), EE_CHAR_COLOR));
717 // add undo now
718 if( GetModel()->IsUndoEnabled() )
719 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
722 pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY), EE_CHAR_COLOR));
727 void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject* pObj)
729 if(pObj->ISA(SdrPathObj))
731 const SfxItemSet& rSet = pObj->GetMergedItemSet();
732 sal_Int32 nLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
733 XLineStyle eLineStyle = (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue();
734 XFillStyle eFillStyle = ITEMVALUE(rSet, XATTR_FILLSTYLE, XFillStyleItem);
736 if(((SdrPathObj*)pObj)->IsClosed()
737 && eLineStyle == XLINE_SOLID
738 && !nLineWidth
739 && eFillStyle != XFILL_NONE)
741 if(pObj->GetPage() && GetModel()->IsUndoEnabled() )
742 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
743 pObj->SetMergedItem(XLineStyleItem(XLINE_NONE));
744 pObj->SetMergedItem(XLineWidthItem(0L));
749 void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, BOOL bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
751 // Einzelnes PathObject, dieses umwanden
752 SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
754 if(pPath)
756 E3dDefaultAttributes aDefault = Get3DDefaultAttributes();
757 if(bExtrude)
758 aDefault.SetDefaultExtrudeCharacterMode(TRUE);
759 else
760 aDefault.SetDefaultLatheCharacterMode(TRUE);
762 // ItemSet des Ursprungsobjektes holen
763 SfxItemSet aSet(pObj->GetMergedItemSet());
765 XFillStyle eFillStyle = ITEMVALUE(aSet, XATTR_FILLSTYLE, XFillStyleItem);
767 // Linienstil ausschalten
768 aSet.Put(XLineStyleItem(XLINE_NONE));
770 // Feststellen, ob ein FILL_Attribut gesetzt ist.
771 if(!pPath->IsClosed() || eFillStyle == XFILL_NONE)
773 // Das SdrPathObj ist nicht gefuellt, lasse die
774 // vordere und hintere Flaeche weg. Ausserdem ist
775 // eine beidseitige Darstellung notwendig.
776 aDefault.SetDefaultExtrudeCloseFront(FALSE);
777 aDefault.SetDefaultExtrudeCloseBack(FALSE);
779 aSet.Put(Svx3DDoubleSidedItem(TRUE));
781 // Fuellattribut setzen
782 aSet.Put(XFillStyleItem(XFILL_SOLID));
784 // Fuellfarbe muss auf Linienfarbe, da das Objekt vorher
785 // nur eine Linie war
786 Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue();
787 aSet.Put(XFillColorItem(String(), aColorLine));
790 // Neues Extrude-Objekt erzeugen
791 E3dObject* p3DObj = NULL;
792 if(bExtrude)
794 p3DObj = new E3dExtrudeObj(aDefault, pPath->GetPathPoly(), fDepth);
796 else
798 basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly());
799 aPolyPoly2D.transform(rLatheMat);
800 p3DObj = new E3dLatheObj(aDefault, aPolyPoly2D);
803 // Attribute setzen
804 if(p3DObj)
806 p3DObj->NbcSetLayer(pObj->GetLayer());
808 p3DObj->SetMergedItemSet(aSet);
810 p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True);
812 // Neues 3D-Objekt einfuegen
813 pScene->Insert3DObj(p3DObj);
818 void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, BOOL bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
820 if(pObj)
822 // change text color attribute for not so dark colors
823 if(pObj->IsGroupObject())
825 SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
826 while(aIter.IsMore())
828 SdrObject* pGroupMember = aIter.Next();
829 ImpChangeSomeAttributesFor3DConversion(pGroupMember);
832 else
833 ImpChangeSomeAttributesFor3DConversion(pObj);
835 // convert completely to path objects
836 SdrObject* pNewObj1 = pObj->ConvertToPolyObj(FALSE, FALSE);
838 if(pNewObj1)
840 // change text color attribute for not so dark colors
841 if(pNewObj1->IsGroupObject())
843 SdrObjListIter aIter(*pNewObj1, IM_DEEPWITHGROUPS);
844 while(aIter.IsMore())
846 SdrObject* pGroupMember = aIter.Next();
847 ImpChangeSomeAttributesFor3DConversion2(pGroupMember);
850 else
851 ImpChangeSomeAttributesFor3DConversion2(pNewObj1);
853 // convert completely to path objects
854 SdrObject* pNewObj2 = pObj->ConvertToContourObj(pNewObj1, TRUE);
856 if(pNewObj2)
858 // add all to flat scene
859 if(pNewObj2->IsGroupObject())
861 SdrObjListIter aIter(*pNewObj2, IM_DEEPWITHGROUPS);
862 while(aIter.IsMore())
864 SdrObject* pGroupMember = aIter.Next();
865 ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat);
868 else
869 ImpCreateSingle3DObjectFlat(pScene, pNewObj2, bExtrude, fDepth, rLatheMat);
871 // delete zwi object
872 if(pNewObj2 != pObj && pNewObj2 != pNewObj1 && pNewObj2)
873 SdrObject::Free( pNewObj2 );
876 // delete zwi object
877 if(pNewObj1 != pObj && pNewObj1)
878 SdrObject::Free( pNewObj1 );
883 /*************************************************************************
885 |* 3D-Konvertierung zu Extrude steuern
887 \************************************************************************/
889 void E3dView::ConvertMarkedObjTo3D(BOOL bExtrude, basegfx::B2DPoint aPnt1, basegfx::B2DPoint aPnt2)
891 if(AreObjectsMarked())
893 // Undo anlegen
894 if(bExtrude)
895 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE));
896 else
897 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE));
899 // Neue Szene fuer zu erzeugende 3D-Objekte anlegen
900 E3dScene* pScene = new E3dPolyScene(Get3DDefaultAttributes());
902 // Rechteck bestimmen und evtl. korrigieren
903 Rectangle aRect = GetAllMarkedRect();
904 if(aRect.GetWidth() <= 1)
905 aRect.SetSize(Size(500, aRect.GetHeight()));
906 if(aRect.GetHeight() <= 1)
907 aRect.SetSize(Size(aRect.GetWidth(), 500));
909 // Tiefe relativ zur Groesse der Selektion bestimmen
910 double fDepth = 0.0;
911 double fRot3D = 0.0;
912 basegfx::B2DHomMatrix aLatheMat;
914 if(bExtrude)
916 double fW = (double)aRect.GetWidth();
917 double fH = (double)aRect.GetHeight();
918 fDepth = sqrt(fW*fW + fH*fH) / 6.0;
920 if(!bExtrude)
922 // Transformation fuer Polygone Rotationskoerper erstellen
923 if(aPnt1 != aPnt2)
925 // Rotation um Kontrollpunkt1 mit eigestelltem Winkel
926 // fuer 3D Koordinaten
927 basegfx::B2DPoint aDiff(aPnt1 - aPnt2);
928 fRot3D = atan2(aDiff.getY(), aDiff.getX()) - F_PI2;
930 if(basegfx::fTools::equalZero(fabs(fRot3D)))
931 fRot3D = 0.0;
933 if(fRot3D != 0.0)
935 aLatheMat.translate(-aPnt2.getX(), -aPnt2.getY());
936 aLatheMat.rotate(-fRot3D);
937 aLatheMat.translate(aPnt2.getX(), aPnt2.getY());
941 if(aPnt2.getX() != 0.0)
943 // Translation auf Y=0 - Achse
944 aLatheMat.translate(-aPnt2.getX(), 0.0);
946 else
948 aLatheMat.translate((double)-aRect.Left(), 0.0);
951 // Inverse Matrix bilden, um die Zielausdehnung zu bestimmen
952 basegfx::B2DHomMatrix aInvLatheMat(aLatheMat);
953 aInvLatheMat.invert();
955 // SnapRect Ausdehnung mittels Spiegelung an der Rotationsachse
956 // erweitern
957 for(UINT32 a=0;a<GetMarkedObjectCount();a++)
959 SdrMark* pMark = GetSdrMarkByIndex(a);
960 SdrObject* pObj = pMark->GetMarkedSdrObj();
961 Rectangle aTurnRect = pObj->GetSnapRect();
962 basegfx::B2DPoint aRot;
963 Point aRotPnt;
965 aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top());
966 aRot *= aLatheMat;
967 aRot.setX(-aRot.getX());
968 aRot *= aInvLatheMat;
969 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
970 aRect.Union(Rectangle(aRotPnt, aRotPnt));
972 aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom());
973 aRot *= aLatheMat;
974 aRot.setX(-aRot.getX());
975 aRot *= aInvLatheMat;
976 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
977 aRect.Union(Rectangle(aRotPnt, aRotPnt));
979 aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top());
980 aRot *= aLatheMat;
981 aRot.setX(-aRot.getX());
982 aRot *= aInvLatheMat;
983 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
984 aRect.Union(Rectangle(aRotPnt, aRotPnt));
986 aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom());
987 aRot *= aLatheMat;
988 aRot.setX(-aRot.getX());
989 aRot *= aInvLatheMat;
990 aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
991 aRect.Union(Rectangle(aRotPnt, aRotPnt));
995 // Ueber die Selektion gehen und in 3D wandeln, komplett mit
996 // Umwandeln in SdrPathObject, auch Schriften
997 for(UINT32 a=0;a<GetMarkedObjectCount();a++)
999 SdrMark* pMark = GetSdrMarkByIndex(a);
1000 SdrObject* pObj = pMark->GetMarkedSdrObj();
1002 ImpCreate3DObject(pScene, pObj, bExtrude, fDepth, aLatheMat);
1005 if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0)
1007 // Alle angelegten Objekte Tiefenarrangieren
1008 if(bExtrude)
1009 DoDepthArrange(pScene, fDepth);
1011 // 3D-Objekte auf die Mitte des Gesamtrechtecks zentrieren
1012 basegfx::B3DPoint aCenter(pScene->GetBoundVolume().getCenter());
1013 basegfx::B3DHomMatrix aMatrix;
1015 aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ());
1016 pScene->SetTransform(aMatrix * pScene->GetTransform()); // #112587#
1018 // Szene initialisieren
1019 pScene->NbcSetSnapRect(aRect);
1020 basegfx::B3DRange aBoundVol = pScene->GetBoundVolume();
1021 InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth());
1023 // Szene anstelle des ersten selektierten Objektes einfuegen
1024 // und alle alten Objekte weghauen
1025 SdrObject* pRepObj = GetMarkedObjectByIndex(0);
1026 SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0);
1027 MarkObj(pRepObj, pPV, TRUE);
1028 ReplaceObjectAtView(pRepObj, *pPV, pScene, FALSE);
1029 DeleteMarked();
1030 MarkObj(pScene, pPV);
1032 // Rotationskoerper um Rotationsachse drehen
1033 basegfx::B3DHomMatrix aRotate;
1035 if(!bExtrude && fRot3D != 0.0)
1037 aRotate.rotate(0.0, 0.0, fRot3D);
1040 // Default-Rotation setzen
1042 double XRotateDefault = 20;
1043 aRotate.rotate(DEG2RAD(XRotateDefault), 0.0, 0.0);
1046 if(!aRotate.isIdentity())
1048 pScene->SetTransform(aRotate * pScene->GetTransform());
1051 // SnapRects der Objekte ungueltig
1052 pScene->SetSnapRect(aRect);
1054 else
1056 // Es wurden keine 3D Objekte erzeugt, schmeiss alles weg
1057 delete pScene;
1060 // Undo abschliessen
1061 EndUndo();
1065 /*************************************************************************
1067 |* Alle enthaltenen Extrude-Objekte Tiefenarrangieren
1069 \************************************************************************/
1071 struct E3dDepthNeighbour
1073 E3dDepthNeighbour* pNext;
1074 E3dExtrudeObj* pObj;
1076 E3dDepthNeighbour() { pNext = NULL; pObj = NULL; }
1079 struct E3dDepthLayer
1081 E3dDepthLayer* pDown;
1082 E3dDepthNeighbour* pNext;
1084 E3dDepthLayer() { pDown = NULL; pNext = NULL; }
1085 ~E3dDepthLayer() { while(pNext) { E3dDepthNeighbour* pSucc = pNext->pNext; delete pNext; pNext = pSucc; }}
1088 bool ImpDoesOverlap(const basegfx::B2DPolygon& rPolygonA, const basegfx::B2DPolygon& rPolygonB)
1090 bool bRetval(false);
1091 const basegfx::B2DRange aRangeA(basegfx::tools::getRange(rPolygonA));
1092 const basegfx::B2DRange aRangeB(basegfx::tools::getRange(rPolygonB));
1094 if(aRangeA.overlaps(aRangeB))
1096 // A in B ?
1097 if(basegfx::tools::isInside(rPolygonA, rPolygonB))
1098 return true;
1100 // B in A ?
1101 if(basegfx::tools::isInside(rPolygonB, rPolygonA))
1102 return true;
1104 // A and B the same ?
1105 if(basegfx::tools::isInside(rPolygonB, rPolygonA, true))
1106 return true;
1109 return bRetval;
1112 bool ImpDoesOverlap(const basegfx::B2DPolyPolygon& rPolyPolygonA, const basegfx::B2DPolyPolygon& rPolyPolygonB)
1114 bool bRetval(false);
1115 const basegfx::B2DRange aRangeA(basegfx::tools::getRange(rPolyPolygonA));
1116 const basegfx::B2DRange aRangeB(basegfx::tools::getRange(rPolyPolygonB));
1118 if(aRangeA.overlaps(aRangeB))
1120 const sal_uInt32 nCntA(rPolyPolygonA.count());
1121 const sal_uInt32 nCntB(rPolyPolygonB.count());
1123 for(sal_uInt32 a(0L); !bRetval && a < nCntA; a++)
1125 const basegfx::B2DPolygon aPolygonA(rPolyPolygonA.getB2DPolygon(a));
1127 if(aPolygonA.isClosed())
1129 for(sal_uInt32 b(0L); !bRetval && b < nCntB; b++)
1131 const basegfx::B2DPolygon aPolygonB(rPolyPolygonB.getB2DPolygon(b));
1133 if(aPolygonB.isClosed())
1135 bRetval = ImpDoesOverlap(aPolygonA, aPolygonB);
1142 return bRetval;
1145 void E3dView::DoDepthArrange(E3dScene* pScene, double fDepth)
1147 if(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1)
1149 SdrObjList* pSubList = pScene->GetSubList();
1150 SdrObjListIter aIter(*pSubList, IM_FLAT);
1151 E3dDepthLayer* pBaseLayer = NULL;
1152 E3dDepthLayer* pLayer = NULL;
1153 INT32 nNumLayers = 0;
1154 //SfxItemPool& rPool = pMod->GetItemPool();
1156 while(aIter.IsMore())
1158 E3dObject* pSubObj = (E3dObject*)aIter.Next();
1160 if(pSubObj && pSubObj->ISA(E3dExtrudeObj))
1162 E3dExtrudeObj* pExtrudeObj = (E3dExtrudeObj*)pSubObj;
1163 const basegfx::B2DPolyPolygon aExtrudePoly(pExtrudeObj->GetExtrudePolygon());
1165 const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet();
1166 XFillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem);
1167 Color aLocalColor = ((const XFillColorItem&)(rLocalSet.Get(XATTR_FILLCOLOR))).GetColorValue();
1169 // ExtrudeObj einordnen
1170 if(pLayer)
1172 // Gibt es eine Ueberschneidung mit einem Objekt dieses
1173 // Layers?
1174 BOOL bOverlap(FALSE);
1175 E3dDepthNeighbour* pAct = pLayer->pNext;
1177 while(!bOverlap && pAct)
1179 // ueberlappen sich pAct->pObj und pExtrudeObj ?
1180 const basegfx::B2DPolyPolygon aActPoly(pAct->pObj->GetExtrudePolygon());
1181 bOverlap = ImpDoesOverlap(aExtrudePoly, aActPoly);
1183 if(bOverlap)
1185 // second ciriteria: is another fillstyle or color used?
1186 const SfxItemSet& rCompareSet = pAct->pObj->GetMergedItemSet();
1188 XFillStyle eCompareFillStyle = ITEMVALUE(rCompareSet, XATTR_FILLSTYLE, XFillStyleItem);
1190 if(eLocalFillStyle == eCompareFillStyle)
1192 if(eLocalFillStyle == XFILL_SOLID)
1194 Color aCompareColor = ((const XFillColorItem&)(rCompareSet.Get(XATTR_FILLCOLOR))).GetColorValue();
1196 if(aCompareColor == aLocalColor)
1198 bOverlap = FALSE;
1201 else if(eLocalFillStyle == XFILL_NONE)
1203 bOverlap = FALSE;
1208 pAct = pAct->pNext;
1211 if(bOverlap)
1213 // ja, beginne einen neuen Layer
1214 pLayer->pDown = new E3dDepthLayer;
1215 pLayer = pLayer->pDown;
1216 nNumLayers++;
1217 pLayer->pNext = new E3dDepthNeighbour;
1218 pLayer->pNext->pObj = pExtrudeObj;
1220 else
1222 // nein, Objekt kann in aktuellen Layer
1223 E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour;
1224 pNewNext->pObj = pExtrudeObj;
1225 pNewNext->pNext = pLayer->pNext;
1226 pLayer->pNext = pNewNext;
1229 else
1231 // erster Layer ueberhaupt
1232 pBaseLayer = new E3dDepthLayer;
1233 pLayer = pBaseLayer;
1234 nNumLayers++;
1235 pLayer->pNext = new E3dDepthNeighbour;
1236 pLayer->pNext->pObj = pExtrudeObj;
1241 // Anzahl Layer steht fest
1242 if(nNumLayers > 1)
1244 // Arrangement ist notwendig
1245 double fMinDepth = fDepth * 0.8;
1246 double fStep = (fDepth - fMinDepth) / (double)nNumLayers;
1247 pLayer = pBaseLayer;
1249 while(pLayer)
1251 // an pLayer entlangspazieren
1252 E3dDepthNeighbour* pAct = pLayer->pNext;
1254 while(pAct)
1256 // Anpassen
1257 pAct->pObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5)));
1259 // Naechster Eintrag
1260 pAct = pAct->pNext;
1263 // naechster Layer
1264 pLayer = pLayer->pDown;
1265 fMinDepth += fStep;
1269 // angelegte Strukturen aufraeumen
1270 while(pBaseLayer)
1272 pLayer = pBaseLayer->pDown;
1273 delete pBaseLayer;
1274 pBaseLayer = pLayer;
1279 /*************************************************************************
1281 |* Drag beginnen, vorher ggf. Drag-Methode fuer 3D-Objekte erzeugen
1283 \************************************************************************/
1285 BOOL E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut,
1286 SdrHdl* pHdl, short nMinMov,
1287 SdrDragMethod* pForcedMeth)
1289 if(Is3DRotationCreationActive() && GetMarkedObjectCount())
1291 // bestimme alle selektierten Polygone und gebe die gespiegelte Hilfsfigur aus
1292 mpMirrorOverlay->SetMirrorAxis(aRef1, aRef2);
1294 else
1296 BOOL bOwnActionNecessary;
1297 if (pHdl == NULL)
1299 bOwnActionNecessary = TRUE;
1301 else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl())
1303 bOwnActionNecessary = TRUE;
1305 else
1307 bOwnActionNecessary = FALSE;
1310 if(bOwnActionNecessary && GetMarkedObjectCount() >= 1)
1312 E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ;
1313 BOOL bThereAreRootScenes = FALSE;
1314 BOOL bThereAre3DObjects = FALSE;
1315 long nCnt = GetMarkedObjectCount();
1316 for(long nObjs = 0;nObjs < nCnt;nObjs++)
1318 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1319 if(pObj)
1321 if(pObj->ISA(E3dScene) && ((E3dScene*)pObj)->GetScene() == pObj)
1322 bThereAreRootScenes = TRUE;
1323 if(pObj->ISA(E3dObject))
1324 bThereAre3DObjects = TRUE;
1327 if( bThereAre3DObjects )
1329 eDragHdl = ( pHdl == NULL ? HDL_MOVE : pHdl->GetKind() );
1330 switch ( eDragMode )
1332 case SDRDRAG_ROTATE:
1333 case SDRDRAG_SHEAR:
1335 switch ( eDragHdl )
1337 case HDL_LEFT:
1338 case HDL_RIGHT:
1340 eConstraint = E3DDRAG_CONSTR_X;
1342 break;
1344 case HDL_UPPER:
1345 case HDL_LOWER:
1347 eConstraint = E3DDRAG_CONSTR_Y;
1349 break;
1351 case HDL_UPLFT:
1352 case HDL_UPRGT:
1353 case HDL_LWLFT:
1354 case HDL_LWRGT:
1356 eConstraint = E3DDRAG_CONSTR_Z;
1358 break;
1359 default: break;
1362 // die nicht erlaubten Rotationen ausmaskieren
1363 eConstraint = E3dDragConstraint(eConstraint& eDragConstraint);
1364 pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint, IsSolidDragging());
1366 break;
1368 case SDRDRAG_MOVE:
1370 if(!bThereAreRootScenes)
1372 pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint, IsSolidDragging());
1375 break;
1377 // spaeter mal
1378 case SDRDRAG_MIRROR:
1379 case SDRDRAG_CROOK:
1380 case SDRDRAG_DISTORT:
1381 case SDRDRAG_TRANSPARENCE:
1382 case SDRDRAG_GRADIENT:
1383 default:
1386 break;
1391 return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth);
1394 /*************************************************************************
1396 |* Pruefen, obj 3D-Szene markiert ist
1398 \************************************************************************/
1400 BOOL E3dView::HasMarkedScene()
1402 return (GetMarkedScene() != NULL);
1405 /*************************************************************************
1407 |* Pruefen, obj 3D-Szene markiert ist
1409 \************************************************************************/
1411 E3dScene* E3dView::GetMarkedScene()
1413 ULONG nCnt = GetMarkedObjectCount();
1415 for ( ULONG i = 0; i < nCnt; i++ )
1416 if ( GetMarkedObjectByIndex(i)->ISA(E3dScene) )
1417 return (E3dScene*) GetMarkedObjectByIndex(i);
1419 return NULL;
1422 /*************************************************************************
1424 |* aktuelles 3D-Zeichenobjekt setzen, dafuer Szene erzeugen
1426 \************************************************************************/
1428 E3dScene* E3dView::SetCurrent3DObj(E3dObject* p3DObj)
1430 DBG_ASSERT(p3DObj != NULL, "Nana, wer steckt denn hier 'nen NULL-Zeiger rein?");
1431 E3dScene* pScene = NULL;
1433 // get transformed BoundVolume of the object
1434 basegfx::B3DRange aVolume(p3DObj->GetBoundVolume());
1435 aVolume.transform(p3DObj->GetTransform());
1436 double fW(aVolume.getWidth());
1437 double fH(aVolume.getHeight());
1439 Rectangle aRect(0,0, (long) fW, (long) fH);
1441 pScene = new E3dPolyScene(Get3DDefaultAttributes());
1443 InitScene(pScene, fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0));
1445 pScene->Insert3DObj(p3DObj);
1446 pScene->NbcSetSnapRect(aRect);
1448 return pScene;
1451 /*************************************************************************
1453 |* neu erzeugte Szene initialisieren
1455 \************************************************************************/
1457 void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ)
1459 Camera3D aCam(pScene->GetCamera());
1461 aCam.SetAutoAdjustProjection(FALSE);
1462 aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1463 basegfx::B3DPoint aLookAt;
1465 double fDefaultCamPosZ = GetDefaultCamPosZ();
1466 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1468 aCam.SetPosAndLookAt(aCamPos, aLookAt);
1469 aCam.SetFocalLength(GetDefaultCamFocal());
1470 aCam.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, GetDefaultCamFocal());
1471 pScene->SetCamera(aCam);
1474 /*************************************************************************
1476 |* startsequenz fuer die erstellung eines 3D-Rotationskoerpers
1478 \************************************************************************/
1480 void E3dView::Start3DCreation()
1482 if (GetMarkedObjectCount())
1484 // irgendwelche Markierungen ermitteln und ausschalten
1485 //HMHBOOL bVis = IsMarkHdlShown();
1487 //HMHif (bVis) HideMarkHdl();
1489 // bestimme die koordinaten fuer JOEs Mirrorachse
1490 // entgegen der normalen Achse wird diese an die linke Seite des Objektes
1491 // positioniert
1492 long nOutMin = 0;
1493 long nOutMax = 0;
1494 long nMinLen = 0;
1495 long nObjDst = 0;
1496 long nOutHgt = 0;
1497 OutputDevice* pOut = GetFirstOutputDevice(); //GetWin(0);
1499 // erstmal Darstellungsgrenzen bestimmen
1500 if (pOut != NULL)
1502 nMinLen = pOut->PixelToLogic(Size(0,50)).Height();
1503 nObjDst = pOut->PixelToLogic(Size(0,20)).Height();
1505 long nDst = pOut->PixelToLogic(Size(0,10)).Height();
1507 nOutMin = -pOut->GetMapMode().GetOrigin().Y();
1508 nOutMax = pOut->GetOutputSize().Height() - 1 + nOutMin;
1509 nOutMin += nDst;
1510 nOutMax -= nDst;
1512 if (nOutMax - nOutMin < nDst)
1514 nOutMin += nOutMax + 1;
1515 nOutMin /= 2;
1516 nOutMin -= (nDst + 1) / 2;
1517 nOutMax = nOutMin + nDst;
1520 nOutHgt = nOutMax - nOutMin;
1522 long nTemp = nOutHgt / 4;
1523 if (nTemp > nMinLen) nMinLen = nTemp;
1526 // und dann die Markierungen oben und unten an das Objekt heften
1527 basegfx::B2DRange aR;
1528 for(sal_uInt32 nMark(0L); nMark < GetMarkedObjectCount(); nMark++)
1530 SdrObject* pMark = GetMarkedObjectByIndex(nMark);
1531 basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly());
1532 aR.expand(basegfx::tools::getRange(aXPP));
1535 basegfx::B2DPoint aCenter(aR.getCenter());
1536 long nMarkHgt = basegfx::fround(aR.getHeight()) - 1;
1537 long nHgt = nMarkHgt + nObjDst * 2;
1539 if (nHgt < nMinLen) nHgt = nMinLen;
1541 long nY1 = basegfx::fround(aCenter.getY()) - (nHgt + 1) / 2;
1542 long nY2 = nY1 + nHgt;
1544 if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt;
1545 if (pOut)
1547 if (nY1 < nOutMin)
1549 nY1 = nOutMin;
1550 if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen;
1552 if (nY2 > nOutMax)
1554 nY2 = nOutMax;
1555 if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen;
1559 aRef1.X() = basegfx::fround(aR.getMinX()); // Initial Achse um 2/100mm nach links
1560 aRef1.Y() = nY1;
1561 aRef2.X() = aRef1.X();
1562 aRef2.Y() = nY2;
1564 // Markierungen einschalten
1565 SetMarkHandles();
1567 //HMHif (bVis) ShowMarkHdl();
1568 if (AreObjectsMarked()) MarkListHasChanged();
1570 // SpiegelPolygone SOFORT zeigen
1571 const SdrHdlList &aHdlList = GetHdlList();
1572 mpMirrorOverlay = new Impl3DMirrorConstructOverlay(*this);
1573 mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(HDL_REF1)->GetPos(), aHdlList.GetHdl(HDL_REF2)->GetPos());
1574 //CreateMirrorPolygons ();
1575 //ShowMirrorPolygons (aHdlList.GetHdl (HDL_REF1)->GetPos (),
1576 // aHdlList.GetHdl (HDL_REF2)->GetPos ());
1580 /*************************************************************************
1582 |* was passiert bei einer Mausbewegung, wenn das Objekt erstellt wird ?
1584 \************************************************************************/
1586 void E3dView::MovAction(const Point& rPnt)
1588 if(Is3DRotationCreationActive())
1590 SdrHdl* pHdl = GetDragHdl();
1592 if (pHdl)
1594 SdrHdlKind eHdlKind = pHdl->GetKind();
1596 // reagiere nur bei einer spiegelachse
1597 if ((eHdlKind == HDL_REF1) ||
1598 (eHdlKind == HDL_REF2) ||
1599 (eHdlKind == HDL_MIRX))
1601 const SdrHdlList &aHdlList = GetHdlList ();
1603 // loesche das gespiegelte Polygon, spiegele das Original und zeichne es neu
1604 //ShowMirrored ();
1605 SdrView::MovAction (rPnt);
1606 mpMirrorOverlay->SetMirrorAxis(
1607 aHdlList.GetHdl (HDL_REF1)->GetPos(),
1608 aHdlList.GetHdl (HDL_REF2)->GetPos());
1611 else
1613 SdrView::MovAction (rPnt);
1616 else
1618 SdrView::MovAction (rPnt);
1622 /*************************************************************************
1624 |* Schluss. Objekt und evtl. Unterobjekte ueber ImpCreate3DLathe erstellen
1625 |* [FG] Mit dem Parameterwert TRUE (SDefault: FALSE) wird einfach ein
1626 |* Rotationskoerper erzeugt, ohne den Benutzer die Lage der
1627 |* Achse fetlegen zu lassen. Es reicht dieser Aufruf, falls
1628 |* ein Objekt selektiert ist. (keine Initialisierung noetig)
1630 \************************************************************************/
1632 void E3dView::End3DCreation(BOOL bUseDefaultValuesForMirrorAxes)
1634 ResetCreationActive();
1636 if(AreObjectsMarked())
1638 if(bUseDefaultValuesForMirrorAxes)
1640 Rectangle aRect = GetAllMarkedRect();
1641 if(aRect.GetWidth() <= 1)
1642 aRect.SetSize(Size(500, aRect.GetHeight()));
1643 if(aRect.GetHeight() <= 1)
1644 aRect.SetSize(Size(aRect.GetWidth(), 500));
1646 basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top());
1647 basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom());
1649 ConvertMarkedObjTo3D(FALSE, aPnt1, aPnt2);
1651 else
1653 // Hilfsfigur ausschalten
1654 // bestimme aus den Handlepositionen und den Versatz der Punkte
1655 const SdrHdlList &aHdlList = GetHdlList();
1656 Point aMirrorRef1 = aHdlList.GetHdl(HDL_REF1)->GetPos();
1657 Point aMirrorRef2 = aHdlList.GetHdl(HDL_REF2)->GetPos();
1659 basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y());
1660 basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y());
1662 ConvertMarkedObjTo3D(FALSE, aPnt1, aPnt2);
1667 /*************************************************************************
1669 |* Destruktor
1671 \************************************************************************/
1673 E3dView::~E3dView ()
1677 /*************************************************************************
1679 |* beende das erzeugen und loesche die polygone
1681 \************************************************************************/
1683 void E3dView::ResetCreationActive ()
1685 if(mpMirrorOverlay)
1687 delete mpMirrorOverlay;
1688 mpMirrorOverlay = 0L;
1692 /*************************************************************************
1694 |* Klasse initialisieren
1696 \************************************************************************/
1698 void E3dView::InitView ()
1700 eDragConstraint = E3DDRAG_CONSTR_XYZ;
1701 fDefaultScaleX =
1702 fDefaultScaleY =
1703 fDefaultScaleZ = 1.0;
1704 fDefaultRotateX =
1705 fDefaultRotateY =
1706 fDefaultRotateZ = 0.0;
1707 fDefaultExtrusionDeepth = 1000; // old: 2000;
1708 fDefaultLightIntensity = 0.8; // old: 0.6;
1709 fDefaultAmbientIntensity = 0.4;
1710 nHDefaultSegments = 12;
1711 nVDefaultSegments = 12;
1712 aDefaultLightColor = RGB_Color(COL_WHITE);
1713 aDefaultAmbientColor = RGB_Color(COL_BLACK);
1714 bDoubleSided = FALSE;
1715 mpMirrorOverlay = 0L;
1718 /*************************************************************************
1720 |* Koennen die selektierten Objekte aufgebrochen werden?
1722 \************************************************************************/
1724 BOOL E3dView::IsBreak3DObjPossible() const
1726 ULONG nCount = GetMarkedObjectCount();
1728 if (nCount > 0)
1730 ULONG i = 0;
1732 while (i < nCount)
1734 SdrObject* pObj = GetMarkedObjectByIndex(i);
1736 if (pObj && pObj->ISA(E3dObject))
1738 if(!(((E3dObject*)pObj)->IsBreakObjPossible()))
1739 return FALSE;
1741 else
1743 return FALSE;
1746 i++;
1749 else
1751 return FALSE;
1754 return TRUE;
1757 /*************************************************************************
1759 |* Selektierte Lathe-Objekte aufbrechen
1761 \************************************************************************/
1763 void E3dView::Break3DObj()
1765 if(IsBreak3DObjPossible())
1767 // ALLE selektierten Objekte werden gewandelt
1768 UINT32 nCount = GetMarkedObjectCount();
1770 BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE)));
1771 for(UINT32 a=0;a<nCount;a++)
1773 E3dObject* pObj = (E3dObject*)GetMarkedObjectByIndex(a);
1774 BreakSingle3DObj(pObj);
1776 DeleteMarked();
1777 EndUndo();
1781 void E3dView::BreakSingle3DObj(E3dObject* pObj)
1783 if(pObj->ISA(E3dScene))
1785 SdrObjList* pSubList = pObj->GetSubList();
1786 SdrObjListIter aIter(*pSubList, IM_FLAT);
1788 while(aIter.IsMore())
1790 E3dObject* pSubObj = (E3dObject*)aIter.Next();
1791 BreakSingle3DObj(pSubObj);
1794 else
1796 SdrAttrObj* pNewObj = pObj->GetBreakObj();
1797 if(pNewObj)
1799 InsertObjectAtView(pNewObj, *GetSdrPageView(), SDRINSERT_DONTMARK);
1800 pNewObj->SetChanged();
1801 pNewObj->BroadcastObjectChange();
1806 /*************************************************************************
1808 |* Szenen mischen
1810 \************************************************************************/
1812 void E3dView::MergeScenes ()
1814 ULONG nCount = GetMarkedObjectCount();
1816 if (nCount > 0)
1818 ULONG nObj = 0;
1819 SdrObject *pObj = GetMarkedObjectByIndex(nObj);
1820 E3dScene *pScene = new E3dPolyScene(Get3DDefaultAttributes());
1821 basegfx::B3DRange aBoundVol;
1822 Rectangle aAllBoundRect (GetMarkedObjBoundRect ());
1823 Point aCenter (aAllBoundRect.Center());
1825 while (pObj)
1827 if (pObj->ISA(E3dScene))
1829 /**********************************************************
1830 * Es ist eine 3D-Scene oder 3D-PolyScene
1831 **********************************************************/
1832 SdrObjList* pSubList = ((E3dObject*) pObj)->GetSubList();
1834 SdrObjListIter aIter(*pSubList, IM_FLAT);
1836 while (aIter.IsMore())
1838 /******************************************************
1839 * LatheObjekte suchen
1840 ******************************************************/
1841 SdrObject* pSubObj = aIter.Next();
1843 E3dObject *pNewObj = 0;
1845 switch (pSubObj->GetObjIdentifier())
1847 case E3D_CUBEOBJ_ID :
1848 pNewObj = new E3dCubeObj;
1849 *(E3dCubeObj*)pNewObj = *(E3dCubeObj*)pSubObj;
1850 break;
1852 case E3D_SPHEREOBJ_ID:
1853 pNewObj = new E3dSphereObj;
1854 *(E3dSphereObj*)pNewObj = *(E3dSphereObj*)pSubObj;
1855 break;
1857 case E3D_EXTRUDEOBJ_ID:
1858 pNewObj = new E3dExtrudeObj;
1859 *(E3dExtrudeObj*)pNewObj = *(E3dExtrudeObj*)pSubObj;
1860 break;
1862 case E3D_LATHEOBJ_ID:
1863 pNewObj = new E3dLatheObj;
1864 *(E3dLatheObj*)pNewObj = *(E3dLatheObj*)pSubObj;
1865 break;
1867 case E3D_COMPOUNDOBJ_ID:
1868 pNewObj = new E3dCompoundObject;
1869 *(E3dCompoundObject*)pNewObj = *(E3dCompoundObject*)pSubObj;
1870 break;
1873 Rectangle aBoundRect = pSubObj->GetCurrentBoundRect();
1875 basegfx::B3DHomMatrix aMatrix;
1876 aMatrix.translate(aBoundRect.Left() - aCenter.getX(), aCenter.getY(), 0.0);
1877 pNewObj->SetTransform(aMatrix * pNewObj->GetTransform()); // #112587#
1879 if (pNewObj) aBoundVol.expand(pNewObj->GetBoundVolume());
1880 pScene->Insert3DObj (pNewObj);
1884 nObj++;
1886 if (nObj < nCount)
1888 pObj = GetMarkedObjectByIndex(nObj);
1890 else
1892 pObj = NULL;
1896 double fW = aAllBoundRect.GetWidth();
1897 double fH = aAllBoundRect.GetHeight();
1898 Rectangle aRect(0,0, (long) fW, (long) fH);
1900 InitScene(pScene, fW, fH, aBoundVol.getMaxZ() + + ((fW + fH) / 4.0));
1901 pScene->NbcSetSnapRect(aRect);
1903 Camera3D &aCamera = (Camera3D&) pScene->GetCamera ();
1904 basegfx::B3DPoint aMinVec(aBoundVol.getMinimum());
1905 basegfx::B3DPoint aMaxVec(aBoundVol.getMaximum());
1906 double fDeepth(fabs(aMaxVec.getZ() - aMinVec.getZ()));
1908 aCamera.SetPRP(basegfx::B3DPoint(0.0, 0.0, 1000.0));
1909 double fDefaultCamPosZ(GetDefaultCamPosZ());
1910 aCamera.SetPosition(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ + fDeepth / 2.0));
1911 aCamera.SetFocalLength(GetDefaultCamFocal());
1912 pScene->SetCamera (aCamera);
1914 // SnapRects der Objekte ungueltig
1915 pScene->SetRectsDirty();
1917 InsertObjectAtView(pScene, *(GetSdrPageViewOfMarkedByIndex(0)));
1919 // SnapRects der Objekte ungueltig
1920 pScene->SetRectsDirty();
1924 /*************************************************************************
1926 |* Possibilities, hauptsaechlich gruppieren/ungruppieren
1928 \************************************************************************/
1929 void E3dView::CheckPossibilities()
1931 // call parent
1932 SdrView::CheckPossibilities();
1934 // Weitere Flags bewerten
1935 if(bGroupPossible || bUnGroupPossible || bGrpEnterPossible)
1937 INT32 nMarkCnt = GetMarkedObjectCount();
1938 BOOL bCoumpound = FALSE;
1939 BOOL b3DObject = FALSE;
1940 for(INT32 nObjs = 0L; (nObjs < nMarkCnt) && !bCoumpound; nObjs++)
1942 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1943 if(pObj && pObj->ISA(E3dCompoundObject))
1944 bCoumpound = TRUE;
1945 if(pObj && pObj->ISA(E3dObject))
1946 b3DObject = TRUE;
1949 // Bisher: Es sind ZWEI oder mehr beliebiger Objekte selektiert.
1950 // Nachsehen, ob CompoundObjects beteiligt sind. Falls ja,
1951 // das Gruppieren verbieten.
1952 if(bGroupPossible && bCoumpound)
1953 bGroupPossible = FALSE;
1955 if(bUnGroupPossible && b3DObject)
1956 bUnGroupPossible = FALSE;
1958 if(bGrpEnterPossible && bCoumpound)
1959 bGrpEnterPossible = FALSE;
1963 // eof