xref: /trunk/main/svx/source/engine3d/view3d.cxx (revision 1cd65da9)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <vcl/wrkwin.hxx>
28 #include <svx/svdogrp.hxx>
29 #include <svx/svdopath.hxx>
30 #include <tools/shl.hxx>
31 #include "svx/svditer.hxx"
32 #include <svx/svdpool.hxx>
33 #include <svx/svdorect.hxx>
34 #include <svx/svdmodel.hxx>
35 #include <svx/svdpagv.hxx>
36 #include <svx/svxids.hrc>
37 #include <editeng/colritem.hxx>
38 #include <svx/xtable.hxx>
39 #include <svx/svdview.hxx>
40 #include <svx/dialogs.hrc>
41 #include <svx/dialmgr.hxx>
42 #include "svx/globl3d.hxx"
43 #include <svx/obj3d.hxx>
44 #include <svx/lathe3d.hxx>
45 #include <svx/sphere3d.hxx>
46 #include <svx/extrud3d.hxx>
47 #include <svx/cube3d.hxx>
48 #include <svx/polysc3d.hxx>
49 #include "dragmt3d.hxx"
50 #include <svx/view3d.hxx>
51 #include <svx/svdundo.hxx>
52 #include <svx/xflclit.hxx>
53 #include <svx/xlnclit.hxx>
54 #include <svx/svdograf.hxx>
55 #include <svx/xbtmpit.hxx>
56 #include <svx/xflbmtit.hxx>
57 #include <basegfx/range/b2drange.hxx>
58 #include <basegfx/polygon/b2dpolygontools.hxx>
59 #include <basegfx/polygon/b2dpolypolygontools.hxx>
60 #include <svx/xlnwtit.hxx>
61 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
62 #include <svx/sdr/overlay/overlaymanager.hxx>
63 #include <svx/sdrpaintwindow.hxx>
64 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
65 #include <drawinglayer/geometry/viewinformation3d.hxx>
66 #include <svx/sdrpagewindow.hxx>
67 #include <svx/sdr/contact/displayinfo.hxx>
68 #include <svx/sdr/contact/objectcontact.hxx>
69 #include <svx/sdr/contact/viewobjectcontact.hxx>
70 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
71 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
72 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
73 #include <basegfx/matrix/b2dhommatrixtools.hxx>
74 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
75 
76 #define ITEMVALUE(ItemSet,Id,Cast)	((const Cast&)(ItemSet).Get(Id)).GetValue()
77 
78 TYPEINIT1(E3dView, SdrView);
79 
80 ////////////////////////////////////////////////////////////////////////////////////////////////////
81 // Migrate Marking
82 
83 class Impl3DMirrorConstructOverlay
84 {
85 	// The OverlayObjects
86 	::sdr::overlay::OverlayObjectList				maObjects;
87 
88 	// the view
89 	const E3dView&									mrView;
90 
91 	// the object count
92 	sal_uInt32										mnCount;
93 
94 	// the unmirrored polygons
95 	basegfx::B2DPolyPolygon*						mpPolygons;
96 
97     // the overlay geometry from selected objects
98     drawinglayer::primitive2d::Primitive2DSequence  maFullOverlay;
99 
100 public:
101 	Impl3DMirrorConstructOverlay(const E3dView& rView);
102 	~Impl3DMirrorConstructOverlay();
103 
104 	void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB);
105 };
106 
Impl3DMirrorConstructOverlay(const E3dView & rView)107 Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView)
108 :	maObjects(),
109     mrView(rView),
110     mnCount(rView.GetMarkedObjectCount()),
111     mpPolygons(0),
112     maFullOverlay()
113 {
114     if(mnCount)
115     {
116         if(mrView.IsSolidDragging())
117         {
118 	        SdrPageView* pPV = rView.GetSdrPageView();
119 
120 	        if(pPV && pPV->PageWindowCount())
121 	        {
122 		        sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
123     	        sdr::contact::DisplayInfo aDisplayInfo;
124 
125                 // Do not use the last ViewPort set at the OC at the last ProcessDisplay()
126                 rOC.resetViewPort();
127 
128 		        for(sal_uInt32 a(0);a < mnCount;a++)
129 		        {
130 			        SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
131 
132 			        if(pObject)
133 			        {
134 				        sdr::contact::ViewContact& rVC = pObject->GetViewContact();
135 				        sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rOC);
136 
137                         const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo));
138                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay, aNewSequence);
139 			        }
140 		        }
141 	        }
142         }
143         else
144         {
145 	        mpPolygons = new basegfx::B2DPolyPolygon[mnCount];
146 
147 	        for(sal_uInt32 a(0); a < mnCount; a++)
148 	        {
149 			    SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
150 		        mpPolygons[mnCount - (a + 1)] = pObject->TakeXorPoly();
151 	        }
152         }
153     }
154 }
155 
~Impl3DMirrorConstructOverlay()156 Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
157 {
158 	// The OverlayObjects are cleared using the destructor of OverlayObjectList.
159 	// That destructor calls clear() at the list which removes all objects from the
160 	// OverlayManager and deletes them.
161     if(!mrView.IsSolidDragging())
162     {
163     	delete[] mpPolygons;
164     }
165 }
166 
SetMirrorAxis(Point aMirrorAxisA,Point aMirrorAxisB)167 void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
168 {
169 	// get rid of old overlay objects
170 	maObjects.clear();
171 
172 	// create new ones
173 	for(sal_uInt32 a(0); a < mrView.PaintWindowCount(); a++)
174 	{
175 		SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a);
176 		::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
177 
178 		if(pTargetOverlay)
179 		{
180 	        // buld transfoprmation: translate and rotate so that given edge is
181             // on x axis, them mirror in y and translate back
182 	        const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y());
183             basegfx::B2DHomMatrix aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(
184                 -aMirrorAxisA.X(), -aMirrorAxisA.Y()));
185 	        aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
186 	        aMatrixTransform.scale(1.0, -1.0);
187 	        aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX()));
188 	        aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y());
189 
190             if(mrView.IsSolidDragging())
191             {
192                 if(maFullOverlay.hasElements())
193                 {
194 					drawinglayer::primitive2d::Primitive2DSequence aContent(maFullOverlay);
195 
196 					if(!aMatrixTransform.isIdentity())
197 					{
198 						// embed in transformation group
199 						drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform, aContent));
200 						aContent = drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1);
201 					}
202 
203                     // if we have full overlay from selected objects, embed with 50% transparence, the
204                     // transformation is added to the OverlayPrimitive2DSequenceObject
205 		            drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aContent, 0.5));
206                     aContent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1);
207 
208 					sdr::overlay::OverlayPrimitive2DSequenceObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent);
209 
210 		            pTargetOverlay->add(*pNew);
211 		            maObjects.append(*pNew);
212                 }
213             }
214             else
215             {
216 		        for(sal_uInt32 b(0); b < mnCount; b++)
217 		        {
218 			        // apply to polygon
219 			        basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]);
220 			        aPolyPolygon.transform(aMatrixTransform);
221 
222 			        ::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
223                         aPolyPolygon);
224 			        pTargetOverlay->add(*pNew);
225 			        maObjects.append(*pNew);
226                 }
227             }
228 		}
229 	}
230 }
231 
232 /*************************************************************************
233 |*
234 |* Konstruktor 1
235 |*
236 \************************************************************************/
237 
E3dView(SdrModel * pModel,OutputDevice * pOut)238 E3dView::E3dView(SdrModel* pModel, OutputDevice* pOut) :
239     SdrView(pModel, pOut)
240 {
241 	InitView ();
242 }
243 
244 /*************************************************************************
245 |*
246 |* DrawMarkedObj ueberladen, da eventuell nur einzelne 3D-Objekte
247 |* gezeichnet werden sollen
248 |*
249 \************************************************************************/
250 
DrawMarkedObj(OutputDevice & rOut) const251 void E3dView::DrawMarkedObj(OutputDevice& rOut) const
252 {
253 	// Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
254 	sal_Bool bSpecialHandling = sal_False;
255 	E3dScene *pScene = NULL;
256 
257 	long nCnt = GetMarkedObjectCount();
258 	for(long nObjs = 0;nObjs < nCnt;nObjs++)
259 	{
260 		SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
261 		if(pObj && pObj->ISA(E3dCompoundObject))
262 		{
263 			// zugehoerige Szene
264 			pScene = ((E3dCompoundObject*)pObj)->GetScene();
265 			if(pScene && !IsObjMarked(pScene))
266 				bSpecialHandling = sal_True;
267 		}
268 		// Alle SelectionFlags zuruecksetzen
269 		if(pObj && pObj->ISA(E3dObject))
270 		{
271 			pScene = ((E3dObject*)pObj)->GetScene();
272 			if(pScene)
273 				pScene->SetSelected(sal_False);
274 		}
275 	}
276 
277 	if(bSpecialHandling)
278 	{
279 		// SelectionFlag bei allen zu 3D Objekten gehoerigen
280 		// Szenen und deren Objekten auf nicht selektiert setzen
281 		long nObjs;
282 		for(nObjs = 0;nObjs < nCnt;nObjs++)
283 		{
284 			SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
285 			if(pObj && pObj->ISA(E3dCompoundObject))
286 			{
287 				// zugehoerige Szene
288 				pScene = ((E3dCompoundObject*)pObj)->GetScene();
289 				if(pScene)
290 					pScene->SetSelected(sal_False);
291 			}
292 		}
293 
294 		// bei allen direkt selektierten Objekten auf selektiert setzen
295 		SdrMark* pM = NULL;
296 
297 		for(nObjs = 0;nObjs < nCnt;nObjs++)
298 		{
299 			SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
300 			if(pObj && pObj->ISA(E3dObject))
301 			{
302 				// Objekt markieren
303 				E3dObject* p3DObj = (E3dObject*)pObj;
304 				p3DObj->SetSelected(sal_True);
305 				pScene = p3DObj->GetScene();
306 				pM = GetSdrMarkByIndex(nObjs);
307 			}
308 		}
309 
310 		if(pScene)
311 		{
312 			// code from parent
313 			SortMarkedObjects();
314 
315 			pScene->SetDrawOnlySelected(sal_True);
316 			pScene->SingleObjectPainter(rOut); // #110094#-17
317 			pScene->SetDrawOnlySelected(sal_False);
318 		}
319 
320 		// SelectionFlag zuruecksetzen
321 		for(nObjs = 0;nObjs < nCnt;nObjs++)
322 		{
323 			SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
324 			if(pObj && pObj->ISA(E3dCompoundObject))
325 			{
326 				// zugehoerige Szene
327 				pScene = ((E3dCompoundObject*)pObj)->GetScene();
328 				if(pScene)
329 					pScene->SetSelected(sal_False);
330 			}
331 		}
332 	}
333 	else
334 	{
335 		// call parent
336 		SdrExchangeView::DrawMarkedObj(rOut);
337 	}
338 }
339 
340 /*************************************************************************
341 |*
342 |* Model holen ueberladen, da bei einzelnen 3D Objekten noch eine Szene
343 |* untergeschoben werden muss
344 |*
345 \************************************************************************/
346 
GetMarkedObjModel() const347 SdrModel* E3dView::GetMarkedObjModel() const
348 {
349 	// Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
350 	bool bSpecialHandling(false);
351 	const sal_uInt32 nCount(GetMarkedObjectCount());
352     sal_uInt32 nObjs(0);
353 	E3dScene *pScene = 0;
354 
355 	for(nObjs = 0; nObjs < nCount; nObjs++)
356 	{
357 		const SdrObject* pObj = GetMarkedObjectByIndex(nObjs);
358 
359         if(!bSpecialHandling && pObj && pObj->ISA(E3dCompoundObject))
360 		{
361 			// if the object is selected, but it's scene not,
362             // we need special handling
363 			pScene = ((E3dCompoundObject*)pObj)->GetScene();
364 
365 			if(pScene && !IsObjMarked(pScene))
366             {
367 				bSpecialHandling = true;
368 			}
369 		}
370 
371 		if(pObj && pObj->ISA(E3dObject))
372 		{
373             // reset all selection flags at 3D objects
374 			pScene = ((E3dObject*)pObj)->GetScene();
375 
376 			if(pScene)
377             {
378 				pScene->SetSelected(false);
379             }
380 		}
381 	}
382 
383     if(!bSpecialHandling)
384 	{
385 		// call parent
386 		return SdrView::GetMarkedObjModel();
387 	}
388 
389 	SdrModel* pNewModel = 0;
390     Rectangle aSelectedSnapRect;
391 
392 	// set 3d selection flags at all directly selected objects
393     // and collect SnapRect of selected objects
394 	for(nObjs = 0; nObjs < nCount; nObjs++)
395 	{
396 		SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
397 
398         if(pObj && pObj->ISA(E3dCompoundObject))
399 		{
400 			// mark object, but not scenes
401 			E3dCompoundObject* p3DObj = (E3dCompoundObject*)pObj;
402 			p3DObj->SetSelected(true);
403             aSelectedSnapRect.Union(p3DObj->GetSnapRect());
404 		}
405 	}
406 
407 	// create new mark list which contains all indirectly selected3d
408     // scenes as selected objects
409     SdrMarkList aOldML(GetMarkedObjectList());
410     SdrMarkList aNewML;
411 	SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess();
412 	rCurrentMarkList = aNewML;
413 
414 	for(nObjs = 0; nObjs < nCount; nObjs++)
415 	{
416 		SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj();
417 
418 		if(pObj && pObj->ISA(E3dObject))
419 		{
420 			pScene = ((E3dObject*)pObj)->GetScene();
421 
422             if(pScene && !IsObjMarked(pScene) && GetSdrPageView())
423 			{
424 				((E3dView*)this)->MarkObj(pScene, GetSdrPageView(), sal_False, sal_True);
425 			}
426 		}
427 	}
428 
429 	// call parent. This will copy all scenes and the selection flags at the 3d objectss. So
430     // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes
431 	pNewModel = SdrView::GetMarkedObjModel();
432 
433 	if(pNewModel)
434 	{
435 		for(sal_uInt16 nPg(0); nPg < pNewModel->GetPageCount(); nPg++)
436 		{
437 			const SdrPage* pSrcPg=pNewModel->GetPage(nPg);
438 			const sal_uInt32 nObAnz(pSrcPg->GetObjCount());
439 
440 			for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
441 			{
442 				const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
443 
444 				if(pSrcOb->ISA(E3dScene))
445 				{
446 					pScene = (E3dScene*)pSrcOb;
447 
448                     // delete all not intentionally cloned 3d objects
449                     pScene->removeAllNonSelectedObjects();
450 
451                     // reset select flags and set SnapRect of all selected objects
452 					pScene->SetSelected(false);
453                     pScene->SetSnapRect(aSelectedSnapRect);
454 				}
455 			}
456 		}
457 	}
458 
459 	// restore old selection
460 	rCurrentMarkList = aOldML;
461 
462 	// model zurueckgeben
463 	return pNewModel;
464 }
465 
466 /*************************************************************************
467 |*
468 |* Bei Paste muss - falls in eine Scene eingefuegt wird - die
469 |* Objekte der Szene eingefuegt werden, die Szene selbst aber nicht
470 |*
471 \************************************************************************/
472 
Paste(const SdrModel & rMod,const Point & rPos,SdrObjList * pLst,sal_uInt32 nOptions)473 sal_Bool E3dView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
474 {
475 	sal_Bool bRetval = sal_False;
476 
477 	// Liste holen
478     Point aPos(rPos);
479 	SdrObjList* pDstList = pLst;
480     ImpGetPasteObjList(aPos, pDstList);
481 
482 	if(!pDstList)
483 		return sal_False;
484 
485 	// Owner der Liste holen
486 	SdrObject* pOwner = pDstList->GetOwnerObj();
487 	if(pOwner && pOwner->ISA(E3dScene))
488 	{
489 		E3dScene* pDstScene = (E3dScene*)pOwner;
490 	    BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE));
491 
492 		// Alle Objekte aus E3dScenes kopieren und direkt einfuegen
493 	    for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++)
494 		{
495 	        const SdrPage* pSrcPg=rMod.GetPage(nPg);
496 	        sal_uInt32 nObAnz(pSrcPg->GetObjCount());
497 
498 			// calculate offset for paste
499 			Rectangle aR = pSrcPg->GetAllObjBoundRect();
500 			Point aDist(aPos - aR.Center());
501 
502 			// Unterobjekte von Szenen einfuegen
503 			for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
504 			{
505 				const SdrObject* pSrcOb = pSrcPg->GetObj(nOb);
506 				if(pSrcOb->ISA(E3dScene))
507 				{
508 					E3dScene* pSrcScene = (E3dScene*)pSrcOb;
509 					ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist);
510 				}
511 			}
512 		}
513 		EndUndo();
514 	}
515 	else
516 	{
517 		// call parent
518 		bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions);
519 	}
520 
521 	// und Rueckgabewert liefern
522 	return bRetval;
523 }
524 
525 // #83403# Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
ImpCloneAll3DObjectsToDestScene(E3dScene * pSrcScene,E3dScene * pDstScene,Point)526 sal_Bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point /*aOffset*/)
527 {
528 	sal_Bool bRetval(sal_False);
529 
530 	if(pSrcScene && pDstScene)
531 	{
532 		const sdr::contact::ViewContactOfE3dScene& rVCSceneDst = static_cast< sdr::contact::ViewContactOfE3dScene& >(pDstScene->GetViewContact());
533 		const drawinglayer::geometry::ViewInformation3D aViewInfo3DDst(rVCSceneDst.getViewInformation3D());
534 		const sdr::contact::ViewContactOfE3dScene& rVCSceneSrc = static_cast< sdr::contact::ViewContactOfE3dScene& >(pSrcScene->GetViewContact());
535 		const drawinglayer::geometry::ViewInformation3D aViewInfo3DSrc(rVCSceneSrc.getViewInformation3D());
536 
537 		for(sal_uInt32 i(0); i < pSrcScene->GetSubList()->GetObjCount(); i++)
538 		{
539 			E3dCompoundObject* pCompoundObj = dynamic_cast< E3dCompoundObject* >(pSrcScene->GetSubList()->GetObj(i));
540 
541 			if(pCompoundObj)
542 			{
543 				// #116235#
544 				E3dCompoundObject* pNewCompoundObj = dynamic_cast< E3dCompoundObject* >(pCompoundObj->Clone());
545 
546 				if(pNewCompoundObj)
547 				{
548                     // get dest scene's current range in 3D world coordinates
549                     const basegfx::B3DHomMatrix aSceneToWorldTrans(pDstScene->GetFullTransform());
550                 	basegfx::B3DRange aSceneRange(pDstScene->GetBoundVolume());
551                     aSceneRange.transform(aSceneToWorldTrans);
552 
553                     // get new object's implied object transformation
554                     const basegfx::B3DHomMatrix aNewObjectTrans(pNewCompoundObj->GetTransform());
555 
556                     // get new object's range in 3D world coordinates in dest scene
557                     // as if it were already added
558                     const basegfx::B3DHomMatrix aObjectToWorldTrans(aSceneToWorldTrans * aNewObjectTrans);
559                     basegfx::B3DRange aObjectRange(pNewCompoundObj->GetBoundVolume());
560                     aObjectRange.transform(aObjectToWorldTrans);
561 
562                     // get scale adaption
563                     const basegfx::B3DVector aSceneScale(aSceneRange.getRange());
564                     const basegfx::B3DVector aObjectScale(aObjectRange.getRange());
565                     double fScale(1.0);
566 
567                     // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
568                     // to not change the scene by the inserted object
569                     const double fSizeFactor(0.5);
570 
571                     if(aObjectScale.getX() * fScale > aSceneScale.getX() * fSizeFactor)
572                     {
573                         const double fObjSize(aObjectScale.getX() * fScale);
574                         const double fFactor((aSceneScale.getX() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
575                         fScale *= fFactor;
576                     }
577 
578                     if(aObjectScale.getY() * fScale > aSceneScale.getY() * fSizeFactor)
579                     {
580                         const double fObjSize(aObjectScale.getY() * fScale);
581                         const double fFactor((aSceneScale.getY() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
582                         fScale *= fFactor;
583 					}
584 
585                     if(aObjectScale.getZ() * fScale > aSceneScale.getZ() * fSizeFactor)
586                     {
587                         const double fObjSize(aObjectScale.getZ() * fScale);
588                         const double fFactor((aSceneScale.getZ() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
589                         fScale *= fFactor;
590                     }
591 
592                     // get translation adaption
593                     const basegfx::B3DPoint aSceneCenter(aSceneRange.getCenter());
594             		const basegfx::B3DPoint aObjectCenter(aObjectRange.getCenter());
595 
596                     // build full modification transform. The object's transformation
597                     // shall be modified, so start at object coordinates; transform to 3d world coor
598                     basegfx::B3DHomMatrix aModifyingTransform(aObjectToWorldTrans);
599 
600                     // translate to absolute center in 3d world coor
601                     aModifyingTransform.translate(-aObjectCenter.getX(), -aObjectCenter.getY(), -aObjectCenter.getZ());
602 
603                     // scale to dest size in 3d world coor
604                     aModifyingTransform.scale(fScale, fScale, fScale);
605 
606                     // translate to dest scene center in 3d world coor
607                     aModifyingTransform.translate(aSceneCenter.getX(), aSceneCenter.getY(), aSceneCenter.getZ());
608 
609                     // transform from 3d world to dest object coordinates
610                     basegfx::B3DHomMatrix aWorldToObject(aObjectToWorldTrans);
611                     aWorldToObject.invert();
612                     aModifyingTransform = aWorldToObject * aModifyingTransform;
613 
614                     // correct implied object transform by applying changing one in object coor
615                     pNewCompoundObj->SetTransform(aModifyingTransform * aNewObjectTrans);
616 
617 					// fill and insert new object
618 					pNewCompoundObj->SetModel(pDstScene->GetModel());
619 					pNewCompoundObj->SetPage(pDstScene->GetPage());
620 					pNewCompoundObj->NbcSetLayer(pCompoundObj->GetLayer());
621 					pNewCompoundObj->NbcSetStyleSheet(pCompoundObj->GetStyleSheet(), sal_True);
622 					pDstScene->Insert3DObj(pNewCompoundObj);
623 					bRetval = sal_True;
624 
625 					// Undo anlegen
626 					if( GetModel()->IsUndoEnabled() )
627 						AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj));
628 				}
629 			}
630 		}
631 	}
632 
633 	return bRetval;
634 }
635 
636 /*************************************************************************
637 |*
638 |* 3D-Konvertierung moeglich?
639 |*
640 \************************************************************************/
641 
IsConvertTo3DObjPossible() const642 sal_Bool E3dView::IsConvertTo3DObjPossible() const
643 {
644 	sal_Bool bAny3D(sal_False);
645 	sal_Bool bGroupSelected(sal_False);
646 	sal_Bool bRetval(sal_True);
647 
648 	for(sal_uInt32 a=0;!bAny3D && a<GetMarkedObjectCount();a++)
649 	{
650 		SdrObject *pObj = GetMarkedObjectByIndex(a);
651 		if(pObj)
652 		{
653 			ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected);
654 		}
655 	}
656 
657 	bRetval = !bAny3D
658 		&& (
659 		   IsConvertToPolyObjPossible(sal_False)
660 		|| IsConvertToPathObjPossible(sal_False)
661 		|| IsImportMtfPossible());
662 	return bRetval;
663 }
664 
ImpIsConvertTo3DPossible(SdrObject * pObj,sal_Bool & rAny3D,sal_Bool & rGroupSelected) const665 void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, sal_Bool& rAny3D,
666 	sal_Bool& rGroupSelected) const
667 {
668 	if(pObj)
669 	{
670 		if(pObj->ISA(E3dObject))
671 		{
672 			rAny3D = sal_True;
673 		}
674 		else
675 		{
676 			if(pObj->IsGroupObject())
677 			{
678 				SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS);
679 				while(aIter.IsMore())
680 				{
681 					SdrObject* pNewObj = aIter.Next();
682 					ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected);
683 				}
684 				rGroupSelected = sal_True;
685 			}
686 		}
687 	}
688 }
689 
690 /*************************************************************************
691 |*
692 |* 3D-Konvertierung zu Extrude ausfuehren
693 |*
694 \************************************************************************/
695 #include <editeng/eeitem.hxx>
696 
ImpChangeSomeAttributesFor3DConversion(SdrObject * pObj)697 void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject* pObj)
698 {
699 	if(pObj->ISA(SdrTextObj))
700 	{
701 		const SfxItemSet& rSet = pObj->GetMergedItemSet();
702 		const SvxColorItem& rTextColorItem = (const SvxColorItem&)rSet.Get(EE_CHAR_COLOR);
703 		if(rTextColorItem.GetValue() == RGB_Color(COL_BLACK))
704 		{
705 			// Bei schwarzen Textobjekten wird die Farbe auf grau gesetzt
706 			if(pObj->GetPage())
707 			{
708 				// #84864# if black is only default attribute from
709 				// pattern set it hard so that it is used in undo.
710 				pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK), EE_CHAR_COLOR));
711 
712 				// add undo now
713 				if( GetModel()->IsUndoEnabled() )
714 					AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
715 			}
716 
717 			pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY), EE_CHAR_COLOR));
718 		}
719 	}
720 }
721 
ImpChangeSomeAttributesFor3DConversion2(SdrObject * pObj)722 void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject* pObj)
723 {
724 	if(pObj->ISA(SdrPathObj))
725 	{
726 		const SfxItemSet& rSet = pObj->GetMergedItemSet();
727 		sal_Int32 nLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
728 		XLineStyle eLineStyle = (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue();
729 		XFillStyle eFillStyle = ITEMVALUE(rSet, XATTR_FILLSTYLE, XFillStyleItem);
730 
731 		if(((SdrPathObj*)pObj)->IsClosed()
732 			&& eLineStyle == XLINE_SOLID
733 			&& !nLineWidth
734 			&& eFillStyle != XFILL_NONE)
735 		{
736 			if(pObj->GetPage() && GetModel()->IsUndoEnabled() )
737 				AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
738 			pObj->SetMergedItem(XLineStyleItem(XLINE_NONE));
739 			pObj->SetMergedItem(XLineWidthItem(0L));
740 		}
741 	}
742 }
743 
ImpCreateSingle3DObjectFlat(E3dScene * pScene,SdrObject * pObj,sal_Bool bExtrude,double fDepth,basegfx::B2DHomMatrix & rLatheMat)744 void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, sal_Bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
745 {
746 	// Einzelnes PathObject, dieses umwanden
747 	SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
748 
749 	if(pPath)
750 	{
751 		E3dDefaultAttributes aDefault = Get3DDefaultAttributes();
752 		if(bExtrude)
753 			aDefault.SetDefaultExtrudeCharacterMode(sal_True);
754 		else
755 			aDefault.SetDefaultLatheCharacterMode(sal_True);
756 
757 		// ItemSet des Ursprungsobjektes holen
758 		SfxItemSet aSet(pObj->GetMergedItemSet());
759 
760 		XFillStyle eFillStyle = ITEMVALUE(aSet, XATTR_FILLSTYLE, XFillStyleItem);
761 
762 		// Linienstil ausschalten
763 		aSet.Put(XLineStyleItem(XLINE_NONE));
764 
765 		// Feststellen, ob ein FILL_Attribut gesetzt ist.
766 		if(!pPath->IsClosed() || eFillStyle == XFILL_NONE)
767 		{
768 			// Das SdrPathObj ist nicht gefuellt, lasse die
769 			// vordere und hintere Flaeche weg. Ausserdem ist
770 			// eine beidseitige Darstellung notwendig.
771 			aDefault.SetDefaultExtrudeCloseFront(sal_False);
772 			aDefault.SetDefaultExtrudeCloseBack(sal_False);
773 
774 			aSet.Put(Svx3DDoubleSidedItem(sal_True));
775 
776 			// Fuellattribut setzen
777 			aSet.Put(XFillStyleItem(XFILL_SOLID));
778 
779 			// Fuellfarbe muss auf Linienfarbe, da das Objekt vorher
780 			// nur eine Linie war
781 			Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue();
782 			aSet.Put(XFillColorItem(String(), aColorLine));
783 		}
784 
785 		// Neues Extrude-Objekt erzeugen
786 		E3dObject* p3DObj = NULL;
787 		if(bExtrude)
788 		{
789 			p3DObj = new E3dExtrudeObj(aDefault, pPath->GetPathPoly(), fDepth);
790 		}
791 		else
792 		{
793 			basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly());
794 			aPolyPoly2D.transform(rLatheMat);
795 			p3DObj = new E3dLatheObj(aDefault, aPolyPoly2D);
796 		}
797 
798 		// Attribute setzen
799 		if(p3DObj)
800 		{
801 			p3DObj->NbcSetLayer(pObj->GetLayer());
802 
803 			p3DObj->SetMergedItemSet(aSet);
804 
805 			p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True);
806 
807 			// Neues 3D-Objekt einfuegen
808 			pScene->Insert3DObj(p3DObj);
809 		}
810 	}
811 }
812 
ImpCreate3DObject(E3dScene * pScene,SdrObject * pObj,sal_Bool bExtrude,double fDepth,basegfx::B2DHomMatrix & rLatheMat)813 void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, sal_Bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
814 {
815 	if(pObj)
816 	{
817 		// change text color attribute for not so dark colors
818 		if(pObj->IsGroupObject())
819 		{
820 			SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
821 			while(aIter.IsMore())
822 			{
823 				SdrObject* pGroupMember = aIter.Next();
824 				ImpChangeSomeAttributesFor3DConversion(pGroupMember);
825 			}
826 		}
827 		else
828 			ImpChangeSomeAttributesFor3DConversion(pObj);
829 
830 		// convert completely to path objects
831 		SdrObject* pNewObj1 = pObj->ConvertToPolyObj(sal_False, sal_False);
832 
833 		if(pNewObj1)
834 		{
835 			// change text color attribute for not so dark colors
836 			if(pNewObj1->IsGroupObject())
837 			{
838 				SdrObjListIter aIter(*pNewObj1, IM_DEEPWITHGROUPS);
839 				while(aIter.IsMore())
840 				{
841 					SdrObject* pGroupMember = aIter.Next();
842 					ImpChangeSomeAttributesFor3DConversion2(pGroupMember);
843 				}
844 			}
845 			else
846 				ImpChangeSomeAttributesFor3DConversion2(pNewObj1);
847 
848 			// convert completely to path objects
849 			SdrObject* pNewObj2 = pObj->ConvertToContourObj(pNewObj1, sal_True);
850 
851 			if(pNewObj2)
852 			{
853 				// add all to flat scene
854 				if(pNewObj2->IsGroupObject())
855 				{
856 					SdrObjListIter aIter(*pNewObj2, IM_DEEPWITHGROUPS);
857 					while(aIter.IsMore())
858 					{
859 						SdrObject* pGroupMember = aIter.Next();
860 						ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat);
861 					}
862 				}
863 				else
864 					ImpCreateSingle3DObjectFlat(pScene, pNewObj2, bExtrude, fDepth, rLatheMat);
865 
866 				// delete zwi object
867 				if(pNewObj2 != pObj && pNewObj2 != pNewObj1 && pNewObj2)
868                     SdrObject::Free( pNewObj2 );
869 			}
870 
871 			// delete zwi object
872 			if(pNewObj1 != pObj && pNewObj1)
873 				SdrObject::Free( pNewObj1 );
874 		}
875 	}
876 }
877 
878 /*************************************************************************
879 |*
880 |* 3D-Konvertierung zu Extrude steuern
881 |*
882 \************************************************************************/
883 
ConvertMarkedObjTo3D(sal_Bool bExtrude,basegfx::B2DPoint aPnt1,basegfx::B2DPoint aPnt2)884 void E3dView::ConvertMarkedObjTo3D(sal_Bool bExtrude, basegfx::B2DPoint aPnt1, basegfx::B2DPoint aPnt2)
885 {
886 	if(AreObjectsMarked())
887 	{
888 		// Undo anlegen
889         if(bExtrude)
890 			BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE));
891 		else
892 			BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE));
893 
894 		// Neue Szene fuer zu erzeugende 3D-Objekte anlegen
895         E3dScene* pScene = new E3dPolyScene(Get3DDefaultAttributes());
896 
897 		// Rechteck bestimmen und evtl. korrigieren
898 		Rectangle aRect = GetAllMarkedRect();
899 		if(aRect.GetWidth() <= 1)
900 			aRect.SetSize(Size(500, aRect.GetHeight()));
901 		if(aRect.GetHeight() <= 1)
902 			aRect.SetSize(Size(aRect.GetWidth(), 500));
903 
904 		// Tiefe relativ zur Groesse der Selektion bestimmen
905 		double fDepth = 0.0;
906 		double fRot3D = 0.0;
907 		basegfx::B2DHomMatrix aLatheMat;
908 
909 		if(bExtrude)
910 		{
911 			double fW = (double)aRect.GetWidth();
912 			double fH = (double)aRect.GetHeight();
913 			fDepth = sqrt(fW*fW + fH*fH) / 6.0;
914 		}
915 		if(!bExtrude)
916 		{
917 			// Transformation fuer Polygone Rotationskoerper erstellen
918 			if(aPnt1 != aPnt2)
919 			{
920 				// Rotation um Kontrollpunkt1 mit eigestelltem Winkel
921 				// fuer 3D Koordinaten
922 				basegfx::B2DPoint aDiff(aPnt1 - aPnt2);
923 				fRot3D = atan2(aDiff.getY(), aDiff.getX()) - F_PI2;
924 
925                 if(basegfx::fTools::equalZero(fabs(fRot3D)))
926 					fRot3D = 0.0;
927 
928 				if(fRot3D != 0.0)
929 				{
930                     aLatheMat = basegfx::tools::createRotateAroundPoint(aPnt2, -fRot3D)
931                         * aLatheMat;
932 				}
933 			}
934 
935 			if(aPnt2.getX() != 0.0)
936 			{
937 				// Translation auf Y=0 - Achse
938 				aLatheMat.translate(-aPnt2.getX(), 0.0);
939 			}
940 			else
941 			{
942 				aLatheMat.translate((double)-aRect.Left(), 0.0);
943 			}
944 
945 			// Inverse Matrix bilden, um die Zielausdehnung zu bestimmen
946 			basegfx::B2DHomMatrix aInvLatheMat(aLatheMat);
947 			aInvLatheMat.invert();
948 
949 			// SnapRect Ausdehnung mittels Spiegelung an der Rotationsachse
950 			// erweitern
951 			for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
952 			{
953 				SdrMark* pMark = GetSdrMarkByIndex(a);
954 				SdrObject* pObj = pMark->GetMarkedSdrObj();
955 				Rectangle aTurnRect = pObj->GetSnapRect();
956 				basegfx::B2DPoint aRot;
957 				Point aRotPnt;
958 
959 				aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top());
960 				aRot *= aLatheMat;
961 				aRot.setX(-aRot.getX());
962 				aRot *= aInvLatheMat;
963 				aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
964 				aRect.Union(Rectangle(aRotPnt, aRotPnt));
965 
966 				aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom());
967 				aRot *= aLatheMat;
968 				aRot.setX(-aRot.getX());
969 				aRot *= aInvLatheMat;
970 				aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
971 				aRect.Union(Rectangle(aRotPnt, aRotPnt));
972 
973 				aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top());
974 				aRot *= aLatheMat;
975 				aRot.setX(-aRot.getX());
976 				aRot *= aInvLatheMat;
977 				aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
978 				aRect.Union(Rectangle(aRotPnt, aRotPnt));
979 
980 				aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom());
981 				aRot *= aLatheMat;
982 				aRot.setX(-aRot.getX());
983 				aRot *= aInvLatheMat;
984 				aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
985 				aRect.Union(Rectangle(aRotPnt, aRotPnt));
986 			}
987 		}
988 
989 		// Ueber die Selektion gehen und in 3D wandeln, komplett mit
990 		// Umwandeln in SdrPathObject, auch Schriften
991 		for(sal_uInt32 a=0;a<GetMarkedObjectCount();a++)
992 		{
993 			SdrMark* pMark = GetSdrMarkByIndex(a);
994 			SdrObject* pObj = pMark->GetMarkedSdrObj();
995 
996 			ImpCreate3DObject(pScene, pObj, bExtrude, fDepth, aLatheMat);
997 		}
998 
999 		if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0)
1000 		{
1001 			// Alle angelegten Objekte Tiefenarrangieren
1002 			if(bExtrude)
1003 				DoDepthArrange(pScene, fDepth);
1004 
1005 			// 3D-Objekte auf die Mitte des Gesamtrechtecks zentrieren
1006 			basegfx::B3DPoint aCenter(pScene->GetBoundVolume().getCenter());
1007 			basegfx::B3DHomMatrix aMatrix;
1008 
1009             aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ());
1010 			pScene->SetTransform(aMatrix * pScene->GetTransform()); // #112587#
1011 
1012 			// Szene initialisieren
1013 			pScene->NbcSetSnapRect(aRect);
1014 			basegfx::B3DRange aBoundVol = pScene->GetBoundVolume();
1015 			InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth());
1016 
1017 			// Szene anstelle des ersten selektierten Objektes einfuegen
1018 			// und alle alten Objekte weghauen
1019 			SdrObject* pRepObj = GetMarkedObjectByIndex(0);
1020 			SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0);
1021 			MarkObj(pRepObj, pPV, sal_True);
1022 			ReplaceObjectAtView(pRepObj, *pPV, pScene, sal_False);
1023 			DeleteMarked();
1024 			MarkObj(pScene, pPV);
1025 
1026 			// Rotationskoerper um Rotationsachse drehen
1027 			basegfx::B3DHomMatrix aRotate;
1028 
1029 			if(!bExtrude && fRot3D != 0.0)
1030 			{
1031 				aRotate.rotate(0.0, 0.0, fRot3D);
1032 			}
1033 
1034 			// Default-Rotation setzen
1035 			{
1036 	            double XRotateDefault = 20;
1037 				aRotate.rotate(DEG2RAD(XRotateDefault), 0.0, 0.0);
1038 			}
1039 
1040 			if(!aRotate.isIdentity())
1041 			{
1042 				pScene->SetTransform(aRotate * pScene->GetTransform());
1043 			}
1044 
1045 			// SnapRects der Objekte ungueltig
1046 			pScene->SetSnapRect(aRect);
1047 		}
1048 		else
1049         {
1050 			// Es wurden keine 3D Objekte erzeugt, schmeiss alles weg
1051 			delete pScene;
1052         }
1053 
1054 		// Undo abschliessen
1055         EndUndo();
1056 	}
1057 }
1058 
1059 /*************************************************************************
1060 |*
1061 |* Alle enthaltenen Extrude-Objekte Tiefenarrangieren
1062 |*
1063 \************************************************************************/
1064 
1065 struct E3dDepthNeighbour
1066 {
1067 	E3dDepthNeighbour*	        mpNext;
1068 	E3dExtrudeObj*		        mpObj;
1069     basegfx::B2DPolyPolygon     maPreparedPolyPolygon;
1070 
E3dDepthNeighbourE3dDepthNeighbour1071     E3dDepthNeighbour()
1072     :   mpNext(0),
1073         mpObj(0),
1074         maPreparedPolyPolygon()
1075     {
1076     }
1077 };
1078 
1079 struct E3dDepthLayer
1080 {
1081 	E3dDepthLayer*		        mpDown;
1082 	E3dDepthNeighbour*	        mpNext;
1083 
E3dDepthLayerE3dDepthLayer1084 	E3dDepthLayer()
1085     :   mpDown(0),
1086         mpNext(0)
1087     {
1088     }
1089 
~E3dDepthLayerE3dDepthLayer1090 	~E3dDepthLayer()
1091     {
1092         while(mpNext)
1093         {
1094             E3dDepthNeighbour* pSucc = mpNext->mpNext;
1095             delete mpNext;
1096             mpNext = pSucc;
1097         }
1098     }
1099 };
1100 
DoDepthArrange(E3dScene * pScene,double fDepth)1101 void E3dView::DoDepthArrange(E3dScene* pScene, double fDepth)
1102 {
1103 	if(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1)
1104 	{
1105 		SdrObjList* pSubList = pScene->GetSubList();
1106 		SdrObjListIter aIter(*pSubList, IM_FLAT);
1107 		E3dDepthLayer* pBaseLayer = NULL;
1108 		E3dDepthLayer* pLayer = NULL;
1109 		sal_Int32 nNumLayers = 0;
1110 
1111 		while(aIter.IsMore())
1112 		{
1113 			E3dExtrudeObj* pExtrudeObj = dynamic_cast< E3dExtrudeObj* >(aIter.Next());
1114 
1115 			if(pExtrudeObj)
1116 			{
1117                 const basegfx::B2DPolyPolygon aExtrudePoly(
1118                     basegfx::tools::prepareForPolygonOperation(pExtrudeObj->GetExtrudePolygon()));
1119 				const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet();
1120 				const XFillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem);
1121 				const Color aLocalColor = ((const XFillColorItem&)(rLocalSet.Get(XATTR_FILLCOLOR))).GetColorValue();
1122 
1123 				// sort in ExtrudeObj
1124 				if(pLayer)
1125 				{
1126 					// do we have overlap with an object of this layer?
1127 					bool bOverlap(false);
1128 					E3dDepthNeighbour* pAct = pLayer->mpNext;
1129 
1130 					while(!bOverlap && pAct)
1131 					{
1132 						// do pAct->mpObj and pExtrudeObj overlap? Check by
1133                         // using logical AND clipping
1134                         const basegfx::B2DPolyPolygon aAndPolyPolygon(
1135                             basegfx::tools::solvePolygonOperationAnd(
1136                                 aExtrudePoly,
1137                                 pAct->maPreparedPolyPolygon));
1138 
1139                         bOverlap = (0 != aAndPolyPolygon.count());
1140 
1141 						if(bOverlap)
1142 						{
1143 							// second ciriteria: is another fillstyle or color used?
1144 							const SfxItemSet& rCompareSet = pAct->mpObj->GetMergedItemSet();
1145 
1146 							XFillStyle eCompareFillStyle = ITEMVALUE(rCompareSet, XATTR_FILLSTYLE, XFillStyleItem);
1147 
1148 							if(eLocalFillStyle == eCompareFillStyle)
1149 							{
1150 								if(eLocalFillStyle == XFILL_SOLID)
1151 								{
1152 									Color aCompareColor = ((const XFillColorItem&)(rCompareSet.Get(XATTR_FILLCOLOR))).GetColorValue();
1153 
1154 									if(aCompareColor == aLocalColor)
1155 									{
1156 										bOverlap = sal_False;
1157 									}
1158 								}
1159 								else if(eLocalFillStyle == XFILL_NONE)
1160 								{
1161 									bOverlap = sal_False;
1162 								}
1163 							}
1164 						}
1165 
1166 						pAct = pAct->mpNext;
1167 					}
1168 
1169 					if(bOverlap)
1170 					{
1171 						// yes, start a new layer
1172 						pLayer->mpDown = new E3dDepthLayer;
1173 						pLayer = pLayer->mpDown;
1174 						nNumLayers++;
1175 						pLayer->mpNext = new E3dDepthNeighbour;
1176 						pLayer->mpNext->mpObj = pExtrudeObj;
1177 						pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly;
1178 					}
1179 					else
1180 					{
1181 						// no, add to current layer
1182 						E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour;
1183 						pNewNext->mpObj = pExtrudeObj;
1184 						pNewNext->maPreparedPolyPolygon = aExtrudePoly;
1185 						pNewNext->mpNext = pLayer->mpNext;
1186 						pLayer->mpNext = pNewNext;
1187 					}
1188 				}
1189 				else
1190 				{
1191 					// first layer ever
1192 					pBaseLayer = new E3dDepthLayer;
1193 					pLayer = pBaseLayer;
1194 					nNumLayers++;
1195 					pLayer->mpNext = new E3dDepthNeighbour;
1196 					pLayer->mpNext->mpObj = pExtrudeObj;
1197 					pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly;
1198 				}
1199 			}
1200 		}
1201 
1202 		// number of layers is done
1203 		if(nNumLayers > 1)
1204 		{
1205 			// need to be arranged
1206 			double fMinDepth = fDepth * 0.8;
1207 			double fStep = (fDepth - fMinDepth) / (double)nNumLayers;
1208 			pLayer = pBaseLayer;
1209 
1210 			while(pLayer)
1211 			{
1212 				// move along layer
1213 				E3dDepthNeighbour* pAct = pLayer->mpNext;
1214 
1215 				while(pAct)
1216 				{
1217 					// adapt extrude value
1218 					pAct->mpObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5)));
1219 
1220 					// next
1221 					pAct = pAct->mpNext;
1222 				}
1223 
1224 				// next layer
1225 				pLayer = pLayer->mpDown;
1226 				fMinDepth += fStep;
1227 			}
1228 		}
1229 
1230 		// cleanup
1231 		while(pBaseLayer)
1232 		{
1233 			pLayer = pBaseLayer->mpDown;
1234 			delete pBaseLayer;
1235 			pBaseLayer = pLayer;
1236 		}
1237 	}
1238 }
1239 
1240 /*************************************************************************
1241 |*
1242 |* Drag beginnen, vorher ggf. Drag-Methode fuer 3D-Objekte erzeugen
1243 |*
1244 \************************************************************************/
1245 
BegDragObj(const Point & rPnt,OutputDevice * pOut,SdrHdl * pHdl,short nMinMov,SdrDragMethod * pForcedMeth)1246 sal_Bool E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut,
1247 	SdrHdl* pHdl, short nMinMov,
1248 	SdrDragMethod* pForcedMeth)
1249 {
1250     if(Is3DRotationCreationActive() && GetMarkedObjectCount())
1251 	{
1252 		// bestimme alle selektierten Polygone und gebe die gespiegelte Hilfsfigur aus
1253 		mpMirrorOverlay->SetMirrorAxis(aRef1, aRef2);
1254 	}
1255 	else
1256     {
1257         sal_Bool bOwnActionNecessary;
1258         if (pHdl == NULL)
1259         {
1260            bOwnActionNecessary = sal_True;
1261         }
1262         else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl())
1263         {
1264            bOwnActionNecessary = sal_True;
1265         }
1266         else
1267         {
1268            bOwnActionNecessary = sal_False;
1269         }
1270 
1271         if(bOwnActionNecessary && GetMarkedObjectCount() >= 1)
1272         {
1273             E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ;
1274 			sal_Bool bThereAreRootScenes = sal_False;
1275 			sal_Bool bThereAre3DObjects = sal_False;
1276 			long nCnt = GetMarkedObjectCount();
1277 			for(long nObjs = 0;nObjs < nCnt;nObjs++)
1278 			{
1279 				SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1280 				if(pObj)
1281 				{
1282 					if(pObj->ISA(E3dScene) && ((E3dScene*)pObj)->GetScene() == pObj)
1283 						bThereAreRootScenes = sal_True;
1284 					if(pObj->ISA(E3dObject))
1285 						bThereAre3DObjects = sal_True;
1286 				}
1287 			}
1288 			if( bThereAre3DObjects )
1289 			{
1290                 eDragHdl = ( pHdl == NULL ? HDL_MOVE : pHdl->GetKind() );
1291                 switch ( eDragMode )
1292                 {
1293                     case SDRDRAG_ROTATE:
1294                     case SDRDRAG_SHEAR:
1295                     {
1296                         switch ( eDragHdl )
1297                         {
1298                             case HDL_LEFT:
1299                             case HDL_RIGHT:
1300                             {
1301                                 eConstraint = E3DDRAG_CONSTR_X;
1302                             }
1303                             break;
1304 
1305                             case HDL_UPPER:
1306                             case HDL_LOWER:
1307                             {
1308                                 eConstraint = E3DDRAG_CONSTR_Y;
1309                             }
1310                             break;
1311 
1312                             case HDL_UPLFT:
1313                             case HDL_UPRGT:
1314                             case HDL_LWLFT:
1315                             case HDL_LWRGT:
1316                             {
1317                                 eConstraint = E3DDRAG_CONSTR_Z;
1318                             }
1319                             break;
1320 							default: break;
1321                         }
1322 
1323                         // die nicht erlaubten Rotationen ausmaskieren
1324                         eConstraint = E3dDragConstraint(eConstraint& eDragConstraint);
1325                         pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint, IsSolidDragging());
1326                     }
1327                     break;
1328 
1329                     case SDRDRAG_MOVE:
1330                     {
1331                         if(!bThereAreRootScenes)
1332 						{
1333 							pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint, IsSolidDragging());
1334 						}
1335                     }
1336                     break;
1337 
1338                     // spaeter mal
1339                     case SDRDRAG_MIRROR:
1340                     case SDRDRAG_CROOK:
1341                     case SDRDRAG_DISTORT:
1342                     case SDRDRAG_TRANSPARENCE:
1343                     case SDRDRAG_GRADIENT:
1344                     default:
1345                     {
1346                     }
1347                     break;
1348                 }
1349 			}
1350         }
1351     }
1352     return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth);
1353 }
1354 
1355 /*************************************************************************
1356 |*
1357 |* Pruefen, obj 3D-Szene markiert ist
1358 |*
1359 \************************************************************************/
1360 
HasMarkedScene()1361 sal_Bool E3dView::HasMarkedScene()
1362 {
1363 	return (GetMarkedScene() != NULL);
1364 }
1365 
1366 /*************************************************************************
1367 |*
1368 |* Pruefen, obj 3D-Szene markiert ist
1369 |*
1370 \************************************************************************/
1371 
GetMarkedScene()1372 E3dScene* E3dView::GetMarkedScene()
1373 {
1374 	sal_uIntPtr nCnt = GetMarkedObjectCount();
1375 
1376 	for ( sal_uIntPtr i = 0; i < nCnt; i++ )
1377 		if ( GetMarkedObjectByIndex(i)->ISA(E3dScene) )
1378 			return (E3dScene*) GetMarkedObjectByIndex(i);
1379 
1380 	return NULL;
1381 }
1382 
1383 /*************************************************************************
1384 |*
1385 |* aktuelles 3D-Zeichenobjekt setzen, dafuer Szene erzeugen
1386 |*
1387 \************************************************************************/
1388 
SetCurrent3DObj(E3dObject * p3DObj)1389 E3dScene* E3dView::SetCurrent3DObj(E3dObject* p3DObj)
1390 {
1391 	DBG_ASSERT(p3DObj != NULL, "Nana, wer steckt denn hier 'nen NULL-Zeiger rein?");
1392 	E3dScene* pScene = NULL;
1393 
1394 	// get transformed BoundVolume of the object
1395 	basegfx::B3DRange aVolume(p3DObj->GetBoundVolume());
1396 	aVolume.transform(p3DObj->GetTransform());
1397 	double fW(aVolume.getWidth());
1398 	double fH(aVolume.getHeight());
1399 
1400 	Rectangle aRect(0,0, (long) fW, (long) fH);
1401 
1402 	pScene = new E3dPolyScene(Get3DDefaultAttributes());
1403 
1404 	InitScene(pScene, fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0));
1405 
1406 	pScene->Insert3DObj(p3DObj);
1407 	pScene->NbcSetSnapRect(aRect);
1408 
1409 	return pScene;
1410 }
1411 
1412 /*************************************************************************
1413 |*
1414 |* neu erzeugte Szene initialisieren
1415 |*
1416 \************************************************************************/
1417 
InitScene(E3dScene * pScene,double fW,double fH,double fCamZ)1418 void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ)
1419 {
1420 	Camera3D aCam(pScene->GetCamera());
1421 
1422 	aCam.SetAutoAdjustProjection(sal_False);
1423 	aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1424 	basegfx::B3DPoint aLookAt;
1425 
1426 	double fDefaultCamPosZ = GetDefaultCamPosZ();
1427 	basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1428 
1429 	aCam.SetPosAndLookAt(aCamPos, aLookAt);
1430 	aCam.SetFocalLength(GetDefaultCamFocal());
1431 	aCam.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, GetDefaultCamFocal());
1432 	pScene->SetCamera(aCam);
1433 }
1434 
1435 /*************************************************************************
1436 |*
1437 |* startsequenz fuer die erstellung eines 3D-Rotationskoerpers
1438 |*
1439 \************************************************************************/
1440 
Start3DCreation()1441 void E3dView::Start3DCreation()
1442 {
1443 	if (GetMarkedObjectCount())
1444 	{
1445 		// irgendwelche Markierungen ermitteln und ausschalten
1446 		//HMHBOOL bVis = IsMarkHdlShown();
1447 
1448 		//HMHif (bVis) HideMarkHdl();
1449 
1450 		// bestimme die koordinaten fuer JOEs Mirrorachse
1451 		// entgegen der normalen Achse wird diese an die linke Seite des Objektes
1452 		// positioniert
1453 		long		  nOutMin = 0;
1454 		long		  nOutMax = 0;
1455 		long		  nMinLen = 0;
1456 		long		  nObjDst = 0;
1457 		long		  nOutHgt = 0;
1458 		OutputDevice* pOut	  = GetFirstOutputDevice(); //GetWin(0);
1459 
1460 		// erstmal Darstellungsgrenzen bestimmen
1461 		if (pOut != NULL)
1462 		{
1463 			nMinLen = pOut->PixelToLogic(Size(0,50)).Height();
1464 			nObjDst = pOut->PixelToLogic(Size(0,20)).Height();
1465 
1466 			long nDst = pOut->PixelToLogic(Size(0,10)).Height();
1467 
1468 			nOutMin =  -pOut->GetMapMode().GetOrigin().Y();
1469 			nOutMax =  pOut->GetOutputSize().Height() - 1 + nOutMin;
1470 			nOutMin += nDst;
1471 			nOutMax -= nDst;
1472 
1473 			if (nOutMax - nOutMin < nDst)
1474 			{
1475 				nOutMin += nOutMax + 1;
1476 				nOutMin /= 2;
1477 				nOutMin -= (nDst + 1) / 2;
1478 				nOutMax  = nOutMin + nDst;
1479 			}
1480 
1481 			nOutHgt = nOutMax - nOutMin;
1482 
1483 			long nTemp = nOutHgt / 4;
1484 			if (nTemp > nMinLen) nMinLen = nTemp;
1485 		}
1486 
1487 		// und dann die Markierungen oben und unten an das Objekt heften
1488 		basegfx::B2DRange aR;
1489 		for(sal_uInt32 nMark(0L); nMark < GetMarkedObjectCount(); nMark++)
1490 		{
1491 			SdrObject* pMark = GetMarkedObjectByIndex(nMark);
1492 			basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly());
1493 			aR.expand(basegfx::tools::getRange(aXPP));
1494 		}
1495 
1496 		basegfx::B2DPoint aCenter(aR.getCenter());
1497         long	  nMarkHgt = basegfx::fround(aR.getHeight()) - 1;
1498 		long	  nHgt	   = nMarkHgt + nObjDst * 2;
1499 
1500 		if (nHgt < nMinLen) nHgt = nMinLen;
1501 
1502 		long nY1 = basegfx::fround(aCenter.getY()) - (nHgt + 1) / 2;
1503 		long nY2 = nY1 + nHgt;
1504 
1505 		if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt;
1506 		if (pOut)
1507 		{
1508 			if (nY1 < nOutMin)
1509 			{
1510 				nY1 = nOutMin;
1511 				if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen;
1512 			}
1513 			if (nY2 > nOutMax)
1514 			{
1515 				nY2 = nOutMax;
1516 				if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen;
1517 			}
1518 		}
1519 
1520         aRef1.X() = basegfx::fround(aR.getMinX());    // Initial Achse um 2/100mm nach links
1521 		aRef1.Y() = nY1;
1522         aRef2.X() = aRef1.X();
1523 		aRef2.Y() = nY2;
1524 
1525 		// Markierungen einschalten
1526 		SetMarkHandles();
1527 
1528 		//HMHif (bVis) ShowMarkHdl();
1529 		if (AreObjectsMarked()) MarkListHasChanged();
1530 
1531 		// SpiegelPolygone SOFORT zeigen
1532 		const SdrHdlList &aHdlList = GetHdlList();
1533 		mpMirrorOverlay = new Impl3DMirrorConstructOverlay(*this);
1534 		mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(HDL_REF1)->GetPos(), aHdlList.GetHdl(HDL_REF2)->GetPos());
1535 		//CreateMirrorPolygons ();
1536 		//ShowMirrorPolygons (aHdlList.GetHdl (HDL_REF1)->GetPos (),
1537 		//					aHdlList.GetHdl (HDL_REF2)->GetPos ());
1538 	}
1539 }
1540 
1541 /*************************************************************************
1542 |*
1543 |* was passiert bei einer Mausbewegung, wenn das Objekt erstellt wird ?
1544 |*
1545 \************************************************************************/
1546 
MovAction(const Point & rPnt)1547 void E3dView::MovAction(const Point& rPnt)
1548 {
1549     if(Is3DRotationCreationActive())
1550 	{
1551 		SdrHdl* pHdl = GetDragHdl();
1552 
1553 		if (pHdl)
1554 		{
1555 			SdrHdlKind eHdlKind = pHdl->GetKind();
1556 
1557 			// reagiere nur bei einer spiegelachse
1558 			if ((eHdlKind == HDL_REF1) ||
1559 				(eHdlKind == HDL_REF2) ||
1560 				(eHdlKind == HDL_MIRX))
1561 			{
1562 				const SdrHdlList &aHdlList = GetHdlList ();
1563 
1564 				// loesche das gespiegelte Polygon, spiegele das Original und zeichne es neu
1565                 //ShowMirrored ();
1566                 SdrView::MovAction (rPnt);
1567 				mpMirrorOverlay->SetMirrorAxis(
1568 					aHdlList.GetHdl (HDL_REF1)->GetPos(),
1569 					aHdlList.GetHdl (HDL_REF2)->GetPos());
1570             }
1571 		}
1572         else
1573         {
1574             SdrView::MovAction (rPnt);
1575         }
1576 	}
1577     else
1578     {
1579         SdrView::MovAction (rPnt);
1580     }
1581 }
1582 
1583 /*************************************************************************
1584 |*
1585 |* Schluss. Objekt und evtl. Unterobjekte ueber ImpCreate3DLathe erstellen
1586 |*          [FG] Mit dem Parameterwert sal_True (SDefault: sal_False) wird einfach ein
1587 |*               Rotationskoerper erzeugt, ohne den Benutzer die Lage der
1588 |*               Achse fetlegen zu lassen. Es reicht dieser Aufruf, falls
1589 |*               ein Objekt selektiert ist. (keine Initialisierung noetig)
1590 |*
1591 \************************************************************************/
1592 
End3DCreation(sal_Bool bUseDefaultValuesForMirrorAxes)1593 void E3dView::End3DCreation(sal_Bool bUseDefaultValuesForMirrorAxes)
1594 {
1595 	ResetCreationActive();
1596 
1597 	if(AreObjectsMarked())
1598 	{
1599 		if(bUseDefaultValuesForMirrorAxes)
1600 		{
1601 			Rectangle aRect = GetAllMarkedRect();
1602 			if(aRect.GetWidth() <= 1)
1603 				aRect.SetSize(Size(500, aRect.GetHeight()));
1604 			if(aRect.GetHeight() <= 1)
1605 				aRect.SetSize(Size(aRect.GetWidth(), 500));
1606 
1607 			basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top());
1608 			basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom());
1609 
1610 			ConvertMarkedObjTo3D(sal_False, aPnt1, aPnt2);
1611 		}
1612 		else
1613 		{
1614 			// Hilfsfigur ausschalten
1615 		    // bestimme aus den Handlepositionen und den Versatz der Punkte
1616             const SdrHdlList &aHdlList = GetHdlList();
1617     		Point aMirrorRef1 = aHdlList.GetHdl(HDL_REF1)->GetPos();
1618 	    	Point aMirrorRef2 = aHdlList.GetHdl(HDL_REF2)->GetPos();
1619 
1620 			basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y());
1621 			basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y());
1622 
1623 			ConvertMarkedObjTo3D(sal_False, aPnt1, aPnt2);
1624 		}
1625 	}
1626 }
1627 
1628 /*************************************************************************
1629 |*
1630 |* Destruktor
1631 |*
1632 \************************************************************************/
1633 
~E3dView()1634 E3dView::~E3dView ()
1635 {
1636 }
1637 
1638 /*************************************************************************
1639 |*
1640 |* beende das erzeugen und loesche die polygone
1641 |*
1642 \************************************************************************/
1643 
ResetCreationActive()1644 void E3dView::ResetCreationActive ()
1645 {
1646 	if(mpMirrorOverlay)
1647 	{
1648 		delete mpMirrorOverlay;
1649 		mpMirrorOverlay = 0L;
1650 	}
1651 }
1652 
1653 /*************************************************************************
1654 |*
1655 |* Klasse initialisieren
1656 |*
1657 \************************************************************************/
1658 
InitView()1659 void E3dView::InitView ()
1660 {
1661 	eDragConstraint 		 = E3DDRAG_CONSTR_XYZ;
1662 	fDefaultScaleX			 =
1663 	fDefaultScaleY			 =
1664 	fDefaultScaleZ			 = 1.0;
1665 	fDefaultRotateX 		 =
1666 	fDefaultRotateY 		 =
1667 	fDefaultRotateZ 		 = 0.0;
1668 	fDefaultExtrusionDeepth  = 1000; // old: 2000;
1669 	fDefaultLightIntensity	 = 0.8; // old: 0.6;
1670 	fDefaultAmbientIntensity = 0.4;
1671     nHDefaultSegments        = 12;
1672     nVDefaultSegments        = 12;
1673     aDefaultLightColor       = RGB_Color(COL_WHITE);
1674     aDefaultAmbientColor     = RGB_Color(COL_BLACK);
1675     bDoubleSided             = sal_False;
1676 	mpMirrorOverlay = 0L;
1677 }
1678 
1679 /*************************************************************************
1680 |*
1681 |* Koennen die selektierten Objekte aufgebrochen werden?
1682 |*
1683 \************************************************************************/
1684 
IsBreak3DObjPossible() const1685 sal_Bool E3dView::IsBreak3DObjPossible() const
1686 {
1687     sal_uIntPtr nCount = GetMarkedObjectCount();
1688 
1689     if (nCount > 0)
1690     {
1691         sal_uIntPtr i = 0;
1692 
1693         while (i < nCount)
1694         {
1695             SdrObject* pObj = GetMarkedObjectByIndex(i);
1696 
1697             if (pObj && pObj->ISA(E3dObject))
1698             {
1699                 if(!(((E3dObject*)pObj)->IsBreakObjPossible()))
1700                     return sal_False;
1701             }
1702             else
1703             {
1704                 return sal_False;
1705             }
1706 
1707             i++;
1708         }
1709     }
1710     else
1711     {
1712         return sal_False;
1713     }
1714 
1715     return sal_True;
1716 }
1717 
1718 /*************************************************************************
1719 |*
1720 |* Selektierte Lathe-Objekte aufbrechen
1721 |*
1722 \************************************************************************/
1723 
Break3DObj()1724 void E3dView::Break3DObj()
1725 {
1726 	if(IsBreak3DObjPossible())
1727 	{
1728 		// ALLE selektierten Objekte werden gewandelt
1729 	    sal_uInt32 nCount = GetMarkedObjectCount();
1730 
1731 		BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE)));
1732 		for(sal_uInt32 a=0;a<nCount;a++)
1733 		{
1734 			E3dObject* pObj = (E3dObject*)GetMarkedObjectByIndex(a);
1735 			BreakSingle3DObj(pObj);
1736 		}
1737 		DeleteMarked();
1738 		EndUndo();
1739 	}
1740 }
1741 
BreakSingle3DObj(E3dObject * pObj)1742 void E3dView::BreakSingle3DObj(E3dObject* pObj)
1743 {
1744 	if(pObj->ISA(E3dScene))
1745 	{
1746 		SdrObjList* pSubList = pObj->GetSubList();
1747 		SdrObjListIter aIter(*pSubList, IM_FLAT);
1748 
1749 		while(aIter.IsMore())
1750 		{
1751 			E3dObject* pSubObj = (E3dObject*)aIter.Next();
1752 			BreakSingle3DObj(pSubObj);
1753 		}
1754 	}
1755 	else
1756 	{
1757 		SdrAttrObj* pNewObj = pObj->GetBreakObj();
1758 		if(pNewObj)
1759 		{
1760 			InsertObjectAtView(pNewObj, *GetSdrPageView(), SDRINSERT_DONTMARK);
1761 			pNewObj->SetChanged();
1762 			pNewObj->BroadcastObjectChange();
1763 		}
1764 	}
1765 }
1766 
1767 /*************************************************************************
1768 |*
1769 |* Szenen mischen
1770 |*
1771 \************************************************************************/
1772 
MergeScenes()1773 void E3dView::MergeScenes ()
1774 {
1775     sal_uIntPtr nCount = GetMarkedObjectCount();
1776 
1777     if (nCount > 0)
1778     {
1779         sal_uIntPtr     nObj    = 0;
1780         SdrObject *pObj   = GetMarkedObjectByIndex(nObj);
1781 		E3dScene  *pScene = new E3dPolyScene(Get3DDefaultAttributes());
1782         basegfx::B3DRange aBoundVol;
1783         Rectangle aAllBoundRect (GetMarkedObjBoundRect ());
1784 		Point     aCenter (aAllBoundRect.Center());
1785 
1786         while (pObj)
1787         {
1788             if (pObj->ISA(E3dScene))
1789             {
1790                 /**********************************************************
1791                 * Es ist eine 3D-Scene oder 3D-PolyScene
1792                 **********************************************************/
1793                 SdrObjList* pSubList = ((E3dObject*) pObj)->GetSubList();
1794 
1795                 SdrObjListIter aIter(*pSubList, IM_FLAT);
1796 
1797                 while (aIter.IsMore())
1798                 {
1799                     /******************************************************
1800                     * LatheObjekte suchen
1801                     ******************************************************/
1802                     SdrObject* pSubObj = aIter.Next();
1803 
1804                         E3dObject *pNewObj = 0;
1805 
1806                         switch (pSubObj->GetObjIdentifier())
1807                         {
1808 			                case E3D_CUBEOBJ_ID	:
1809 								pNewObj = new E3dCubeObj;
1810 								*(E3dCubeObj*)pNewObj = *(E3dCubeObj*)pSubObj;
1811 				                break;
1812 
1813 			                case E3D_SPHEREOBJ_ID:
1814 								pNewObj = new E3dSphereObj;
1815 								*(E3dSphereObj*)pNewObj = *(E3dSphereObj*)pSubObj;
1816 				                break;
1817 
1818 			                case E3D_EXTRUDEOBJ_ID:
1819 								pNewObj = new E3dExtrudeObj;
1820 								*(E3dExtrudeObj*)pNewObj = *(E3dExtrudeObj*)pSubObj;
1821 				                break;
1822 
1823 			                case E3D_LATHEOBJ_ID:
1824 								pNewObj = new E3dLatheObj;
1825 								*(E3dLatheObj*)pNewObj = *(E3dLatheObj*)pSubObj;
1826 				                break;
1827 
1828                             case E3D_COMPOUNDOBJ_ID:
1829 								pNewObj = new E3dCompoundObject;
1830 								*(E3dCompoundObject*)pNewObj = *(E3dCompoundObject*)pSubObj;
1831 				                break;
1832                         }
1833 
1834                         Rectangle aBoundRect = pSubObj->GetCurrentBoundRect();
1835 
1836             			basegfx::B3DHomMatrix aMatrix;
1837             			aMatrix.translate(aBoundRect.Left() - aCenter.getX(), aCenter.getY(), 0.0);
1838 			            pNewObj->SetTransform(aMatrix * pNewObj->GetTransform()); // #112587#
1839 
1840                         if (pNewObj) aBoundVol.expand(pNewObj->GetBoundVolume());
1841 						pScene->Insert3DObj (pNewObj);
1842 				}
1843             }
1844 
1845             nObj++;
1846 
1847             if (nObj < nCount)
1848             {
1849                 pObj = GetMarkedObjectByIndex(nObj);
1850             }
1851             else
1852             {
1853                 pObj = NULL;
1854             }
1855         }
1856 
1857 	    double fW = aAllBoundRect.GetWidth();
1858 	    double fH = aAllBoundRect.GetHeight();
1859 	    Rectangle aRect(0,0, (long) fW, (long) fH);
1860 
1861 	    InitScene(pScene, fW, fH, aBoundVol.getMaxZ() +  + ((fW + fH) / 4.0));
1862 	    pScene->NbcSetSnapRect(aRect);
1863 
1864         Camera3D &aCamera  = (Camera3D&) pScene->GetCamera ();
1865 		basegfx::B3DPoint aMinVec(aBoundVol.getMinimum());
1866         basegfx::B3DPoint aMaxVec(aBoundVol.getMaximum());
1867         double fDeepth(fabs(aMaxVec.getZ() - aMinVec.getZ()));
1868 
1869         aCamera.SetPRP(basegfx::B3DPoint(0.0, 0.0, 1000.0));
1870 		double fDefaultCamPosZ(GetDefaultCamPosZ());
1871 		aCamera.SetPosition(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ + fDeepth / 2.0));
1872 	    aCamera.SetFocalLength(GetDefaultCamFocal());
1873         pScene->SetCamera (aCamera);
1874 
1875 		// SnapRects der Objekte ungueltig
1876 		pScene->SetRectsDirty();
1877 
1878 		InsertObjectAtView(pScene, *(GetSdrPageViewOfMarkedByIndex(0)));
1879 
1880 		// SnapRects der Objekte ungueltig
1881 		pScene->SetRectsDirty();
1882     }
1883 }
1884 
1885 /*************************************************************************
1886 |*
1887 |* Possibilities, hauptsaechlich gruppieren/ungruppieren
1888 |*
1889 \************************************************************************/
CheckPossibilities()1890 void E3dView::CheckPossibilities()
1891 {
1892 	// call parent
1893 	SdrView::CheckPossibilities();
1894 
1895 	// Weitere Flags bewerten
1896 	if(bGroupPossible || bUnGroupPossible || bGrpEnterPossible)
1897 	{
1898 		sal_Int32 nMarkCnt = GetMarkedObjectCount();
1899 		sal_Bool bCoumpound = sal_False;
1900 		sal_Bool b3DObject = sal_False;
1901 		for(sal_Int32 nObjs = 0L; (nObjs < nMarkCnt) && !bCoumpound; nObjs++)
1902 		{
1903 			SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1904 			if(pObj && pObj->ISA(E3dCompoundObject))
1905 				bCoumpound = sal_True;
1906 			if(pObj && pObj->ISA(E3dObject))
1907 				b3DObject = sal_True;
1908 		}
1909 
1910 		// Bisher: Es sind ZWEI oder mehr beliebiger Objekte selektiert.
1911 		// Nachsehen, ob CompoundObjects beteiligt sind. Falls ja,
1912 		// das Gruppieren verbieten.
1913 		if(bGroupPossible && bCoumpound)
1914 			bGroupPossible = sal_False;
1915 
1916 		if(bUnGroupPossible && b3DObject)
1917 			bUnGroupPossible = sal_False;
1918 
1919 		if(bGrpEnterPossible && bCoumpound)
1920 			bGrpEnterPossible = sal_False;
1921 	}
1922 }
1923 
1924 // eof
1925