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 <tools/shl.hxx>
25 #include "svx/svditer.hxx"
26 #include <svx/svdpool.hxx>
27 #include <svx/svdorect.hxx>
28 #include <svx/svdmodel.hxx>
29 #include <svx/svdpagv.hxx>
30 #include <svx/svxids.hrc>
31 #include <editeng/colritem.hxx>
32 #include <svx/xtable.hxx>
33 #include <svx/svdview.hxx>
34 #include <svx/dialogs.hrc>
35 #include <svx/dialmgr.hxx>
36 #include "svx/globl3d.hxx"
37 #include <svx/obj3d.hxx>
38 #include <svx/lathe3d.hxx>
39 #include <svx/sphere3d.hxx>
40 #include <svx/extrud3d.hxx>
41 #include <svx/cube3d.hxx>
42 #include <svx/polysc3d.hxx>
43 #include "dragmt3d.hxx"
44 #include <svx/view3d.hxx>
45 #include <svx/svdundo.hxx>
46 #include <svx/xflclit.hxx>
47 #include <svx/xlnclit.hxx>
48 #include <svx/svdograf.hxx>
49 #include <svx/xbtmpit.hxx>
50 #include <svx/xflbmtit.hxx>
51 #include <basegfx/range/b2drange.hxx>
52 #include <basegfx/polygon/b2dpolygontools.hxx>
53 #include <basegfx/polygon/b2dpolypolygontools.hxx>
54 #include <svx/xlnwtit.hxx>
55 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
56 #include <svx/sdr/overlay/overlaymanager.hxx>
57 #include <svx/sdrpaintwindow.hxx>
58 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
59 #include <drawinglayer/geometry/viewinformation3d.hxx>
60 #include <svx/sdrpagewindow.hxx>
61 #include <svx/sdr/contact/displayinfo.hxx>
62 #include <svx/sdr/contact/objectcontact.hxx>
63 #include <svx/sdr/contact/viewobjectcontact.hxx>
64 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
65 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
66 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
67 #include <basegfx/matrix/b2dhommatrixtools.hxx>
68 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
70 #define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
72 TYPEINIT1(E3dView
, SdrView
);
74 //////////////////////////////////////////////////////////////////////////////
77 class Impl3DMirrorConstructOverlay
80 ::sdr::overlay::OverlayObjectList maObjects
;
83 const E3dView
& mrView
;
88 // the unmirrored polygons
89 basegfx::B2DPolyPolygon
* mpPolygons
;
91 // the overlay geometry from selected objects
92 drawinglayer::primitive2d::Primitive2DSequence maFullOverlay
;
95 Impl3DMirrorConstructOverlay(const E3dView
& rView
);
96 ~Impl3DMirrorConstructOverlay();
98 void SetMirrorAxis(Point aMirrorAxisA
, Point aMirrorAxisB
);
101 Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView
& rView
)
104 mnCount(rView
.GetMarkedObjectCount()),
110 if(mrView
.IsSolidDragging())
112 SdrPageView
* pPV
= rView
.GetSdrPageView();
114 if(pPV
&& pPV
->PageWindowCount())
116 sdr::contact::ObjectContact
& rOC
= pPV
->GetPageWindow(0)->GetObjectContact();
117 sdr::contact::DisplayInfo aDisplayInfo
;
119 // Do not use the last ViewPort set at the OC at the last ProcessDisplay()
122 for(sal_uInt32
a(0);a
< mnCount
;a
++)
124 SdrObject
* pObject
= mrView
.GetMarkedObjectByIndex(a
);
128 sdr::contact::ViewContact
& rVC
= pObject
->GetViewContact();
129 sdr::contact::ViewObjectContact
& rVOC
= rVC
.GetViewObjectContact(rOC
);
131 const drawinglayer::primitive2d::Primitive2DSequence
aNewSequence(rVOC
.getPrimitive2DSequenceHierarchy(aDisplayInfo
));
132 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay
, aNewSequence
);
139 mpPolygons
= new basegfx::B2DPolyPolygon
[mnCount
];
141 for(sal_uInt32
a(0); a
< mnCount
; a
++)
143 SdrObject
* pObject
= mrView
.GetMarkedObjectByIndex(a
);
144 mpPolygons
[mnCount
- (a
+ 1)] = pObject
->TakeXorPoly();
150 Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
152 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
153 // That destructor calls clear() at the list which removes all objects from the
154 // OverlayManager and deletes them.
155 if(!mrView
.IsSolidDragging())
161 void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA
, Point aMirrorAxisB
)
163 // get rid of old overlay objects
167 for(sal_uInt32
a(0); a
< mrView
.PaintWindowCount(); a
++)
169 SdrPaintWindow
* pCandidate
= mrView
.GetPaintWindow(a
);
170 rtl::Reference
< ::sdr::overlay::OverlayManager
> xTargetOverlay
= pCandidate
->GetOverlayManager();
172 if(xTargetOverlay
.is())
174 // buld transfoprmation: translate and rotate so that given edge is
175 // on x axis, them mirror in y and translate back
176 const basegfx::B2DVector
aEdge(aMirrorAxisB
.X() - aMirrorAxisA
.X(), aMirrorAxisB
.Y() - aMirrorAxisA
.Y());
177 basegfx::B2DHomMatrix
aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(
178 -aMirrorAxisA
.X(), -aMirrorAxisA
.Y()));
179 aMatrixTransform
.rotate(-atan2(aEdge
.getY(), aEdge
.getX()));
180 aMatrixTransform
.scale(1.0, -1.0);
181 aMatrixTransform
.rotate(atan2(aEdge
.getY(), aEdge
.getX()));
182 aMatrixTransform
.translate(aMirrorAxisA
.X(), aMirrorAxisA
.Y());
184 if(mrView
.IsSolidDragging())
186 if(maFullOverlay
.hasElements())
188 drawinglayer::primitive2d::Primitive2DSequence
aContent(maFullOverlay
);
190 if(!aMatrixTransform
.isIdentity())
192 // embed in transformation group
193 drawinglayer::primitive2d::Primitive2DReference
aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform
, aContent
));
194 aContent
= drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D
, 1);
197 // if we have full overlay from selected objects, embed with 50% transparence, the
198 // transformation is added to the OverlayPrimitive2DSequenceObject
199 drawinglayer::primitive2d::Primitive2DReference
aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aContent
, 0.5));
200 aContent
= drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D
, 1);
202 sdr::overlay::OverlayPrimitive2DSequenceObject
* pNew
= new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent
);
204 xTargetOverlay
->add(*pNew
);
205 maObjects
.append(*pNew
);
210 for(sal_uInt32
b(0); b
< mnCount
; b
++)
213 basegfx::B2DPolyPolygon
aPolyPolygon(mpPolygons
[b
]);
214 aPolyPolygon
.transform(aMatrixTransform
);
216 ::sdr::overlay::OverlayPolyPolygonStriped
* pNew
= new ::sdr::overlay::OverlayPolyPolygonStriped(aPolyPolygon
);
217 xTargetOverlay
->add(*pNew
);
218 maObjects
.append(*pNew
);
225 E3dView::E3dView(SdrModel
* pModel
, OutputDevice
* pOut
) :
226 SdrView(pModel
, pOut
)
231 // DrawMarkedObj overloaded, since possibly only a single 3D object is to be
234 void E3dView::DrawMarkedObj(OutputDevice
& rOut
) const
236 // Does 3D objects exist which scenes are not selected?
237 bool bSpecialHandling
= false;
238 E3dScene
*pScene
= NULL
;
240 long nCnt
= GetMarkedObjectCount();
241 for(long nObjs
= 0;nObjs
< nCnt
;nObjs
++)
243 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
244 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
247 pScene
= ((E3dCompoundObject
*)pObj
)->GetScene();
248 if(pScene
&& !IsObjMarked(pScene
))
249 bSpecialHandling
= true;
251 // Reset all selection flags
252 if(pObj
&& pObj
->ISA(E3dObject
))
254 pScene
= ((E3dObject
*)pObj
)->GetScene();
256 pScene
->SetSelected(sal_False
);
262 // Set selection flag to "not selected" for scenes related to all 3D
265 for(nObjs
= 0;nObjs
< nCnt
;nObjs
++)
267 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
268 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
271 pScene
= ((E3dCompoundObject
*)pObj
)->GetScene();
273 pScene
->SetSelected(sal_False
);
277 for(nObjs
= 0;nObjs
< nCnt
;nObjs
++)
279 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
280 if(pObj
&& pObj
->ISA(E3dObject
))
283 E3dObject
* p3DObj
= (E3dObject
*)pObj
;
284 p3DObj
->SetSelected(sal_True
);
285 pScene
= p3DObj
->GetScene();
294 pScene
->SetDrawOnlySelected(sal_True
);
295 pScene
->SingleObjectPainter(rOut
);
296 pScene
->SetDrawOnlySelected(sal_False
);
299 // Reset selection flag
300 for(nObjs
= 0;nObjs
< nCnt
;nObjs
++)
302 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
303 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
306 pScene
= ((E3dCompoundObject
*)pObj
)->GetScene();
308 pScene
->SetSelected(sal_False
);
315 SdrExchangeView::DrawMarkedObj(rOut
);
319 // Get overloaded model, since in some 3D objects an additional scene
322 SdrModel
* E3dView::GetMarkedObjModel() const
324 // Does 3D objects exist which scenes are not selected?
325 bool bSpecialHandling(false);
326 const sal_uInt32
nCount(GetMarkedObjectCount());
328 E3dScene
*pScene
= 0;
330 for(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
= ((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
= ((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(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
= (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
= ((E3dView
*)this)->GetMarkedObjectListWriteAccess();
387 rCurrentMarkList
= aNewML
;
389 for(nObjs
= 0; nObjs
< nCount
; nObjs
++)
391 SdrObject
*pObj
= aOldML
.GetMark(nObjs
)->GetMarkedSdrObj();
393 if(pObj
&& pObj
->ISA(E3dObject
))
395 pScene
= ((E3dObject
*)pObj
)->GetScene();
397 if(pScene
&& !IsObjMarked(pScene
) && GetSdrPageView())
399 ((E3dView
*)this)->MarkObj(pScene
, GetSdrPageView(), sal_False
, sal_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 sal_uInt32
nObAnz(pSrcPg
->GetObjCount());
415 for(sal_uInt32
nOb(0); nOb
< nObAnz
; nOb
++)
417 const SdrObject
* pSrcOb
=pSrcPg
->GetObj(nOb
);
419 if(pSrcOb
->ISA(E3dScene
))
421 pScene
= (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
443 sal_Bool
E3dView::Paste(const SdrModel
& rMod
, const Point
& rPos
, SdrObjList
* pLst
, sal_uInt32 nOptions
)
445 sal_Bool bRetval
= sal_False
;
449 SdrObjList
* pDstList
= pLst
;
450 ImpGetPasteObjList(aPos
, pDstList
);
455 // Get owner of the list
456 SdrObject
* pOwner
= pDstList
->GetOwnerObj();
457 if(pOwner
&& pOwner
->ISA(E3dScene
))
459 E3dScene
* pDstScene
= (E3dScene
*)pOwner
;
460 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE
));
462 // Copy all objects from E3dScenes and insert them directly
463 for(sal_uInt16
nPg(0); nPg
< rMod
.GetPageCount(); nPg
++)
465 const SdrPage
* pSrcPg
=rMod
.GetPage(nPg
);
466 sal_uInt32
nObAnz(pSrcPg
->GetObjCount());
468 // calculate offset for paste
469 Rectangle aR
= pSrcPg
->GetAllObjBoundRect();
470 Point
aDist(aPos
- aR
.Center());
472 // Insert sub-objects for scenes
473 for(sal_uInt32
nOb(0); nOb
< nObAnz
; nOb
++)
475 const SdrObject
* pSrcOb
= pSrcPg
->GetObj(nOb
);
476 if(pSrcOb
->ISA(E3dScene
))
478 E3dScene
* pSrcScene
= (E3dScene
*)pSrcOb
;
479 ImpCloneAll3DObjectsToDestScene(pSrcScene
, pDstScene
, aDist
);
488 bRetval
= SdrView::Paste(rMod
, rPos
, pLst
, nOptions
);
494 // Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
495 bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene
* pSrcScene
, E3dScene
* pDstScene
, Point
/*aOffset*/)
499 if(pSrcScene
&& pDstScene
)
501 const sdr::contact::ViewContactOfE3dScene
& rVCSceneDst
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pDstScene
->GetViewContact());
502 const drawinglayer::geometry::ViewInformation3D
aViewInfo3DDst(rVCSceneDst
.getViewInformation3D());
503 const sdr::contact::ViewContactOfE3dScene
& rVCSceneSrc
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pSrcScene
->GetViewContact());
504 const drawinglayer::geometry::ViewInformation3D
aViewInfo3DSrc(rVCSceneSrc
.getViewInformation3D());
506 for(sal_uInt32
i(0); i
< pSrcScene
->GetSubList()->GetObjCount(); i
++)
508 E3dCompoundObject
* pCompoundObj
= dynamic_cast< E3dCompoundObject
* >(pSrcScene
->GetSubList()->GetObj(i
));
512 E3dCompoundObject
* pNewCompoundObj
= dynamic_cast< E3dCompoundObject
* >(pCompoundObj
->Clone());
516 // get dest scene's current range in 3D world coordinates
517 const basegfx::B3DHomMatrix
aSceneToWorldTrans(pDstScene
->GetFullTransform());
518 basegfx::B3DRange
aSceneRange(pDstScene
->GetBoundVolume());
519 aSceneRange
.transform(aSceneToWorldTrans
);
521 // get new object's implied object transformation
522 const basegfx::B3DHomMatrix
aNewObjectTrans(pNewCompoundObj
->GetTransform());
524 // get new object's range in 3D world coordinates in dest scene
525 // as if it were already added
526 const basegfx::B3DHomMatrix
aObjectToWorldTrans(aSceneToWorldTrans
* aNewObjectTrans
);
527 basegfx::B3DRange
aObjectRange(pNewCompoundObj
->GetBoundVolume());
528 aObjectRange
.transform(aObjectToWorldTrans
);
530 // get scale adaption
531 const basegfx::B3DVector
aSceneScale(aSceneRange
.getRange());
532 const basegfx::B3DVector
aObjectScale(aObjectRange
.getRange());
535 // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
536 // to not change the scene by the inserted object
537 const double fSizeFactor(0.5);
539 if(aObjectScale
.getX() * fScale
> aSceneScale
.getX() * fSizeFactor
)
541 const double fObjSize(aObjectScale
.getX() * fScale
);
542 const double fFactor((aSceneScale
.getX() * fSizeFactor
) / (basegfx::fTools::equalZero(fObjSize
) ? 1.0 : fObjSize
));
546 if(aObjectScale
.getY() * fScale
> aSceneScale
.getY() * fSizeFactor
)
548 const double fObjSize(aObjectScale
.getY() * fScale
);
549 const double fFactor((aSceneScale
.getY() * fSizeFactor
) / (basegfx::fTools::equalZero(fObjSize
) ? 1.0 : fObjSize
));
553 if(aObjectScale
.getZ() * fScale
> aSceneScale
.getZ() * fSizeFactor
)
555 const double fObjSize(aObjectScale
.getZ() * fScale
);
556 const double fFactor((aSceneScale
.getZ() * fSizeFactor
) / (basegfx::fTools::equalZero(fObjSize
) ? 1.0 : fObjSize
));
560 // get translation adaption
561 const basegfx::B3DPoint
aSceneCenter(aSceneRange
.getCenter());
562 const basegfx::B3DPoint
aObjectCenter(aObjectRange
.getCenter());
564 // build full modification transform. The object's transformation
565 // shall be modified, so start at object coordinates; transform to 3d world coor
566 basegfx::B3DHomMatrix
aModifyingTransform(aObjectToWorldTrans
);
568 // translate to absolute center in 3d world coor
569 aModifyingTransform
.translate(-aObjectCenter
.getX(), -aObjectCenter
.getY(), -aObjectCenter
.getZ());
571 // scale to dest size in 3d world coor
572 aModifyingTransform
.scale(fScale
, fScale
, fScale
);
574 // translate to dest scene center in 3d world coor
575 aModifyingTransform
.translate(aSceneCenter
.getX(), aSceneCenter
.getY(), aSceneCenter
.getZ());
577 // transform from 3d world to dest object coordinates
578 basegfx::B3DHomMatrix
aWorldToObject(aObjectToWorldTrans
);
579 aWorldToObject
.invert();
580 aModifyingTransform
= aWorldToObject
* aModifyingTransform
;
582 // correct implied object transform by applying changing one in object coor
583 pNewCompoundObj
->SetTransform(aModifyingTransform
* aNewObjectTrans
);
585 // fill and insert new object
586 pNewCompoundObj
->SetModel(pDstScene
->GetModel());
587 pNewCompoundObj
->SetPage(pDstScene
->GetPage());
588 pNewCompoundObj
->NbcSetLayer(pCompoundObj
->GetLayer());
589 pNewCompoundObj
->NbcSetStyleSheet(pCompoundObj
->GetStyleSheet(), sal_True
);
590 pDstScene
->Insert3DObj(pNewCompoundObj
);
594 if( GetModel()->IsUndoEnabled() )
595 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj
));
604 bool E3dView::IsConvertTo3DObjPossible() const
607 bool bGroupSelected(false);
610 for(sal_uInt32 a
=0;!bAny3D
&& a
<GetMarkedObjectCount();a
++)
612 SdrObject
*pObj
= GetMarkedObjectByIndex(a
);
615 ImpIsConvertTo3DPossible(pObj
, bAny3D
, bGroupSelected
);
621 IsConvertToPolyObjPossible(sal_False
)
622 || IsConvertToPathObjPossible(sal_False
)
623 || IsImportMtfPossible());
627 void E3dView::ImpIsConvertTo3DPossible(SdrObject
* pObj
, bool& rAny3D
,
628 bool& rGroupSelected
) const
632 if(pObj
->ISA(E3dObject
))
638 if(pObj
->IsGroupObject())
640 SdrObjListIter
aIter(*pObj
, IM_DEEPNOGROUPS
);
641 while(aIter
.IsMore())
643 SdrObject
* pNewObj
= aIter
.Next();
644 ImpIsConvertTo3DPossible(pNewObj
, rAny3D
, rGroupSelected
);
646 rGroupSelected
= true;
652 #include <editeng/eeitem.hxx>
654 void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject
* pObj
)
656 if(pObj
->ISA(SdrTextObj
))
658 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
659 const SvxColorItem
& rTextColorItem
= (const SvxColorItem
&)rSet
.Get(EE_CHAR_COLOR
);
660 if(rTextColorItem
.GetValue() == RGB_Color(COL_BLACK
))
662 //For black text objects, the color set to gray
665 // if black is only default attribute from
666 // pattern set it hard so that it is used in undo.
667 pObj
->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK
), EE_CHAR_COLOR
));
670 if( GetModel()->IsUndoEnabled() )
671 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
, false, false));
674 pObj
->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY
), EE_CHAR_COLOR
));
679 void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject
* pObj
)
681 if(pObj
->ISA(SdrPathObj
))
683 const SfxItemSet
& rSet
= pObj
->GetMergedItemSet();
684 sal_Int32 nLineWidth
= ((const XLineWidthItem
&)(rSet
.Get(XATTR_LINEWIDTH
))).GetValue();
685 XLineStyle eLineStyle
= (XLineStyle
)((const XLineStyleItem
&)rSet
.Get(XATTR_LINESTYLE
)).GetValue();
686 XFillStyle eFillStyle
= ITEMVALUE(rSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
688 if(((SdrPathObj
*)pObj
)->IsClosed()
689 && eLineStyle
== XLINE_SOLID
691 && eFillStyle
!= XFILL_NONE
)
693 if(pObj
->GetPage() && GetModel()->IsUndoEnabled() )
694 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
, false, false));
695 pObj
->SetMergedItem(XLineStyleItem(XLINE_NONE
));
696 pObj
->SetMergedItem(XLineWidthItem(0L));
701 void E3dView::ImpCreateSingle3DObjectFlat(E3dScene
* pScene
, SdrObject
* pObj
, bool bExtrude
, double fDepth
, basegfx::B2DHomMatrix
& rLatheMat
)
703 // Single PathObject, transform this
704 SdrPathObj
* pPath
= PTR_CAST(SdrPathObj
, pObj
);
708 E3dDefaultAttributes aDefault
= Get3DDefaultAttributes();
710 aDefault
.SetDefaultExtrudeCharacterMode(sal_True
);
712 aDefault
.SetDefaultLatheCharacterMode(sal_True
);
714 // Get Itemset of the original object
715 SfxItemSet
aSet(pObj
->GetMergedItemSet());
717 XFillStyle eFillStyle
= ITEMVALUE(aSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
719 // line style turned off
720 aSet
.Put(XLineStyleItem(XLINE_NONE
));
722 //Determining if FILL_Attribut is set.
723 if(!pPath
->IsClosed() || eFillStyle
== XFILL_NONE
)
725 // This SdrPathObj is not filled, leave the front and rear face out.
726 // Moreover, a two-sided representation necessary.
727 aDefault
.SetDefaultExtrudeCloseFront(sal_False
);
728 aDefault
.SetDefaultExtrudeCloseBack(sal_False
);
730 aSet
.Put(Svx3DDoubleSidedItem(sal_True
));
732 // Set fill attribute
733 aSet
.Put(XFillStyleItem(XFILL_SOLID
));
735 // Fill color must be the color line, because the object was
736 // previously just a line
737 Color aColorLine
= ((const XLineColorItem
&)(aSet
.Get(XATTR_LINECOLOR
))).GetColorValue();
738 aSet
.Put(XFillColorItem(String(), aColorLine
));
741 // Create a new extrude object
742 E3dObject
* p3DObj
= NULL
;
745 p3DObj
= new E3dExtrudeObj(aDefault
, pPath
->GetPathPoly(), fDepth
);
749 basegfx::B2DPolyPolygon
aPolyPoly2D(pPath
->GetPathPoly());
750 aPolyPoly2D
.transform(rLatheMat
);
751 p3DObj
= new E3dLatheObj(aDefault
, aPolyPoly2D
);
757 p3DObj
->NbcSetLayer(pObj
->GetLayer());
759 p3DObj
->SetMergedItemSet(aSet
);
761 p3DObj
->NbcSetStyleSheet(pObj
->GetStyleSheet(), sal_True
);
763 // Insert a new extrude object
764 pScene
->Insert3DObj(p3DObj
);
769 void E3dView::ImpCreate3DObject(E3dScene
* pScene
, SdrObject
* pObj
, bool bExtrude
, double fDepth
, basegfx::B2DHomMatrix
& rLatheMat
)
773 // change text color attribute for not so dark colors
774 if(pObj
->IsGroupObject())
776 SdrObjListIter
aIter(*pObj
, IM_DEEPWITHGROUPS
);
777 while(aIter
.IsMore())
779 SdrObject
* pGroupMember
= aIter
.Next();
780 ImpChangeSomeAttributesFor3DConversion(pGroupMember
);
784 ImpChangeSomeAttributesFor3DConversion(pObj
);
786 // convert completely to path objects
787 SdrObject
* pNewObj1
= pObj
->ConvertToPolyObj(sal_False
, sal_False
);
791 // change text color attribute for not so dark colors
792 if(pNewObj1
->IsGroupObject())
794 SdrObjListIter
aIter(*pNewObj1
, IM_DEEPWITHGROUPS
);
795 while(aIter
.IsMore())
797 SdrObject
* pGroupMember
= aIter
.Next();
798 ImpChangeSomeAttributesFor3DConversion2(pGroupMember
);
802 ImpChangeSomeAttributesFor3DConversion2(pNewObj1
);
804 // convert completely to path objects
805 SdrObject
* pNewObj2
= pObj
->ConvertToContourObj(pNewObj1
, sal_True
);
809 // add all to flat scene
810 if(pNewObj2
->IsGroupObject())
812 SdrObjListIter
aIter(*pNewObj2
, IM_DEEPWITHGROUPS
);
813 while(aIter
.IsMore())
815 SdrObject
* pGroupMember
= aIter
.Next();
816 ImpCreateSingle3DObjectFlat(pScene
, pGroupMember
, bExtrude
, fDepth
, rLatheMat
);
820 ImpCreateSingle3DObjectFlat(pScene
, pNewObj2
, bExtrude
, fDepth
, rLatheMat
);
822 // delete object in between
823 if(pNewObj2
!= pObj
&& pNewObj2
!= pNewObj1
&& pNewObj2
)
824 SdrObject::Free( pNewObj2
);
827 // delete object in between
828 if(pNewObj1
!= pObj
&& pNewObj1
)
829 SdrObject::Free( pNewObj1
);
834 void E3dView::ConvertMarkedObjTo3D(bool bExtrude
, basegfx::B2DPoint aPnt1
, basegfx::B2DPoint aPnt2
)
836 if(AreObjectsMarked())
840 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE
));
842 BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE
));
844 // Create a new scene for the created 3D object
845 E3dScene
* pScene
= new E3dPolyScene(Get3DDefaultAttributes());
847 // Determine rectangle and possibly correct it
848 Rectangle aRect
= GetAllMarkedRect();
849 if(aRect
.GetWidth() <= 1)
850 aRect
.SetSize(Size(500, aRect
.GetHeight()));
851 if(aRect
.GetHeight() <= 1)
852 aRect
.SetSize(Size(aRect
.GetWidth(), 500));
854 // Determine the depth relative to the size of the selection
857 basegfx::B2DHomMatrix aLatheMat
;
861 double fW
= (double)aRect
.GetWidth();
862 double fH
= (double)aRect
.GetHeight();
863 fDepth
= sqrt(fW
*fW
+ fH
*fH
) / 6.0;
867 // Create transformation for the polygons rotating body
870 // Rotation around control point #1 with set angle
871 // for 3D coordinates
872 basegfx::B2DPoint
aDiff(aPnt1
- aPnt2
);
873 fRot3D
= atan2(aDiff
.getY(), aDiff
.getX()) - F_PI2
;
875 if(basegfx::fTools::equalZero(fabs(fRot3D
)))
880 aLatheMat
= basegfx::tools::createRotateAroundPoint(aPnt2
, -fRot3D
)
885 if(aPnt2
.getX() != 0.0)
887 // Translation to Y=0 - axis
888 aLatheMat
.translate(-aPnt2
.getX(), 0.0);
892 aLatheMat
.translate((double)-aRect
.Left(), 0.0);
895 // Form the inverse matrix to determine the target expansion
896 basegfx::B2DHomMatrix
aInvLatheMat(aLatheMat
);
897 aInvLatheMat
.invert();
899 // SnapRect extension enables mirroring in the axis of rotation
900 for(sal_uInt32 a
=0;a
<GetMarkedObjectCount();a
++)
902 SdrMark
* pMark
= GetSdrMarkByIndex(a
);
903 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
904 Rectangle aTurnRect
= pObj
->GetSnapRect();
905 basegfx::B2DPoint aRot
;
908 aRot
= basegfx::B2DPoint(aTurnRect
.Left(), -aTurnRect
.Top());
910 aRot
.setX(-aRot
.getX());
911 aRot
*= aInvLatheMat
;
912 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
913 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
915 aRot
= basegfx::B2DPoint(aTurnRect
.Left(), -aTurnRect
.Bottom());
917 aRot
.setX(-aRot
.getX());
918 aRot
*= aInvLatheMat
;
919 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
920 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
922 aRot
= basegfx::B2DPoint(aTurnRect
.Right(), -aTurnRect
.Top());
924 aRot
.setX(-aRot
.getX());
925 aRot
*= aInvLatheMat
;
926 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
927 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
929 aRot
= basegfx::B2DPoint(aTurnRect
.Right(), -aTurnRect
.Bottom());
931 aRot
.setX(-aRot
.getX());
932 aRot
*= aInvLatheMat
;
933 aRotPnt
= Point((long)(aRot
.getX() + 0.5), (long)(-aRot
.getY() - 0.5));
934 aRect
.Union(Rectangle(aRotPnt
, aRotPnt
));
938 // Walk throguh the selection and convert it into 3D, complete with
939 // Convertion to SdrPathObject, also fonts
940 for(sal_uInt32 a
=0;a
<GetMarkedObjectCount();a
++)
942 SdrMark
* pMark
= GetSdrMarkByIndex(a
);
943 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
945 ImpCreate3DObject(pScene
, pObj
, bExtrude
, fDepth
, aLatheMat
);
948 if(pScene
->GetSubList() && pScene
->GetSubList()->GetObjCount() != 0)
950 // Arrange all created objects by depth
952 DoDepthArrange(pScene
, fDepth
);
954 // Center 3D objects in the middle of the overall rectangle
955 basegfx::B3DPoint
aCenter(pScene
->GetBoundVolume().getCenter());
956 basegfx::B3DHomMatrix aMatrix
;
958 aMatrix
.translate(-aCenter
.getX(), -aCenter
.getY(), -aCenter
.getZ());
959 pScene
->SetTransform(aMatrix
* pScene
->GetTransform());
962 pScene
->NbcSetSnapRect(aRect
);
963 basegfx::B3DRange aBoundVol
= pScene
->GetBoundVolume();
964 InitScene(pScene
, (double)aRect
.GetWidth(), (double)aRect
.GetHeight(), aBoundVol
.getDepth());
966 // Insert scene instead of the first selected object and throw away
967 // all the old objects
968 SdrObject
* pRepObj
= GetMarkedObjectByIndex(0);
969 SdrPageView
* pPV
= GetSdrPageViewOfMarkedByIndex(0);
970 MarkObj(pRepObj
, pPV
, sal_True
);
971 ReplaceObjectAtView(pRepObj
, *pPV
, pScene
, sal_False
);
973 MarkObj(pScene
, pPV
);
975 // Rotate Rotation body around the axis of rotation
976 basegfx::B3DHomMatrix aRotate
;
978 if(!bExtrude
&& fRot3D
!= 0.0)
980 aRotate
.rotate(0.0, 0.0, fRot3D
);
983 // Set default rotation
985 double XRotateDefault
= 20;
986 aRotate
.rotate(DEG2RAD(XRotateDefault
), 0.0, 0.0);
989 if(!aRotate
.isIdentity())
991 pScene
->SetTransform(aRotate
* pScene
->GetTransform());
994 // Invalid SnapRects of objects
995 pScene
->SetSnapRect(aRect
);
999 // No 3D object was created, throw away everything
1007 //Arrange all created extrude objects by depth
1009 struct E3dDepthNeighbour
1011 E3dDepthNeighbour
* mpNext
;
1012 E3dExtrudeObj
* mpObj
;
1013 basegfx::B2DPolyPolygon maPreparedPolyPolygon
;
1018 maPreparedPolyPolygon()
1023 struct E3dDepthLayer
1025 E3dDepthLayer
* mpDown
;
1026 E3dDepthNeighbour
* mpNext
;
1038 E3dDepthNeighbour
* pSucc
= mpNext
->mpNext
;
1045 void E3dView::DoDepthArrange(E3dScene
* pScene
, double fDepth
)
1047 if(pScene
&& pScene
->GetSubList() && pScene
->GetSubList()->GetObjCount() > 1)
1049 SdrObjList
* pSubList
= pScene
->GetSubList();
1050 SdrObjListIter
aIter(*pSubList
, IM_FLAT
);
1051 E3dDepthLayer
* pBaseLayer
= NULL
;
1052 E3dDepthLayer
* pLayer
= NULL
;
1053 sal_Int32 nNumLayers
= 0;
1055 while(aIter
.IsMore())
1057 E3dExtrudeObj
* pExtrudeObj
= dynamic_cast< E3dExtrudeObj
* >(aIter
.Next());
1061 const basegfx::B2DPolyPolygon
aExtrudePoly(
1062 basegfx::tools::prepareForPolygonOperation(pExtrudeObj
->GetExtrudePolygon()));
1063 const SfxItemSet
& rLocalSet
= pExtrudeObj
->GetMergedItemSet();
1064 const XFillStyle eLocalFillStyle
= ITEMVALUE(rLocalSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
1065 const Color aLocalColor
= ((const XFillColorItem
&)(rLocalSet
.Get(XATTR_FILLCOLOR
))).GetColorValue();
1067 // sort in ExtrudeObj
1070 // do we have overlap with an object of this layer?
1071 bool bOverlap(false);
1072 E3dDepthNeighbour
* pAct
= pLayer
->mpNext
;
1074 while(!bOverlap
&& pAct
)
1076 // do pAct->mpObj and pExtrudeObj overlap? Check by
1077 // using logical AND clipping
1078 const basegfx::B2DPolyPolygon
aAndPolyPolygon(
1079 basegfx::tools::solvePolygonOperationAnd(
1081 pAct
->maPreparedPolyPolygon
));
1083 bOverlap
= (0 != aAndPolyPolygon
.count());
1087 // second ciriteria: is another fillstyle or color used?
1088 const SfxItemSet
& rCompareSet
= pAct
->mpObj
->GetMergedItemSet();
1090 XFillStyle eCompareFillStyle
= ITEMVALUE(rCompareSet
, XATTR_FILLSTYLE
, XFillStyleItem
);
1092 if(eLocalFillStyle
== eCompareFillStyle
)
1094 if(eLocalFillStyle
== XFILL_SOLID
)
1096 Color aCompareColor
= ((const XFillColorItem
&)(rCompareSet
.Get(XATTR_FILLCOLOR
))).GetColorValue();
1098 if(aCompareColor
== aLocalColor
)
1103 else if(eLocalFillStyle
== XFILL_NONE
)
1110 pAct
= pAct
->mpNext
;
1115 // yes, start a new layer
1116 pLayer
->mpDown
= new E3dDepthLayer
;
1117 pLayer
= pLayer
->mpDown
;
1119 pLayer
->mpNext
= new E3dDepthNeighbour
;
1120 pLayer
->mpNext
->mpObj
= pExtrudeObj
;
1121 pLayer
->mpNext
->maPreparedPolyPolygon
= aExtrudePoly
;
1125 // no, add to current layer
1126 E3dDepthNeighbour
* pNewNext
= new E3dDepthNeighbour
;
1127 pNewNext
->mpObj
= pExtrudeObj
;
1128 pNewNext
->maPreparedPolyPolygon
= aExtrudePoly
;
1129 pNewNext
->mpNext
= pLayer
->mpNext
;
1130 pLayer
->mpNext
= pNewNext
;
1136 pBaseLayer
= new E3dDepthLayer
;
1137 pLayer
= pBaseLayer
;
1139 pLayer
->mpNext
= new E3dDepthNeighbour
;
1140 pLayer
->mpNext
->mpObj
= pExtrudeObj
;
1141 pLayer
->mpNext
->maPreparedPolyPolygon
= aExtrudePoly
;
1146 // number of layers is done
1149 // need to be arranged
1150 double fMinDepth
= fDepth
* 0.8;
1151 double fStep
= (fDepth
- fMinDepth
) / (double)nNumLayers
;
1152 pLayer
= pBaseLayer
;
1157 E3dDepthNeighbour
* pAct
= pLayer
->mpNext
;
1161 // adapt extrude value
1162 pAct
->mpObj
->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH
, sal_uInt32(fMinDepth
+ 0.5)));
1165 pAct
= pAct
->mpNext
;
1169 pLayer
= pLayer
->mpDown
;
1177 pLayer
= pBaseLayer
->mpDown
;
1179 pBaseLayer
= pLayer
;
1184 // Start drag, create for 3D objects before possibly drag method
1186 sal_Bool
E3dView::BegDragObj(const Point
& rPnt
, OutputDevice
* pOut
,
1187 SdrHdl
* pHdl
, short nMinMov
,
1188 SdrDragMethod
* pForcedMeth
)
1190 if(Is3DRotationCreationActive() && GetMarkedObjectCount())
1192 // Determine all selected polygons and return rhe mirrored helper overlay
1193 mpMirrorOverlay
->SetMirrorAxis(aRef1
, aRef2
);
1197 bool bOwnActionNecessary
;
1200 bOwnActionNecessary
= true;
1202 else if (pHdl
->IsVertexHdl() || pHdl
->IsCornerHdl())
1204 bOwnActionNecessary
= true;
1208 bOwnActionNecessary
= false;
1211 if(bOwnActionNecessary
&& GetMarkedObjectCount() >= 1)
1213 E3dDragConstraint eConstraint
= E3DDRAG_CONSTR_XYZ
;
1214 bool bThereAreRootScenes
= false;
1215 bool bThereAre3DObjects
= false;
1216 long nCnt
= GetMarkedObjectCount();
1217 for(long nObjs
= 0;nObjs
< nCnt
;nObjs
++)
1219 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
1222 if(pObj
->ISA(E3dScene
) && ((E3dScene
*)pObj
)->GetScene() == pObj
)
1223 bThereAreRootScenes
= true;
1224 if(pObj
->ISA(E3dObject
))
1225 bThereAre3DObjects
= true;
1228 if( bThereAre3DObjects
)
1230 eDragHdl
= ( pHdl
== NULL
? HDL_MOVE
: pHdl
->GetKind() );
1231 switch ( eDragMode
)
1233 case SDRDRAG_ROTATE
:
1241 eConstraint
= E3DDRAG_CONSTR_X
;
1248 eConstraint
= E3DDRAG_CONSTR_Y
;
1257 eConstraint
= E3DDRAG_CONSTR_Z
;
1263 // do not mask the allowed rotations
1264 eConstraint
= E3dDragConstraint(eConstraint
& eDragConstraint
);
1265 pForcedMeth
= new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint
, IsSolidDragging());
1271 if(!bThereAreRootScenes
)
1273 pForcedMeth
= new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl
, eConstraint
, IsSolidDragging());
1279 case SDRDRAG_MIRROR
:
1281 case SDRDRAG_DISTORT
:
1282 case SDRDRAG_TRANSPARENCE
:
1283 case SDRDRAG_GRADIENT
:
1292 return SdrView::BegDragObj(rPnt
, pOut
, pHdl
, nMinMov
, pForcedMeth
);
1295 // Set current 3D drawing object, create the scene for this
1297 E3dScene
* E3dView::SetCurrent3DObj(E3dObject
* p3DObj
)
1299 DBG_ASSERT(p3DObj
!= NULL
, "Who puts in a NULL-pointer here");
1300 E3dScene
* pScene
= NULL
;
1302 // get transformed BoundVolume of the object
1303 basegfx::B3DRange
aVolume(p3DObj
->GetBoundVolume());
1304 aVolume
.transform(p3DObj
->GetTransform());
1305 double fW(aVolume
.getWidth());
1306 double fH(aVolume
.getHeight());
1308 Rectangle
aRect(0,0, (long) fW
, (long) fH
);
1310 pScene
= new E3dPolyScene(Get3DDefaultAttributes());
1312 InitScene(pScene
, fW
, fH
, aVolume
.getMaxZ() + ((fW
+ fH
) / 4.0));
1314 pScene
->Insert3DObj(p3DObj
);
1315 pScene
->NbcSetSnapRect(aRect
);
1320 void E3dView::InitScene(E3dScene
* pScene
, double fW
, double fH
, double fCamZ
)
1322 Camera3D
aCam(pScene
->GetCamera());
1324 aCam
.SetAutoAdjustProjection(sal_False
);
1325 aCam
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
1326 basegfx::B3DPoint aLookAt
;
1328 double fDefaultCamPosZ
= GetDefaultCamPosZ();
1329 basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
1331 aCam
.SetPosAndLookAt(aCamPos
, aLookAt
);
1332 aCam
.SetFocalLength(GetDefaultCamFocal());
1333 aCam
.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ
), aLookAt
, GetDefaultCamFocal());
1334 pScene
->SetCamera(aCam
);
1337 void E3dView::Start3DCreation()
1339 if (GetMarkedObjectCount())
1347 OutputDevice
* pOut
= GetFirstOutputDevice();
1349 // first determine representation boundaries
1352 nMinLen
= pOut
->PixelToLogic(Size(0,50)).Height();
1353 nObjDst
= pOut
->PixelToLogic(Size(0,20)).Height();
1355 long nDst
= pOut
->PixelToLogic(Size(0,10)).Height();
1357 nOutMin
= -pOut
->GetMapMode().GetOrigin().Y();
1358 nOutMax
= pOut
->GetOutputSize().Height() - 1 + nOutMin
;
1362 if (nOutMax
- nOutMin
< nDst
)
1364 nOutMin
+= nOutMax
+ 1;
1366 nOutMin
-= (nDst
+ 1) / 2;
1367 nOutMax
= nOutMin
+ nDst
;
1370 nOutHgt
= nOutMax
- nOutMin
;
1372 long nTemp
= nOutHgt
/ 4;
1373 if (nTemp
> nMinLen
) nMinLen
= nTemp
;
1376 // and then attach the marks at the top and bottom of the object
1377 basegfx::B2DRange aR
;
1378 for(sal_uInt32
nMark(0L); nMark
< GetMarkedObjectCount(); nMark
++)
1380 SdrObject
* pMark
= GetMarkedObjectByIndex(nMark
);
1381 basegfx::B2DPolyPolygon
aXPP(pMark
->TakeXorPoly());
1382 aR
.expand(basegfx::tools::getRange(aXPP
));
1385 basegfx::B2DPoint
aCenter(aR
.getCenter());
1386 long nMarkHgt
= basegfx::fround(aR
.getHeight()) - 1;
1387 long nHgt
= nMarkHgt
+ nObjDst
* 2;
1389 if (nHgt
< nMinLen
) nHgt
= nMinLen
;
1391 long nY1
= basegfx::fround(aCenter
.getY()) - (nHgt
+ 1) / 2;
1392 long nY2
= nY1
+ nHgt
;
1394 if (pOut
&& (nMinLen
> nOutHgt
)) nMinLen
= nOutHgt
;
1400 if (nY2
< nY1
+ nMinLen
) nY2
= nY1
+ nMinLen
;
1405 if (nY1
> nY2
- nMinLen
) nY1
= nY2
- nMinLen
;
1409 aRef1
.X() = basegfx::fround(aR
.getMinX()); // Initial move axis 2/100mm to the left
1411 aRef2
.X() = aRef1
.X();
1417 //HMHif (bVis) ShowMarkHdl();
1418 if (AreObjectsMarked()) MarkListHasChanged();
1420 // Show mirror polygon IMMEDIATELY
1421 const SdrHdlList
&aHdlList
= GetHdlList();
1422 mpMirrorOverlay
= new Impl3DMirrorConstructOverlay(*this);
1423 mpMirrorOverlay
->SetMirrorAxis(aHdlList
.GetHdl(HDL_REF1
)->GetPos(), aHdlList
.GetHdl(HDL_REF2
)->GetPos());
1427 // what happens with a mouse movement when the object is created?
1429 void E3dView::MovAction(const Point
& rPnt
)
1431 if(Is3DRotationCreationActive())
1433 SdrHdl
* pHdl
= GetDragHdl();
1437 SdrHdlKind eHdlKind
= pHdl
->GetKind();
1439 // reacts only due to a mirror axis
1440 if ((eHdlKind
== HDL_REF1
) ||
1441 (eHdlKind
== HDL_REF2
) ||
1442 (eHdlKind
== HDL_MIRX
))
1444 const SdrHdlList
&aHdlList
= GetHdlList ();
1446 // delete the mirroed polygon, mirrors the original and draws
1448 SdrView::MovAction (rPnt
);
1449 mpMirrorOverlay
->SetMirrorAxis(
1450 aHdlList
.GetHdl (HDL_REF1
)->GetPos(),
1451 aHdlList
.GetHdl (HDL_REF2
)->GetPos());
1456 SdrView::MovAction (rPnt
);
1461 SdrView::MovAction (rPnt
);
1465 // The End. Create object and any child objects through ImpCreate3DLathe.
1466 // With the parameter value sal_True (SDefault: sal_False) is simply a
1467 // rotation body created, without letting the user set the position of the
1468 // axis. It is sufficient with this call, if an object is selected.
1469 // (No initialization necessary)
1471 void E3dView::End3DCreation(bool bUseDefaultValuesForMirrorAxes
)
1473 ResetCreationActive();
1475 if(AreObjectsMarked())
1477 if(bUseDefaultValuesForMirrorAxes
)
1479 Rectangle aRect
= GetAllMarkedRect();
1480 if(aRect
.GetWidth() <= 1)
1481 aRect
.SetSize(Size(500, aRect
.GetHeight()));
1482 if(aRect
.GetHeight() <= 1)
1483 aRect
.SetSize(Size(aRect
.GetWidth(), 500));
1485 basegfx::B2DPoint
aPnt1(aRect
.Left(), -aRect
.Top());
1486 basegfx::B2DPoint
aPnt2(aRect
.Left(), -aRect
.Bottom());
1488 ConvertMarkedObjTo3D(false, aPnt1
, aPnt2
);
1492 // Turn off helper overlay
1493 // Determine from the handle positions and the displacement of
1495 const SdrHdlList
&aHdlList
= GetHdlList();
1496 Point aMirrorRef1
= aHdlList
.GetHdl(HDL_REF1
)->GetPos();
1497 Point aMirrorRef2
= aHdlList
.GetHdl(HDL_REF2
)->GetPos();
1499 basegfx::B2DPoint
aPnt1(aMirrorRef1
.X(), -aMirrorRef1
.Y());
1500 basegfx::B2DPoint
aPnt2(aMirrorRef2
.X(), -aMirrorRef2
.Y());
1502 ConvertMarkedObjTo3D(false, aPnt1
, aPnt2
);
1507 E3dView::~E3dView ()
1511 void E3dView::ResetCreationActive ()
1515 delete mpMirrorOverlay
;
1516 mpMirrorOverlay
= 0L;
1520 void E3dView::InitView ()
1522 eDragConstraint
= E3DDRAG_CONSTR_XYZ
;
1525 fDefaultScaleZ
= 1.0;
1528 fDefaultRotateZ
= 0.0;
1529 fDefaultExtrusionDeepth
= 1000; // old: 2000;
1530 fDefaultLightIntensity
= 0.8; // old: 0.6;
1531 fDefaultAmbientIntensity
= 0.4;
1532 nHDefaultSegments
= 12;
1533 nVDefaultSegments
= 12;
1534 aDefaultLightColor
= RGB_Color(COL_WHITE
);
1535 aDefaultAmbientColor
= RGB_Color(COL_BLACK
);
1536 bDoubleSided
= sal_False
;
1537 mpMirrorOverlay
= 0L;
1540 bool E3dView::IsBreak3DObjPossible() const
1542 sal_uIntPtr nCount
= GetMarkedObjectCount();
1550 SdrObject
* pObj
= GetMarkedObjectByIndex(i
);
1552 if (pObj
&& pObj
->ISA(E3dObject
))
1554 if(!(((E3dObject
*)pObj
)->IsBreakObjPossible()))
1573 void E3dView::Break3DObj()
1575 if(IsBreak3DObjPossible())
1577 // ALL selected objects are changed
1578 sal_uInt32 nCount
= GetMarkedObjectCount();
1580 BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE
)));
1581 for(sal_uInt32 a
=0;a
<nCount
;a
++)
1583 E3dObject
* pObj
= (E3dObject
*)GetMarkedObjectByIndex(a
);
1584 BreakSingle3DObj(pObj
);
1591 void E3dView::BreakSingle3DObj(E3dObject
* pObj
)
1593 if(pObj
->ISA(E3dScene
))
1595 SdrObjList
* pSubList
= pObj
->GetSubList();
1596 SdrObjListIter
aIter(*pSubList
, IM_FLAT
);
1598 while(aIter
.IsMore())
1600 E3dObject
* pSubObj
= (E3dObject
*)aIter
.Next();
1601 BreakSingle3DObj(pSubObj
);
1606 SdrAttrObj
* pNewObj
= pObj
->GetBreakObj();
1609 InsertObjectAtView(pNewObj
, *GetSdrPageView(), SDRINSERT_DONTMARK
);
1610 pNewObj
->SetChanged();
1611 pNewObj
->BroadcastObjectChange();
1616 void E3dView::CheckPossibilities()
1619 SdrView::CheckPossibilities();
1622 if(bGroupPossible
|| bUnGroupPossible
|| bGrpEnterPossible
)
1624 sal_Int32 nMarkCnt
= GetMarkedObjectCount();
1625 bool bCoumpound
= false;
1626 bool b3DObject
= false;
1627 for(sal_Int32 nObjs
= 0L; (nObjs
< nMarkCnt
) && !bCoumpound
; nObjs
++)
1629 SdrObject
*pObj
= GetMarkedObjectByIndex(nObjs
);
1630 if(pObj
&& pObj
->ISA(E3dCompoundObject
))
1632 if(pObj
&& pObj
->ISA(E3dObject
))
1636 // So far: there are two or more of any objects selected. See if
1637 // compound objects are involved. If yes, ban grouping.
1638 if(bGroupPossible
&& bCoumpound
)
1639 bGroupPossible
= sal_False
;
1641 if(bUnGroupPossible
&& b3DObject
)
1642 bUnGroupPossible
= sal_False
;
1644 if(bGrpEnterPossible
&& bCoumpound
)
1645 bGrpEnterPossible
= sal_False
;
1649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */