1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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 ////////////////////////////////////////////////////////////////////////////////////////////////////
88 class Impl3DMirrorConstructOverlay
91 ::sdr::overlay::OverlayObjectList maObjects
;
94 const E3dView
& mrView
;
99 // the unmirrored polygons
100 basegfx::B2DPolyPolygon
* mpPolygons
;
102 // the overlay geometry from selected objects
103 drawinglayer::primitive2d::Primitive2DSequence maFullOverlay
;
106 Impl3DMirrorConstructOverlay(const E3dView
& rView
);
107 ~Impl3DMirrorConstructOverlay();
109 void SetMirrorAxis(Point aMirrorAxisA
, Point aMirrorAxisB
);
112 Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView
& rView
)
115 mnCount(rView
.GetMarkedObjectCount()),
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()
133 for(sal_uInt32
a(0);a
< mnCount
;a
++)
135 SdrObject
* pObject
= mrView
.GetMarkedObjectByIndex(a
);
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
);
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())
172 void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA
, Point aMirrorAxisB
)
174 // get rid of old overlay objects
178 for(sal_uInt32
a(0); a
< mrView
.PaintWindowCount(); a
++)
180 SdrPaintWindow
* pCandidate
= mrView
.GetPaintWindow(a
);
181 ::sdr::overlay::OverlayManager
* pTargetOverlay
= pCandidate
->GetOverlayManager();
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
);
222 for(sal_uInt32
b(0); b
< mnCount
; b
++)
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 /*************************************************************************
241 \************************************************************************/
243 E3dView::E3dView(SdrModel
* pModel
, OutputDevice
* pOut
) :
244 SdrView(pModel
, pOut
)
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
))
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();
278 pScene
->SetSelected(FALSE
);
284 // SelectionFlag bei allen zu 3D Objekten gehoerigen
285 // Szenen und deren Objekten auf nicht selektiert setzen
287 for(nObjs
= 0;nObjs
< nCnt
;nObjs
++)
289 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
290 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
293 pScene
= ((E3dCompoundObject
*)pObj
)->GetScene();
295 pScene
->SetSelected(FALSE
);
299 // bei allen direkt selektierten Objekten auf selektiert setzen
302 for(nObjs
= 0;nObjs
< nCnt
;nObjs
++)
304 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
305 if(pObj
&& pObj
->ISA(E3dObject
))
308 E3dObject
* p3DObj
= (E3dObject
*)pObj
;
309 p3DObj
->SetSelected(TRUE
);
310 pScene
= p3DObj
->GetScene();
311 pM
= GetSdrMarkByIndex(nObjs
);
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
))
332 pScene
= ((E3dCompoundObject
*)pObj
)->GetScene();
334 pScene
->SetSelected(FALSE
);
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());
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();
383 pScene
->SetSelected(false);
388 if(!bSpecialHandling
)
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());
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();
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
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
;
484 SdrObjList
* pDstList
= pLst
;
485 ImpGetPasteObjList(aPos
, pDstList
);
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
);
523 bRetval
= SdrView::Paste(rMod
, rPos
, pLst
, nOptions
);
526 // und Rueckgabewert liefern
530 // #83403# Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
531 BOOL
E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene
* pSrcScene
, E3dScene
* pDstScene
, Point
/*aOffset*/)
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
));
549 E3dCompoundObject
* pNewCompoundObj
= dynamic_cast< E3dCompoundObject
* >(pCompoundObj
->Clone());
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());
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
));
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
));
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
));
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
);
631 if( GetModel()->IsUndoEnabled() )
632 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj
));
641 /*************************************************************************
643 |* 3D-Konvertierung moeglich?
645 \************************************************************************/
647 BOOL
E3dView::IsConvertTo3DObjPossible() const
650 BOOL
bGroupSelected(FALSE
);
653 for(sal_uInt32 a
=0;!bAny3D
&& a
<GetMarkedObjectCount();a
++)
655 SdrObject
*pObj
= GetMarkedObjectByIndex(a
);
658 ImpIsConvertTo3DPossible(pObj
, bAny3D
, bGroupSelected
);
664 IsConvertToPolyObjPossible(FALSE
)
665 || IsConvertToPathObjPossible(FALSE
)
666 || IsImportMtfPossible());
670 void E3dView::ImpIsConvertTo3DPossible(SdrObject
* pObj
, BOOL
& rAny3D
,
671 BOOL
& rGroupSelected
) const
675 if(pObj
->ISA(E3dObject
))
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
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
));
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
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
);
756 E3dDefaultAttributes aDefault
= Get3DDefaultAttributes();
758 aDefault
.SetDefaultExtrudeCharacterMode(TRUE
);
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
;
794 p3DObj
= new E3dExtrudeObj(aDefault
, pPath
->GetPathPoly(), fDepth
);
798 basegfx::B2DPolyPolygon
aPolyPoly2D(pPath
->GetPathPoly());
799 aPolyPoly2D
.transform(rLatheMat
);
800 p3DObj
= new E3dLatheObj(aDefault
, aPolyPoly2D
);
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
)
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
);
833 ImpChangeSomeAttributesFor3DConversion(pObj
);
835 // convert completely to path objects
836 SdrObject
* pNewObj1
= pObj
->ConvertToPolyObj(FALSE
, FALSE
);
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
);
851 ImpChangeSomeAttributesFor3DConversion2(pNewObj1
);
853 // convert completely to path objects
854 SdrObject
* pNewObj2
= pObj
->ConvertToContourObj(pNewObj1
, TRUE
);
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
);
869 ImpCreateSingle3DObjectFlat(pScene
, pNewObj2
, bExtrude
, fDepth
, rLatheMat
);
872 if(pNewObj2
!= pObj
&& pNewObj2
!= pNewObj1
&& pNewObj2
)
873 SdrObject::Free( pNewObj2
);
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())
895 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE
));
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
912 basegfx::B2DHomMatrix aLatheMat
;
916 double fW
= (double)aRect
.GetWidth();
917 double fH
= (double)aRect
.GetHeight();
918 fDepth
= sqrt(fW
*fW
+ fH
*fH
) / 6.0;
922 // Transformation fuer Polygone Rotationskoerper erstellen
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
)))
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);
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
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
;
965 aRot
= basegfx::B2DPoint(aTurnRect
.Left(), -aTurnRect
.Top());
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());
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());
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());
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
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
);
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
);
1056 // Es wurden keine 3D Objekte erzeugt, schmeiss alles weg
1060 // Undo abschliessen
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
))
1097 if(basegfx::tools::isInside(rPolygonA
, rPolygonB
))
1101 if(basegfx::tools::isInside(rPolygonB
, rPolygonA
))
1104 // A and B the same ?
1105 if(basegfx::tools::isInside(rPolygonB
, rPolygonA
, true))
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
);
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
1172 // Gibt es eine Ueberschneidung mit einem Objekt dieses
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
);
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
)
1201 else if(eLocalFillStyle
== XFILL_NONE
)
1213 // ja, beginne einen neuen Layer
1214 pLayer
->pDown
= new E3dDepthLayer
;
1215 pLayer
= pLayer
->pDown
;
1217 pLayer
->pNext
= new E3dDepthNeighbour
;
1218 pLayer
->pNext
->pObj
= pExtrudeObj
;
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
;
1231 // erster Layer ueberhaupt
1232 pBaseLayer
= new E3dDepthLayer
;
1233 pLayer
= pBaseLayer
;
1235 pLayer
->pNext
= new E3dDepthNeighbour
;
1236 pLayer
->pNext
->pObj
= pExtrudeObj
;
1241 // Anzahl Layer steht fest
1244 // Arrangement ist notwendig
1245 double fMinDepth
= fDepth
* 0.8;
1246 double fStep
= (fDepth
- fMinDepth
) / (double)nNumLayers
;
1247 pLayer
= pBaseLayer
;
1251 // an pLayer entlangspazieren
1252 E3dDepthNeighbour
* pAct
= pLayer
->pNext
;
1257 pAct
->pObj
->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH
, sal_uInt32(fMinDepth
+ 0.5)));
1259 // Naechster Eintrag
1264 pLayer
= pLayer
->pDown
;
1269 // angelegte Strukturen aufraeumen
1272 pLayer
= pBaseLayer
->pDown
;
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
);
1296 BOOL bOwnActionNecessary
;
1299 bOwnActionNecessary
= TRUE
;
1301 else if (pHdl
->IsVertexHdl() || pHdl
->IsCornerHdl())
1303 bOwnActionNecessary
= TRUE
;
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
);
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
:
1340 eConstraint
= E3DDRAG_CONSTR_X
;
1347 eConstraint
= E3DDRAG_CONSTR_Y
;
1356 eConstraint
= E3DDRAG_CONSTR_Z
;
1362 // die nicht erlaubten Rotationen ausmaskieren
1363 eConstraint
= E3dDragConstraint(eConstraint
& eDragConstraint
);
1364 pForcedMeth
= new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint
, IsSolidDragging());
1370 if(!bThereAreRootScenes
)
1372 pForcedMeth
= new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl
, eConstraint
, IsSolidDragging());
1378 case SDRDRAG_MIRROR
:
1380 case SDRDRAG_DISTORT
:
1381 case SDRDRAG_TRANSPARENCE
:
1382 case SDRDRAG_GRADIENT
:
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
);
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
);
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
1497 OutputDevice
* pOut
= GetFirstOutputDevice(); //GetWin(0);
1499 // erstmal Darstellungsgrenzen bestimmen
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
;
1512 if (nOutMax
- nOutMin
< nDst
)
1514 nOutMin
+= nOutMax
+ 1;
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
;
1550 if (nY2
< nY1
+ nMinLen
) nY2
= nY1
+ nMinLen
;
1555 if (nY1
> nY2
- nMinLen
) nY1
= nY2
- nMinLen
;
1559 aRef1
.X() = basegfx::fround(aR
.getMinX()); // Initial Achse um 2/100mm nach links
1561 aRef2
.X() = aRef1
.X();
1564 // Markierungen einschalten
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();
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
1605 SdrView::MovAction (rPnt
);
1606 mpMirrorOverlay
->SetMirrorAxis(
1607 aHdlList
.GetHdl (HDL_REF1
)->GetPos(),
1608 aHdlList
.GetHdl (HDL_REF2
)->GetPos());
1613 SdrView::MovAction (rPnt
);
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
);
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 /*************************************************************************
1671 \************************************************************************/
1673 E3dView::~E3dView ()
1677 /*************************************************************************
1679 |* beende das erzeugen und loesche die polygone
1681 \************************************************************************/
1683 void E3dView::ResetCreationActive ()
1687 delete mpMirrorOverlay
;
1688 mpMirrorOverlay
= 0L;
1692 /*************************************************************************
1694 |* Klasse initialisieren
1696 \************************************************************************/
1698 void E3dView::InitView ()
1700 eDragConstraint
= E3DDRAG_CONSTR_XYZ
;
1703 fDefaultScaleZ
= 1.0;
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();
1734 SdrObject
* pObj
= GetMarkedObjectByIndex(i
);
1736 if (pObj
&& pObj
->ISA(E3dObject
))
1738 if(!(((E3dObject
*)pObj
)->IsBreakObjPossible()))
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
);
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
);
1796 SdrAttrObj
* pNewObj
= pObj
->GetBreakObj();
1799 InsertObjectAtView(pNewObj
, *GetSdrPageView(), SDRINSERT_DONTMARK
);
1800 pNewObj
->SetChanged();
1801 pNewObj
->BroadcastObjectChange();
1806 /*************************************************************************
1810 \************************************************************************/
1812 void E3dView::MergeScenes ()
1814 ULONG nCount
= GetMarkedObjectCount();
1819 SdrObject
*pObj
= GetMarkedObjectByIndex(nObj
);
1820 E3dScene
*pScene
= new E3dPolyScene(Get3DDefaultAttributes());
1821 basegfx::B3DRange aBoundVol
;
1822 Rectangle
aAllBoundRect (GetMarkedObjBoundRect ());
1823 Point
aCenter (aAllBoundRect
.Center());
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
;
1852 case E3D_SPHEREOBJ_ID
:
1853 pNewObj
= new E3dSphereObj
;
1854 *(E3dSphereObj
*)pNewObj
= *(E3dSphereObj
*)pSubObj
;
1857 case E3D_EXTRUDEOBJ_ID
:
1858 pNewObj
= new E3dExtrudeObj
;
1859 *(E3dExtrudeObj
*)pNewObj
= *(E3dExtrudeObj
*)pSubObj
;
1862 case E3D_LATHEOBJ_ID
:
1863 pNewObj
= new E3dLatheObj
;
1864 *(E3dLatheObj
*)pNewObj
= *(E3dLatheObj
*)pSubObj
;
1867 case E3D_COMPOUNDOBJ_ID
:
1868 pNewObj
= new E3dCompoundObject
;
1869 *(E3dCompoundObject
*)pNewObj
= *(E3dCompoundObject
*)pSubObj
;
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
);
1888 pObj
= GetMarkedObjectByIndex(nObj
);
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()
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
))
1945 if(pObj
&& pObj
->ISA(E3dObject
))
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
;