| /************************************************************** | 
 |  *  | 
 |  * 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 |