| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svx.hxx" |
| |
| #include <vcl/wrkwin.hxx> |
| #include <svx/svdogrp.hxx> |
| #include <svx/svdopath.hxx> |
| #include <tools/shl.hxx> |
| #include "svx/svditer.hxx" |
| #include <svx/svdpool.hxx> |
| #include <svx/svdorect.hxx> |
| #include <svx/svdmodel.hxx> |
| #include <svx/svdpagv.hxx> |
| #include <svx/svxids.hrc> |
| #include <editeng/colritem.hxx> |
| #include <svx/xtable.hxx> |
| #include <svx/svdview.hxx> |
| #include <svx/dialogs.hrc> |
| #include <svx/dialmgr.hxx> |
| #include "svx/globl3d.hxx" |
| #include <svx/obj3d.hxx> |
| #include <svx/lathe3d.hxx> |
| #include <svx/sphere3d.hxx> |
| #include <svx/extrud3d.hxx> |
| #include <svx/cube3d.hxx> |
| #include <svx/polysc3d.hxx> |
| #include "dragmt3d.hxx" |
| #include <svx/view3d.hxx> |
| #include <svx/svdundo.hxx> |
| #include <svx/xflclit.hxx> |
| #include <svx/xlnclit.hxx> |
| #include <svx/svdograf.hxx> |
| #include <svx/xbtmpit.hxx> |
| #include <svx/xflbmtit.hxx> |
| #include <basegfx/range/b2drange.hxx> |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <basegfx/polygon/b2dpolypolygontools.hxx> |
| #include <svx/xlnwtit.hxx> |
| #include <svx/sdr/overlay/overlaypolypolygon.hxx> |
| #include <svx/sdr/overlay/overlaymanager.hxx> |
| #include <svx/sdrpaintwindow.hxx> |
| #include <svx/sdr/contact/viewcontactofe3dscene.hxx> |
| #include <drawinglayer/geometry/viewinformation3d.hxx> |
| #include <svx/sdrpagewindow.hxx> |
| #include <svx/sdr/contact/displayinfo.hxx> |
| #include <svx/sdr/contact/objectcontact.hxx> |
| #include <svx/sdr/contact/viewobjectcontact.hxx> |
| #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> |
| #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx> |
| #include <drawinglayer/primitive2d/transformprimitive2d.hxx> |
| #include <basegfx/matrix/b2dhommatrixtools.hxx> |
| #include <basegfx/polygon/b2dpolypolygoncutter.hxx> |
| |
| #define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() |
| |
| TYPEINIT1(E3dView, SdrView); |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // Migrate Marking |
| |
| class Impl3DMirrorConstructOverlay |
| { |
| // The OverlayObjects |
| ::sdr::overlay::OverlayObjectList maObjects; |
| |
| // the view |
| const E3dView& mrView; |
| |
| // the object count |
| sal_uInt32 mnCount; |
| |
| // the unmirrored polygons |
| basegfx::B2DPolyPolygon* mpPolygons; |
| |
| // the overlay geometry from selected objects |
| drawinglayer::primitive2d::Primitive2DSequence maFullOverlay; |
| |
| public: |
| Impl3DMirrorConstructOverlay(const E3dView& rView); |
| ~Impl3DMirrorConstructOverlay(); |
| |
| void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB); |
| }; |
| |
| Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView) |
| : maObjects(), |
| mrView(rView), |
| mnCount(rView.GetMarkedObjectCount()), |
| mpPolygons(0), |
| maFullOverlay() |
| { |
| if(mnCount) |
| { |
| if(mrView.IsSolidDragging()) |
| { |
| SdrPageView* pPV = rView.GetSdrPageView(); |
| |
| if(pPV && pPV->PageWindowCount()) |
| { |
| sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact(); |
| sdr::contact::DisplayInfo aDisplayInfo; |
| |
| // Do not use the last ViewPort set at the OC at the last ProcessDisplay() |
| rOC.resetViewPort(); |
| |
| for(sal_uInt32 a(0);a < mnCount;a++) |
| { |
| SdrObject* pObject = mrView.GetMarkedObjectByIndex(a); |
| |
| if(pObject) |
| { |
| sdr::contact::ViewContact& rVC = pObject->GetViewContact(); |
| sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rOC); |
| |
| const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo)); |
| drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay, aNewSequence); |
| } |
| } |
| } |
| } |
| else |
| { |
| mpPolygons = new basegfx::B2DPolyPolygon[mnCount]; |
| |
| for(sal_uInt32 a(0); a < mnCount; a++) |
| { |
| SdrObject* pObject = mrView.GetMarkedObjectByIndex(a); |
| mpPolygons[mnCount - (a + 1)] = pObject->TakeXorPoly(); |
| } |
| } |
| } |
| } |
| |
| Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay() |
| { |
| // The OverlayObjects are cleared using the destructor of OverlayObjectList. |
| // That destructor calls clear() at the list which removes all objects from the |
| // OverlayManager and deletes them. |
| if(!mrView.IsSolidDragging()) |
| { |
| delete[] mpPolygons; |
| } |
| } |
| |
| void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB) |
| { |
| // get rid of old overlay objects |
| maObjects.clear(); |
| |
| // create new ones |
| for(sal_uInt32 a(0); a < mrView.PaintWindowCount(); a++) |
| { |
| SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a); |
| ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); |
| |
| if(pTargetOverlay) |
| { |
| // buld transfoprmation: translate and rotate so that given edge is |
| // on x axis, them mirror in y and translate back |
| const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y()); |
| basegfx::B2DHomMatrix aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix( |
| -aMirrorAxisA.X(), -aMirrorAxisA.Y())); |
| aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX())); |
| aMatrixTransform.scale(1.0, -1.0); |
| aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX())); |
| aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y()); |
| |
| if(mrView.IsSolidDragging()) |
| { |
| if(maFullOverlay.hasElements()) |
| { |
| drawinglayer::primitive2d::Primitive2DSequence aContent(maFullOverlay); |
| |
| if(!aMatrixTransform.isIdentity()) |
| { |
| // embed in transformation group |
| drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform, aContent)); |
| aContent = drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1); |
| } |
| |
| // if we have full overlay from selected objects, embed with 50% transparence, the |
| // transformation is added to the OverlayPrimitive2DSequenceObject |
| drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aContent, 0.5)); |
| aContent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1); |
| |
| sdr::overlay::OverlayPrimitive2DSequenceObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent); |
| |
| pTargetOverlay->add(*pNew); |
| maObjects.append(*pNew); |
| } |
| } |
| else |
| { |
| for(sal_uInt32 b(0); b < mnCount; b++) |
| { |
| // apply to polygon |
| basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]); |
| aPolyPolygon.transform(aMatrixTransform); |
| |
| ::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled( |
| aPolyPolygon); |
| pTargetOverlay->add(*pNew); |
| maObjects.append(*pNew); |
| } |
| } |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Konstruktor 1 |
| |* |
| \************************************************************************/ |
| |
| E3dView::E3dView(SdrModel* pModel, OutputDevice* pOut) : |
| SdrView(pModel, pOut) |
| { |
| InitView (); |
| } |
| |
| /************************************************************************* |
| |* |
| |* DrawMarkedObj ueberladen, da eventuell nur einzelne 3D-Objekte |
| |* gezeichnet werden sollen |
| |* |
| \************************************************************************/ |
| |
| void E3dView::DrawMarkedObj(OutputDevice& rOut) const |
| { |
| // Existieren 3D-Objekte, deren Szenen nicht selektiert sind? |
| sal_Bool bSpecialHandling = sal_False; |
| E3dScene *pScene = NULL; |
| |
| long nCnt = GetMarkedObjectCount(); |
| for(long nObjs = 0;nObjs < nCnt;nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| if(pObj && pObj->ISA(E3dCompoundObject)) |
| { |
| // zugehoerige Szene |
| pScene = ((E3dCompoundObject*)pObj)->GetScene(); |
| if(pScene && !IsObjMarked(pScene)) |
| bSpecialHandling = sal_True; |
| } |
| // Alle SelectionFlags zuruecksetzen |
| if(pObj && pObj->ISA(E3dObject)) |
| { |
| pScene = ((E3dObject*)pObj)->GetScene(); |
| if(pScene) |
| pScene->SetSelected(sal_False); |
| } |
| } |
| |
| if(bSpecialHandling) |
| { |
| // SelectionFlag bei allen zu 3D Objekten gehoerigen |
| // Szenen und deren Objekten auf nicht selektiert setzen |
| long nObjs; |
| for(nObjs = 0;nObjs < nCnt;nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| if(pObj && pObj->ISA(E3dCompoundObject)) |
| { |
| // zugehoerige Szene |
| pScene = ((E3dCompoundObject*)pObj)->GetScene(); |
| if(pScene) |
| pScene->SetSelected(sal_False); |
| } |
| } |
| |
| // bei allen direkt selektierten Objekten auf selektiert setzen |
| SdrMark* pM = NULL; |
| |
| for(nObjs = 0;nObjs < nCnt;nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| if(pObj && pObj->ISA(E3dObject)) |
| { |
| // Objekt markieren |
| E3dObject* p3DObj = (E3dObject*)pObj; |
| p3DObj->SetSelected(sal_True); |
| pScene = p3DObj->GetScene(); |
| pM = GetSdrMarkByIndex(nObjs); |
| } |
| } |
| |
| if(pScene) |
| { |
| // code from parent |
| SortMarkedObjects(); |
| |
| pScene->SetDrawOnlySelected(sal_True); |
| pScene->SingleObjectPainter(rOut); // #110094#-17 |
| pScene->SetDrawOnlySelected(sal_False); |
| } |
| |
| // SelectionFlag zuruecksetzen |
| for(nObjs = 0;nObjs < nCnt;nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| if(pObj && pObj->ISA(E3dCompoundObject)) |
| { |
| // zugehoerige Szene |
| pScene = ((E3dCompoundObject*)pObj)->GetScene(); |
| if(pScene) |
| pScene->SetSelected(sal_False); |
| } |
| } |
| } |
| else |
| { |
| // call parent |
| SdrExchangeView::DrawMarkedObj(rOut); |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Model holen ueberladen, da bei einzelnen 3D Objekten noch eine Szene |
| |* untergeschoben werden muss |
| |* |
| \************************************************************************/ |
| |
| SdrModel* E3dView::GetMarkedObjModel() const |
| { |
| // Existieren 3D-Objekte, deren Szenen nicht selektiert sind? |
| bool bSpecialHandling(false); |
| const sal_uInt32 nCount(GetMarkedObjectCount()); |
| sal_uInt32 nObjs(0); |
| E3dScene *pScene = 0; |
| |
| for(nObjs = 0; nObjs < nCount; nObjs++) |
| { |
| const SdrObject* pObj = GetMarkedObjectByIndex(nObjs); |
| |
| if(!bSpecialHandling && pObj && pObj->ISA(E3dCompoundObject)) |
| { |
| // if the object is selected, but it's scene not, |
| // we need special handling |
| pScene = ((E3dCompoundObject*)pObj)->GetScene(); |
| |
| if(pScene && !IsObjMarked(pScene)) |
| { |
| bSpecialHandling = true; |
| } |
| } |
| |
| if(pObj && pObj->ISA(E3dObject)) |
| { |
| // reset all selection flags at 3D objects |
| pScene = ((E3dObject*)pObj)->GetScene(); |
| |
| if(pScene) |
| { |
| pScene->SetSelected(false); |
| } |
| } |
| } |
| |
| if(!bSpecialHandling) |
| { |
| // call parent |
| return SdrView::GetMarkedObjModel(); |
| } |
| |
| SdrModel* pNewModel = 0; |
| Rectangle aSelectedSnapRect; |
| |
| // set 3d selection flags at all directly selected objects |
| // and collect SnapRect of selected objects |
| for(nObjs = 0; nObjs < nCount; nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| |
| if(pObj && pObj->ISA(E3dCompoundObject)) |
| { |
| // mark object, but not scenes |
| E3dCompoundObject* p3DObj = (E3dCompoundObject*)pObj; |
| p3DObj->SetSelected(true); |
| aSelectedSnapRect.Union(p3DObj->GetSnapRect()); |
| } |
| } |
| |
| // create new mark list which contains all indirectly selected3d |
| // scenes as selected objects |
| SdrMarkList aOldML(GetMarkedObjectList()); |
| SdrMarkList aNewML; |
| SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess(); |
| rCurrentMarkList = aNewML; |
| |
| for(nObjs = 0; nObjs < nCount; nObjs++) |
| { |
| SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj(); |
| |
| if(pObj && pObj->ISA(E3dObject)) |
| { |
| pScene = ((E3dObject*)pObj)->GetScene(); |
| |
| if(pScene && !IsObjMarked(pScene) && GetSdrPageView()) |
| { |
| ((E3dView*)this)->MarkObj(pScene, GetSdrPageView(), sal_False, sal_True); |
| } |
| } |
| } |
| |
| // call parent. This will copy all scenes and the selection flags at the 3d objectss. So |
| // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes |
| pNewModel = SdrView::GetMarkedObjModel(); |
| |
| if(pNewModel) |
| { |
| for(sal_uInt16 nPg(0); nPg < pNewModel->GetPageCount(); nPg++) |
| { |
| const SdrPage* pSrcPg=pNewModel->GetPage(nPg); |
| const sal_uInt32 nObAnz(pSrcPg->GetObjCount()); |
| |
| for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++) |
| { |
| const SdrObject* pSrcOb=pSrcPg->GetObj(nOb); |
| |
| if(pSrcOb->ISA(E3dScene)) |
| { |
| pScene = (E3dScene*)pSrcOb; |
| |
| // delete all not intentionally cloned 3d objects |
| pScene->removeAllNonSelectedObjects(); |
| |
| // reset select flags and set SnapRect of all selected objects |
| pScene->SetSelected(false); |
| pScene->SetSnapRect(aSelectedSnapRect); |
| } |
| } |
| } |
| } |
| |
| // restore old selection |
| rCurrentMarkList = aOldML; |
| |
| // model zurueckgeben |
| return pNewModel; |
| } |
| |
| /************************************************************************* |
| |* |
| |* Bei Paste muss - falls in eine Scene eingefuegt wird - die |
| |* Objekte der Szene eingefuegt werden, die Szene selbst aber nicht |
| |* |
| \************************************************************************/ |
| |
| sal_Bool E3dView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions) |
| { |
| sal_Bool bRetval = sal_False; |
| |
| // Liste holen |
| Point aPos(rPos); |
| SdrObjList* pDstList = pLst; |
| ImpGetPasteObjList(aPos, pDstList); |
| |
| if(!pDstList) |
| return sal_False; |
| |
| // Owner der Liste holen |
| SdrObject* pOwner = pDstList->GetOwnerObj(); |
| if(pOwner && pOwner->ISA(E3dScene)) |
| { |
| E3dScene* pDstScene = (E3dScene*)pOwner; |
| BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE)); |
| |
| // Alle Objekte aus E3dScenes kopieren und direkt einfuegen |
| for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++) |
| { |
| const SdrPage* pSrcPg=rMod.GetPage(nPg); |
| sal_uInt32 nObAnz(pSrcPg->GetObjCount()); |
| |
| // calculate offset for paste |
| Rectangle aR = pSrcPg->GetAllObjBoundRect(); |
| Point aDist(aPos - aR.Center()); |
| |
| // Unterobjekte von Szenen einfuegen |
| for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++) |
| { |
| const SdrObject* pSrcOb = pSrcPg->GetObj(nOb); |
| if(pSrcOb->ISA(E3dScene)) |
| { |
| E3dScene* pSrcScene = (E3dScene*)pSrcOb; |
| ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist); |
| } |
| } |
| } |
| EndUndo(); |
| } |
| else |
| { |
| // call parent |
| bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions); |
| } |
| |
| // und Rueckgabewert liefern |
| return bRetval; |
| } |
| |
| // #83403# Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...) |
| sal_Bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point /*aOffset*/) |
| { |
| sal_Bool bRetval(sal_False); |
| |
| if(pSrcScene && pDstScene) |
| { |
| const sdr::contact::ViewContactOfE3dScene& rVCSceneDst = static_cast< sdr::contact::ViewContactOfE3dScene& >(pDstScene->GetViewContact()); |
| const drawinglayer::geometry::ViewInformation3D aViewInfo3DDst(rVCSceneDst.getViewInformation3D()); |
| const sdr::contact::ViewContactOfE3dScene& rVCSceneSrc = static_cast< sdr::contact::ViewContactOfE3dScene& >(pSrcScene->GetViewContact()); |
| const drawinglayer::geometry::ViewInformation3D aViewInfo3DSrc(rVCSceneSrc.getViewInformation3D()); |
| |
| for(sal_uInt32 i(0); i < pSrcScene->GetSubList()->GetObjCount(); i++) |
| { |
| E3dCompoundObject* pCompoundObj = dynamic_cast< E3dCompoundObject* >(pSrcScene->GetSubList()->GetObj(i)); |
| |
| if(pCompoundObj) |
| { |
| // #116235# |
| E3dCompoundObject* pNewCompoundObj = dynamic_cast< E3dCompoundObject* >(pCompoundObj->Clone()); |
| |
| if(pNewCompoundObj) |
| { |
| // get dest scene's current range in 3D world coordinates |
| const basegfx::B3DHomMatrix aSceneToWorldTrans(pDstScene->GetFullTransform()); |
| basegfx::B3DRange aSceneRange(pDstScene->GetBoundVolume()); |
| aSceneRange.transform(aSceneToWorldTrans); |
| |
| // get new object's implied object transformation |
| const basegfx::B3DHomMatrix aNewObjectTrans(pNewCompoundObj->GetTransform()); |
| |
| // get new object's range in 3D world coordinates in dest scene |
| // as if it were already added |
| const basegfx::B3DHomMatrix aObjectToWorldTrans(aSceneToWorldTrans * aNewObjectTrans); |
| basegfx::B3DRange aObjectRange(pNewCompoundObj->GetBoundVolume()); |
| aObjectRange.transform(aObjectToWorldTrans); |
| |
| // get scale adaption |
| const basegfx::B3DVector aSceneScale(aSceneRange.getRange()); |
| const basegfx::B3DVector aObjectScale(aObjectRange.getRange()); |
| double fScale(1.0); |
| |
| // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale |
| // to not change the scene by the inserted object |
| const double fSizeFactor(0.5); |
| |
| if(aObjectScale.getX() * fScale > aSceneScale.getX() * fSizeFactor) |
| { |
| const double fObjSize(aObjectScale.getX() * fScale); |
| const double fFactor((aSceneScale.getX() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize)); |
| fScale *= fFactor; |
| } |
| |
| if(aObjectScale.getY() * fScale > aSceneScale.getY() * fSizeFactor) |
| { |
| const double fObjSize(aObjectScale.getY() * fScale); |
| const double fFactor((aSceneScale.getY() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize)); |
| fScale *= fFactor; |
| } |
| |
| if(aObjectScale.getZ() * fScale > aSceneScale.getZ() * fSizeFactor) |
| { |
| const double fObjSize(aObjectScale.getZ() * fScale); |
| const double fFactor((aSceneScale.getZ() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize)); |
| fScale *= fFactor; |
| } |
| |
| // get translation adaption |
| const basegfx::B3DPoint aSceneCenter(aSceneRange.getCenter()); |
| const basegfx::B3DPoint aObjectCenter(aObjectRange.getCenter()); |
| |
| // build full modification transform. The object's transformation |
| // shall be modified, so start at object coordinates; transform to 3d world coor |
| basegfx::B3DHomMatrix aModifyingTransform(aObjectToWorldTrans); |
| |
| // translate to absolute center in 3d world coor |
| aModifyingTransform.translate(-aObjectCenter.getX(), -aObjectCenter.getY(), -aObjectCenter.getZ()); |
| |
| // scale to dest size in 3d world coor |
| aModifyingTransform.scale(fScale, fScale, fScale); |
| |
| // translate to dest scene center in 3d world coor |
| aModifyingTransform.translate(aSceneCenter.getX(), aSceneCenter.getY(), aSceneCenter.getZ()); |
| |
| // transform from 3d world to dest object coordinates |
| basegfx::B3DHomMatrix aWorldToObject(aObjectToWorldTrans); |
| aWorldToObject.invert(); |
| aModifyingTransform = aWorldToObject * aModifyingTransform; |
| |
| // correct implied object transform by applying changing one in object coor |
| pNewCompoundObj->SetTransform(aModifyingTransform * aNewObjectTrans); |
| |
| // fill and insert new object |
| pNewCompoundObj->SetModel(pDstScene->GetModel()); |
| pNewCompoundObj->SetPage(pDstScene->GetPage()); |
| pNewCompoundObj->NbcSetLayer(pCompoundObj->GetLayer()); |
| pNewCompoundObj->NbcSetStyleSheet(pCompoundObj->GetStyleSheet(), sal_True); |
| pDstScene->Insert3DObj(pNewCompoundObj); |
| bRetval = sal_True; |
| |
| // Undo anlegen |
| if( GetModel()->IsUndoEnabled() ) |
| AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj)); |
| } |
| } |
| } |
| } |
| |
| return bRetval; |
| } |
| |
| /************************************************************************* |
| |* |
| |* 3D-Konvertierung moeglich? |
| |* |
| \************************************************************************/ |
| |
| sal_Bool E3dView::IsConvertTo3DObjPossible() const |
| { |
| sal_Bool bAny3D(sal_False); |
| sal_Bool bGroupSelected(sal_False); |
| sal_Bool bRetval(sal_True); |
| |
| for(sal_uInt32 a=0;!bAny3D && a<GetMarkedObjectCount();a++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(a); |
| if(pObj) |
| { |
| ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected); |
| } |
| } |
| |
| bRetval = !bAny3D |
| && ( |
| IsConvertToPolyObjPossible(sal_False) |
| || IsConvertToPathObjPossible(sal_False) |
| || IsImportMtfPossible()); |
| return bRetval; |
| } |
| |
| void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, sal_Bool& rAny3D, |
| sal_Bool& rGroupSelected) const |
| { |
| if(pObj) |
| { |
| if(pObj->ISA(E3dObject)) |
| { |
| rAny3D = sal_True; |
| } |
| else |
| { |
| if(pObj->IsGroupObject()) |
| { |
| SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS); |
| while(aIter.IsMore()) |
| { |
| SdrObject* pNewObj = aIter.Next(); |
| ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected); |
| } |
| rGroupSelected = sal_True; |
| } |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* 3D-Konvertierung zu Extrude ausfuehren |
| |* |
| \************************************************************************/ |
| #include <editeng/eeitem.hxx> |
| |
| void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject* pObj) |
| { |
| if(pObj->ISA(SdrTextObj)) |
| { |
| const SfxItemSet& rSet = pObj->GetMergedItemSet(); |
| const SvxColorItem& rTextColorItem = (const SvxColorItem&)rSet.Get(EE_CHAR_COLOR); |
| if(rTextColorItem.GetValue() == RGB_Color(COL_BLACK)) |
| { |
| // Bei schwarzen Textobjekten wird die Farbe auf grau gesetzt |
| if(pObj->GetPage()) |
| { |
| // #84864# if black is only default attribute from |
| // pattern set it hard so that it is used in undo. |
| pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK), EE_CHAR_COLOR)); |
| |
| // add undo now |
| if( GetModel()->IsUndoEnabled() ) |
| AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false)); |
| } |
| |
| pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY), EE_CHAR_COLOR)); |
| } |
| } |
| } |
| |
| void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject* pObj) |
| { |
| if(pObj->ISA(SdrPathObj)) |
| { |
| const SfxItemSet& rSet = pObj->GetMergedItemSet(); |
| sal_Int32 nLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); |
| XLineStyle eLineStyle = (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue(); |
| XFillStyle eFillStyle = ITEMVALUE(rSet, XATTR_FILLSTYLE, XFillStyleItem); |
| |
| if(((SdrPathObj*)pObj)->IsClosed() |
| && eLineStyle == XLINE_SOLID |
| && !nLineWidth |
| && eFillStyle != XFILL_NONE) |
| { |
| if(pObj->GetPage() && GetModel()->IsUndoEnabled() ) |
| AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false)); |
| pObj->SetMergedItem(XLineStyleItem(XLINE_NONE)); |
| pObj->SetMergedItem(XLineWidthItem(0L)); |
| } |
| } |
| } |
| |
| void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, sal_Bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat) |
| { |
| // Einzelnes PathObject, dieses umwanden |
| SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj); |
| |
| if(pPath) |
| { |
| E3dDefaultAttributes aDefault = Get3DDefaultAttributes(); |
| if(bExtrude) |
| aDefault.SetDefaultExtrudeCharacterMode(sal_True); |
| else |
| aDefault.SetDefaultLatheCharacterMode(sal_True); |
| |
| // ItemSet des Ursprungsobjektes holen |
| SfxItemSet aSet(pObj->GetMergedItemSet()); |
| |
| XFillStyle eFillStyle = ITEMVALUE(aSet, XATTR_FILLSTYLE, XFillStyleItem); |
| |
| // Linienstil ausschalten |
| aSet.Put(XLineStyleItem(XLINE_NONE)); |
| |
| // Feststellen, ob ein FILL_Attribut gesetzt ist. |
| if(!pPath->IsClosed() || eFillStyle == XFILL_NONE) |
| { |
| // Das SdrPathObj ist nicht gefuellt, lasse die |
| // vordere und hintere Flaeche weg. Ausserdem ist |
| // eine beidseitige Darstellung notwendig. |
| aDefault.SetDefaultExtrudeCloseFront(sal_False); |
| aDefault.SetDefaultExtrudeCloseBack(sal_False); |
| |
| aSet.Put(Svx3DDoubleSidedItem(sal_True)); |
| |
| // Fuellattribut setzen |
| aSet.Put(XFillStyleItem(XFILL_SOLID)); |
| |
| // Fuellfarbe muss auf Linienfarbe, da das Objekt vorher |
| // nur eine Linie war |
| Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue(); |
| aSet.Put(XFillColorItem(String(), aColorLine)); |
| } |
| |
| // Neues Extrude-Objekt erzeugen |
| E3dObject* p3DObj = NULL; |
| if(bExtrude) |
| { |
| p3DObj = new E3dExtrudeObj(aDefault, pPath->GetPathPoly(), fDepth); |
| } |
| else |
| { |
| basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly()); |
| aPolyPoly2D.transform(rLatheMat); |
| p3DObj = new E3dLatheObj(aDefault, aPolyPoly2D); |
| } |
| |
| // Attribute setzen |
| if(p3DObj) |
| { |
| p3DObj->NbcSetLayer(pObj->GetLayer()); |
| |
| p3DObj->SetMergedItemSet(aSet); |
| |
| p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True); |
| |
| // Neues 3D-Objekt einfuegen |
| pScene->Insert3DObj(p3DObj); |
| } |
| } |
| } |
| |
| void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, sal_Bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat) |
| { |
| if(pObj) |
| { |
| // change text color attribute for not so dark colors |
| if(pObj->IsGroupObject()) |
| { |
| SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS); |
| while(aIter.IsMore()) |
| { |
| SdrObject* pGroupMember = aIter.Next(); |
| ImpChangeSomeAttributesFor3DConversion(pGroupMember); |
| } |
| } |
| else |
| ImpChangeSomeAttributesFor3DConversion(pObj); |
| |
| // convert completely to path objects |
| SdrObject* pNewObj1 = pObj->ConvertToPolyObj(sal_False, sal_False); |
| |
| if(pNewObj1) |
| { |
| // change text color attribute for not so dark colors |
| if(pNewObj1->IsGroupObject()) |
| { |
| SdrObjListIter aIter(*pNewObj1, IM_DEEPWITHGROUPS); |
| while(aIter.IsMore()) |
| { |
| SdrObject* pGroupMember = aIter.Next(); |
| ImpChangeSomeAttributesFor3DConversion2(pGroupMember); |
| } |
| } |
| else |
| ImpChangeSomeAttributesFor3DConversion2(pNewObj1); |
| |
| // convert completely to path objects |
| SdrObject* pNewObj2 = pObj->ConvertToContourObj(pNewObj1, sal_True); |
| |
| if(pNewObj2) |
| { |
| // add all to flat scene |
| if(pNewObj2->IsGroupObject()) |
| { |
| SdrObjListIter aIter(*pNewObj2, IM_DEEPWITHGROUPS); |
| while(aIter.IsMore()) |
| { |
| SdrObject* pGroupMember = aIter.Next(); |
| ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat); |
| } |
| } |
| else |
| ImpCreateSingle3DObjectFlat(pScene, pNewObj2, bExtrude, fDepth, rLatheMat); |
| |
| // delete zwi object |
| if(pNewObj2 != pObj && pNewObj2 != pNewObj1 && pNewObj2) |
| SdrObject::Free( pNewObj2 ); |
| } |
| |
| // delete zwi object |
| if(pNewObj1 != pObj && pNewObj1) |
| SdrObject::Free( pNewObj1 ); |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* 3D-Konvertierung zu Extrude steuern |
| |* |
| \************************************************************************/ |
| |
| void E3dView::ConvertMarkedObjTo3D(sal_Bool bExtrude, basegfx::B2DPoint aPnt1, basegfx::B2DPoint aPnt2) |
| { |
| if(AreObjectsMarked()) |
| { |
| // Undo anlegen |
| if(bExtrude) |
| BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE)); |
| else |
| BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE)); |
| |
| // Neue Szene fuer zu erzeugende 3D-Objekte anlegen |
| E3dScene* pScene = new E3dPolyScene(Get3DDefaultAttributes()); |
| |
| // Rechteck bestimmen und evtl. korrigieren |
| Rectangle aRect = GetAllMarkedRect(); |
| if(aRect.GetWidth() <= 1) |
| aRect.SetSize(Size(500, aRect.GetHeight())); |
| if(aRect.GetHeight() <= 1) |
| aRect.SetSize(Size(aRect.GetWidth(), 500)); |
| |
| // Tiefe relativ zur Groesse der Selektion bestimmen |
| double fDepth = 0.0; |
| double fRot3D = 0.0; |
| basegfx::B2DHomMatrix aLatheMat; |
| |
| if(bExtrude) |
| { |
| double fW = (double)aRect.GetWidth(); |
| double fH = (double)aRect.GetHeight(); |
| fDepth = sqrt(fW*fW + fH*fH) / 6.0; |
| } |
| if(!bExtrude) |
| { |
| // Transformation fuer Polygone Rotationskoerper erstellen |
| if(aPnt1 != aPnt2) |
| { |
| // Rotation um Kontrollpunkt1 mit eigestelltem Winkel |
| // fuer 3D Koordinaten |
| basegfx::B2DPoint aDiff(aPnt1 - aPnt2); |
| fRot3D = atan2(aDiff.getY(), aDiff.getX()) - F_PI2; |
| |
| if(basegfx::fTools::equalZero(fabs(fRot3D))) |
| fRot3D = 0.0; |
| |
| if(fRot3D != 0.0) |
| { |
| aLatheMat = basegfx::tools::createRotateAroundPoint(aPnt2, -fRot3D) |
| * aLatheMat; |
| } |
| } |
| |
| if(aPnt2.getX() != 0.0) |
| { |
| // Translation auf Y=0 - Achse |
| aLatheMat.translate(-aPnt2.getX(), 0.0); |
| } |
| else |
| { |
| aLatheMat.translate((double)-aRect.Left(), 0.0); |
| } |
| |
| // Inverse Matrix bilden, um die Zielausdehnung zu bestimmen |
| basegfx::B2DHomMatrix aInvLatheMat(aLatheMat); |
| aInvLatheMat.invert(); |
| |
| // SnapRect Ausdehnung mittels Spiegelung an der Rotationsachse |
| // erweitern |
| for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++) |
| { |
| SdrMark* pMark = GetSdrMarkByIndex(a); |
| SdrObject* pObj = pMark->GetMarkedSdrObj(); |
| Rectangle aTurnRect = pObj->GetSnapRect(); |
| basegfx::B2DPoint aRot; |
| Point aRotPnt; |
| |
| aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top()); |
| aRot *= aLatheMat; |
| aRot.setX(-aRot.getX()); |
| aRot *= aInvLatheMat; |
| aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5)); |
| aRect.Union(Rectangle(aRotPnt, aRotPnt)); |
| |
| aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom()); |
| aRot *= aLatheMat; |
| aRot.setX(-aRot.getX()); |
| aRot *= aInvLatheMat; |
| aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5)); |
| aRect.Union(Rectangle(aRotPnt, aRotPnt)); |
| |
| aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top()); |
| aRot *= aLatheMat; |
| aRot.setX(-aRot.getX()); |
| aRot *= aInvLatheMat; |
| aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5)); |
| aRect.Union(Rectangle(aRotPnt, aRotPnt)); |
| |
| aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom()); |
| aRot *= aLatheMat; |
| aRot.setX(-aRot.getX()); |
| aRot *= aInvLatheMat; |
| aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5)); |
| aRect.Union(Rectangle(aRotPnt, aRotPnt)); |
| } |
| } |
| |
| // Ueber die Selektion gehen und in 3D wandeln, komplett mit |
| // Umwandeln in SdrPathObject, auch Schriften |
| for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++) |
| { |
| SdrMark* pMark = GetSdrMarkByIndex(a); |
| SdrObject* pObj = pMark->GetMarkedSdrObj(); |
| |
| ImpCreate3DObject(pScene, pObj, bExtrude, fDepth, aLatheMat); |
| } |
| |
| if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0) |
| { |
| // Alle angelegten Objekte Tiefenarrangieren |
| if(bExtrude) |
| DoDepthArrange(pScene, fDepth); |
| |
| // 3D-Objekte auf die Mitte des Gesamtrechtecks zentrieren |
| basegfx::B3DPoint aCenter(pScene->GetBoundVolume().getCenter()); |
| basegfx::B3DHomMatrix aMatrix; |
| |
| aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ()); |
| pScene->SetTransform(aMatrix * pScene->GetTransform()); // #112587# |
| |
| // Szene initialisieren |
| pScene->NbcSetSnapRect(aRect); |
| basegfx::B3DRange aBoundVol = pScene->GetBoundVolume(); |
| InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth()); |
| |
| // Szene anstelle des ersten selektierten Objektes einfuegen |
| // und alle alten Objekte weghauen |
| SdrObject* pRepObj = GetMarkedObjectByIndex(0); |
| SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0); |
| MarkObj(pRepObj, pPV, sal_True); |
| ReplaceObjectAtView(pRepObj, *pPV, pScene, sal_False); |
| DeleteMarked(); |
| MarkObj(pScene, pPV); |
| |
| // Rotationskoerper um Rotationsachse drehen |
| basegfx::B3DHomMatrix aRotate; |
| |
| if(!bExtrude && fRot3D != 0.0) |
| { |
| aRotate.rotate(0.0, 0.0, fRot3D); |
| } |
| |
| // Default-Rotation setzen |
| { |
| double XRotateDefault = 20; |
| aRotate.rotate(DEG2RAD(XRotateDefault), 0.0, 0.0); |
| } |
| |
| if(!aRotate.isIdentity()) |
| { |
| pScene->SetTransform(aRotate * pScene->GetTransform()); |
| } |
| |
| // SnapRects der Objekte ungueltig |
| pScene->SetSnapRect(aRect); |
| } |
| else |
| { |
| // Es wurden keine 3D Objekte erzeugt, schmeiss alles weg |
| delete pScene; |
| } |
| |
| // Undo abschliessen |
| EndUndo(); |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Alle enthaltenen Extrude-Objekte Tiefenarrangieren |
| |* |
| \************************************************************************/ |
| |
| struct E3dDepthNeighbour |
| { |
| E3dDepthNeighbour* mpNext; |
| E3dExtrudeObj* mpObj; |
| basegfx::B2DPolyPolygon maPreparedPolyPolygon; |
| |
| E3dDepthNeighbour() |
| : mpNext(0), |
| mpObj(0), |
| maPreparedPolyPolygon() |
| { |
| } |
| }; |
| |
| struct E3dDepthLayer |
| { |
| E3dDepthLayer* mpDown; |
| E3dDepthNeighbour* mpNext; |
| |
| E3dDepthLayer() |
| : mpDown(0), |
| mpNext(0) |
| { |
| } |
| |
| ~E3dDepthLayer() |
| { |
| while(mpNext) |
| { |
| E3dDepthNeighbour* pSucc = mpNext->mpNext; |
| delete mpNext; |
| mpNext = pSucc; |
| } |
| } |
| }; |
| |
| void E3dView::DoDepthArrange(E3dScene* pScene, double fDepth) |
| { |
| if(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1) |
| { |
| SdrObjList* pSubList = pScene->GetSubList(); |
| SdrObjListIter aIter(*pSubList, IM_FLAT); |
| E3dDepthLayer* pBaseLayer = NULL; |
| E3dDepthLayer* pLayer = NULL; |
| sal_Int32 nNumLayers = 0; |
| |
| while(aIter.IsMore()) |
| { |
| E3dExtrudeObj* pExtrudeObj = dynamic_cast< E3dExtrudeObj* >(aIter.Next()); |
| |
| if(pExtrudeObj) |
| { |
| const basegfx::B2DPolyPolygon aExtrudePoly( |
| basegfx::tools::prepareForPolygonOperation(pExtrudeObj->GetExtrudePolygon())); |
| const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet(); |
| const XFillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem); |
| const Color aLocalColor = ((const XFillColorItem&)(rLocalSet.Get(XATTR_FILLCOLOR))).GetColorValue(); |
| |
| // sort in ExtrudeObj |
| if(pLayer) |
| { |
| // do we have overlap with an object of this layer? |
| bool bOverlap(false); |
| E3dDepthNeighbour* pAct = pLayer->mpNext; |
| |
| while(!bOverlap && pAct) |
| { |
| // do pAct->mpObj and pExtrudeObj overlap? Check by |
| // using logical AND clipping |
| const basegfx::B2DPolyPolygon aAndPolyPolygon( |
| basegfx::tools::solvePolygonOperationAnd( |
| aExtrudePoly, |
| pAct->maPreparedPolyPolygon)); |
| |
| bOverlap = (0 != aAndPolyPolygon.count()); |
| |
| if(bOverlap) |
| { |
| // second ciriteria: is another fillstyle or color used? |
| const SfxItemSet& rCompareSet = pAct->mpObj->GetMergedItemSet(); |
| |
| XFillStyle eCompareFillStyle = ITEMVALUE(rCompareSet, XATTR_FILLSTYLE, XFillStyleItem); |
| |
| if(eLocalFillStyle == eCompareFillStyle) |
| { |
| if(eLocalFillStyle == XFILL_SOLID) |
| { |
| Color aCompareColor = ((const XFillColorItem&)(rCompareSet.Get(XATTR_FILLCOLOR))).GetColorValue(); |
| |
| if(aCompareColor == aLocalColor) |
| { |
| bOverlap = sal_False; |
| } |
| } |
| else if(eLocalFillStyle == XFILL_NONE) |
| { |
| bOverlap = sal_False; |
| } |
| } |
| } |
| |
| pAct = pAct->mpNext; |
| } |
| |
| if(bOverlap) |
| { |
| // yes, start a new layer |
| pLayer->mpDown = new E3dDepthLayer; |
| pLayer = pLayer->mpDown; |
| nNumLayers++; |
| pLayer->mpNext = new E3dDepthNeighbour; |
| pLayer->mpNext->mpObj = pExtrudeObj; |
| pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly; |
| } |
| else |
| { |
| // no, add to current layer |
| E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour; |
| pNewNext->mpObj = pExtrudeObj; |
| pNewNext->maPreparedPolyPolygon = aExtrudePoly; |
| pNewNext->mpNext = pLayer->mpNext; |
| pLayer->mpNext = pNewNext; |
| } |
| } |
| else |
| { |
| // first layer ever |
| pBaseLayer = new E3dDepthLayer; |
| pLayer = pBaseLayer; |
| nNumLayers++; |
| pLayer->mpNext = new E3dDepthNeighbour; |
| pLayer->mpNext->mpObj = pExtrudeObj; |
| pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly; |
| } |
| } |
| } |
| |
| // number of layers is done |
| if(nNumLayers > 1) |
| { |
| // need to be arranged |
| double fMinDepth = fDepth * 0.8; |
| double fStep = (fDepth - fMinDepth) / (double)nNumLayers; |
| pLayer = pBaseLayer; |
| |
| while(pLayer) |
| { |
| // move along layer |
| E3dDepthNeighbour* pAct = pLayer->mpNext; |
| |
| while(pAct) |
| { |
| // adapt extrude value |
| pAct->mpObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5))); |
| |
| // next |
| pAct = pAct->mpNext; |
| } |
| |
| // next layer |
| pLayer = pLayer->mpDown; |
| fMinDepth += fStep; |
| } |
| } |
| |
| // cleanup |
| while(pBaseLayer) |
| { |
| pLayer = pBaseLayer->mpDown; |
| delete pBaseLayer; |
| pBaseLayer = pLayer; |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Drag beginnen, vorher ggf. Drag-Methode fuer 3D-Objekte erzeugen |
| |* |
| \************************************************************************/ |
| |
| sal_Bool E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut, |
| SdrHdl* pHdl, short nMinMov, |
| SdrDragMethod* pForcedMeth) |
| { |
| if(Is3DRotationCreationActive() && GetMarkedObjectCount()) |
| { |
| // bestimme alle selektierten Polygone und gebe die gespiegelte Hilfsfigur aus |
| mpMirrorOverlay->SetMirrorAxis(aRef1, aRef2); |
| } |
| else |
| { |
| sal_Bool bOwnActionNecessary; |
| if (pHdl == NULL) |
| { |
| bOwnActionNecessary = sal_True; |
| } |
| else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl()) |
| { |
| bOwnActionNecessary = sal_True; |
| } |
| else |
| { |
| bOwnActionNecessary = sal_False; |
| } |
| |
| if(bOwnActionNecessary && GetMarkedObjectCount() >= 1) |
| { |
| E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ; |
| sal_Bool bThereAreRootScenes = sal_False; |
| sal_Bool bThereAre3DObjects = sal_False; |
| long nCnt = GetMarkedObjectCount(); |
| for(long nObjs = 0;nObjs < nCnt;nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| if(pObj) |
| { |
| if(pObj->ISA(E3dScene) && ((E3dScene*)pObj)->GetScene() == pObj) |
| bThereAreRootScenes = sal_True; |
| if(pObj->ISA(E3dObject)) |
| bThereAre3DObjects = sal_True; |
| } |
| } |
| if( bThereAre3DObjects ) |
| { |
| eDragHdl = ( pHdl == NULL ? HDL_MOVE : pHdl->GetKind() ); |
| switch ( eDragMode ) |
| { |
| case SDRDRAG_ROTATE: |
| case SDRDRAG_SHEAR: |
| { |
| switch ( eDragHdl ) |
| { |
| case HDL_LEFT: |
| case HDL_RIGHT: |
| { |
| eConstraint = E3DDRAG_CONSTR_X; |
| } |
| break; |
| |
| case HDL_UPPER: |
| case HDL_LOWER: |
| { |
| eConstraint = E3DDRAG_CONSTR_Y; |
| } |
| break; |
| |
| case HDL_UPLFT: |
| case HDL_UPRGT: |
| case HDL_LWLFT: |
| case HDL_LWRGT: |
| { |
| eConstraint = E3DDRAG_CONSTR_Z; |
| } |
| break; |
| default: break; |
| } |
| |
| // die nicht erlaubten Rotationen ausmaskieren |
| eConstraint = E3dDragConstraint(eConstraint& eDragConstraint); |
| pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint, IsSolidDragging()); |
| } |
| break; |
| |
| case SDRDRAG_MOVE: |
| { |
| if(!bThereAreRootScenes) |
| { |
| pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint, IsSolidDragging()); |
| } |
| } |
| break; |
| |
| // spaeter mal |
| case SDRDRAG_MIRROR: |
| case SDRDRAG_CROOK: |
| case SDRDRAG_DISTORT: |
| case SDRDRAG_TRANSPARENCE: |
| case SDRDRAG_GRADIENT: |
| default: |
| { |
| } |
| break; |
| } |
| } |
| } |
| } |
| return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth); |
| } |
| |
| /************************************************************************* |
| |* |
| |* Pruefen, obj 3D-Szene markiert ist |
| |* |
| \************************************************************************/ |
| |
| sal_Bool E3dView::HasMarkedScene() |
| { |
| return (GetMarkedScene() != NULL); |
| } |
| |
| /************************************************************************* |
| |* |
| |* Pruefen, obj 3D-Szene markiert ist |
| |* |
| \************************************************************************/ |
| |
| E3dScene* E3dView::GetMarkedScene() |
| { |
| sal_uIntPtr nCnt = GetMarkedObjectCount(); |
| |
| for ( sal_uIntPtr i = 0; i < nCnt; i++ ) |
| if ( GetMarkedObjectByIndex(i)->ISA(E3dScene) ) |
| return (E3dScene*) GetMarkedObjectByIndex(i); |
| |
| return NULL; |
| } |
| |
| /************************************************************************* |
| |* |
| |* aktuelles 3D-Zeichenobjekt setzen, dafuer Szene erzeugen |
| |* |
| \************************************************************************/ |
| |
| E3dScene* E3dView::SetCurrent3DObj(E3dObject* p3DObj) |
| { |
| DBG_ASSERT(p3DObj != NULL, "Nana, wer steckt denn hier 'nen NULL-Zeiger rein?"); |
| E3dScene* pScene = NULL; |
| |
| // get transformed BoundVolume of the object |
| basegfx::B3DRange aVolume(p3DObj->GetBoundVolume()); |
| aVolume.transform(p3DObj->GetTransform()); |
| double fW(aVolume.getWidth()); |
| double fH(aVolume.getHeight()); |
| |
| Rectangle aRect(0,0, (long) fW, (long) fH); |
| |
| pScene = new E3dPolyScene(Get3DDefaultAttributes()); |
| |
| InitScene(pScene, fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0)); |
| |
| pScene->Insert3DObj(p3DObj); |
| pScene->NbcSetSnapRect(aRect); |
| |
| return pScene; |
| } |
| |
| /************************************************************************* |
| |* |
| |* neu erzeugte Szene initialisieren |
| |* |
| \************************************************************************/ |
| |
| void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ) |
| { |
| Camera3D aCam(pScene->GetCamera()); |
| |
| aCam.SetAutoAdjustProjection(sal_False); |
| aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH); |
| basegfx::B3DPoint aLookAt; |
| |
| double fDefaultCamPosZ = GetDefaultCamPosZ(); |
| basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ); |
| |
| aCam.SetPosAndLookAt(aCamPos, aLookAt); |
| aCam.SetFocalLength(GetDefaultCamFocal()); |
| aCam.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, GetDefaultCamFocal()); |
| pScene->SetCamera(aCam); |
| } |
| |
| /************************************************************************* |
| |* |
| |* startsequenz fuer die erstellung eines 3D-Rotationskoerpers |
| |* |
| \************************************************************************/ |
| |
| void E3dView::Start3DCreation() |
| { |
| if (GetMarkedObjectCount()) |
| { |
| // irgendwelche Markierungen ermitteln und ausschalten |
| //HMHBOOL bVis = IsMarkHdlShown(); |
| |
| //HMHif (bVis) HideMarkHdl(); |
| |
| // bestimme die koordinaten fuer JOEs Mirrorachse |
| // entgegen der normalen Achse wird diese an die linke Seite des Objektes |
| // positioniert |
| long nOutMin = 0; |
| long nOutMax = 0; |
| long nMinLen = 0; |
| long nObjDst = 0; |
| long nOutHgt = 0; |
| OutputDevice* pOut = GetFirstOutputDevice(); //GetWin(0); |
| |
| // erstmal Darstellungsgrenzen bestimmen |
| if (pOut != NULL) |
| { |
| nMinLen = pOut->PixelToLogic(Size(0,50)).Height(); |
| nObjDst = pOut->PixelToLogic(Size(0,20)).Height(); |
| |
| long nDst = pOut->PixelToLogic(Size(0,10)).Height(); |
| |
| nOutMin = -pOut->GetMapMode().GetOrigin().Y(); |
| nOutMax = pOut->GetOutputSize().Height() - 1 + nOutMin; |
| nOutMin += nDst; |
| nOutMax -= nDst; |
| |
| if (nOutMax - nOutMin < nDst) |
| { |
| nOutMin += nOutMax + 1; |
| nOutMin /= 2; |
| nOutMin -= (nDst + 1) / 2; |
| nOutMax = nOutMin + nDst; |
| } |
| |
| nOutHgt = nOutMax - nOutMin; |
| |
| long nTemp = nOutHgt / 4; |
| if (nTemp > nMinLen) nMinLen = nTemp; |
| } |
| |
| // und dann die Markierungen oben und unten an das Objekt heften |
| basegfx::B2DRange aR; |
| for(sal_uInt32 nMark(0L); nMark < GetMarkedObjectCount(); nMark++) |
| { |
| SdrObject* pMark = GetMarkedObjectByIndex(nMark); |
| basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly()); |
| aR.expand(basegfx::tools::getRange(aXPP)); |
| } |
| |
| basegfx::B2DPoint aCenter(aR.getCenter()); |
| long nMarkHgt = basegfx::fround(aR.getHeight()) - 1; |
| long nHgt = nMarkHgt + nObjDst * 2; |
| |
| if (nHgt < nMinLen) nHgt = nMinLen; |
| |
| long nY1 = basegfx::fround(aCenter.getY()) - (nHgt + 1) / 2; |
| long nY2 = nY1 + nHgt; |
| |
| if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt; |
| if (pOut) |
| { |
| if (nY1 < nOutMin) |
| { |
| nY1 = nOutMin; |
| if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen; |
| } |
| if (nY2 > nOutMax) |
| { |
| nY2 = nOutMax; |
| if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen; |
| } |
| } |
| |
| aRef1.X() = basegfx::fround(aR.getMinX()); // Initial Achse um 2/100mm nach links |
| aRef1.Y() = nY1; |
| aRef2.X() = aRef1.X(); |
| aRef2.Y() = nY2; |
| |
| // Markierungen einschalten |
| SetMarkHandles(); |
| |
| //HMHif (bVis) ShowMarkHdl(); |
| if (AreObjectsMarked()) MarkListHasChanged(); |
| |
| // SpiegelPolygone SOFORT zeigen |
| const SdrHdlList &aHdlList = GetHdlList(); |
| mpMirrorOverlay = new Impl3DMirrorConstructOverlay(*this); |
| mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(HDL_REF1)->GetPos(), aHdlList.GetHdl(HDL_REF2)->GetPos()); |
| //CreateMirrorPolygons (); |
| //ShowMirrorPolygons (aHdlList.GetHdl (HDL_REF1)->GetPos (), |
| // aHdlList.GetHdl (HDL_REF2)->GetPos ()); |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* was passiert bei einer Mausbewegung, wenn das Objekt erstellt wird ? |
| |* |
| \************************************************************************/ |
| |
| void E3dView::MovAction(const Point& rPnt) |
| { |
| if(Is3DRotationCreationActive()) |
| { |
| SdrHdl* pHdl = GetDragHdl(); |
| |
| if (pHdl) |
| { |
| SdrHdlKind eHdlKind = pHdl->GetKind(); |
| |
| // reagiere nur bei einer spiegelachse |
| if ((eHdlKind == HDL_REF1) || |
| (eHdlKind == HDL_REF2) || |
| (eHdlKind == HDL_MIRX)) |
| { |
| const SdrHdlList &aHdlList = GetHdlList (); |
| |
| // loesche das gespiegelte Polygon, spiegele das Original und zeichne es neu |
| //ShowMirrored (); |
| SdrView::MovAction (rPnt); |
| mpMirrorOverlay->SetMirrorAxis( |
| aHdlList.GetHdl (HDL_REF1)->GetPos(), |
| aHdlList.GetHdl (HDL_REF2)->GetPos()); |
| } |
| } |
| else |
| { |
| SdrView::MovAction (rPnt); |
| } |
| } |
| else |
| { |
| SdrView::MovAction (rPnt); |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Schluss. Objekt und evtl. Unterobjekte ueber ImpCreate3DLathe erstellen |
| |* [FG] Mit dem Parameterwert sal_True (SDefault: sal_False) wird einfach ein |
| |* Rotationskoerper erzeugt, ohne den Benutzer die Lage der |
| |* Achse fetlegen zu lassen. Es reicht dieser Aufruf, falls |
| |* ein Objekt selektiert ist. (keine Initialisierung noetig) |
| |* |
| \************************************************************************/ |
| |
| void E3dView::End3DCreation(sal_Bool bUseDefaultValuesForMirrorAxes) |
| { |
| ResetCreationActive(); |
| |
| if(AreObjectsMarked()) |
| { |
| if(bUseDefaultValuesForMirrorAxes) |
| { |
| Rectangle aRect = GetAllMarkedRect(); |
| if(aRect.GetWidth() <= 1) |
| aRect.SetSize(Size(500, aRect.GetHeight())); |
| if(aRect.GetHeight() <= 1) |
| aRect.SetSize(Size(aRect.GetWidth(), 500)); |
| |
| basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top()); |
| basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom()); |
| |
| ConvertMarkedObjTo3D(sal_False, aPnt1, aPnt2); |
| } |
| else |
| { |
| // Hilfsfigur ausschalten |
| // bestimme aus den Handlepositionen und den Versatz der Punkte |
| const SdrHdlList &aHdlList = GetHdlList(); |
| Point aMirrorRef1 = aHdlList.GetHdl(HDL_REF1)->GetPos(); |
| Point aMirrorRef2 = aHdlList.GetHdl(HDL_REF2)->GetPos(); |
| |
| basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y()); |
| basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y()); |
| |
| ConvertMarkedObjTo3D(sal_False, aPnt1, aPnt2); |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Destruktor |
| |* |
| \************************************************************************/ |
| |
| E3dView::~E3dView () |
| { |
| } |
| |
| /************************************************************************* |
| |* |
| |* beende das erzeugen und loesche die polygone |
| |* |
| \************************************************************************/ |
| |
| void E3dView::ResetCreationActive () |
| { |
| if(mpMirrorOverlay) |
| { |
| delete mpMirrorOverlay; |
| mpMirrorOverlay = 0L; |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Klasse initialisieren |
| |* |
| \************************************************************************/ |
| |
| void E3dView::InitView () |
| { |
| eDragConstraint = E3DDRAG_CONSTR_XYZ; |
| fDefaultScaleX = |
| fDefaultScaleY = |
| fDefaultScaleZ = 1.0; |
| fDefaultRotateX = |
| fDefaultRotateY = |
| fDefaultRotateZ = 0.0; |
| fDefaultExtrusionDeepth = 1000; // old: 2000; |
| fDefaultLightIntensity = 0.8; // old: 0.6; |
| fDefaultAmbientIntensity = 0.4; |
| nHDefaultSegments = 12; |
| nVDefaultSegments = 12; |
| aDefaultLightColor = RGB_Color(COL_WHITE); |
| aDefaultAmbientColor = RGB_Color(COL_BLACK); |
| bDoubleSided = sal_False; |
| mpMirrorOverlay = 0L; |
| } |
| |
| /************************************************************************* |
| |* |
| |* Koennen die selektierten Objekte aufgebrochen werden? |
| |* |
| \************************************************************************/ |
| |
| sal_Bool E3dView::IsBreak3DObjPossible() const |
| { |
| sal_uIntPtr nCount = GetMarkedObjectCount(); |
| |
| if (nCount > 0) |
| { |
| sal_uIntPtr i = 0; |
| |
| while (i < nCount) |
| { |
| SdrObject* pObj = GetMarkedObjectByIndex(i); |
| |
| if (pObj && pObj->ISA(E3dObject)) |
| { |
| if(!(((E3dObject*)pObj)->IsBreakObjPossible())) |
| return sal_False; |
| } |
| else |
| { |
| return sal_False; |
| } |
| |
| i++; |
| } |
| } |
| else |
| { |
| return sal_False; |
| } |
| |
| return sal_True; |
| } |
| |
| /************************************************************************* |
| |* |
| |* Selektierte Lathe-Objekte aufbrechen |
| |* |
| \************************************************************************/ |
| |
| void E3dView::Break3DObj() |
| { |
| if(IsBreak3DObjPossible()) |
| { |
| // ALLE selektierten Objekte werden gewandelt |
| sal_uInt32 nCount = GetMarkedObjectCount(); |
| |
| BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE))); |
| for(sal_uInt32 a=0;a<nCount;a++) |
| { |
| E3dObject* pObj = (E3dObject*)GetMarkedObjectByIndex(a); |
| BreakSingle3DObj(pObj); |
| } |
| DeleteMarked(); |
| EndUndo(); |
| } |
| } |
| |
| void E3dView::BreakSingle3DObj(E3dObject* pObj) |
| { |
| if(pObj->ISA(E3dScene)) |
| { |
| SdrObjList* pSubList = pObj->GetSubList(); |
| SdrObjListIter aIter(*pSubList, IM_FLAT); |
| |
| while(aIter.IsMore()) |
| { |
| E3dObject* pSubObj = (E3dObject*)aIter.Next(); |
| BreakSingle3DObj(pSubObj); |
| } |
| } |
| else |
| { |
| SdrAttrObj* pNewObj = pObj->GetBreakObj(); |
| if(pNewObj) |
| { |
| InsertObjectAtView(pNewObj, *GetSdrPageView(), SDRINSERT_DONTMARK); |
| pNewObj->SetChanged(); |
| pNewObj->BroadcastObjectChange(); |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Szenen mischen |
| |* |
| \************************************************************************/ |
| |
| void E3dView::MergeScenes () |
| { |
| sal_uIntPtr nCount = GetMarkedObjectCount(); |
| |
| if (nCount > 0) |
| { |
| sal_uIntPtr nObj = 0; |
| SdrObject *pObj = GetMarkedObjectByIndex(nObj); |
| E3dScene *pScene = new E3dPolyScene(Get3DDefaultAttributes()); |
| basegfx::B3DRange aBoundVol; |
| Rectangle aAllBoundRect (GetMarkedObjBoundRect ()); |
| Point aCenter (aAllBoundRect.Center()); |
| |
| while (pObj) |
| { |
| if (pObj->ISA(E3dScene)) |
| { |
| /********************************************************** |
| * Es ist eine 3D-Scene oder 3D-PolyScene |
| **********************************************************/ |
| SdrObjList* pSubList = ((E3dObject*) pObj)->GetSubList(); |
| |
| SdrObjListIter aIter(*pSubList, IM_FLAT); |
| |
| while (aIter.IsMore()) |
| { |
| /****************************************************** |
| * LatheObjekte suchen |
| ******************************************************/ |
| SdrObject* pSubObj = aIter.Next(); |
| |
| E3dObject *pNewObj = 0; |
| |
| switch (pSubObj->GetObjIdentifier()) |
| { |
| case E3D_CUBEOBJ_ID : |
| pNewObj = new E3dCubeObj; |
| *(E3dCubeObj*)pNewObj = *(E3dCubeObj*)pSubObj; |
| break; |
| |
| case E3D_SPHEREOBJ_ID: |
| pNewObj = new E3dSphereObj; |
| *(E3dSphereObj*)pNewObj = *(E3dSphereObj*)pSubObj; |
| break; |
| |
| case E3D_EXTRUDEOBJ_ID: |
| pNewObj = new E3dExtrudeObj; |
| *(E3dExtrudeObj*)pNewObj = *(E3dExtrudeObj*)pSubObj; |
| break; |
| |
| case E3D_LATHEOBJ_ID: |
| pNewObj = new E3dLatheObj; |
| *(E3dLatheObj*)pNewObj = *(E3dLatheObj*)pSubObj; |
| break; |
| |
| case E3D_COMPOUNDOBJ_ID: |
| pNewObj = new E3dCompoundObject; |
| *(E3dCompoundObject*)pNewObj = *(E3dCompoundObject*)pSubObj; |
| break; |
| } |
| |
| Rectangle aBoundRect = pSubObj->GetCurrentBoundRect(); |
| |
| basegfx::B3DHomMatrix aMatrix; |
| aMatrix.translate(aBoundRect.Left() - aCenter.getX(), aCenter.getY(), 0.0); |
| pNewObj->SetTransform(aMatrix * pNewObj->GetTransform()); // #112587# |
| |
| if (pNewObj) aBoundVol.expand(pNewObj->GetBoundVolume()); |
| pScene->Insert3DObj (pNewObj); |
| } |
| } |
| |
| nObj++; |
| |
| if (nObj < nCount) |
| { |
| pObj = GetMarkedObjectByIndex(nObj); |
| } |
| else |
| { |
| pObj = NULL; |
| } |
| } |
| |
| double fW = aAllBoundRect.GetWidth(); |
| double fH = aAllBoundRect.GetHeight(); |
| Rectangle aRect(0,0, (long) fW, (long) fH); |
| |
| InitScene(pScene, fW, fH, aBoundVol.getMaxZ() + + ((fW + fH) / 4.0)); |
| pScene->NbcSetSnapRect(aRect); |
| |
| Camera3D &aCamera = (Camera3D&) pScene->GetCamera (); |
| basegfx::B3DPoint aMinVec(aBoundVol.getMinimum()); |
| basegfx::B3DPoint aMaxVec(aBoundVol.getMaximum()); |
| double fDeepth(fabs(aMaxVec.getZ() - aMinVec.getZ())); |
| |
| aCamera.SetPRP(basegfx::B3DPoint(0.0, 0.0, 1000.0)); |
| double fDefaultCamPosZ(GetDefaultCamPosZ()); |
| aCamera.SetPosition(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ + fDeepth / 2.0)); |
| aCamera.SetFocalLength(GetDefaultCamFocal()); |
| pScene->SetCamera (aCamera); |
| |
| // SnapRects der Objekte ungueltig |
| pScene->SetRectsDirty(); |
| |
| InsertObjectAtView(pScene, *(GetSdrPageViewOfMarkedByIndex(0))); |
| |
| // SnapRects der Objekte ungueltig |
| pScene->SetRectsDirty(); |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* Possibilities, hauptsaechlich gruppieren/ungruppieren |
| |* |
| \************************************************************************/ |
| void E3dView::CheckPossibilities() |
| { |
| // call parent |
| SdrView::CheckPossibilities(); |
| |
| // Weitere Flags bewerten |
| if(bGroupPossible || bUnGroupPossible || bGrpEnterPossible) |
| { |
| sal_Int32 nMarkCnt = GetMarkedObjectCount(); |
| sal_Bool bCoumpound = sal_False; |
| sal_Bool b3DObject = sal_False; |
| for(sal_Int32 nObjs = 0L; (nObjs < nMarkCnt) && !bCoumpound; nObjs++) |
| { |
| SdrObject *pObj = GetMarkedObjectByIndex(nObjs); |
| if(pObj && pObj->ISA(E3dCompoundObject)) |
| bCoumpound = sal_True; |
| if(pObj && pObj->ISA(E3dObject)) |
| b3DObject = sal_True; |
| } |
| |
| // Bisher: Es sind ZWEI oder mehr beliebiger Objekte selektiert. |
| // Nachsehen, ob CompoundObjects beteiligt sind. Falls ja, |
| // das Gruppieren verbieten. |
| if(bGroupPossible && bCoumpound) |
| bGroupPossible = sal_False; |
| |
| if(bUnGroupPossible && b3DObject) |
| bUnGroupPossible = sal_False; |
| |
| if(bGrpEnterPossible && bCoumpound) |
| bGrpEnterPossible = sal_False; |
| } |
| } |
| |
| // eof |