1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/wrkwin.hxx>
22 #include <svx/svdogrp.hxx>
23 #include <svx/svdopath.hxx>
24 #include "svx/svditer.hxx"
25 #include <svx/svdpool.hxx>
26 #include <svx/svdorect.hxx>
27 #include <svx/svdmodel.hxx>
28 #include <svx/svdpagv.hxx>
29 #include <svx/svxids.hrc>
30 #include <editeng/colritem.hxx>
31 #include <svx/xtable.hxx>
32 #include <svx/svdview.hxx>
33 #include <svx/dialogs.hrc>
34 #include <svx/dialmgr.hxx>
35 #include "svx/globl3d.hxx"
36 #include <svx/obj3d.hxx>
37 #include <svx/lathe3d.hxx>
38 #include <svx/sphere3d.hxx>
39 #include <svx/extrud3d.hxx>
40 #include <svx/cube3d.hxx>
41 #include <svx/polysc3d.hxx>
42 #include "dragmt3d.hxx"
43 #include <svx/view3d.hxx>
44 #include <svx/svdundo.hxx>
45 #include <svx/xflclit.hxx>
46 #include <svx/xlnclit.hxx>
47 #include <svx/svdograf.hxx>
48 #include <svx/xbtmpit.hxx>
49 #include <svx/xflbmtit.hxx>
50 #include <basegfx/range/b2drange.hxx>
51 #include <basegfx/polygon/b2dpolygontools.hxx>
52 #include <basegfx/polygon/b2dpolypolygontools.hxx>
53 #include <svx/xlnwtit.hxx>
54 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
55 #include <svx/sdr/overlay/overlaymanager.hxx>
56 #include <svx/sdrpaintwindow.hxx>
57 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
58 #include <drawinglayer/geometry/viewinformation3d.hxx>
59 #include <svx/sdrpagewindow.hxx>
60 #include <svx/sdr/contact/displayinfo.hxx>
61 #include <svx/sdr/contact/objectcontact.hxx>
62 #include <svx/sdr/contact/viewobjectcontact.hxx>
63 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
64 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
65 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
66 #include <basegfx/matrix/b2dhommatrixtools.hxx>
67 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
69 using namespace com::sun::star
;
71 #define ITEMVALUE(ItemSet,Id,Cast) (static_cast<const Cast&>((ItemSet).Get(Id))).GetValue()
73 TYPEINIT1(E3dView
, SdrView
);
78 class Impl3DMirrorConstructOverlay
81 sdr::overlay::OverlayObjectList maObjects
;
84 const E3dView
& mrView
;
89 // the unmirrored polygons
90 basegfx::B2DPolyPolygon
* mpPolygons
;
92 // the overlay geometry from selected objects
93 drawinglayer::primitive2d::Primitive2DSequence maFullOverlay
;
96 Impl3DMirrorConstructOverlay(const E3dView
& rView
);
97 ~Impl3DMirrorConstructOverlay();
99 void SetMirrorAxis(Point aMirrorAxisA
, Point aMirrorAxisB
);
102 Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView
& rView
)
105 mnCount(rView
.GetMarkedObjectCount()),
111 if(mrView
.IsSolidDragging())
113 SdrPageView
* pPV
= rView
.GetSdrPageView();
115 if(pPV
&& pPV
->PageWindowCount())
117 sdr::contact::ObjectContact
& rOC
= pPV
->GetPageWindow(0)->GetObjectContact();
118 sdr::contact::DisplayInfo aDisplayInfo
;
120 // Do not use the last ViewPort set at the OC at the last ProcessDisplay()
123 for(size_t a
= 0; a
< mnCount
; ++a
)
125 SdrObject
* pObject
= mrView
.GetMarkedObjectByIndex(a
);
129 sdr::contact::ViewContact
& rVC
= pObject
->GetViewContact();
130 sdr::contact::ViewObjectContact
& rVOC
= rVC
.GetViewObjectContact(rOC
);
132 const drawinglayer::primitive2d::Primitive2DSequence
aNewSequence(rVOC
.getPrimitive2DSequenceHierarchy(aDisplayInfo
));
133 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay
, aNewSequence
);
140 mpPolygons
= new basegfx::B2DPolyPolygon
[mnCount
];
142 for(size_t a
= 0; a
< mnCount
; ++a
)
144 SdrObject
* pObject
= mrView
.GetMarkedObjectByIndex(a
);
145 mpPolygons
[mnCount
- (a
+ 1)] = pObject
->TakeXorPoly();
151 Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
153 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
154 // That destructor calls clear() at the list which removes all objects from the
155 // OverlayManager and deletes them.
156 if(!mrView
.IsSolidDragging())
162 void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA
, Point aMirrorAxisB
)
164 // get rid of old overlay objects
168 for(sal_uInt32
a(0); a
< mrView
.PaintWindowCount(); a
++)
170 SdrPaintWindow
* pCandidate
= mrView
.GetPaintWindow(a
);
171 rtl::Reference
< sdr::overlay::OverlayManager
> xTargetOverlay
= pCandidate
->GetOverlayManager();
173 if(xTargetOverlay
.is())
175 // buld transfoprmation: translate and rotate so that given edge is
176 // on x axis, them mirror in y and translate back
177 const basegfx::B2DVector
aEdge(aMirrorAxisB
.X() - aMirrorAxisA
.X(), aMirrorAxisB
.Y() - aMirrorAxisA
.Y());
178 basegfx::B2DHomMatrix
aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(
179 -aMirrorAxisA
.X(), -aMirrorAxisA
.Y()));
180 aMatrixTransform
.rotate(-atan2(aEdge
.getY(), aEdge
.getX()));
181 aMatrixTransform
.scale(1.0, -1.0);
182 aMatrixTransform
.rotate(atan2(aEdge
.getY(), aEdge
.getX()));
183 aMatrixTransform
.translate(aMirrorAxisA
.X(), aMirrorAxisA
.Y());
185 if(mrView
.IsSolidDragging())
187 if(maFullOverlay
.hasElements())
189 drawinglayer::primitive2d::Primitive2DSequence
aContent(maFullOverlay
);
191 if(!aMatrixTransform
.isIdentity())
193 // embed in transformation group
194 drawinglayer::primitive2d::Primitive2DReference
aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform
, aContent
));
195 aContent
= drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D
, 1);
198 // if we have full overlay from selected objects, embed with 50% transparence, the
199 // transformation is added to the OverlayPrimitive2DSequenceObject
200 drawinglayer::primitive2d::Primitive2DReference
aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aContent
, 0.5));
201 aContent
= drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D
, 1);
203 sdr::overlay::OverlayPrimitive2DSequenceObject
* pNew
= new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent
);
205 xTargetOverlay
->add(*pNew
);
206 maObjects
.append(*pNew
);
211 for(size_t b
= 0; b
< mnCount
; ++b
)
214 basegfx::B2DPolyPolygon
aPolyPolygon(mpPolygons
[b
]);
215 aPolyPolygon
.transform(aMatrixTransform
);
217 sdr::overlay::OverlayPolyPolygonStripedAndFilled
* pNew
= new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
219 xTargetOverlay
->add(*pNew
);
220 maObjects
.append(*pNew
);
227 E3dView::E3dView(SdrModel
* pModel
, OutputDevice
* pOut
) :
228 SdrView(pModel
, pOut
)
233 // DrawMarkedObj override, since possibly only a single 3D object is to be
236 void E3dView::DrawMarkedObj(OutputDevice
& rOut
) const
238 // Does 3D objects exist which scenes are not selected?
239 bool bSpecialHandling
= false;
240 E3dScene
*pScene
= NULL
;
242 const size_t nCnt
= GetMarkedObjectCount();
243 for(size_t nObjs
= 0; nObjs
< nCnt
; ++nObjs
)
245 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
246 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
249 pScene
= static_cast<E3dCompoundObject
*>(pObj
)->GetScene();
250 if(pScene
&& !IsObjMarked(pScene
))
251 bSpecialHandling
= true;
253 // Reset all selection flags
254 if(pObj
&& pObj
->ISA(E3dObject
))
256 pScene
= static_cast<E3dObject
*>(pObj
)->GetScene();
258 pScene
->SetSelected(false);
264 // Set selection flag to "not selected" for scenes related to all 3D
266 for(size_t nObjs
= 0; nObjs
< nCnt
; ++nObjs
)
268 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
269 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
272 pScene
= static_cast<E3dCompoundObject
*>(pObj
)->GetScene();
274 pScene
->SetSelected(false);
278 for(size_t nObjs
= 0; nObjs
< nCnt
; ++nObjs
)
280 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
281 if(pObj
&& pObj
->ISA(E3dObject
))
284 E3dObject
* p3DObj
= static_cast<E3dObject
*>(pObj
);
285 p3DObj
->SetSelected(true);
286 pScene
= p3DObj
->GetScene();
295 pScene
->SetDrawOnlySelected(true);
296 pScene
->SingleObjectPainter(rOut
);
297 pScene
->SetDrawOnlySelected(false);
300 // Reset selection flag
301 for(size_t nObjs
= 0; nObjs
< nCnt
; ++nObjs
)
303 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
304 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
307 pScene
= static_cast<E3dCompoundObject
*>(pObj
)->GetScene();
309 pScene
->SetSelected(false);
316 SdrExchangeView::DrawMarkedObj(rOut
);
320 // override get model, since in some 3D objects an additional scene
323 SdrModel
* E3dView::GetMarkedObjModel() const
325 // Does 3D objects exist which scenes are not selected?
326 bool bSpecialHandling(false);
327 const size_t nCount(GetMarkedObjectCount());
328 E3dScene
*pScene
= 0;
330 for(size_t nObjs
= 0; nObjs
< nCount
; ++nObjs
)
332 const SdrObject
* pObj
= GetMarkedObjectByIndex(nObjs
);
334 if(!bSpecialHandling
&& pObj
&& pObj
->ISA(E3dCompoundObject
))
336 // if the object is selected, but it's scene not,
337 // we need special handling
338 pScene
= static_cast<const E3dCompoundObject
*>(pObj
)->GetScene();
340 if(pScene
&& !IsObjMarked(pScene
))
342 bSpecialHandling
= true;
346 if(pObj
&& pObj
->ISA(E3dObject
))
348 // reset all selection flags at 3D objects
349 pScene
= static_cast<const E3dObject
*>(pObj
)->GetScene();
353 pScene
->SetSelected(false);
358 if(!bSpecialHandling
)
361 return SdrView::GetMarkedObjModel();
364 SdrModel
* pNewModel
= 0;
365 Rectangle aSelectedSnapRect
;
367 // set 3d selection flags at all directly selected objects
368 // and collect SnapRect of selected objects
369 for(size_t nObjs
= 0; nObjs
< nCount
; ++nObjs
)
371 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
373 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
375 // mark object, but not scenes
376 E3dCompoundObject
* p3DObj
= static_cast<E3dCompoundObject
*>(pObj
);
377 p3DObj
->SetSelected(true);
378 aSelectedSnapRect
.Union(p3DObj
->GetSnapRect());
382 // create new mark list which contains all indirectly selected3d
383 // scenes as selected objects
384 SdrMarkList
aOldML(GetMarkedObjectList());
386 SdrMarkList
& rCurrentMarkList
= const_cast<E3dView
*>(this)->GetMarkedObjectListWriteAccess();
387 rCurrentMarkList
= aNewML
;
389 for(size_t nObjs
= 0; nObjs
< nCount
; ++nObjs
)
391 SdrObject
*pObj
= aOldML
.GetMark(nObjs
)->GetMarkedSdrObj();
393 if(pObj
&& pObj
->ISA(E3dObject
))
395 pScene
= static_cast<E3dObject
*>(pObj
)->GetScene();
397 if(pScene
&& !IsObjMarked(pScene
) && GetSdrPageView())
399 const_cast<E3dView
*>(this)->MarkObj(pScene
, GetSdrPageView(), false, true);
404 // call parent. This will copy all scenes and the selection flags at the 3d objectss. So
405 // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes
406 pNewModel
= SdrView::GetMarkedObjModel();
410 for(sal_uInt16
nPg(0); nPg
< pNewModel
->GetPageCount(); nPg
++)
412 const SdrPage
* pSrcPg
=pNewModel
->GetPage(nPg
);
413 const size_t nObjCount(pSrcPg
->GetObjCount());
415 for(size_t nOb
= 0; nOb
< nObjCount
; ++nOb
)
417 const SdrObject
* pSrcOb
=pSrcPg
->GetObj(nOb
);
419 if(pSrcOb
->ISA(E3dScene
))
421 pScene
= const_cast<E3dScene
*>(static_cast<const E3dScene
*>(pSrcOb
));
423 // delete all not intentionally cloned 3d objects
424 pScene
->removeAllNonSelectedObjects();
426 // reset select flags and set SnapRect of all selected objects
427 pScene
->SetSelected(false);
428 pScene
->SetSnapRect(aSelectedSnapRect
);
434 // restore old selection
435 rCurrentMarkList
= aOldML
;
440 // When pasting objects have to integrated if a scene is inserted, but
441 // not the scene itself
444 const SdrModel
& rMod
, const Point
& rPos
, SdrObjList
* pLst
, SdrInsertFlags nOptions
,
445 const OUString
& rSrcShellID
, const OUString
& rDestShellID
)
447 bool bRetval
= false;
451 SdrObjList
* pDstList
= pLst
;
452 ImpGetPasteObjList(aPos
, pDstList
);
457 // Get owner of the list
458 SdrObject
* pOwner
= pDstList
->GetOwnerObj();
459 if(pOwner
&& pOwner
->ISA(E3dScene
))
461 E3dScene
* pDstScene
= static_cast<E3dScene
*>(pOwner
);
462 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE
));
464 // Copy all objects from E3dScenes and insert them directly
465 for(sal_uInt16
nPg(0); nPg
< rMod
.GetPageCount(); nPg
++)
467 const SdrPage
* pSrcPg
=rMod
.GetPage(nPg
);
468 const size_t nObjCount(pSrcPg
->GetObjCount());
470 // calculate offset for paste
471 Rectangle aR
= pSrcPg
->GetAllObjBoundRect();
472 Point
aDist(aPos
- aR
.Center());
474 // Insert sub-objects for scenes
475 for(size_t nOb
= 0; nOb
< nObjCount
; ++nOb
)
477 const SdrObject
* pSrcOb
= pSrcPg
->GetObj(nOb
);
478 if(pSrcOb
->ISA(E3dScene
))
480 E3dScene
* pSrcScene
= const_cast<E3dScene
*>(static_cast<const E3dScene
*>(pSrcOb
));
481 ImpCloneAll3DObjectsToDestScene(pSrcScene
, pDstScene
, aDist
);
490 bRetval
= SdrView::Paste(rMod
, rPos
, pLst
, nOptions
, rSrcShellID
, rDestShellID
);
496 // Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
497 bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene
* pSrcScene
, E3dScene
* pDstScene
, Point
/*aOffset*/)
501 if(pSrcScene
&& pDstScene
)
503 const sdr::contact::ViewContactOfE3dScene
& rVCSceneDst
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pDstScene
->GetViewContact());
504 const drawinglayer::geometry::ViewInformation3D
aViewInfo3DDst(rVCSceneDst
.getViewInformation3D());
505 const sdr::contact::ViewContactOfE3dScene
& rVCSceneSrc
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pSrcScene
->GetViewContact());
506 const drawinglayer::geometry::ViewInformation3D
aViewInfo3DSrc(rVCSceneSrc
.getViewInformation3D());
508 for(size_t i
= 0; i
< pSrcScene
->GetSubList()->GetObjCount(); ++i
)
510 E3dCompoundObject
* pCompoundObj
= dynamic_cast< E3dCompoundObject
* >(pSrcScene
->GetSubList()->GetObj(i
));
514 E3dCompoundObject
* pNewCompoundObj
= dynamic_cast< E3dCompoundObject
* >(pCompoundObj
->Clone());
518 // get dest scene's current range in 3D world coordinates
519 const basegfx::B3DHomMatrix
aSceneToWorldTrans(pDstScene
->GetFullTransform());
520 basegfx::B3DRange
aSceneRange(pDstScene
->GetBoundVolume());
521 aSceneRange
.transform(aSceneToWorldTrans
);
523 // get new object's implied object transformation
524 const basegfx::B3DHomMatrix
aNewObjectTrans(pNewCompoundObj
->GetTransform());
526 // get new object's range in 3D world coordinates in dest scene
527 // as if it were already added
528 const basegfx::B3DHomMatrix
aObjectToWorldTrans(aSceneToWorldTrans
* aNewObjectTrans
);
529 basegfx::B3DRange
aObjectRange(pNewCompoundObj
->GetBoundVolume());
530 aObjectRange
.transform(aObjectToWorldTrans
);
532 // get scale adaption
533 const basegfx::B3DVector
aSceneScale(aSceneRange
.getRange());
534 const basegfx::B3DVector
aObjectScale(aObjectRange
.getRange());
537 // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
538 // to not change the scene by the inserted object
539 const double fSizeFactor(0.5);
541 if(aObjectScale
.getX() * fScale
> aSceneScale
.getX() * fSizeFactor
)
543 const double fObjSize(aObjectScale
.getX() * fScale
);
544 const double fFactor((aSceneScale
.getX() * fSizeFactor
) / (basegfx::fTools::equalZero(fObjSize
) ? 1.0 : fObjSize
));
548 if(aObjectScale
.getY() * fScale
> aSceneScale
.getY() * fSizeFactor
)
550 const double fObjSize(aObjectScale
.getY() * fScale
);
551 const double fFactor((aSceneScale
.getY() * fSizeFactor
) / (basegfx::fTools::equalZero(fObjSize
) ? 1.0 : fObjSize
));
555 if(aObjectScale
.getZ() * fScale
> aSceneScale
.getZ() * fSizeFactor
)
557 const double fObjSize(aObjectScale
.getZ() * fScale
);
558 const double fFactor((aSceneScale
.getZ() * fSizeFactor
) / (basegfx::fTools::equalZero(fObjSize
) ? 1.0 : fObjSize
));
562 // get translation adaption
563 const basegfx::B3DPoint
aSceneCenter(aSceneRange
.getCenter());
564 const basegfx::B3DPoint
aObjectCenter(aObjectRange
.getCenter());
566 // build full modification transform. The object's transformation
567 // shall be modified, so start at object coordinates; transform to 3d world coor
568 basegfx::B3DHomMatrix
aModifyingTransform(aObjectToWorldTrans
);
570 // translate to absolute center in 3d world coor
571 aModifyingTransform
.translate(-aObjectCenter
.getX(), -aObjectCenter
.getY(), -aObjectCenter
.getZ());
573 // scale to dest size in 3d world coor
574 aModifyingTransform
.scale(fScale
, fScale
, fScale
);
576 // translate to dest scene center in 3d world coor
577 aModifyingTransform
.translate(aSceneCenter
.getX(), aSceneCenter
.getY(), aSceneCenter
.getZ());
579 // transform from 3d world to dest object coordinates
580 basegfx::B3DHomMatrix
aWorldToObject(aObjectToWorldTrans
);
581 aWorldToObject
.invert();
582 aModifyingTransform
= aWorldToObject
* aModifyingTransform
;
584 // correct implied object transform by applying changing one in object coor
585 pNewCompoundObj
->SetTransform(aModifyingTransform
* aNewObjectTrans
);
587 // fill and insert new object
588 pNewCompoundObj
->SetModel(pDstScene
->GetModel());
589 pNewCompoundObj
->SetPage(pDstScene
->GetPage());
590 pNewCompoundObj
->NbcSetLayer(pCompoundObj
->GetLayer());
591 pNewCompoundObj
->NbcSetStyleSheet(pCompoundObj
->GetStyleSheet(), true);
592 pDstScene
->Insert3DObj(pNewCompoundObj
);
596 if( GetModel()->IsUndoEnabled() )
597 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj
));
606 bool E3dView::IsConvertTo3DObjPossible() const
609 bool bGroupSelected(false);
612 for(size_t a
=0; !bAny3D
&& a
<GetMarkedObjectCount(); ++a
)
614 SdrObject
*pObj
= GetMarkedObjectByIndex(a
);
617 ImpIsConvertTo3DPossible(pObj
, bAny3D
, bGroupSelected
);
623 IsConvertToPolyObjPossible(false)
624 || IsConvertToPathObjPossible(false)
625 || IsImportMtfPossible());
629 void E3dView::ImpIsConvertTo3DPossible(SdrObject
* pObj
, bool& rAny3D
,
630 bool& rGroupSelected
) const
634 if(pObj
->ISA(E3dObject
))
640 if(pObj
->IsGroupObject())
642 SdrObjListIter
aIter(*pObj
, IM_DEEPNOGROUPS
);
643 while(aIter
.IsMore())
645 SdrObject
* pNewObj
= aIter
.Next();
646 ImpIsConvertTo3DPossible(pNewObj
, rAny3D
, rGroupSelected
);
648 rGroupSelected
= true;
654 #include <editeng/eeitem.hxx>
656 void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject
* pObj
)
658 if(pObj
->ISA(SdrTextObj
))
660 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
661 const SvxColorItem
& rTextColorItem
= static_cast<const SvxColorItem
&>(rSet
.Get(EE_CHAR_COLOR
));
662 if(rTextColorItem
.GetValue() == RGB_Color(COL_BLACK
))
664 //For black text objects, the color set to gray
667 // if black is only default attribute from
668 // pattern set it hard so that it is used in undo.
669 pObj
->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK
), EE_CHAR_COLOR
));
672 if( GetModel()->IsUndoEnabled() )
673 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
, false, false));
676 pObj
->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY
), EE_CHAR_COLOR
));
681 void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject
* pObj
)
683 if(pObj
->ISA(SdrPathObj
))
685 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
686 sal_Int32 nLineWidth
= static_cast<const XLineWidthItem
&>(rSet
.Get(XATTR_LINEWIDTH
)).GetValue();
687 drawing::LineStyle eLineStyle
= (drawing::LineStyle
)static_cast<const XLineStyleItem
&>(rSet
.Get(XATTR_LINESTYLE
)).GetValue();
688 drawing::FillStyle eFillStyle
= ITEMVALUE(rSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
690 if(static_cast<SdrPathObj
*>(pObj
)->IsClosed()
691 && eLineStyle
== drawing::LineStyle_SOLID
693 && eFillStyle
!= drawing::FillStyle_NONE
)
695 if(pObj
->GetPage() && GetModel()->IsUndoEnabled() )
696 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
, false, false));
697 pObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
698 pObj
->SetMergedItem(XLineWidthItem(0L));
703 void E3dView::ImpCreateSingle3DObjectFlat(E3dScene
* pScene
, SdrObject
* pObj
, bool bExtrude
, double fDepth
, basegfx::B2DHomMatrix
& rLatheMat
)
705 // Single PathObject, transform this
706 SdrPathObj
* pPath
= PTR_CAST(SdrPathObj
, pObj
);
710 E3dDefaultAttributes aDefault
= Get3DDefaultAttributes();
712 aDefault
.SetDefaultExtrudeCharacterMode(true);
714 aDefault
.SetDefaultLatheCharacterMode(true);
716 // Get Itemset of the original object
717 SfxItemSet
aSet(pObj
->GetMergedItemSet());
719 drawing::FillStyle eFillStyle
= ITEMVALUE(aSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
721 // line style turned off
722 aSet
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
724 //Determining if FILL_Attribut is set.
725 if(!pPath
->IsClosed() || eFillStyle
== drawing::FillStyle_NONE
)
727 // This SdrPathObj is not filled, leave the front and rear face out.
728 // Moreover, a two-sided representation necessary.
729 aDefault
.SetDefaultExtrudeCloseFront(false);
730 aDefault
.SetDefaultExtrudeCloseBack(false);
732 aSet
.Put(makeSvx3DDoubleSidedItem(true));
734 // Set fill attribute
735 aSet
.Put(XFillStyleItem(drawing::FillStyle_SOLID
));
737 // Fill color must be the color line, because the object was
738 // previously just a line
739 Color aColorLine
= static_cast<const XLineColorItem
&>(aSet
.Get(XATTR_LINECOLOR
)).GetColorValue();
740 aSet
.Put(XFillColorItem(OUString(), aColorLine
));
743 // Create a new extrude object
744 E3dObject
* p3DObj
= NULL
;
747 p3DObj
= new E3dExtrudeObj(aDefault
, pPath
->GetPathPoly(), fDepth
);
751 basegfx::B2DPolyPolygon
aPolyPoly2D(pPath
->GetPathPoly());
752 aPolyPoly2D
.transform(rLatheMat
);
753 p3DObj
= new E3dLatheObj(aDefault
, aPolyPoly2D
);
759 p3DObj
->NbcSetLayer(pObj
->GetLayer());
761 p3DObj
->SetMergedItemSet(aSet
);
763 p3DObj
->NbcSetStyleSheet(pObj
->GetStyleSheet(), true);
765 // Insert a new extrude object
766 pScene
->Insert3DObj(p3DObj
);
771 void E3dView::ImpCreate3DObject(E3dScene
* pScene
, SdrObject
* pObj
, bool bExtrude
, double fDepth
, basegfx::B2DHomMatrix
& rLatheMat
)
775 // change text color attribute for not so dark colors
776 if(pObj
->IsGroupObject())
778 SdrObjListIter
aIter(*pObj
, IM_DEEPWITHGROUPS
);
779 while(aIter
.IsMore())
781 SdrObject
* pGroupMember
= aIter
.Next();
782 ImpChangeSomeAttributesFor3DConversion(pGroupMember
);
786 ImpChangeSomeAttributesFor3DConversion(pObj
);
788 // convert completely to path objects
789 SdrObject
* pNewObj1
= pObj
->ConvertToPolyObj(false, false);
793 // change text color attribute for not so dark colors
794 if(pNewObj1
->IsGroupObject())
796 SdrObjListIter
aIter(*pNewObj1
, IM_DEEPWITHGROUPS
);
797 while(aIter
.IsMore())
799 SdrObject
* pGroupMember
= aIter
.Next();
800 ImpChangeSomeAttributesFor3DConversion2(pGroupMember
);
804 ImpChangeSomeAttributesFor3DConversion2(pNewObj1
);
806 // convert completely to path objects
807 SdrObject
* pNewObj2
= pObj
->ConvertToContourObj(pNewObj1
, true);
811 // add all to flat scene
812 if(pNewObj2
->IsGroupObject())
814 SdrObjListIter
aIter(*pNewObj2
, IM_DEEPWITHGROUPS
);
815 while(aIter
.IsMore())
817 SdrObject
* pGroupMember
= aIter
.Next();
818 ImpCreateSingle3DObjectFlat(pScene
, pGroupMember
, bExtrude
, fDepth
, rLatheMat
);
822 ImpCreateSingle3DObjectFlat(pScene
, pNewObj2
, bExtrude
, fDepth
, rLatheMat
);
824 // delete object in between
825 if(pNewObj2
!= pObj
&& pNewObj2
!= pNewObj1
&& pNewObj2
)
826 SdrObject::Free( pNewObj2
);
829 // delete object in between
830 if(pNewObj1
!= pObj
&& pNewObj1
)
831 SdrObject::Free( pNewObj1
);
836 void E3dView::ConvertMarkedObjTo3D(bool bExtrude
, const basegfx::B2DPoint
& rPnt1
, const basegfx::B2DPoint
& rPnt2
)
838 if(AreObjectsMarked())
842 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE
));
844 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE
));
846 // Create a new scene for the created 3D object
847 E3dScene
* pScene
= new E3dPolyScene(Get3DDefaultAttributes());
849 // Determine rectangle and possibly correct it
850 Rectangle aRect
= GetAllMarkedRect();
851 if(aRect
.GetWidth() <= 1)
852 aRect
.SetSize(Size(500, aRect
.GetHeight()));
853 if(aRect
.GetHeight() <= 1)
854 aRect
.SetSize(Size(aRect
.GetWidth(), 500));
856 // Determine the depth relative to the size of the selection
859 basegfx::B2DHomMatrix aLatheMat
;
863 double fW
= (double)aRect
.GetWidth();
864 double fH
= (double)aRect
.GetHeight();
865 fDepth
= sqrt(fW
*fW
+ fH
*fH
) / 6.0;
869 // Create transformation for the polygons rotating body
872 // Rotation around control point #1 with set angle
873 // for 3D coordinates
874 basegfx::B2DPoint
aDiff(rPnt1
- rPnt2
);
875 fRot3D
= atan2(aDiff
.getY(), aDiff
.getX()) - F_PI2
;
877 if(basegfx::fTools::equalZero(fabs(fRot3D
)))
882 aLatheMat
= basegfx::tools::createRotateAroundPoint(rPnt2
, -fRot3D
)
887 if (rPnt2
.getX() != 0.0)
889 // Translation to Y=0 - axis
890 aLatheMat
.translate(-rPnt2
.getX(), 0.0);
894 aLatheMat
.translate((double)-aRect
.Left(), 0.0);
897 // Form the inverse matrix to determine the target expansion
898 basegfx::B2DHomMatrix
aInvLatheMat(aLatheMat
);
899 aInvLatheMat
.invert();
901 // SnapRect extension enables mirroring in the axis of rotation
902 for(size_t a
=0; a
<GetMarkedObjectCount(); ++a
)
904 SdrMark
* pMark
= GetSdrMarkByIndex(a
);
905 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
906 Rectangle aTurnRect
= pObj
->GetSnapRect();
907 basegfx::B2DPoint aRot
;
910 aRot
= basegfx::B2DPoint(aTurnRect
.Left(), -aTurnRect
.Top());
912 aRot
.setX(-aRot
.getX());
913 aRot
*= aInvLatheMat
;
914 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
915 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
917 aRot
= basegfx::B2DPoint(aTurnRect
.Left(), -aTurnRect
.Bottom());
919 aRot
.setX(-aRot
.getX());
920 aRot
*= aInvLatheMat
;
921 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
922 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
924 aRot
= basegfx::B2DPoint(aTurnRect
.Right(), -aTurnRect
.Top());
926 aRot
.setX(-aRot
.getX());
927 aRot
*= aInvLatheMat
;
928 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
929 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
931 aRot
= basegfx::B2DPoint(aTurnRect
.Right(), -aTurnRect
.Bottom());
933 aRot
.setX(-aRot
.getX());
934 aRot
*= aInvLatheMat
;
935 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
936 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
940 // Walk through the selection and convert it into 3D, complete with
941 // Conversion to SdrPathObject, also fonts
942 for(size_t a
=0; a
<GetMarkedObjectCount(); ++a
)
944 SdrMark
* pMark
= GetSdrMarkByIndex(a
);
945 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
947 ImpCreate3DObject(pScene
, pObj
, bExtrude
, fDepth
, aLatheMat
);
950 if(pScene
->GetSubList() && pScene
->GetSubList()->GetObjCount() != 0)
952 // Arrange all created objects by depth
954 DoDepthArrange(pScene
, fDepth
);
956 // Center 3D objects in the middle of the overall rectangle
957 basegfx::B3DPoint
aCenter(pScene
->GetBoundVolume().getCenter());
958 basegfx::B3DHomMatrix aMatrix
;
960 aMatrix
.translate(-aCenter
.getX(), -aCenter
.getY(), -aCenter
.getZ());
961 pScene
->SetTransform(aMatrix
* pScene
->GetTransform());
964 pScene
->NbcSetSnapRect(aRect
);
965 basegfx::B3DRange aBoundVol
= pScene
->GetBoundVolume();
966 InitScene(pScene
, (double)aRect
.GetWidth(), (double)aRect
.GetHeight(), aBoundVol
.getDepth());
968 // Insert scene instead of the first selected object and throw away
969 // all the old objects
970 SdrObject
* pRepObj
= GetMarkedObjectByIndex(0);
971 SdrPageView
* pPV
= GetSdrPageViewOfMarkedByIndex(0);
972 MarkObj(pRepObj
, pPV
, true);
973 ReplaceObjectAtView(pRepObj
, *pPV
, pScene
, false);
975 MarkObj(pScene
, pPV
);
977 // Rotate Rotation body around the axis of rotation
978 basegfx::B3DHomMatrix aRotate
;
980 if(!bExtrude
&& fRot3D
!= 0.0)
982 aRotate
.rotate(0.0, 0.0, fRot3D
);
985 // Set default rotation
987 double XRotateDefault
= 20;
988 aRotate
.rotate(DEG2RAD(XRotateDefault
), 0.0, 0.0);
991 if(!aRotate
.isIdentity())
993 pScene
->SetTransform(aRotate
* pScene
->GetTransform());
996 // Invalid SnapRects of objects
997 pScene
->SetSnapRect(aRect
);
1001 // No 3D object was created, throw away everything
1009 //Arrange all created extrude objects by depth
1011 struct E3dDepthNeighbour
1013 E3dDepthNeighbour
* mpNext
;
1014 E3dExtrudeObj
* mpObj
;
1015 basegfx::B2DPolyPolygon maPreparedPolyPolygon
;
1020 maPreparedPolyPolygon()
1025 struct E3dDepthLayer
1027 E3dDepthLayer
* mpDown
;
1028 E3dDepthNeighbour
* mpNext
;
1040 E3dDepthNeighbour
* pSucc
= mpNext
->mpNext
;
1047 void E3dView::DoDepthArrange(E3dScene
* pScene
, double fDepth
)
1049 if(pScene
&& pScene
->GetSubList() && pScene
->GetSubList()->GetObjCount() > 1)
1051 SdrObjList
* pSubList
= pScene
->GetSubList();
1052 SdrObjListIter
aIter(*pSubList
, IM_FLAT
);
1053 E3dDepthLayer
* pBaseLayer
= NULL
;
1054 E3dDepthLayer
* pLayer
= NULL
;
1055 sal_Int32 nNumLayers
= 0;
1057 while(aIter
.IsMore())
1059 E3dExtrudeObj
* pExtrudeObj
= dynamic_cast< E3dExtrudeObj
* >(aIter
.Next());
1063 const basegfx::B2DPolyPolygon
aExtrudePoly(
1064 basegfx::tools::prepareForPolygonOperation(pExtrudeObj
->GetExtrudePolygon()));
1065 const SfxItemSet
& rLocalSet
= pExtrudeObj
->GetMergedItemSet();
1066 const drawing::FillStyle eLocalFillStyle
= ITEMVALUE(rLocalSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
1067 const Color aLocalColor
= static_cast<const XFillColorItem
&>(rLocalSet
.Get(XATTR_FILLCOLOR
)).GetColorValue();
1069 // sort in ExtrudeObj
1072 // do we have overlap with an object of this layer?
1073 bool bOverlap(false);
1074 E3dDepthNeighbour
* pAct
= pLayer
->mpNext
;
1076 while(!bOverlap
&& pAct
)
1078 // do pAct->mpObj and pExtrudeObj overlap? Check by
1079 // using logical AND clipping
1080 const basegfx::B2DPolyPolygon
aAndPolyPolygon(
1081 basegfx::tools::solvePolygonOperationAnd(
1083 pAct
->maPreparedPolyPolygon
));
1085 bOverlap
= (0 != aAndPolyPolygon
.count());
1089 // second ciriteria: is another fillstyle or color used?
1090 const SfxItemSet
& rCompareSet
= pAct
->mpObj
->GetMergedItemSet();
1092 drawing::FillStyle eCompareFillStyle
= ITEMVALUE(rCompareSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
1094 if(eLocalFillStyle
== eCompareFillStyle
)
1096 if(eLocalFillStyle
== drawing::FillStyle_SOLID
)
1098 Color aCompareColor
= static_cast<const XFillColorItem
&>(rCompareSet
.Get(XATTR_FILLCOLOR
)).GetColorValue();
1100 if(aCompareColor
== aLocalColor
)
1105 else if(eLocalFillStyle
== drawing::FillStyle_NONE
)
1112 pAct
= pAct
->mpNext
;
1117 // yes, start a new layer
1118 pLayer
->mpDown
= new E3dDepthLayer
;
1119 pLayer
= pLayer
->mpDown
;
1121 pLayer
->mpNext
= new E3dDepthNeighbour
;
1122 pLayer
->mpNext
->mpObj
= pExtrudeObj
;
1123 pLayer
->mpNext
->maPreparedPolyPolygon
= aExtrudePoly
;
1127 // no, add to current layer
1128 E3dDepthNeighbour
* pNewNext
= new E3dDepthNeighbour
;
1129 pNewNext
->mpObj
= pExtrudeObj
;
1130 pNewNext
->maPreparedPolyPolygon
= aExtrudePoly
;
1131 pNewNext
->mpNext
= pLayer
->mpNext
;
1132 pLayer
->mpNext
= pNewNext
;
1138 pBaseLayer
= new E3dDepthLayer
;
1139 pLayer
= pBaseLayer
;
1141 pLayer
->mpNext
= new E3dDepthNeighbour
;
1142 pLayer
->mpNext
->mpObj
= pExtrudeObj
;
1143 pLayer
->mpNext
->maPreparedPolyPolygon
= aExtrudePoly
;
1148 // number of layers is done
1151 // need to be arranged
1152 double fMinDepth
= fDepth
* 0.8;
1153 double fStep
= (fDepth
- fMinDepth
) / (double)nNumLayers
;
1154 pLayer
= pBaseLayer
;
1159 E3dDepthNeighbour
* pAct
= pLayer
->mpNext
;
1163 // adapt extrude value
1164 pAct
->mpObj
->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH
, sal_uInt32(fMinDepth
+ 0.5)));
1167 pAct
= pAct
->mpNext
;
1171 pLayer
= pLayer
->mpDown
;
1179 pLayer
= pBaseLayer
->mpDown
;
1181 pBaseLayer
= pLayer
;
1186 // Start drag, create for 3D objects before possibly drag method
1188 bool E3dView::BegDragObj(const Point
& rPnt
, OutputDevice
* pOut
,
1189 SdrHdl
* pHdl
, short nMinMov
,
1190 SdrDragMethod
* pForcedMeth
)
1192 if(Is3DRotationCreationActive() && GetMarkedObjectCount())
1194 // Determine all selected polygons and return the mirrored helper overlay
1195 mpMirrorOverlay
->SetMirrorAxis(aRef1
, aRef2
);
1199 bool bOwnActionNecessary
;
1202 bOwnActionNecessary
= true;
1204 else if (pHdl
->IsVertexHdl() || pHdl
->IsCornerHdl())
1206 bOwnActionNecessary
= true;
1210 bOwnActionNecessary
= false;
1213 if(bOwnActionNecessary
&& GetMarkedObjectCount() > 0)
1215 E3dDragConstraint eConstraint
= E3DDRAG_CONSTR_XYZ
;
1216 bool bThereAreRootScenes
= false;
1217 bool bThereAre3DObjects
= false;
1218 const size_t nCnt
= GetMarkedObjectCount();
1219 for(size_t nObjs
= 0; nObjs
< nCnt
; ++nObjs
)
1221 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
1224 if(pObj
->ISA(E3dScene
) && static_cast<E3dScene
*>(pObj
)->GetScene() == pObj
)
1225 bThereAreRootScenes
= true;
1226 if(pObj
->ISA(E3dObject
))
1227 bThereAre3DObjects
= true;
1230 if( bThereAre3DObjects
)
1232 eDragHdl
= ( pHdl
== NULL
? HDL_MOVE
: pHdl
->GetKind() );
1233 switch ( eDragMode
)
1235 case SDRDRAG_ROTATE
:
1243 eConstraint
= E3DDRAG_CONSTR_X
;
1250 eConstraint
= E3DDRAG_CONSTR_Y
;
1259 eConstraint
= E3DDRAG_CONSTR_Z
;
1265 // do not mask the allowed rotations
1266 eConstraint
= E3dDragConstraint(eConstraint
& eDragConstraint
);
1267 pForcedMeth
= new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint
, IsSolidDragging());
1273 if(!bThereAreRootScenes
)
1275 pForcedMeth
= new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl
, eConstraint
, IsSolidDragging());
1281 case SDRDRAG_MIRROR
:
1283 case SDRDRAG_DISTORT
:
1284 case SDRDRAG_TRANSPARENCE
:
1285 case SDRDRAG_GRADIENT
:
1294 return SdrView::BegDragObj(rPnt
, pOut
, pHdl
, nMinMov
, pForcedMeth
);
1297 // Set current 3D drawing object, create the scene for this
1299 E3dScene
* E3dView::SetCurrent3DObj(E3dObject
* p3DObj
)
1301 DBG_ASSERT(p3DObj
!= NULL
, "Who puts in a NULL-pointer here");
1302 E3dScene
* pScene
= NULL
;
1304 // get transformed BoundVolume of the object
1305 basegfx::B3DRange
aVolume(p3DObj
->GetBoundVolume());
1306 aVolume
.transform(p3DObj
->GetTransform());
1307 double fW(aVolume
.getWidth());
1308 double fH(aVolume
.getHeight());
1310 Rectangle
aRect(0,0, (long) fW
, (long) fH
);
1312 pScene
= new E3dPolyScene(Get3DDefaultAttributes());
1314 InitScene(pScene
, fW
, fH
, aVolume
.getMaxZ() + ((fW
+ fH
) / 4.0));
1316 pScene
->Insert3DObj(p3DObj
);
1317 pScene
->NbcSetSnapRect(aRect
);
1322 void E3dView::InitScene(E3dScene
* pScene
, double fW
, double fH
, double fCamZ
)
1324 Camera3D
aCam(pScene
->GetCamera());
1326 aCam
.SetAutoAdjustProjection(false);
1327 aCam
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
1328 basegfx::B3DPoint aLookAt
;
1330 double fDefaultCamPosZ
= GetDefaultCamPosZ();
1331 basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
1333 aCam
.SetPosAndLookAt(aCamPos
, aLookAt
);
1334 aCam
.SetFocalLength(GetDefaultCamFocal());
1335 aCam
.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ
), aLookAt
, GetDefaultCamFocal());
1336 pScene
->SetCamera(aCam
);
1339 void E3dView::Start3DCreation()
1341 if (GetMarkedObjectCount())
1349 OutputDevice
* pOut
= GetFirstOutputDevice();
1351 // first determine representation boundaries
1354 nMinLen
= pOut
->PixelToLogic(Size(0,50)).Height();
1355 nObjDst
= pOut
->PixelToLogic(Size(0,20)).Height();
1357 long nDst
= pOut
->PixelToLogic(Size(0,10)).Height();
1359 nOutMin
= -pOut
->GetMapMode().GetOrigin().Y();
1360 nOutMax
= pOut
->GetOutputSize().Height() - 1 + nOutMin
;
1364 if (nOutMax
- nOutMin
< nDst
)
1366 nOutMin
+= nOutMax
+ 1;
1368 nOutMin
-= (nDst
+ 1) / 2;
1369 nOutMax
= nOutMin
+ nDst
;
1372 nOutHgt
= nOutMax
- nOutMin
;
1374 long nTemp
= nOutHgt
/ 4;
1375 if (nTemp
> nMinLen
) nMinLen
= nTemp
;
1378 // and then attach the marks at the top and bottom of the object
1379 basegfx::B2DRange aR
;
1380 for(size_t nMark
= 0; nMark
< GetMarkedObjectCount(); ++nMark
)
1382 SdrObject
* pMark
= GetMarkedObjectByIndex(nMark
);
1383 basegfx::B2DPolyPolygon
aXPP(pMark
->TakeXorPoly());
1384 aR
.expand(basegfx::tools::getRange(aXPP
));
1387 basegfx::B2DPoint
aCenter(aR
.getCenter());
1388 long nMarkHgt
= basegfx::fround(aR
.getHeight()) - 1;
1389 long nHgt
= nMarkHgt
+ nObjDst
* 2;
1391 if (nHgt
< nMinLen
) nHgt
= nMinLen
;
1393 long nY1
= basegfx::fround(aCenter
.getY()) - (nHgt
+ 1) / 2;
1394 long nY2
= nY1
+ nHgt
;
1396 if (pOut
&& (nMinLen
> nOutHgt
)) nMinLen
= nOutHgt
;
1402 if (nY2
< nY1
+ nMinLen
) nY2
= nY1
+ nMinLen
;
1407 if (nY1
> nY2
- nMinLen
) nY1
= nY2
- nMinLen
;
1411 aRef1
.X() = basegfx::fround(aR
.getMinX()); // Initial move axis 2/100mm to the left
1413 aRef2
.X() = aRef1
.X();
1419 //HMHif (bVis) ShowMarkHdl();
1420 if (AreObjectsMarked()) MarkListHasChanged();
1422 // Show mirror polygon IMMEDIATELY
1423 const SdrHdlList
&aHdlList
= GetHdlList();
1424 mpMirrorOverlay
= new Impl3DMirrorConstructOverlay(*this);
1425 mpMirrorOverlay
->SetMirrorAxis(aHdlList
.GetHdl(HDL_REF1
)->GetPos(), aHdlList
.GetHdl(HDL_REF2
)->GetPos());
1429 // what happens with a mouse movement when the object is created?
1431 void E3dView::MovAction(const Point
& rPnt
)
1433 if(Is3DRotationCreationActive())
1435 SdrHdl
* pHdl
= GetDragHdl();
1439 SdrHdlKind eHdlKind
= pHdl
->GetKind();
1441 // reacts only due to a mirror axis
1442 if ((eHdlKind
== HDL_REF1
) ||
1443 (eHdlKind
== HDL_REF2
) ||
1444 (eHdlKind
== HDL_MIRX
))
1446 const SdrHdlList
&aHdlList
= GetHdlList ();
1448 // delete the mirroed polygon, mirrors the original and draws
1450 SdrView::MovAction (rPnt
);
1451 mpMirrorOverlay
->SetMirrorAxis(
1452 aHdlList
.GetHdl (HDL_REF1
)->GetPos(),
1453 aHdlList
.GetHdl (HDL_REF2
)->GetPos());
1458 SdrView::MovAction (rPnt
);
1463 SdrView::MovAction (rPnt
);
1467 // The End. Create object and any child objects through ImpCreate3DLathe.
1468 // With the parameter value sal_True (SDefault: sal_False) is simply a
1469 // rotation body created, without letting the user set the position of the
1470 // axis. It is sufficient with this call, if an object is selected.
1471 // (No initialization necessary)
1473 void E3dView::End3DCreation(bool bUseDefaultValuesForMirrorAxes
)
1475 ResetCreationActive();
1477 if(AreObjectsMarked())
1479 if(bUseDefaultValuesForMirrorAxes
)
1481 Rectangle aRect
= GetAllMarkedRect();
1482 if(aRect
.GetWidth() <= 1)
1483 aRect
.SetSize(Size(500, aRect
.GetHeight()));
1484 if(aRect
.GetHeight() <= 1)
1485 aRect
.SetSize(Size(aRect
.GetWidth(), 500));
1487 basegfx::B2DPoint
aPnt1(aRect
.Left(), -aRect
.Top());
1488 basegfx::B2DPoint
aPnt2(aRect
.Left(), -aRect
.Bottom());
1490 ConvertMarkedObjTo3D(false, aPnt1
, aPnt2
);
1494 // Turn off helper overlay
1495 // Determine from the handle positions and the displacement of
1497 const SdrHdlList
&aHdlList
= GetHdlList();
1498 Point aMirrorRef1
= aHdlList
.GetHdl(HDL_REF1
)->GetPos();
1499 Point aMirrorRef2
= aHdlList
.GetHdl(HDL_REF2
)->GetPos();
1501 basegfx::B2DPoint
aPnt1(aMirrorRef1
.X(), -aMirrorRef1
.Y());
1502 basegfx::B2DPoint
aPnt2(aMirrorRef2
.X(), -aMirrorRef2
.Y());
1504 ConvertMarkedObjTo3D(false, aPnt1
, aPnt2
);
1509 E3dView::~E3dView ()
1513 void E3dView::ResetCreationActive ()
1517 delete mpMirrorOverlay
;
1518 mpMirrorOverlay
= 0L;
1522 void E3dView::InitView ()
1524 eDragConstraint
= E3DDRAG_CONSTR_XYZ
;
1527 fDefaultScaleZ
= 1.0;
1530 fDefaultRotateZ
= 0.0;
1531 fDefaultExtrusionDeepth
= 1000; // old: 2000;
1532 fDefaultLightIntensity
= 0.8; // old: 0.6;
1533 fDefaultAmbientIntensity
= 0.4;
1534 nHDefaultSegments
= 12;
1535 nVDefaultSegments
= 12;
1536 aDefaultLightColor
= RGB_Color(COL_WHITE
);
1537 aDefaultAmbientColor
= RGB_Color(COL_BLACK
);
1538 bDoubleSided
= false;
1539 mpMirrorOverlay
= 0L;
1542 bool E3dView::IsBreak3DObjPossible() const
1544 const size_t nCount
= GetMarkedObjectCount();
1548 for (size_t i
= 0; i
< nCount
; ++i
)
1550 SdrObject
* pObj
= GetMarkedObjectByIndex(i
);
1552 if (pObj
&& pObj
->ISA(E3dObject
))
1554 if(!(static_cast<E3dObject
*>(pObj
)->IsBreakObjPossible()))
1571 void E3dView::Break3DObj()
1573 if(IsBreak3DObjPossible())
1575 // ALL selected objects are changed
1576 const size_t nCount
= GetMarkedObjectCount();
1578 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE
));
1579 for(size_t a
=0; a
<nCount
; ++a
)
1581 E3dObject
* pObj
= static_cast<E3dObject
*>(GetMarkedObjectByIndex(a
));
1582 BreakSingle3DObj(pObj
);
1589 void E3dView::BreakSingle3DObj(E3dObject
* pObj
)
1591 if(pObj
->ISA(E3dScene
))
1593 SdrObjList
* pSubList
= pObj
->GetSubList();
1594 SdrObjListIter
aIter(*pSubList
, IM_FLAT
);
1596 while(aIter
.IsMore())
1598 E3dObject
* pSubObj
= static_cast<E3dObject
*>(aIter
.Next());
1599 BreakSingle3DObj(pSubObj
);
1604 SdrAttrObj
* pNewObj
= pObj
->GetBreakObj();
1607 InsertObjectAtView(pNewObj
, *GetSdrPageView(), SdrInsertFlags::DONTMARK
);
1608 pNewObj
->SetChanged();
1609 pNewObj
->BroadcastObjectChange();
1614 void E3dView::CheckPossibilities()
1617 SdrView::CheckPossibilities();
1620 if(bGroupPossible
|| bUnGroupPossible
|| bGrpEnterPossible
)
1622 const size_t nMarkCnt
= GetMarkedObjectCount();
1623 bool bCoumpound
= false;
1624 bool b3DObject
= false;
1625 for(size_t nObjs
= 0; (nObjs
< nMarkCnt
) && !bCoumpound
; ++nObjs
)
1627 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
1628 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
1630 if(pObj
&& pObj
->ISA(E3dObject
))
1634 // So far: there are two or more of any objects selected. See if
1635 // compound objects are involved. If yes, ban grouping.
1636 if(bGroupPossible
&& bCoumpound
)
1637 bGroupPossible
= false;
1639 if(bUnGroupPossible
&& b3DObject
)
1640 bUnGroupPossible
= false;
1642 if(bGrpEnterPossible
&& bCoumpound
)
1643 bGrpEnterPossible
= false;
1647 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */