Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <vcl/wrkwin.hxx>
22 : #include <svx/svdogrp.hxx>
23 : #include <svx/svdopath.hxx>
24 : #include "svx/svditer.hxx"
25 : #include <svx/svdpool.hxx>
26 : #include <svx/svdorect.hxx>
27 : #include <svx/svdmodel.hxx>
28 : #include <svx/svdpagv.hxx>
29 : #include <svx/svxids.hrc>
30 : #include <editeng/colritem.hxx>
31 : #include <svx/xtable.hxx>
32 : #include <svx/svdview.hxx>
33 : #include <svx/dialogs.hrc>
34 : #include <svx/dialmgr.hxx>
35 : #include "svx/globl3d.hxx"
36 : #include <svx/obj3d.hxx>
37 : #include <svx/lathe3d.hxx>
38 : #include <svx/sphere3d.hxx>
39 : #include <svx/extrud3d.hxx>
40 : #include <svx/cube3d.hxx>
41 : #include <svx/polysc3d.hxx>
42 : #include "dragmt3d.hxx"
43 : #include <svx/view3d.hxx>
44 : #include <svx/svdundo.hxx>
45 : #include <svx/xflclit.hxx>
46 : #include <svx/xlnclit.hxx>
47 : #include <svx/svdograf.hxx>
48 : #include <svx/xbtmpit.hxx>
49 : #include <svx/xflbmtit.hxx>
50 : #include <basegfx/range/b2drange.hxx>
51 : #include <basegfx/polygon/b2dpolygontools.hxx>
52 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
53 : #include <svx/xlnwtit.hxx>
54 : #include <svx/sdr/overlay/overlaypolypolygon.hxx>
55 : #include <svx/sdr/overlay/overlaymanager.hxx>
56 : #include <svx/sdrpaintwindow.hxx>
57 : #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
58 : #include <drawinglayer/geometry/viewinformation3d.hxx>
59 : #include <svx/sdrpagewindow.hxx>
60 : #include <svx/sdr/contact/displayinfo.hxx>
61 : #include <svx/sdr/contact/objectcontact.hxx>
62 : #include <svx/sdr/contact/viewobjectcontact.hxx>
63 : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
64 : #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
65 : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
66 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
67 : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
68 :
69 : using namespace com::sun::star;
70 :
71 : #define ITEMVALUE(ItemSet,Id,Cast) (static_cast<const Cast&>((ItemSet).Get(Id))).GetValue()
72 :
73 20145 : TYPEINIT1(E3dView, SdrView);
74 :
75 :
76 : // Migrate Marking
77 :
78 : class Impl3DMirrorConstructOverlay
79 : {
80 : // The OverlayObjects
81 : ::sdr::overlay::OverlayObjectList maObjects;
82 :
83 : // the view
84 : const E3dView& mrView;
85 :
86 : // the object count
87 : size_t mnCount;
88 :
89 : // the unmirrored polygons
90 : basegfx::B2DPolyPolygon* mpPolygons;
91 :
92 : // the overlay geometry from selected objects
93 : drawinglayer::primitive2d::Primitive2DSequence maFullOverlay;
94 :
95 : public:
96 : Impl3DMirrorConstructOverlay(const E3dView& rView);
97 : ~Impl3DMirrorConstructOverlay();
98 :
99 : void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB);
100 : };
101 :
102 0 : Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView)
103 : : maObjects(),
104 : mrView(rView),
105 0 : mnCount(rView.GetMarkedObjectCount()),
106 : mpPolygons(0),
107 0 : maFullOverlay()
108 : {
109 0 : if(mnCount)
110 : {
111 0 : if(mrView.IsSolidDragging())
112 : {
113 0 : SdrPageView* pPV = rView.GetSdrPageView();
114 :
115 0 : if(pPV && pPV->PageWindowCount())
116 : {
117 0 : sdr::contact::ObjectContact& rOC = pPV->GetPageWindow(0)->GetObjectContact();
118 0 : sdr::contact::DisplayInfo aDisplayInfo;
119 :
120 : // Do not use the last ViewPort set at the OC at the last ProcessDisplay()
121 0 : rOC.resetViewPort();
122 :
123 0 : for(size_t a = 0; a < mnCount; ++a)
124 : {
125 0 : SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
126 :
127 0 : if(pObject)
128 : {
129 0 : sdr::contact::ViewContact& rVC = pObject->GetViewContact();
130 0 : sdr::contact::ViewObjectContact& rVOC = rVC.GetViewObjectContact(rOC);
131 :
132 0 : const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(rVOC.getPrimitive2DSequenceHierarchy(aDisplayInfo));
133 0 : drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(maFullOverlay, aNewSequence);
134 : }
135 0 : }
136 : }
137 : }
138 : else
139 : {
140 0 : mpPolygons = new basegfx::B2DPolyPolygon[mnCount];
141 :
142 0 : for(size_t a = 0; a < mnCount; ++a)
143 : {
144 0 : SdrObject* pObject = mrView.GetMarkedObjectByIndex(a);
145 0 : mpPolygons[mnCount - (a + 1)] = pObject->TakeXorPoly();
146 : }
147 : }
148 : }
149 0 : }
150 :
151 0 : Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
152 : {
153 : // The OverlayObjects are cleared using the destructor of OverlayObjectList.
154 : // That destructor calls clear() at the list which removes all objects from the
155 : // OverlayManager and deletes them.
156 0 : if(!mrView.IsSolidDragging())
157 : {
158 0 : delete[] mpPolygons;
159 : }
160 0 : }
161 :
162 0 : void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
163 : {
164 : // get rid of old overlay objects
165 0 : maObjects.clear();
166 :
167 : // create new ones
168 0 : for(sal_uInt32 a(0); a < mrView.PaintWindowCount(); a++)
169 : {
170 0 : SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a);
171 0 : rtl::Reference< ::sdr::overlay::OverlayManager > xTargetOverlay = pCandidate->GetOverlayManager();
172 :
173 0 : if(xTargetOverlay.is())
174 : {
175 : // buld transfoprmation: translate and rotate so that given edge is
176 : // on x axis, them mirror in y and translate back
177 0 : const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y());
178 : basegfx::B2DHomMatrix aMatrixTransform(basegfx::tools::createTranslateB2DHomMatrix(
179 0 : -aMirrorAxisA.X(), -aMirrorAxisA.Y()));
180 0 : aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
181 0 : aMatrixTransform.scale(1.0, -1.0);
182 0 : aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX()));
183 0 : aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y());
184 :
185 0 : if(mrView.IsSolidDragging())
186 : {
187 0 : if(maFullOverlay.hasElements())
188 : {
189 0 : drawinglayer::primitive2d::Primitive2DSequence aContent(maFullOverlay);
190 :
191 0 : if(!aMatrixTransform.isIdentity())
192 : {
193 : // embed in transformation group
194 0 : drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform, aContent));
195 0 : aContent = drawinglayer::primitive2d::Primitive2DSequence(&aTransformPrimitive2D, 1);
196 : }
197 :
198 : // if we have full overlay from selected objects, embed with 50% transparence, the
199 : // transformation is added to the OverlayPrimitive2DSequenceObject
200 0 : drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(aContent, 0.5));
201 0 : aContent = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparencePrimitive2D, 1);
202 :
203 0 : sdr::overlay::OverlayPrimitive2DSequenceObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aContent);
204 :
205 0 : xTargetOverlay->add(*pNew);
206 0 : maObjects.append(*pNew);
207 : }
208 : }
209 : else
210 : {
211 0 : for(size_t b = 0; b < mnCount; ++b)
212 : {
213 : // apply to polygon
214 0 : basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]);
215 0 : aPolyPolygon.transform(aMatrixTransform);
216 :
217 : ::sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
218 0 : aPolyPolygon);
219 0 : xTargetOverlay->add(*pNew);
220 0 : maObjects.append(*pNew);
221 0 : }
222 0 : }
223 : }
224 0 : }
225 0 : }
226 :
227 7010 : E3dView::E3dView(SdrModel* pModel, OutputDevice* pOut) :
228 7010 : SdrView(pModel, pOut)
229 : {
230 7010 : InitView ();
231 7010 : }
232 :
233 : // DrawMarkedObj overloaded, since possibly only a single 3D object is to be
234 : // drawn
235 :
236 516 : void E3dView::DrawMarkedObj(OutputDevice& rOut) const
237 : {
238 : // Does 3D objects exist which scenes are not selected?
239 516 : bool bSpecialHandling = false;
240 516 : E3dScene *pScene = NULL;
241 :
242 516 : const size_t nCnt = GetMarkedObjectCount();
243 1032 : for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
244 : {
245 516 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
246 516 : if(pObj && pObj->ISA(E3dCompoundObject))
247 : {
248 : // related scene
249 0 : pScene = static_cast<E3dCompoundObject*>(pObj)->GetScene();
250 0 : if(pScene && !IsObjMarked(pScene))
251 0 : bSpecialHandling = true;
252 : }
253 : // Reset all selection flags
254 516 : if(pObj && pObj->ISA(E3dObject))
255 : {
256 0 : pScene = static_cast<E3dObject*>(pObj)->GetScene();
257 0 : if(pScene)
258 0 : pScene->SetSelected(false);
259 : }
260 : }
261 :
262 516 : if(bSpecialHandling)
263 : {
264 : // Set selection flag to "not selected" for scenes related to all 3D
265 : // objects
266 0 : for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
267 : {
268 0 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
269 0 : if(pObj && pObj->ISA(E3dCompoundObject))
270 : {
271 : // relatated scene
272 0 : pScene = static_cast<E3dCompoundObject*>(pObj)->GetScene();
273 0 : if(pScene)
274 0 : pScene->SetSelected(false);
275 : }
276 : }
277 :
278 0 : for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
279 : {
280 0 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
281 0 : if(pObj && pObj->ISA(E3dObject))
282 : {
283 : // Select object
284 0 : E3dObject* p3DObj = static_cast<E3dObject*>(pObj);
285 0 : p3DObj->SetSelected(true);
286 0 : pScene = p3DObj->GetScene();
287 : }
288 : }
289 :
290 0 : if(pScene)
291 : {
292 : // code from parent
293 0 : SortMarkedObjects();
294 :
295 0 : pScene->SetDrawOnlySelected(true);
296 0 : pScene->SingleObjectPainter(rOut);
297 0 : pScene->SetDrawOnlySelected(false);
298 : }
299 :
300 : // Reset selection flag
301 0 : for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
302 : {
303 0 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
304 0 : if(pObj && pObj->ISA(E3dCompoundObject))
305 : {
306 : // releated scene
307 0 : pScene = static_cast<E3dCompoundObject*>(pObj)->GetScene();
308 0 : if(pScene)
309 0 : pScene->SetSelected(false);
310 : }
311 : }
312 : }
313 : else
314 : {
315 : // call parent
316 516 : SdrExchangeView::DrawMarkedObj(rOut);
317 : }
318 516 : }
319 :
320 : // Get overloaded model, since in some 3D objects an additional scene
321 : // must be pushed in
322 :
323 0 : SdrModel* E3dView::GetMarkedObjModel() const
324 : {
325 : // Does 3D objects exist which scenes are not selected?
326 0 : bool bSpecialHandling(false);
327 0 : const size_t nCount(GetMarkedObjectCount());
328 0 : E3dScene *pScene = 0;
329 :
330 0 : for(size_t nObjs = 0; nObjs < nCount; ++nObjs)
331 : {
332 0 : const SdrObject* pObj = GetMarkedObjectByIndex(nObjs);
333 :
334 0 : if(!bSpecialHandling && pObj && pObj->ISA(E3dCompoundObject))
335 : {
336 : // if the object is selected, but it's scene not,
337 : // we need special handling
338 0 : pScene = static_cast<const E3dCompoundObject*>(pObj)->GetScene();
339 :
340 0 : if(pScene && !IsObjMarked(pScene))
341 : {
342 0 : bSpecialHandling = true;
343 : }
344 : }
345 :
346 0 : if(pObj && pObj->ISA(E3dObject))
347 : {
348 : // reset all selection flags at 3D objects
349 0 : pScene = static_cast<const E3dObject*>(pObj)->GetScene();
350 :
351 0 : if(pScene)
352 : {
353 0 : pScene->SetSelected(false);
354 : }
355 : }
356 : }
357 :
358 0 : if(!bSpecialHandling)
359 : {
360 : // call parent
361 0 : return SdrView::GetMarkedObjModel();
362 : }
363 :
364 0 : SdrModel* pNewModel = 0;
365 0 : Rectangle aSelectedSnapRect;
366 :
367 : // set 3d selection flags at all directly selected objects
368 : // and collect SnapRect of selected objects
369 0 : for(size_t nObjs = 0; nObjs < nCount; ++nObjs)
370 : {
371 0 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
372 :
373 0 : if(pObj && pObj->ISA(E3dCompoundObject))
374 : {
375 : // mark object, but not scenes
376 0 : E3dCompoundObject* p3DObj = static_cast<E3dCompoundObject*>(pObj);
377 0 : p3DObj->SetSelected(true);
378 0 : aSelectedSnapRect.Union(p3DObj->GetSnapRect());
379 : }
380 : }
381 :
382 : // create new mark list which contains all indirectly selected3d
383 : // scenes as selected objects
384 0 : SdrMarkList aOldML(GetMarkedObjectList());
385 0 : SdrMarkList aNewML;
386 0 : SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess();
387 0 : rCurrentMarkList = aNewML;
388 :
389 0 : for(size_t nObjs = 0; nObjs < nCount; ++nObjs)
390 : {
391 0 : SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj();
392 :
393 0 : if(pObj && pObj->ISA(E3dObject))
394 : {
395 0 : pScene = static_cast<E3dObject*>(pObj)->GetScene();
396 :
397 0 : if(pScene && !IsObjMarked(pScene) && GetSdrPageView())
398 : {
399 0 : ((E3dView*)this)->MarkObj(pScene, GetSdrPageView(), false, true);
400 : }
401 : }
402 : }
403 :
404 : // call parent. This will copy all scenes and the selection flags at the 3d objectss. So
405 : // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes
406 0 : pNewModel = SdrView::GetMarkedObjModel();
407 :
408 0 : if(pNewModel)
409 : {
410 0 : for(sal_uInt16 nPg(0); nPg < pNewModel->GetPageCount(); nPg++)
411 : {
412 0 : const SdrPage* pSrcPg=pNewModel->GetPage(nPg);
413 0 : const size_t nObAnz(pSrcPg->GetObjCount());
414 :
415 0 : for(size_t nOb = 0; nOb < nObAnz; ++nOb)
416 : {
417 0 : const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
418 :
419 0 : if(pSrcOb->ISA(E3dScene))
420 : {
421 0 : pScene = const_cast<E3dScene*>(static_cast<const E3dScene*>(pSrcOb));
422 :
423 : // delete all not intentionally cloned 3d objects
424 0 : pScene->removeAllNonSelectedObjects();
425 :
426 : // reset select flags and set SnapRect of all selected objects
427 0 : pScene->SetSelected(false);
428 0 : pScene->SetSnapRect(aSelectedSnapRect);
429 : }
430 : }
431 : }
432 : }
433 :
434 : // restore old selection
435 0 : rCurrentMarkList = aOldML;
436 :
437 0 : return pNewModel;
438 : }
439 :
440 : // When pasting objects have to integrated if a scene is inserted, but
441 : // not the scene itself
442 :
443 0 : bool E3dView::Paste(
444 : const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions,
445 : const OUString& rSrcShellID, const OUString& rDestShellID )
446 : {
447 0 : bool bRetval = false;
448 :
449 : // Get list
450 0 : Point aPos(rPos);
451 0 : SdrObjList* pDstList = pLst;
452 0 : ImpGetPasteObjList(aPos, pDstList);
453 :
454 0 : if(!pDstList)
455 0 : return false;
456 :
457 : // Get owner of the list
458 0 : SdrObject* pOwner = pDstList->GetOwnerObj();
459 0 : if(pOwner && pOwner->ISA(E3dScene))
460 : {
461 0 : E3dScene* pDstScene = static_cast<E3dScene*>(pOwner);
462 0 : BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE));
463 :
464 : // Copy all objects from E3dScenes and insert them directly
465 0 : for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++)
466 : {
467 0 : const SdrPage* pSrcPg=rMod.GetPage(nPg);
468 0 : const size_t nObAnz(pSrcPg->GetObjCount());
469 :
470 : // calculate offset for paste
471 0 : Rectangle aR = pSrcPg->GetAllObjBoundRect();
472 0 : Point aDist(aPos - aR.Center());
473 :
474 : // Insert sub-objects for scenes
475 0 : for(size_t nOb = 0; nOb < nObAnz; ++nOb)
476 : {
477 0 : const SdrObject* pSrcOb = pSrcPg->GetObj(nOb);
478 0 : if(pSrcOb->ISA(E3dScene))
479 : {
480 0 : E3dScene* pSrcScene = const_cast<E3dScene*>(static_cast<const E3dScene*>(pSrcOb));
481 0 : ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist);
482 : }
483 : }
484 : }
485 0 : EndUndo();
486 : }
487 : else
488 : {
489 : // call parent
490 0 : bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions, rSrcShellID, rDestShellID);
491 : }
492 :
493 0 : return bRetval;
494 : }
495 :
496 : // Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
497 0 : bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point /*aOffset*/)
498 : {
499 0 : bool bRetval(false);
500 :
501 0 : if(pSrcScene && pDstScene)
502 : {
503 0 : const sdr::contact::ViewContactOfE3dScene& rVCSceneDst = static_cast< sdr::contact::ViewContactOfE3dScene& >(pDstScene->GetViewContact());
504 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3DDst(rVCSceneDst.getViewInformation3D());
505 0 : const sdr::contact::ViewContactOfE3dScene& rVCSceneSrc = static_cast< sdr::contact::ViewContactOfE3dScene& >(pSrcScene->GetViewContact());
506 0 : const drawinglayer::geometry::ViewInformation3D aViewInfo3DSrc(rVCSceneSrc.getViewInformation3D());
507 :
508 0 : for(size_t i = 0; i < pSrcScene->GetSubList()->GetObjCount(); ++i)
509 : {
510 0 : E3dCompoundObject* pCompoundObj = dynamic_cast< E3dCompoundObject* >(pSrcScene->GetSubList()->GetObj(i));
511 :
512 0 : if(pCompoundObj)
513 : {
514 0 : E3dCompoundObject* pNewCompoundObj = dynamic_cast< E3dCompoundObject* >(pCompoundObj->Clone());
515 :
516 0 : if(pNewCompoundObj)
517 : {
518 : // get dest scene's current range in 3D world coordinates
519 0 : const basegfx::B3DHomMatrix aSceneToWorldTrans(pDstScene->GetFullTransform());
520 0 : basegfx::B3DRange aSceneRange(pDstScene->GetBoundVolume());
521 0 : aSceneRange.transform(aSceneToWorldTrans);
522 :
523 : // get new object's implied object transformation
524 0 : const basegfx::B3DHomMatrix aNewObjectTrans(pNewCompoundObj->GetTransform());
525 :
526 : // get new object's range in 3D world coordinates in dest scene
527 : // as if it were already added
528 0 : const basegfx::B3DHomMatrix aObjectToWorldTrans(aSceneToWorldTrans * aNewObjectTrans);
529 0 : basegfx::B3DRange aObjectRange(pNewCompoundObj->GetBoundVolume());
530 0 : aObjectRange.transform(aObjectToWorldTrans);
531 :
532 : // get scale adaption
533 0 : const basegfx::B3DVector aSceneScale(aSceneRange.getRange());
534 0 : const basegfx::B3DVector aObjectScale(aObjectRange.getRange());
535 0 : double fScale(1.0);
536 :
537 : // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
538 : // to not change the scene by the inserted object
539 0 : const double fSizeFactor(0.5);
540 :
541 0 : if(aObjectScale.getX() * fScale > aSceneScale.getX() * fSizeFactor)
542 : {
543 0 : const double fObjSize(aObjectScale.getX() * fScale);
544 0 : const double fFactor((aSceneScale.getX() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
545 0 : fScale *= fFactor;
546 : }
547 :
548 0 : if(aObjectScale.getY() * fScale > aSceneScale.getY() * fSizeFactor)
549 : {
550 0 : const double fObjSize(aObjectScale.getY() * fScale);
551 0 : const double fFactor((aSceneScale.getY() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
552 0 : fScale *= fFactor;
553 : }
554 :
555 0 : if(aObjectScale.getZ() * fScale > aSceneScale.getZ() * fSizeFactor)
556 : {
557 0 : const double fObjSize(aObjectScale.getZ() * fScale);
558 0 : const double fFactor((aSceneScale.getZ() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
559 0 : fScale *= fFactor;
560 : }
561 :
562 : // get translation adaption
563 0 : const basegfx::B3DPoint aSceneCenter(aSceneRange.getCenter());
564 0 : const basegfx::B3DPoint aObjectCenter(aObjectRange.getCenter());
565 :
566 : // build full modification transform. The object's transformation
567 : // shall be modified, so start at object coordinates; transform to 3d world coor
568 0 : basegfx::B3DHomMatrix aModifyingTransform(aObjectToWorldTrans);
569 :
570 : // translate to absolute center in 3d world coor
571 0 : aModifyingTransform.translate(-aObjectCenter.getX(), -aObjectCenter.getY(), -aObjectCenter.getZ());
572 :
573 : // scale to dest size in 3d world coor
574 0 : aModifyingTransform.scale(fScale, fScale, fScale);
575 :
576 : // translate to dest scene center in 3d world coor
577 0 : aModifyingTransform.translate(aSceneCenter.getX(), aSceneCenter.getY(), aSceneCenter.getZ());
578 :
579 : // transform from 3d world to dest object coordinates
580 0 : basegfx::B3DHomMatrix aWorldToObject(aObjectToWorldTrans);
581 0 : aWorldToObject.invert();
582 0 : aModifyingTransform = aWorldToObject * aModifyingTransform;
583 :
584 : // correct implied object transform by applying changing one in object coor
585 0 : pNewCompoundObj->SetTransform(aModifyingTransform * aNewObjectTrans);
586 :
587 : // fill and insert new object
588 0 : pNewCompoundObj->SetModel(pDstScene->GetModel());
589 0 : pNewCompoundObj->SetPage(pDstScene->GetPage());
590 0 : pNewCompoundObj->NbcSetLayer(pCompoundObj->GetLayer());
591 0 : pNewCompoundObj->NbcSetStyleSheet(pCompoundObj->GetStyleSheet(), true);
592 0 : pDstScene->Insert3DObj(pNewCompoundObj);
593 0 : bRetval = true;
594 :
595 : // Create undo
596 0 : if( GetModel()->IsUndoEnabled() )
597 0 : AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj));
598 : }
599 : }
600 0 : }
601 : }
602 :
603 0 : return bRetval;
604 : }
605 :
606 4221 : bool E3dView::IsConvertTo3DObjPossible() const
607 : {
608 4221 : bool bAny3D(false);
609 4221 : bool bGroupSelected(false);
610 4221 : bool bRetval(true);
611 :
612 4223 : for(size_t a=0; !bAny3D && a<GetMarkedObjectCount(); ++a)
613 : {
614 2 : SdrObject *pObj = GetMarkedObjectByIndex(a);
615 2 : if(pObj)
616 : {
617 2 : ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected);
618 : }
619 : }
620 :
621 4221 : bRetval = !bAny3D
622 8444 : && (
623 4221 : IsConvertToPolyObjPossible(false)
624 4219 : || IsConvertToPathObjPossible(false)
625 8440 : || IsImportMtfPossible());
626 4221 : return bRetval;
627 : }
628 :
629 2 : void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, bool& rAny3D,
630 : bool& rGroupSelected) const
631 : {
632 2 : if(pObj)
633 : {
634 2 : if(pObj->ISA(E3dObject))
635 : {
636 0 : rAny3D = true;
637 : }
638 : else
639 : {
640 2 : if(pObj->IsGroupObject())
641 : {
642 0 : SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS);
643 0 : while(aIter.IsMore())
644 : {
645 0 : SdrObject* pNewObj = aIter.Next();
646 0 : ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected);
647 : }
648 0 : rGroupSelected = true;
649 : }
650 : }
651 : }
652 2 : }
653 :
654 : #include <editeng/eeitem.hxx>
655 :
656 0 : void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject* pObj)
657 : {
658 0 : if(pObj->ISA(SdrTextObj))
659 : {
660 0 : const SfxItemSet& rSet = pObj->GetMergedItemSet();
661 0 : const SvxColorItem& rTextColorItem = static_cast<const SvxColorItem&>(rSet.Get(EE_CHAR_COLOR));
662 0 : if(rTextColorItem.GetValue() == RGB_Color(COL_BLACK))
663 : {
664 : //For black text objects, the color set to gray
665 0 : if(pObj->GetPage())
666 : {
667 : // if black is only default attribute from
668 : // pattern set it hard so that it is used in undo.
669 0 : pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK), EE_CHAR_COLOR));
670 :
671 : // add undo now
672 0 : if( GetModel()->IsUndoEnabled() )
673 0 : AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
674 : }
675 :
676 0 : pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY), EE_CHAR_COLOR));
677 : }
678 : }
679 0 : }
680 :
681 0 : void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject* pObj)
682 : {
683 0 : if(pObj->ISA(SdrPathObj))
684 : {
685 0 : const SfxItemSet& rSet = pObj->GetMergedItemSet();
686 0 : sal_Int32 nLineWidth = static_cast<const XLineWidthItem&>(rSet.Get(XATTR_LINEWIDTH)).GetValue();
687 0 : XLineStyle eLineStyle = (XLineStyle)static_cast<const XLineStyleItem&>(rSet.Get(XATTR_LINESTYLE)).GetValue();
688 0 : drawing::FillStyle eFillStyle = ITEMVALUE(rSet, XATTR_FILLSTYLE, XFillStyleItem);
689 :
690 0 : if(static_cast<SdrPathObj*>(pObj)->IsClosed()
691 0 : && eLineStyle == XLINE_SOLID
692 0 : && !nLineWidth
693 0 : && eFillStyle != drawing::FillStyle_NONE)
694 : {
695 0 : if(pObj->GetPage() && GetModel()->IsUndoEnabled() )
696 0 : AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
697 0 : pObj->SetMergedItem(XLineStyleItem(XLINE_NONE));
698 0 : pObj->SetMergedItem(XLineWidthItem(0L));
699 : }
700 : }
701 0 : }
702 :
703 0 : void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
704 : {
705 : // Single PathObject, transform this
706 0 : SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
707 :
708 0 : if(pPath)
709 : {
710 0 : E3dDefaultAttributes aDefault = Get3DDefaultAttributes();
711 0 : if(bExtrude)
712 0 : aDefault.SetDefaultExtrudeCharacterMode(true);
713 : else
714 0 : aDefault.SetDefaultLatheCharacterMode(true);
715 :
716 : // Get Itemset of the original object
717 0 : SfxItemSet aSet(pObj->GetMergedItemSet());
718 :
719 0 : drawing::FillStyle eFillStyle = ITEMVALUE(aSet, XATTR_FILLSTYLE, XFillStyleItem);
720 :
721 : // line style turned off
722 0 : aSet.Put(XLineStyleItem(XLINE_NONE));
723 :
724 : //Determining if FILL_Attribut is set.
725 0 : if(!pPath->IsClosed() || eFillStyle == drawing::FillStyle_NONE)
726 : {
727 : // This SdrPathObj is not filled, leave the front and rear face out.
728 : // Moreover, a two-sided representation necessary.
729 0 : aDefault.SetDefaultExtrudeCloseFront(false);
730 0 : aDefault.SetDefaultExtrudeCloseBack(false);
731 :
732 0 : aSet.Put(makeSvx3DDoubleSidedItem(true));
733 :
734 : // Set fill attribute
735 0 : aSet.Put(XFillStyleItem(drawing::FillStyle_SOLID));
736 :
737 : // Fill color must be the color line, because the object was
738 : // previously just a line
739 0 : Color aColorLine = static_cast<const XLineColorItem&>(aSet.Get(XATTR_LINECOLOR)).GetColorValue();
740 0 : aSet.Put(XFillColorItem(OUString(), aColorLine));
741 : }
742 :
743 : // Create a new extrude object
744 0 : E3dObject* p3DObj = NULL;
745 0 : if(bExtrude)
746 : {
747 0 : p3DObj = new E3dExtrudeObj(aDefault, pPath->GetPathPoly(), fDepth);
748 : }
749 : else
750 : {
751 0 : basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly());
752 0 : aPolyPoly2D.transform(rLatheMat);
753 0 : p3DObj = new E3dLatheObj(aDefault, aPolyPoly2D);
754 : }
755 :
756 : // Set attribute
757 0 : if(p3DObj)
758 : {
759 0 : p3DObj->NbcSetLayer(pObj->GetLayer());
760 :
761 0 : p3DObj->SetMergedItemSet(aSet);
762 :
763 0 : p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), true);
764 :
765 : // Insert a new extrude object
766 0 : pScene->Insert3DObj(p3DObj);
767 0 : }
768 : }
769 0 : }
770 :
771 0 : void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, bool bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
772 : {
773 0 : if(pObj)
774 : {
775 : // change text color attribute for not so dark colors
776 0 : if(pObj->IsGroupObject())
777 : {
778 0 : SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
779 0 : while(aIter.IsMore())
780 : {
781 0 : SdrObject* pGroupMember = aIter.Next();
782 0 : ImpChangeSomeAttributesFor3DConversion(pGroupMember);
783 0 : }
784 : }
785 : else
786 0 : ImpChangeSomeAttributesFor3DConversion(pObj);
787 :
788 : // convert completely to path objects
789 0 : SdrObject* pNewObj1 = pObj->ConvertToPolyObj(false, false);
790 :
791 0 : if(pNewObj1)
792 : {
793 : // change text color attribute for not so dark colors
794 0 : if(pNewObj1->IsGroupObject())
795 : {
796 0 : SdrObjListIter aIter(*pNewObj1, IM_DEEPWITHGROUPS);
797 0 : while(aIter.IsMore())
798 : {
799 0 : SdrObject* pGroupMember = aIter.Next();
800 0 : ImpChangeSomeAttributesFor3DConversion2(pGroupMember);
801 0 : }
802 : }
803 : else
804 0 : ImpChangeSomeAttributesFor3DConversion2(pNewObj1);
805 :
806 : // convert completely to path objects
807 0 : SdrObject* pNewObj2 = pObj->ConvertToContourObj(pNewObj1, true);
808 :
809 0 : if(pNewObj2)
810 : {
811 : // add all to flat scene
812 0 : if(pNewObj2->IsGroupObject())
813 : {
814 0 : SdrObjListIter aIter(*pNewObj2, IM_DEEPWITHGROUPS);
815 0 : while(aIter.IsMore())
816 : {
817 0 : SdrObject* pGroupMember = aIter.Next();
818 0 : ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat);
819 0 : }
820 : }
821 : else
822 0 : ImpCreateSingle3DObjectFlat(pScene, pNewObj2, bExtrude, fDepth, rLatheMat);
823 :
824 : // delete object in between
825 0 : if(pNewObj2 != pObj && pNewObj2 != pNewObj1 && pNewObj2)
826 0 : SdrObject::Free( pNewObj2 );
827 : }
828 :
829 : // delete object in between
830 0 : if(pNewObj1 != pObj && pNewObj1)
831 0 : SdrObject::Free( pNewObj1 );
832 : }
833 : }
834 0 : }
835 :
836 0 : void E3dView::ConvertMarkedObjTo3D(bool bExtrude, basegfx::B2DPoint aPnt1, basegfx::B2DPoint aPnt2)
837 : {
838 0 : if(AreObjectsMarked())
839 : {
840 : // Create undo
841 0 : if(bExtrude)
842 0 : BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE));
843 : else
844 0 : BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE));
845 :
846 : // Create a new scene for the created 3D object
847 0 : E3dScene* pScene = new E3dPolyScene(Get3DDefaultAttributes());
848 :
849 : // Determine rectangle and possibly correct it
850 0 : Rectangle aRect = GetAllMarkedRect();
851 0 : if(aRect.GetWidth() <= 1)
852 0 : aRect.SetSize(Size(500, aRect.GetHeight()));
853 0 : if(aRect.GetHeight() <= 1)
854 0 : aRect.SetSize(Size(aRect.GetWidth(), 500));
855 :
856 : // Determine the depth relative to the size of the selection
857 0 : double fDepth = 0.0;
858 0 : double fRot3D = 0.0;
859 0 : basegfx::B2DHomMatrix aLatheMat;
860 :
861 0 : if(bExtrude)
862 : {
863 0 : double fW = (double)aRect.GetWidth();
864 0 : double fH = (double)aRect.GetHeight();
865 0 : fDepth = sqrt(fW*fW + fH*fH) / 6.0;
866 : }
867 0 : if(!bExtrude)
868 : {
869 : // Create transformation for the polygons rotating body
870 0 : if(aPnt1 != aPnt2)
871 : {
872 : // Rotation around control point #1 with set angle
873 : // for 3D coordinates
874 0 : basegfx::B2DPoint aDiff(aPnt1 - aPnt2);
875 0 : fRot3D = atan2(aDiff.getY(), aDiff.getX()) - F_PI2;
876 :
877 0 : if(basegfx::fTools::equalZero(fabs(fRot3D)))
878 0 : fRot3D = 0.0;
879 :
880 0 : if(fRot3D != 0.0)
881 : {
882 : aLatheMat = basegfx::tools::createRotateAroundPoint(aPnt2, -fRot3D)
883 0 : * aLatheMat;
884 0 : }
885 : }
886 :
887 0 : if(aPnt2.getX() != 0.0)
888 : {
889 : // Translation to Y=0 - axis
890 0 : aLatheMat.translate(-aPnt2.getX(), 0.0);
891 : }
892 : else
893 : {
894 0 : aLatheMat.translate((double)-aRect.Left(), 0.0);
895 : }
896 :
897 : // Form the inverse matrix to determine the target expansion
898 0 : basegfx::B2DHomMatrix aInvLatheMat(aLatheMat);
899 0 : aInvLatheMat.invert();
900 :
901 : // SnapRect extension enables mirroring in the axis of rotation
902 0 : for(size_t a=0; a<GetMarkedObjectCount(); ++a)
903 : {
904 0 : SdrMark* pMark = GetSdrMarkByIndex(a);
905 0 : SdrObject* pObj = pMark->GetMarkedSdrObj();
906 0 : Rectangle aTurnRect = pObj->GetSnapRect();
907 0 : basegfx::B2DPoint aRot;
908 0 : Point aRotPnt;
909 :
910 0 : aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top());
911 0 : aRot *= aLatheMat;
912 0 : aRot.setX(-aRot.getX());
913 0 : aRot *= aInvLatheMat;
914 0 : aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
915 0 : aRect.Union(Rectangle(aRotPnt, aRotPnt));
916 :
917 0 : aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom());
918 0 : aRot *= aLatheMat;
919 0 : aRot.setX(-aRot.getX());
920 0 : aRot *= aInvLatheMat;
921 0 : aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
922 0 : aRect.Union(Rectangle(aRotPnt, aRotPnt));
923 :
924 0 : aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top());
925 0 : aRot *= aLatheMat;
926 0 : aRot.setX(-aRot.getX());
927 0 : aRot *= aInvLatheMat;
928 0 : aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
929 0 : aRect.Union(Rectangle(aRotPnt, aRotPnt));
930 :
931 0 : aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom());
932 0 : aRot *= aLatheMat;
933 0 : aRot.setX(-aRot.getX());
934 0 : aRot *= aInvLatheMat;
935 0 : aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
936 0 : aRect.Union(Rectangle(aRotPnt, aRotPnt));
937 0 : }
938 : }
939 :
940 : // Walk through the selection and convert it into 3D, complete with
941 : // Conversion to SdrPathObject, also fonts
942 0 : for(size_t a=0; a<GetMarkedObjectCount(); ++a)
943 : {
944 0 : SdrMark* pMark = GetSdrMarkByIndex(a);
945 0 : SdrObject* pObj = pMark->GetMarkedSdrObj();
946 :
947 0 : ImpCreate3DObject(pScene, pObj, bExtrude, fDepth, aLatheMat);
948 : }
949 :
950 0 : if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0)
951 : {
952 : // Arrange all created objects by depth
953 0 : if(bExtrude)
954 0 : DoDepthArrange(pScene, fDepth);
955 :
956 : // Center 3D objects in the middle of the overall rectangle
957 0 : basegfx::B3DPoint aCenter(pScene->GetBoundVolume().getCenter());
958 0 : basegfx::B3DHomMatrix aMatrix;
959 :
960 0 : aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ());
961 0 : pScene->SetTransform(aMatrix * pScene->GetTransform());
962 :
963 : // Initialize scene
964 0 : pScene->NbcSetSnapRect(aRect);
965 0 : basegfx::B3DRange aBoundVol = pScene->GetBoundVolume();
966 0 : InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth());
967 :
968 : // Insert scene instead of the first selected object and throw away
969 : // all the old objects
970 0 : SdrObject* pRepObj = GetMarkedObjectByIndex(0);
971 0 : SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0);
972 0 : MarkObj(pRepObj, pPV, true);
973 0 : ReplaceObjectAtView(pRepObj, *pPV, pScene, false);
974 0 : DeleteMarked();
975 0 : MarkObj(pScene, pPV);
976 :
977 : // Rotate Rotation body around the axis of rotation
978 0 : basegfx::B3DHomMatrix aRotate;
979 :
980 0 : if(!bExtrude && fRot3D != 0.0)
981 : {
982 0 : aRotate.rotate(0.0, 0.0, fRot3D);
983 : }
984 :
985 : // Set default rotation
986 : {
987 0 : double XRotateDefault = 20;
988 0 : aRotate.rotate(DEG2RAD(XRotateDefault), 0.0, 0.0);
989 : }
990 :
991 0 : if(!aRotate.isIdentity())
992 : {
993 0 : pScene->SetTransform(aRotate * pScene->GetTransform());
994 : }
995 :
996 : // Invalid SnapRects of objects
997 0 : pScene->SetSnapRect(aRect);
998 : }
999 : else
1000 : {
1001 : // No 3D object was created, throw away everything
1002 0 : delete pScene;
1003 : }
1004 :
1005 0 : EndUndo();
1006 : }
1007 0 : }
1008 :
1009 : //Arrange all created extrude objects by depth
1010 :
1011 0 : struct E3dDepthNeighbour
1012 : {
1013 : E3dDepthNeighbour* mpNext;
1014 : E3dExtrudeObj* mpObj;
1015 : basegfx::B2DPolyPolygon maPreparedPolyPolygon;
1016 :
1017 0 : E3dDepthNeighbour()
1018 : : mpNext(0),
1019 : mpObj(0),
1020 0 : maPreparedPolyPolygon()
1021 : {
1022 0 : }
1023 : };
1024 :
1025 : struct E3dDepthLayer
1026 : {
1027 : E3dDepthLayer* mpDown;
1028 : E3dDepthNeighbour* mpNext;
1029 :
1030 0 : E3dDepthLayer()
1031 : : mpDown(0),
1032 0 : mpNext(0)
1033 : {
1034 0 : }
1035 :
1036 0 : ~E3dDepthLayer()
1037 : {
1038 0 : while(mpNext)
1039 : {
1040 0 : E3dDepthNeighbour* pSucc = mpNext->mpNext;
1041 0 : delete mpNext;
1042 0 : mpNext = pSucc;
1043 : }
1044 0 : }
1045 : };
1046 :
1047 0 : void E3dView::DoDepthArrange(E3dScene* pScene, double fDepth)
1048 : {
1049 0 : if(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1)
1050 : {
1051 0 : SdrObjList* pSubList = pScene->GetSubList();
1052 0 : SdrObjListIter aIter(*pSubList, IM_FLAT);
1053 0 : E3dDepthLayer* pBaseLayer = NULL;
1054 0 : E3dDepthLayer* pLayer = NULL;
1055 0 : sal_Int32 nNumLayers = 0;
1056 :
1057 0 : while(aIter.IsMore())
1058 : {
1059 0 : E3dExtrudeObj* pExtrudeObj = dynamic_cast< E3dExtrudeObj* >(aIter.Next());
1060 :
1061 0 : if(pExtrudeObj)
1062 : {
1063 : const basegfx::B2DPolyPolygon aExtrudePoly(
1064 0 : basegfx::tools::prepareForPolygonOperation(pExtrudeObj->GetExtrudePolygon()));
1065 0 : const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet();
1066 0 : const drawing::FillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem);
1067 0 : const Color aLocalColor = static_cast<const XFillColorItem&>(rLocalSet.Get(XATTR_FILLCOLOR)).GetColorValue();
1068 :
1069 : // sort in ExtrudeObj
1070 0 : if(pLayer)
1071 : {
1072 : // do we have overlap with an object of this layer?
1073 0 : bool bOverlap(false);
1074 0 : E3dDepthNeighbour* pAct = pLayer->mpNext;
1075 :
1076 0 : while(!bOverlap && pAct)
1077 : {
1078 : // do pAct->mpObj and pExtrudeObj overlap? Check by
1079 : // using logical AND clipping
1080 : const basegfx::B2DPolyPolygon aAndPolyPolygon(
1081 : basegfx::tools::solvePolygonOperationAnd(
1082 : aExtrudePoly,
1083 0 : pAct->maPreparedPolyPolygon));
1084 :
1085 0 : bOverlap = (0 != aAndPolyPolygon.count());
1086 :
1087 0 : if(bOverlap)
1088 : {
1089 : // second ciriteria: is another fillstyle or color used?
1090 0 : const SfxItemSet& rCompareSet = pAct->mpObj->GetMergedItemSet();
1091 :
1092 0 : drawing::FillStyle eCompareFillStyle = ITEMVALUE(rCompareSet, XATTR_FILLSTYLE, XFillStyleItem);
1093 :
1094 0 : if(eLocalFillStyle == eCompareFillStyle)
1095 : {
1096 0 : if(eLocalFillStyle == drawing::FillStyle_SOLID)
1097 : {
1098 0 : Color aCompareColor = static_cast<const XFillColorItem&>(rCompareSet.Get(XATTR_FILLCOLOR)).GetColorValue();
1099 :
1100 0 : if(aCompareColor == aLocalColor)
1101 : {
1102 0 : bOverlap = false;
1103 : }
1104 : }
1105 0 : else if(eLocalFillStyle == drawing::FillStyle_NONE)
1106 : {
1107 0 : bOverlap = false;
1108 : }
1109 : }
1110 : }
1111 :
1112 0 : pAct = pAct->mpNext;
1113 0 : }
1114 :
1115 0 : if(bOverlap)
1116 : {
1117 : // yes, start a new layer
1118 0 : pLayer->mpDown = new E3dDepthLayer;
1119 0 : pLayer = pLayer->mpDown;
1120 0 : nNumLayers++;
1121 0 : pLayer->mpNext = new E3dDepthNeighbour;
1122 0 : pLayer->mpNext->mpObj = pExtrudeObj;
1123 0 : pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly;
1124 : }
1125 : else
1126 : {
1127 : // no, add to current layer
1128 0 : E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour;
1129 0 : pNewNext->mpObj = pExtrudeObj;
1130 0 : pNewNext->maPreparedPolyPolygon = aExtrudePoly;
1131 0 : pNewNext->mpNext = pLayer->mpNext;
1132 0 : pLayer->mpNext = pNewNext;
1133 : }
1134 : }
1135 : else
1136 : {
1137 : // first layer ever
1138 0 : pBaseLayer = new E3dDepthLayer;
1139 0 : pLayer = pBaseLayer;
1140 0 : nNumLayers++;
1141 0 : pLayer->mpNext = new E3dDepthNeighbour;
1142 0 : pLayer->mpNext->mpObj = pExtrudeObj;
1143 0 : pLayer->mpNext->maPreparedPolyPolygon = aExtrudePoly;
1144 0 : }
1145 : }
1146 : }
1147 :
1148 : // number of layers is done
1149 0 : if(nNumLayers > 1)
1150 : {
1151 : // need to be arranged
1152 0 : double fMinDepth = fDepth * 0.8;
1153 0 : double fStep = (fDepth - fMinDepth) / (double)nNumLayers;
1154 0 : pLayer = pBaseLayer;
1155 :
1156 0 : while(pLayer)
1157 : {
1158 : // move along layer
1159 0 : E3dDepthNeighbour* pAct = pLayer->mpNext;
1160 :
1161 0 : while(pAct)
1162 : {
1163 : // adapt extrude value
1164 0 : pAct->mpObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5)));
1165 :
1166 : // next
1167 0 : pAct = pAct->mpNext;
1168 : }
1169 :
1170 : // next layer
1171 0 : pLayer = pLayer->mpDown;
1172 0 : fMinDepth += fStep;
1173 : }
1174 : }
1175 :
1176 : // cleanup
1177 0 : while(pBaseLayer)
1178 : {
1179 0 : pLayer = pBaseLayer->mpDown;
1180 0 : delete pBaseLayer;
1181 0 : pBaseLayer = pLayer;
1182 0 : }
1183 : }
1184 0 : }
1185 :
1186 : // Start drag, create for 3D objects before possibly drag method
1187 :
1188 0 : bool E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut,
1189 : SdrHdl* pHdl, short nMinMov,
1190 : SdrDragMethod* pForcedMeth)
1191 : {
1192 0 : if(Is3DRotationCreationActive() && GetMarkedObjectCount())
1193 : {
1194 : // Determine all selected polygons and return the mirrored helper overlay
1195 0 : mpMirrorOverlay->SetMirrorAxis(aRef1, aRef2);
1196 : }
1197 : else
1198 : {
1199 : bool bOwnActionNecessary;
1200 0 : if (pHdl == NULL)
1201 : {
1202 0 : bOwnActionNecessary = true;
1203 : }
1204 0 : else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl())
1205 : {
1206 0 : bOwnActionNecessary = true;
1207 : }
1208 : else
1209 : {
1210 0 : bOwnActionNecessary = false;
1211 : }
1212 :
1213 0 : if(bOwnActionNecessary && GetMarkedObjectCount() > 0)
1214 : {
1215 0 : E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ;
1216 0 : bool bThereAreRootScenes = false;
1217 0 : bool bThereAre3DObjects = false;
1218 0 : const size_t nCnt = GetMarkedObjectCount();
1219 0 : for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
1220 : {
1221 0 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1222 0 : if(pObj)
1223 : {
1224 0 : if(pObj->ISA(E3dScene) && static_cast<E3dScene*>(pObj)->GetScene() == pObj)
1225 0 : bThereAreRootScenes = true;
1226 0 : if(pObj->ISA(E3dObject))
1227 0 : bThereAre3DObjects = true;
1228 : }
1229 : }
1230 0 : if( bThereAre3DObjects )
1231 : {
1232 0 : eDragHdl = ( pHdl == NULL ? HDL_MOVE : pHdl->GetKind() );
1233 0 : switch ( eDragMode )
1234 : {
1235 : case SDRDRAG_ROTATE:
1236 : case SDRDRAG_SHEAR:
1237 : {
1238 0 : switch ( eDragHdl )
1239 : {
1240 : case HDL_LEFT:
1241 : case HDL_RIGHT:
1242 : {
1243 0 : eConstraint = E3DDRAG_CONSTR_X;
1244 : }
1245 0 : break;
1246 :
1247 : case HDL_UPPER:
1248 : case HDL_LOWER:
1249 : {
1250 0 : eConstraint = E3DDRAG_CONSTR_Y;
1251 : }
1252 0 : break;
1253 :
1254 : case HDL_UPLFT:
1255 : case HDL_UPRGT:
1256 : case HDL_LWLFT:
1257 : case HDL_LWRGT:
1258 : {
1259 0 : eConstraint = E3DDRAG_CONSTR_Z;
1260 : }
1261 0 : break;
1262 0 : default: break;
1263 : }
1264 :
1265 : // do not mask the allowed rotations
1266 0 : eConstraint = E3dDragConstraint(eConstraint& eDragConstraint);
1267 0 : pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint, IsSolidDragging());
1268 : }
1269 0 : break;
1270 :
1271 : case SDRDRAG_MOVE:
1272 : {
1273 0 : if(!bThereAreRootScenes)
1274 : {
1275 0 : pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint, IsSolidDragging());
1276 : }
1277 : }
1278 0 : break;
1279 :
1280 : // later on
1281 : case SDRDRAG_MIRROR:
1282 : case SDRDRAG_CROOK:
1283 : case SDRDRAG_DISTORT:
1284 : case SDRDRAG_TRANSPARENCE:
1285 : case SDRDRAG_GRADIENT:
1286 : default:
1287 : {
1288 : }
1289 0 : break;
1290 : }
1291 : }
1292 : }
1293 : }
1294 0 : return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth);
1295 : }
1296 :
1297 : // Set current 3D drawing object, create the scene for this
1298 :
1299 0 : E3dScene* E3dView::SetCurrent3DObj(E3dObject* p3DObj)
1300 : {
1301 : DBG_ASSERT(p3DObj != NULL, "Who puts in a NULL-pointer here");
1302 0 : E3dScene* pScene = NULL;
1303 :
1304 : // get transformed BoundVolume of the object
1305 0 : basegfx::B3DRange aVolume(p3DObj->GetBoundVolume());
1306 0 : aVolume.transform(p3DObj->GetTransform());
1307 0 : double fW(aVolume.getWidth());
1308 0 : double fH(aVolume.getHeight());
1309 :
1310 0 : Rectangle aRect(0,0, (long) fW, (long) fH);
1311 :
1312 0 : pScene = new E3dPolyScene(Get3DDefaultAttributes());
1313 :
1314 0 : InitScene(pScene, fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0));
1315 :
1316 0 : pScene->Insert3DObj(p3DObj);
1317 0 : pScene->NbcSetSnapRect(aRect);
1318 :
1319 0 : return pScene;
1320 : }
1321 :
1322 0 : void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ)
1323 : {
1324 0 : Camera3D aCam(pScene->GetCamera());
1325 :
1326 0 : aCam.SetAutoAdjustProjection(false);
1327 0 : aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1328 0 : basegfx::B3DPoint aLookAt;
1329 :
1330 0 : double fDefaultCamPosZ = GetDefaultCamPosZ();
1331 0 : basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1332 :
1333 0 : aCam.SetPosAndLookAt(aCamPos, aLookAt);
1334 0 : aCam.SetFocalLength(GetDefaultCamFocal());
1335 0 : aCam.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, GetDefaultCamFocal());
1336 0 : pScene->SetCamera(aCam);
1337 0 : }
1338 :
1339 0 : void E3dView::Start3DCreation()
1340 : {
1341 0 : if (GetMarkedObjectCount())
1342 : {
1343 : //positioned
1344 0 : long nOutMin = 0;
1345 0 : long nOutMax = 0;
1346 0 : long nMinLen = 0;
1347 0 : long nObjDst = 0;
1348 0 : long nOutHgt = 0;
1349 0 : OutputDevice* pOut = GetFirstOutputDevice();
1350 :
1351 : // first determine representation boundaries
1352 0 : if (pOut != NULL)
1353 : {
1354 0 : nMinLen = pOut->PixelToLogic(Size(0,50)).Height();
1355 0 : nObjDst = pOut->PixelToLogic(Size(0,20)).Height();
1356 :
1357 0 : long nDst = pOut->PixelToLogic(Size(0,10)).Height();
1358 :
1359 0 : nOutMin = -pOut->GetMapMode().GetOrigin().Y();
1360 0 : nOutMax = pOut->GetOutputSize().Height() - 1 + nOutMin;
1361 0 : nOutMin += nDst;
1362 0 : nOutMax -= nDst;
1363 :
1364 0 : if (nOutMax - nOutMin < nDst)
1365 : {
1366 0 : nOutMin += nOutMax + 1;
1367 0 : nOutMin /= 2;
1368 0 : nOutMin -= (nDst + 1) / 2;
1369 0 : nOutMax = nOutMin + nDst;
1370 : }
1371 :
1372 0 : nOutHgt = nOutMax - nOutMin;
1373 :
1374 0 : long nTemp = nOutHgt / 4;
1375 0 : if (nTemp > nMinLen) nMinLen = nTemp;
1376 : }
1377 :
1378 : // and then attach the marks at the top and bottom of the object
1379 0 : basegfx::B2DRange aR;
1380 0 : for(size_t nMark = 0; nMark < GetMarkedObjectCount(); ++nMark)
1381 : {
1382 0 : SdrObject* pMark = GetMarkedObjectByIndex(nMark);
1383 0 : basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly());
1384 0 : aR.expand(basegfx::tools::getRange(aXPP));
1385 0 : }
1386 :
1387 0 : basegfx::B2DPoint aCenter(aR.getCenter());
1388 0 : long nMarkHgt = basegfx::fround(aR.getHeight()) - 1;
1389 0 : long nHgt = nMarkHgt + nObjDst * 2;
1390 :
1391 0 : if (nHgt < nMinLen) nHgt = nMinLen;
1392 :
1393 0 : long nY1 = basegfx::fround(aCenter.getY()) - (nHgt + 1) / 2;
1394 0 : long nY2 = nY1 + nHgt;
1395 :
1396 0 : if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt;
1397 0 : if (pOut)
1398 : {
1399 0 : if (nY1 < nOutMin)
1400 : {
1401 0 : nY1 = nOutMin;
1402 0 : if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen;
1403 : }
1404 0 : if (nY2 > nOutMax)
1405 : {
1406 0 : nY2 = nOutMax;
1407 0 : if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen;
1408 : }
1409 : }
1410 :
1411 0 : aRef1.X() = basegfx::fround(aR.getMinX()); // Initial move axis 2/100mm to the left
1412 0 : aRef1.Y() = nY1;
1413 0 : aRef2.X() = aRef1.X();
1414 0 : aRef2.Y() = nY2;
1415 :
1416 : // Turn on marks
1417 0 : SetMarkHandles();
1418 :
1419 : //HMHif (bVis) ShowMarkHdl();
1420 0 : if (AreObjectsMarked()) MarkListHasChanged();
1421 :
1422 : // Show mirror polygon IMMEDIATELY
1423 0 : const SdrHdlList &aHdlList = GetHdlList();
1424 0 : mpMirrorOverlay = new Impl3DMirrorConstructOverlay(*this);
1425 0 : mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(HDL_REF1)->GetPos(), aHdlList.GetHdl(HDL_REF2)->GetPos());
1426 : }
1427 0 : }
1428 :
1429 : // what happens with a mouse movement when the object is created?
1430 :
1431 0 : void E3dView::MovAction(const Point& rPnt)
1432 : {
1433 0 : if(Is3DRotationCreationActive())
1434 : {
1435 0 : SdrHdl* pHdl = GetDragHdl();
1436 :
1437 0 : if (pHdl)
1438 : {
1439 0 : SdrHdlKind eHdlKind = pHdl->GetKind();
1440 :
1441 : // reacts only due to a mirror axis
1442 0 : if ((eHdlKind == HDL_REF1) ||
1443 0 : (eHdlKind == HDL_REF2) ||
1444 : (eHdlKind == HDL_MIRX))
1445 : {
1446 0 : const SdrHdlList &aHdlList = GetHdlList ();
1447 :
1448 : // delete the mirroed polygon, mirrors the original and draws
1449 : // it anew
1450 0 : SdrView::MovAction (rPnt);
1451 : mpMirrorOverlay->SetMirrorAxis(
1452 0 : aHdlList.GetHdl (HDL_REF1)->GetPos(),
1453 0 : aHdlList.GetHdl (HDL_REF2)->GetPos());
1454 : }
1455 : }
1456 : else
1457 : {
1458 0 : SdrView::MovAction (rPnt);
1459 : }
1460 : }
1461 : else
1462 : {
1463 0 : SdrView::MovAction (rPnt);
1464 : }
1465 0 : }
1466 :
1467 : // The End. Create object and any child objects through ImpCreate3DLathe.
1468 : // With the parameter value sal_True (SDefault: sal_False) is simply a
1469 : // rotation body created, without letting the user set the position of the
1470 : // axis. It is sufficient with this call, if an object is selected.
1471 : // (No initialization necessary)
1472 :
1473 0 : void E3dView::End3DCreation(bool bUseDefaultValuesForMirrorAxes)
1474 : {
1475 0 : ResetCreationActive();
1476 :
1477 0 : if(AreObjectsMarked())
1478 : {
1479 0 : if(bUseDefaultValuesForMirrorAxes)
1480 : {
1481 0 : Rectangle aRect = GetAllMarkedRect();
1482 0 : if(aRect.GetWidth() <= 1)
1483 0 : aRect.SetSize(Size(500, aRect.GetHeight()));
1484 0 : if(aRect.GetHeight() <= 1)
1485 0 : aRect.SetSize(Size(aRect.GetWidth(), 500));
1486 :
1487 0 : basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top());
1488 0 : basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom());
1489 :
1490 0 : ConvertMarkedObjTo3D(false, aPnt1, aPnt2);
1491 : }
1492 : else
1493 : {
1494 : // Turn off helper overlay
1495 : // Determine from the handle positions and the displacement of
1496 : // the points
1497 0 : const SdrHdlList &aHdlList = GetHdlList();
1498 0 : Point aMirrorRef1 = aHdlList.GetHdl(HDL_REF1)->GetPos();
1499 0 : Point aMirrorRef2 = aHdlList.GetHdl(HDL_REF2)->GetPos();
1500 :
1501 0 : basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y());
1502 0 : basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y());
1503 :
1504 0 : ConvertMarkedObjTo3D(false, aPnt1, aPnt2);
1505 : }
1506 : }
1507 0 : }
1508 :
1509 7492 : E3dView::~E3dView ()
1510 : {
1511 7492 : }
1512 :
1513 762 : void E3dView::ResetCreationActive ()
1514 : {
1515 762 : if(mpMirrorOverlay)
1516 : {
1517 0 : delete mpMirrorOverlay;
1518 0 : mpMirrorOverlay = 0L;
1519 : }
1520 762 : }
1521 :
1522 7010 : void E3dView::InitView ()
1523 : {
1524 7010 : eDragConstraint = E3DDRAG_CONSTR_XYZ;
1525 : fDefaultScaleX =
1526 : fDefaultScaleY =
1527 7010 : fDefaultScaleZ = 1.0;
1528 : fDefaultRotateX =
1529 : fDefaultRotateY =
1530 7010 : fDefaultRotateZ = 0.0;
1531 7010 : fDefaultExtrusionDeepth = 1000; // old: 2000;
1532 7010 : fDefaultLightIntensity = 0.8; // old: 0.6;
1533 7010 : fDefaultAmbientIntensity = 0.4;
1534 7010 : nHDefaultSegments = 12;
1535 7010 : nVDefaultSegments = 12;
1536 7010 : aDefaultLightColor = RGB_Color(COL_WHITE);
1537 7010 : aDefaultAmbientColor = RGB_Color(COL_BLACK);
1538 7010 : bDoubleSided = false;
1539 7010 : mpMirrorOverlay = 0L;
1540 7010 : }
1541 :
1542 0 : bool E3dView::IsBreak3DObjPossible() const
1543 : {
1544 0 : const size_t nCount = GetMarkedObjectCount();
1545 :
1546 0 : if (nCount > 0)
1547 : {
1548 0 : for (size_t i = 0; i < nCount; ++i)
1549 : {
1550 0 : SdrObject* pObj = GetMarkedObjectByIndex(i);
1551 :
1552 0 : if (pObj && pObj->ISA(E3dObject))
1553 : {
1554 0 : if(!(static_cast<E3dObject*>(pObj)->IsBreakObjPossible()))
1555 0 : return false;
1556 : }
1557 : else
1558 : {
1559 0 : return false;
1560 : }
1561 : }
1562 : }
1563 : else
1564 : {
1565 0 : return false;
1566 : }
1567 :
1568 0 : return true;
1569 : }
1570 :
1571 0 : void E3dView::Break3DObj()
1572 : {
1573 0 : if(IsBreak3DObjPossible())
1574 : {
1575 : // ALL selected objects are changed
1576 0 : const size_t nCount = GetMarkedObjectCount();
1577 :
1578 0 : BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE));
1579 0 : for(size_t a=0; a<nCount; ++a)
1580 : {
1581 0 : E3dObject* pObj = static_cast<E3dObject*>(GetMarkedObjectByIndex(a));
1582 0 : BreakSingle3DObj(pObj);
1583 : }
1584 0 : DeleteMarked();
1585 0 : EndUndo();
1586 : }
1587 0 : }
1588 :
1589 0 : void E3dView::BreakSingle3DObj(E3dObject* pObj)
1590 : {
1591 0 : if(pObj->ISA(E3dScene))
1592 : {
1593 0 : SdrObjList* pSubList = pObj->GetSubList();
1594 0 : SdrObjListIter aIter(*pSubList, IM_FLAT);
1595 :
1596 0 : while(aIter.IsMore())
1597 : {
1598 0 : E3dObject* pSubObj = static_cast<E3dObject*>(aIter.Next());
1599 0 : BreakSingle3DObj(pSubObj);
1600 0 : }
1601 : }
1602 : else
1603 : {
1604 0 : SdrAttrObj* pNewObj = pObj->GetBreakObj();
1605 0 : if(pNewObj)
1606 : {
1607 0 : InsertObjectAtView(pNewObj, *GetSdrPageView(), SDRINSERT_DONTMARK);
1608 0 : pNewObj->SetChanged();
1609 0 : pNewObj->BroadcastObjectChange();
1610 : }
1611 : }
1612 0 : }
1613 :
1614 3892 : void E3dView::CheckPossibilities()
1615 : {
1616 : // call parent
1617 3892 : SdrView::CheckPossibilities();
1618 :
1619 : // Set other flags
1620 3892 : if(bGroupPossible || bUnGroupPossible || bGrpEnterPossible)
1621 : {
1622 0 : const size_t nMarkCnt = GetMarkedObjectCount();
1623 0 : bool bCoumpound = false;
1624 0 : bool b3DObject = false;
1625 0 : for(size_t nObjs = 0; (nObjs < nMarkCnt) && !bCoumpound; ++nObjs)
1626 : {
1627 0 : SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1628 0 : if(pObj && pObj->ISA(E3dCompoundObject))
1629 0 : bCoumpound = true;
1630 0 : if(pObj && pObj->ISA(E3dObject))
1631 0 : b3DObject = true;
1632 : }
1633 :
1634 : // So far: there are two or more of any objects selected. See if
1635 : // compound objects are involved. If yes, ban grouping.
1636 0 : if(bGroupPossible && bCoumpound)
1637 0 : bGroupPossible = false;
1638 :
1639 0 : if(bUnGroupPossible && b3DObject)
1640 0 : bUnGroupPossible = false;
1641 :
1642 0 : if(bGrpEnterPossible && bCoumpound)
1643 0 : bGrpEnterPossible = false;
1644 : }
1645 4543 : }
1646 :
1647 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|