/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: view3d.cxx,v $ * * $Revision: 1.28 $ * * last change: $Author: kz $ $Date: 2007-05-10 14:47:33 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svx.hxx" #ifndef _SV_WRKWIN_HXX #include <vcl/wrkwin.hxx> #endif #ifndef INCLUDED_SVTOOLS_OPTIONS3D_HXX #include <svtools/options3d.hxx> #endif #ifndef _SVDOGRP_HXX #include "svdogrp.hxx" #endif #ifndef _SVDOPATH_HXX #include "svdopath.hxx" #endif #ifndef _SHL_HXX #include <tools/shl.hxx> #endif #ifndef _SVDITER_HXX #include "svditer.hxx" #endif #ifndef _SVDPOOL_HXX #include "svdpool.hxx" #endif #ifndef _SVDORECT_HXX #include "svdorect.hxx" #endif #ifndef _SVDMODEL_HXX #include "svdmodel.hxx" #endif #ifndef _SVDPAGV_HXX #include "svdpagv.hxx" #endif #ifndef _XOUTX_HXX #include "xoutx.hxx" #endif #ifndef _SVX_SVXIDS_HRC #include <svxids.hrc> #endif #ifndef _SVX_COLRITEM_HXX #include "colritem.hxx" #endif #ifndef _XTABLE_HXX #include "xtable.hxx" #endif #ifndef _SVDVIEW_HXX #include "svdview.hxx" #endif #ifndef _SVX_DIALOGS_HRC #include "dialogs.hrc" #endif #ifndef _SVX_DIALMGR_HXX #include "dialmgr.hxx" #endif #ifndef _E3D_GLOBL3D_HXX #include "globl3d.hxx" #endif #ifndef _E3D_OBJ3D_HXX #include "obj3d.hxx" #endif #ifndef _E3D_LATHE3D_HXX #include "lathe3d.hxx" #endif #ifndef _E3D_SPHERE3D_HXX #include "sphere3d.hxx" #endif #ifndef _E3D_EXTRUD3D_HXX #include "extrud3d.hxx" #endif #ifndef _E3D_CUBE3D_HXX #include "cube3d.hxx" #endif #ifndef _E3D_POLYSC3D_HXX #include "polysc3d.hxx" #endif #ifndef _E3D_DRAGMT3D_HXX #include "dragmt3d.hxx" #endif #ifndef _E3D_VIEW3D_HXX #include "view3d.hxx" #endif #ifndef _SVDUNDO_HXX #include "svdundo.hxx" #endif #ifndef _SVX_XFLCLIT_HXX #include "xflclit.hxx" #endif #ifndef _SVX_XLNCLIT_HXX #include "xlnclit.hxx" #endif #ifndef _SVDOGRAF_HXX #include <svdograf.hxx> #endif #ifndef _SVX_XBTMPIT_HXX #include <xbtmpit.hxx> #endif #ifndef _SVX_XFLBMTIT_HXX #include <xflbmtit.hxx> #endif #ifndef _BGFX_RANGE_B2DRANGE_HXX #include <basegfx/range/b2drange.hxx> #endif #ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX #include <basegfx/polygon/b2dpolygontools.hxx> #endif #ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX #include <basegfx/polygon/b2dpolypolygontools.hxx> #endif #include "xlnwtit.hxx" #ifndef _SDR_OVERLAY_OVERLAYPOLYPOLYGON_HXX #include <svx/sdr/overlay/overlaypolypolygon.hxx> #endif #ifndef _SDR_OVERLAY_OVERLAYMANAGER_HXX #include <svx/sdr/overlay/overlaymanager.hxx> #endif #ifndef _SDRPAINTWINDOW_HXX #include <sdrpaintwindow.hxx> #endif #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 unmirrored polygons and their count sal_uInt32 mnCount; basegfx::B2DPolyPolygon* mpPolygons; public: Impl3DMirrorConstructOverlay(const E3dView& rView); ~Impl3DMirrorConstructOverlay(); void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB); }; Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView) : mrView(rView) { const SdrMarkList& rMarkList = mrView.GetMarkedObjectList(); mnCount = rMarkList.GetMarkCount(); mpPolygons = new basegfx::B2DPolyPolygon[mnCount]; for(sal_uInt32 a(0L); a < mnCount; a++) { SdrMark *pMark = rMarkList.GetMark(a); SdrObject *pObj = pMark->GetMarkedSdrObj(); mpPolygons[mnCount - (a + 1L)] = pObj->TakeXorPoly(sal_False); } } 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. delete[] mpPolygons; } void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB) { // get rid of old overlay objects maObjects.clear(); // create new ones for(sal_uInt32 a(0L); a < mrView.PaintWindowCount(); a++) { SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a); ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); if(pTargetOverlay) { for(sal_uInt32 b(0L); b < mnCount; b++) { basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]); // translate and rotate polygon 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; aMatrixTransform.translate(-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()); // apply to polygon aPolyPolygon.transform(aMatrixTransform); ::sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(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 Point& rOfs) const { // Existieren 3D-Objekte, deren Szenen nicht selektiert sind? BOOL bSpecialHandling = 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 = TRUE; } // Alle SelectionFlags zuruecksetzen if(pObj && pObj->ISA(E3dObject)) { pScene = ((E3dObject*)pObj)->GetScene(); if(pScene) pScene->SetSelected(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(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(TRUE); pScene = p3DObj->GetScene(); pM = GetSdrMarkByIndex(nObjs); } } if(pScene) { // code from parent SortMarkedObjects(); pXOut->SetOutDev(&rOut); SdrPaintInfoRec aInfoRec; aInfoRec.nPaintMode|=SDRPAINTMODE_ANILIKEPRN; Point aOfs(-rOfs.X(), -rOfs.Y()); // aOfs += pM->GetPageView()->GetOffset(); if(aOfs != pXOut->GetOffset()) pXOut->SetOffset(aOfs); pScene->SetDrawOnlySelected(TRUE); pScene->SingleObjectPainter(*pXOut,aInfoRec); // #110094#-17 pScene->SetDrawOnlySelected(FALSE); pXOut->SetOffset(Point(0,0)); } // 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(FALSE); } } } else { // call parent SdrExchangeView::DrawMarkedObj(rOut, rOfs); } } /************************************************************************* |* |* 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; 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 = TRUE; } // Alle SelectionFlags zuruecksetzen if(pObj && pObj->ISA(E3dObject)) { pScene = ((E3dObject*)pObj)->GetScene(); if(pScene) pScene->SetSelected(FALSE); } } SdrModel* pNewModel = 0L; 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(FALSE); } } // bei allen direkt selektierten Objekten auf selektiert setzen for(nObjs = 0;nObjs < nCnt;nObjs++) { SdrObject *pObj = GetMarkedObjectByIndex(nObjs); if(pObj && pObj->ISA(E3dObject)) { // Objekt markieren E3dObject* p3DObj = (E3dObject*)pObj; p3DObj->SetSelected(TRUE); } } // Neue MarkList generieren, die die betroffenen // Szenen als markierte Objekte enthaelt SdrMarkList aOldML(GetMarkedObjectList()); // alte Marklist merken SdrMarkList aNewML; // neue leere Marklist SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess(); rCurrentMarkList = aNewML; // ((E3dView*)this)->maMarkedObjectList = aNewML; for(nObjs = 0;nObjs < nCnt;nObjs++) { SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj(); if(pObj) { if(pObj->ISA(E3dCompoundObject)) { // zugehoerige Szene holen pScene = ((E3dCompoundObject*)pObj)->GetScene(); if(pScene) pObj = pScene; } // Keine Objekte doppelt markieren // (dies koennten nur Szenen sein) if(!IsObjMarked(pObj)) { if(GetSdrPageView()) { ((E3dView*)this)->MarkObj(pObj, GetSdrPageView(), FALSE, TRUE); } } } } // call parent pNewModel = SdrView::GetMarkedObjModel(); // Alle Szenen im kopierten Model in Ihren Ausdehnungen Korrigieren // und IsSelected zuruecksetzen if(pNewModel) { for(UINT16 nPg=0; nPg < pNewModel->GetPageCount(); nPg++) { const SdrPage* pSrcPg=pNewModel->GetPage(nPg); UINT32 nObAnz=pSrcPg->GetObjCount(); // Unterobjekte von Szenen einfuegen for(UINT32 nOb=0; nOb<nObAnz; nOb++) { const SdrObject* pSrcOb=pSrcPg->GetObj(nOb); if(pSrcOb->ISA(E3dScene)) { pScene = (E3dScene*)pSrcOb; pScene->CorrectSceneDimensions(); pScene->SetSelected(FALSE); } } } } // Alte Liste wieder setzen // ((E3dView*)this)->maMarkedObjectList= aOldML; rCurrentMarkList = aOldML; // 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(FALSE); } } } else { // call parent pNewModel = SdrView::GetMarkedObjModel(); } // model zurueckgeben return pNewModel; } /************************************************************************* |* |* Bei Paste muss - falls in eine Scene eingefuegt wird - die |* Objekte der Szene eingefuegt werden, die Szene selbst aber nicht |* \************************************************************************/ BOOL E3dView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, UINT32 nOptions) { BOOL bRetval = FALSE; // Liste holen Point aPos(rPos); SdrObjList* pDstList = pLst; ImpGetPasteObjList(aPos, pDstList); if(!pDstList) return FALSE; // Owner der Liste holen SdrObject* pOwner = pDstList->GetOwnerObj(); if(pOwner && pOwner->ISA(E3dScene)) { E3dScene* pDstScene = (E3dScene*)pOwner; BOOL bDstInserted(FALSE); 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; bDstInserted = ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist); } } } EndUndo(); // DestScene anpassen if(bDstInserted) { pDstScene->SetRectsDirty(); pDstScene->CorrectSceneDimensions(); bRetval = TRUE; } } 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(...) BOOL E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point aOffset) { BOOL bRetval(FALSE); if(pSrcScene && pDstScene) { B3dCamera& rCameraSetDst = pDstScene->GetCameraSet(); B3dCamera& rCameraSetSrc = pSrcScene->GetCameraSet(); for(sal_uInt32 i(0); i < pSrcScene->GetSubList()->GetObjCount(); i++) { SdrObject* pObj = pSrcScene->GetSubList()->GetObj(i); if(pObj && pObj->ISA(E3dCompoundObject)) { // Kopieren // E3dObject* pNew = (E3dObject*)pObj->Clone(pDstScene->GetPage(), pDstScene->GetModel()); // #116235# E3dObject* pNew = (E3dObject*)pObj->Clone(); if(pNew) { // #116235# pNew->SetModel(pDstScene->GetModel()); pNew->SetPage(pDstScene->GetPage()); // Neues Objekt in Szene einfuegen pNew->NbcSetLayer(pObj->GetLayer()); pNew->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True); pDstScene->Insert3DObj(pNew); bRetval = TRUE; // Transformation ObjectToEye Src basegfx::B3DHomMatrix aMatSrc; aMatSrc = ((E3dCompoundObject*)pObj)->GetFullTransform(); aMatSrc *= rCameraSetSrc.GetOrientation(); // Tanslation und scale von source basegfx::B3DRange aDevVolSrc(rCameraSetSrc.GetDeviceVolume()); // auf Augkoordinaten umstellen aDevVolSrc = basegfx::B3DRange( aDevVolSrc.getMinX(), aDevVolSrc.getMinY(), -aDevVolSrc.getMaxZ(), aDevVolSrc.getMaxX(), aDevVolSrc.getMaxY(), -aDevVolSrc.getMinZ()); basegfx::B3DPoint aProjScaleSrc( 2.0 / aDevVolSrc.getWidth(), 2.0 / aDevVolSrc.getHeight(), 2.0 / aDevVolSrc.getDepth()); basegfx::B3DPoint aProjTransSrc( -1.0 * ((aDevVolSrc.getMaxX() + aDevVolSrc.getMinX()) / aDevVolSrc.getWidth()), -1.0 * ((aDevVolSrc.getMaxY() + aDevVolSrc.getMinY()) / aDevVolSrc.getHeight()), -1.0 * ((aDevVolSrc.getMaxZ() + aDevVolSrc.getMinZ()) / aDevVolSrc.getDepth())); basegfx::B3DPoint aViewScaleSrc(rCameraSetSrc.GetScale()); aViewScaleSrc.setZ(1.0); // Tanslation und scale von dest basegfx::B3DRange aDevVolDst(rCameraSetDst.GetDeviceVolume()); // auf Augkoordinaten umstellen aDevVolDst = basegfx::B3DRange( aDevVolDst.getMinX(), aDevVolDst.getMinY(), -aDevVolDst.getMaxZ(), aDevVolDst.getMaxX(), aDevVolDst.getMaxY(), -aDevVolDst.getMinZ()); basegfx::B3DPoint aProjScaleDst( 2.0 / aDevVolDst.getWidth(), 2.0 / aDevVolDst.getHeight(), 2.0 / aDevVolDst.getDepth()); basegfx::B3DPoint aProjTransDst( -1.0 * ((aDevVolDst.getMaxX() + aDevVolDst.getMinX()) / aDevVolDst.getWidth()), -1.0 * ((aDevVolDst.getMaxY() + aDevVolDst.getMinY()) / aDevVolDst.getHeight()), -1.0 * ((aDevVolDst.getMaxZ() + aDevVolDst.getMinZ()) / aDevVolDst.getDepth())); basegfx::B3DPoint aViewScaleDst(rCameraSetDst.GetScale()); aViewScaleDst.setZ(1.0); // Groesse des Objektes in Augkoordinaten Src basegfx::B3DRange aObjVolSrc(((E3dCompoundObject*)pObj)->GetBoundVolume().GetTransformVolume(aMatSrc)); // Vorlaeufige Groesse in Augkoordinaten Dst basegfx::B3DHomMatrix aMatZwi = aMatSrc; aMatZwi.scale(aProjScaleSrc.getX(), aProjScaleSrc.getY(), aProjScaleSrc.getZ()); aMatZwi.translate(aProjTransSrc.getX(), aProjTransSrc.getY(), aProjTransSrc.getZ()); aMatZwi.scale(aViewScaleSrc.getX(), aViewScaleSrc.getY(), aViewScaleSrc.getZ()); basegfx::B3DHomMatrix aMatDst; aMatDst.scale(aProjScaleDst.getX(), aProjScaleDst.getY(), aProjScaleDst.getZ()); aMatDst.translate(aProjTransDst.getX(), aProjTransDst.getY(), aProjTransDst.getZ()); aMatDst.scale(aViewScaleDst.getX(), aViewScaleDst.getY(), aViewScaleDst.getZ()); aMatDst.invert(); aMatZwi *= aMatDst; basegfx::B3DRange aObjVolDst(((E3dCompoundObject*)pObj)->GetBoundVolume().GetTransformVolume(aMatZwi)); // Beide verhaeltnistiefen berechnen und mitteln double fDepthOne = (aObjVolSrc.getDepth() * aObjVolDst.getWidth()) / aObjVolSrc.getWidth(); double fDepthTwo = (aObjVolSrc.getDepth() * aObjVolDst.getHeight()) / aObjVolSrc.getHeight(); double fWantedDepth = (fDepthOne + fDepthTwo) / 2.0; // Faktor zum Tiefe anpassen bilden double fFactor = fWantedDepth / aObjVolDst.getDepth(); basegfx::B3DPoint aDepthScale(1.0, 1.0, fFactor); // Endgueltige Transformation bilden aMatSrc.scale(aProjScaleSrc.getX(), aProjScaleSrc.getY(), aProjScaleSrc.getZ()); aMatSrc.translate(aProjTransSrc.getX(), aProjTransSrc.getY(), aProjTransSrc.getZ()); aMatSrc.scale(aViewScaleSrc.getX(), aViewScaleSrc.getY(), aViewScaleSrc.getZ()); aMatSrc.scale(aDepthScale.getX(), aDepthScale.getY(), aDepthScale.getZ()); aMatDst = pDstScene->GetFullTransform(); aMatDst *= rCameraSetDst.GetOrientation(); aMatDst.scale(aProjScaleDst.getX(), aProjScaleDst.getY(), aProjScaleDst.getZ()); aMatDst.translate(aProjTransDst.getX(), aProjTransDst.getY(), aProjTransDst.getZ()); aMatDst.scale(aViewScaleDst.getX(), aViewScaleDst.getY(), aViewScaleDst.getZ()); aMatDst.invert(); aMatSrc *= aMatDst; // Neue Objekttransformation setzen pNew->SetTransform(aMatSrc); // force new camera and SnapRect on scene, geometry may have really // changed pDstScene->CorrectSceneDimensions(); // #83403# translate in view coor { // screen position of center of old object basegfx::B3DHomMatrix aSrcFullTrans = ((E3dCompoundObject*)pObj)->GetFullTransform(); rCameraSetSrc.SetObjectTrans(aSrcFullTrans); basegfx::B3DPoint aSrcCenter(((E3dCompoundObject*)pObj)->GetCenter()); aSrcCenter = rCameraSetSrc.ObjectToViewCoor(aSrcCenter); if(aOffset.X() != 0 || aOffset.Y() != 0) { aSrcCenter += basegfx::B3DPoint((double)aOffset.X(), (double)aOffset.Y(), 0.0); } // to have a valid Z-Coor in dst system, calc current center of dst object basegfx::B3DHomMatrix aDstFullTrans = pNew->GetFullTransform(); rCameraSetDst.SetObjectTrans(aDstFullTrans); basegfx::B3DPoint aDstCenter(pNew->GetCenter()); aDstCenter = rCameraSetDst.ObjectToEyeCoor(aDstCenter); // convert aSrcCenter to a eye position of dst scene basegfx::B3DPoint aNewDstCenter(rCameraSetDst.ViewToEyeCoor(aSrcCenter)); aNewDstCenter.setZ(aDstCenter.getZ()); // transform back to object coor aNewDstCenter = rCameraSetDst.EyeToObjectCoor(aNewDstCenter); // get transform vector basegfx::B3DPoint aTransformCorrection(aNewDstCenter - pNew->GetCenter()); basegfx::B3DHomMatrix aTransCorrMat; aTransCorrMat.translate(aTransformCorrection.getX(), aTransformCorrection.getY(), aTransformCorrection.getZ()); // treanslate new object, add translate in front of obj transform pNew->SetTransform(pNew->GetTransform() * aTransCorrMat); // #112587# // force new camera and SnapRect on scene, geometry may have really // changed pDstScene->CorrectSceneDimensions(); //Rectangle aOldPosSize = pObj->GetSnapRect(); //if(aOffset.X() != 0 || aOffset.Y() != 0) // aOldPosSize.Move(aOffset.X(), aOffset.Y()); //Rectangle aNewPosSize = pNew->GetSnapRect(); } // Undo anlegen AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNew)); } } } } return bRetval; } /************************************************************************* |* |* 3D-Konvertierung moeglich? |* \************************************************************************/ BOOL E3dView::IsConvertTo3DObjPossible() const { BOOL bAny3D(FALSE); BOOL bGroupSelected(FALSE); BOOL bRetval(TRUE); for(sal_uInt32 a=0;!bAny3D && a<GetMarkedObjectCount();a++) { SdrObject *pObj = GetMarkedObjectByIndex(a); if(pObj) { ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected); } } bRetval = !bAny3D && ( IsConvertToPolyObjPossible(FALSE) || IsConvertToPathObjPossible(FALSE) || IsImportMtfPossible()); return bRetval; } void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, BOOL& rAny3D, BOOL& rGroupSelected) const { if(pObj) { if(pObj->ISA(E3dObject)) { rAny3D = TRUE; } else { if(pObj->IsGroupObject()) { SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS); while(aIter.IsMore()) { SdrObject* pNewObj = aIter.Next(); ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected); } rGroupSelected = TRUE; } } } } /************************************************************************* |* |* 3D-Konvertierung zu Extrude ausfuehren |* \************************************************************************/ #ifndef _EEITEM_HXX #include "eeitem.hxx" #endif 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 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()) AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false)); pObj->SetMergedItem(XLineStyleItem(XLINE_NONE)); pObj->SetMergedItem(XLineWidthItem(0L)); } } } void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, 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(TRUE); else aDefault.SetDefaultLatheCharacterMode(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(FALSE); aDefault.SetDefaultExtrudeCloseBack(FALSE); aSet.Put(Svx3DDoubleSidedItem(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, 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(FALSE, 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, 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) delete pNewObj2; } // delete zwi object if(pNewObj1 != pObj && pNewObj1) delete pNewObj1; } } } /************************************************************************* |* |* 3D-Konvertierung zu Extrude steuern |* \************************************************************************/ void E3dView::ConvertMarkedObjTo3D(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(fabs(fRot3D) < SMALL_DVALUE) fRot3D = 0.0; if(fRot3D != 0.0) { aLatheMat.translate(-aPnt2.getX(), -aPnt2.getY()); aLatheMat.rotate(-fRot3D); aLatheMat.translate(aPnt2.getX(), aPnt2.getY()); } } 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(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(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->GetCenter()); basegfx::B3DHomMatrix aMatrix; aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ()); pScene->SetTransform(aMatrix * pScene->GetTransform()); // #112587# // Szene initialisieren pScene->NbcSetSnapRect(aRect); Volume3D aBoundVol = pScene->GetBoundVolume(); InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth()); // Transformationen initialisieren, damit bei RecalcSnapRect() // richtig gerechnet wird pScene->InitTransformationSet(); // Szene anstelle des ersten selektierten Objektes einfuegen // und alle alten Objekte weghauen SdrObject* pRepObj = GetMarkedObjectByIndex(0); SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0); MarkObj(pRepObj, pPV, TRUE); ReplaceObjectAtView(pRepObj, *pPV, pScene, FALSE); DeleteMarked(); MarkObj(pScene, pPV); // Rotationskoerper um Rotationsachse drehen if(!bExtrude && fRot3D != 0.0) { pScene->RotateZ(fRot3D); } // Default-Rotation setzen double XRotateDefault = 20; pScene->RotateX(DEG2RAD(XRotateDefault)); // SnapRects der Objekte ungueltig pScene->CorrectSceneDimensions(); 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* pNext; E3dExtrudeObj* pObj; E3dDepthNeighbour() { pNext = NULL; pObj = NULL; } }; struct E3dDepthLayer { E3dDepthLayer* pDown; E3dDepthNeighbour* pNext; E3dDepthLayer() { pDown = NULL; pNext = NULL; } ~E3dDepthLayer() { while(pNext) { E3dDepthNeighbour* pSucc = pNext->pNext; delete pNext; pNext = pSucc; }} }; bool ImpDoesOverlap(const basegfx::B2DPolygon& rPolygonA, const basegfx::B2DPolygon& rPolygonB) { bool bRetval(false); const basegfx::B2DRange aRangeA(basegfx::tools::getRange(rPolygonA)); const basegfx::B2DRange aRangeB(basegfx::tools::getRange(rPolygonB)); if(aRangeA.overlaps(aRangeB)) { // A in B ? if(basegfx::tools::isInside(rPolygonA, rPolygonB)) return true; // B in A ? if(basegfx::tools::isInside(rPolygonB, rPolygonA)) return true; // A and B the same ? if(basegfx::tools::isInside(rPolygonB, rPolygonA, true)) return true; } return bRetval; } bool ImpDoesOverlap(const basegfx::B2DPolyPolygon& rPolyPolygonA, const basegfx::B2DPolyPolygon& rPolyPolygonB) { bool bRetval(false); const basegfx::B2DRange aRangeA(basegfx::tools::getRange(rPolyPolygonA)); const basegfx::B2DRange aRangeB(basegfx::tools::getRange(rPolyPolygonB)); if(aRangeA.overlaps(aRangeB)) { const sal_uInt32 nCntA(rPolyPolygonA.count()); const sal_uInt32 nCntB(rPolyPolygonB.count()); for(sal_uInt32 a(0L); !bRetval && a < nCntA; a++) { const basegfx::B2DPolygon aPolygonA(rPolyPolygonA.getB2DPolygon(a)); if(aPolygonA.isClosed()) { for(sal_uInt32 b(0L); !bRetval && b < nCntB; b++) { const basegfx::B2DPolygon aPolygonB(rPolyPolygonB.getB2DPolygon(b)); if(aPolygonB.isClosed()) { bRetval = ImpDoesOverlap(aPolygonA, aPolygonB); } } } } } return bRetval; } 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; INT32 nNumLayers = 0; //SfxItemPool& rPool = pMod->GetItemPool(); while(aIter.IsMore()) { E3dObject* pSubObj = (E3dObject*)aIter.Next(); if(pSubObj && pSubObj->ISA(E3dExtrudeObj)) { E3dExtrudeObj* pExtrudeObj = (E3dExtrudeObj*)pSubObj; const basegfx::B2DPolyPolygon aExtrudePoly(pExtrudeObj->GetExtrudePolygon()); const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet(); XFillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem); Color aLocalColor = ((const XFillColorItem&)(rLocalSet.Get(XATTR_FILLCOLOR))).GetColorValue(); // ExtrudeObj einordnen if(pLayer) { // Gibt es eine Ueberschneidung mit einem Objekt dieses // Layers? BOOL bOverlap(FALSE); E3dDepthNeighbour* pAct = pLayer->pNext; while(!bOverlap && pAct) { // ueberlappen sich pAct->pObj und pExtrudeObj ? const basegfx::B2DPolyPolygon aActPoly(pAct->pObj->GetExtrudePolygon()); bOverlap = ImpDoesOverlap(aExtrudePoly, aActPoly); if(bOverlap) { // second ciriteria: is another fillstyle or color used? const SfxItemSet& rCompareSet = pAct->pObj->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 = FALSE; } } else if(eLocalFillStyle == XFILL_NONE) { bOverlap = FALSE; } } } pAct = pAct->pNext; } if(bOverlap) { // ja, beginne einen neuen Layer pLayer->pDown = new E3dDepthLayer; pLayer = pLayer->pDown; nNumLayers++; pLayer->pNext = new E3dDepthNeighbour; pLayer->pNext->pObj = pExtrudeObj; } else { // nein, Objekt kann in aktuellen Layer E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour; pNewNext->pObj = pExtrudeObj; pNewNext->pNext = pLayer->pNext; pLayer->pNext = pNewNext; } } else { // erster Layer ueberhaupt pBaseLayer = new E3dDepthLayer; pLayer = pBaseLayer; nNumLayers++; pLayer->pNext = new E3dDepthNeighbour; pLayer->pNext->pObj = pExtrudeObj; } } } // Anzahl Layer steht fest if(nNumLayers > 1) { // Arrangement ist notwendig double fMinDepth = fDepth * 0.8; double fStep = (fDepth - fMinDepth) / (double)nNumLayers; pLayer = pBaseLayer; while(pLayer) { // an pLayer entlangspazieren E3dDepthNeighbour* pAct = pLayer->pNext; while(pAct) { // Anpassen pAct->pObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5))); // Naechster Eintrag pAct = pAct->pNext; } // naechster Layer pLayer = pLayer->pDown; fMinDepth += fStep; } } // angelegte Strukturen aufraeumen while(pBaseLayer) { pLayer = pBaseLayer->pDown; delete pBaseLayer; pBaseLayer = pLayer; } } } /************************************************************************* |* |* Drag beginnen, vorher ggf. Drag-Methode fuer 3D-Objekte erzeugen |* \************************************************************************/ 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 { BOOL bOwnActionNecessary; if (pHdl == NULL) { bOwnActionNecessary = TRUE; } else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl()) { bOwnActionNecessary = TRUE; } else { bOwnActionNecessary = FALSE; } if(bOwnActionNecessary && GetMarkedObjectCount() >= 1) { E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ; BOOL bThereAreRootScenes = FALSE; BOOL bThereAre3DObjects = 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 = TRUE; if(pObj->ISA(E3dObject)) bThereAre3DObjects = 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, SvtOptions3D().IsShowFull() ); } break; case SDRDRAG_MOVE: { if(!bThereAreRootScenes) { pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint, SvtOptions3D().IsShowFull() ); } } 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 |* \************************************************************************/ BOOL E3dView::HasMarkedScene() { return (GetMarkedScene() != NULL); } /************************************************************************* |* |* Pruefen, obj 3D-Szene markiert ist |* \************************************************************************/ E3dScene* E3dView::GetMarkedScene() { ULONG nCnt = GetMarkedObjectCount(); for ( ULONG 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 Volume3D aVolume; const Volume3D& rObjVol = p3DObj->GetBoundVolume(); const basegfx::B3DHomMatrix& rObjTrans = p3DObj->GetTransform(); aVolume.expand(rObjVol.GetTransformVolume(rObjTrans)); 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(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(FALSE)); aR.expand(basegfx::tools::getRange(aXPP)); } basegfx::B2DPoint aCenter(aR.getCenter()); long nMarkHgt = FRound(aR.getHeight()) - 1; long nHgt = nMarkHgt + nObjDst * 2; if (nHgt < nMinLen) nHgt = nMinLen; long nY1 = 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() = 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 TRUE (SDefault: 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(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(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(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 = FALSE; mpMirrorOverlay = 0L; } /************************************************************************* |* |* Koennen die selektierten Objekte aufgebrochen werden? |* \************************************************************************/ BOOL E3dView::IsBreak3DObjPossible() const { ULONG nCount = GetMarkedObjectCount(); if (nCount > 0) { ULONG i = 0; while (i < nCount) { SdrObject* pObj = GetMarkedObjectByIndex(i); if (pObj && pObj->ISA(E3dObject)) { if(!(((E3dObject*)pObj)->IsBreakObjPossible())) return FALSE; } else { return FALSE; } i++; } } else { return FALSE; } return TRUE; } /************************************************************************* |* |* Selektierte Lathe-Objekte aufbrechen |* \************************************************************************/ void E3dView::Break3DObj() { if(IsBreak3DObjPossible()) { // ALLE selektierten Objekte werden gewandelt UINT32 nCount = GetMarkedObjectCount(); BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE))); for(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 () { ULONG nCount = GetMarkedObjectCount(); if (nCount > 0) { ULONG nObj = 0; SdrObject *pObj = GetMarkedObjectByIndex(nObj); E3dScene *pScene = new E3dPolyScene(Get3DDefaultAttributes()); Volume3D 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_OBJECT_ID: pNewObj = new E3dObject; *(E3dObject*)pNewObj = *(E3dObject*)pSubObj; break; 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_POINTOBJ_ID: pNewObj = new E3dPointObj; *(E3dPointObj*)pNewObj = *(E3dPointObj*)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_LABELOBJ_ID: pNewObj = new E3dLabelObj; *(E3dLabelObj*)pNewObj = *(E3dLabelObj*)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->FitSnapRectToBoundVol(); 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(); // Transformationen initialisieren, damit bei RecalcSnapRect() // richtig gerechnet wird pScene->InitTransformationSet(); 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) { INT32 nMarkCnt = GetMarkedObjectCount(); BOOL bCoumpound = FALSE; BOOL b3DObject = FALSE; for(INT32 nObjs = 0L; (nObjs < nMarkCnt) && !bCoumpound; nObjs++) { SdrObject *pObj = GetMarkedObjectByIndex(nObjs); if(pObj && pObj->ISA(E3dCompoundObject)) bCoumpound = TRUE; if(pObj && pObj->ISA(E3dObject)) b3DObject = TRUE; } // Bisher: Es sind ZWEI oder mehr beliebiger Objekte selektiert. // Nachsehen, ob CompoundObjects beteiligt sind. Falls ja, // das Gruppieren verbieten. if(bGroupPossible && bCoumpound) bGroupPossible = FALSE; if(bUnGroupPossible && b3DObject) bUnGroupPossible = FALSE; if(bGrpEnterPossible && bCoumpound) bGrpEnterPossible = FALSE; } } // eof