LibreOffice Module svx (master) 1
view3d.cxx
Go to the documentation of this file.
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 <svx/svdopath.hxx>
22#include <svx/svditer.hxx>
23#include <svx/svdmodel.hxx>
24#include <svx/svdpagv.hxx>
25#include <editeng/colritem.hxx>
26#include <editeng/eeitem.hxx>
27#include <svx/svdview.hxx>
28#include <svx/strings.hrc>
29#include <svx/dialmgr.hxx>
30#include <svx/obj3d.hxx>
31#include <svx/lathe3d.hxx>
32#include <extrud3d.hxx>
33#include <dragmt3d.hxx>
34#include <svx/scene3d.hxx>
35#include <svx/view3d.hxx>
36#include <svx/svdundo.hxx>
37#include <svx/xflclit.hxx>
38#include <svx/xlnclit.hxx>
39#include <svx/xfillit0.hxx>
40#include <svx/xlineit0.hxx>
43#include <svx/xlnwtit.hxx>
54#include <utility>
55
56using namespace com::sun::star;
57
58
59// Migrate Marking
60
62{
63 // The OverlayObjects
65
66 // the view
68
69 // the object count
70 size_t mnCount;
71
72 // the unmirrored polygons
74
75 // the overlay geometry from selected objects
77
78 // Copy assignment is forbidden and not implemented.
81
82public:
83 explicit Impl3DMirrorConstructOverlay(const E3dView& rView);
85
86 void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB);
87};
88
90: mrView(rView),
91 mnCount(rView.GetMarkedObjectCount()),
92 mpPolygons(nullptr)
93{
94 if(!mnCount)
95 return;
96
98 {
99 SdrPageView* pPV = rView.GetSdrPageView();
100
101 if(pPV && pPV->PageWindowCount())
102 {
103 for(size_t a = 0; a < mnCount; ++a)
104 {
106
107 if(pObject)
108 {
109 // use the view-independent primitive representation (without
110 // evtl. GridOffset, that may be applied to the DragEntry individually)
111 pObject->GetViewContact().getViewIndependentPrimitive2DContainer(maFullOverlay);
112 }
113 }
114 }
115 }
116 else
117 {
119
120 for(size_t a = 0; a < mnCount; ++a)
121 {
123 mpPolygons[mnCount - (a + 1)] = pObject->TakeXorPoly();
124 }
125 }
126}
127
129{
130 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
131 // That destructor calls clear() at the list which removes all objects from the
132 // OverlayManager and deletes them.
133 delete[] mpPolygons;
134}
135
136void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
137{
138 // get rid of old overlay objects
140
141 // create new ones
142 for(sal_uInt32 a(0); a < mrView.PaintWindowCount(); a++)
143 {
144 SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a);
145 const rtl::Reference< sdr::overlay::OverlayManager >& xTargetOverlay = pCandidate->GetOverlayManager();
146
147 if(xTargetOverlay.is())
148 {
149 // build transformation: translate and rotate so that given edge is
150 // on x axis, them mirror in y and translate back
151 const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y());
153 -aMirrorAxisA.X(), -aMirrorAxisA.Y()));
154 aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
155 aMatrixTransform.scale(1.0, -1.0);
156 aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX()));
157 aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y());
158
160 {
161 if(!maFullOverlay.empty())
162 {
164
165 if(!aMatrixTransform.isIdentity())
166 {
167 // embed in transformation group
168 drawinglayer::primitive2d::Primitive2DReference aTransformPrimitive2D(new drawinglayer::primitive2d::TransformPrimitive2D(aMatrixTransform, std::move(aContent)));
169 aContent = drawinglayer::primitive2d::Primitive2DContainer { aTransformPrimitive2D };
170 }
171
172 // if we have full overlay from selected objects, embed with 50% transparence, the
173 // transformation is added to the OverlayPrimitive2DSequenceObject
174 drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparencePrimitive2D(new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(std::move(aContent), 0.5));
175 aContent = drawinglayer::primitive2d::Primitive2DContainer { aUnifiedTransparencePrimitive2D };
176
177 std::unique_ptr<sdr::overlay::OverlayPrimitive2DSequenceObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(std::move(aContent)));
178
179 xTargetOverlay->add(*pNew);
180 maObjects.append(std::move(pNew));
181 }
182 }
183 else
184 {
185 for(size_t b = 0; b < mnCount; ++b)
186 {
187 // apply to polygon
188 basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]);
189 aPolyPolygon.transform(aMatrixTransform);
190
191 std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
192 std::move(aPolyPolygon)));
193 xTargetOverlay->add(*pNew);
194 maObjects.append(std::move(pNew));
195 }
196 }
197 }
198 }
199}
200
202 SdrModel& rSdrModel,
203 OutputDevice* pOut)
204: SdrView(rSdrModel, pOut)
205{
206 InitView();
207}
208
209// DrawMarkedObj override, since possibly only a single 3D object is to be
210// drawn
211
213{
214 // Does 3D objects exist which scenes are not selected?
215 bool bSpecialHandling = false;
216 E3dScene *pScene = nullptr;
217
218 const size_t nCnt = GetMarkedObjectCount();
219 for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
220 {
221 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
222 if(auto pCompoundObject = dynamic_cast<E3dCompoundObject*>(pObj))
223 {
224 // related scene
225 pScene = pCompoundObject->getRootE3dSceneFromE3dObject();
226
227 if(nullptr != pScene && !IsObjMarked(pScene))
228 {
229 bSpecialHandling = true;
230 }
231 }
232 // Reset all selection flags
233 if(auto p3dObject = dynamic_cast< const E3dObject*>(pObj))
234 {
235 pScene = p3dObject->getRootE3dSceneFromE3dObject();
236
237 if(nullptr != pScene)
238 {
239 pScene->SetSelected(false);
240 }
241 }
242 }
243
244 if(bSpecialHandling)
245 {
246 // Set selection flag to "not selected" for scenes related to all 3D
247 // objects
248 for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
249 {
250 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
251 if(auto pCompoundObject = dynamic_cast<E3dCompoundObject*>(pObj))
252 {
253 // related scene
254 pScene = pCompoundObject->getRootE3dSceneFromE3dObject();
255
256 if(nullptr != pScene)
257 {
258 pScene->SetSelected(false);
259 }
260 }
261 }
262
263 for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
264 {
265 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
266 if(auto p3DObj = dynamic_cast<E3dObject*>(pObj))
267 {
268 // Select object
269 p3DObj->SetSelected(true);
270 pScene = p3DObj->getRootE3dSceneFromE3dObject();
271 }
272 }
273
274 if(nullptr != pScene)
275 {
276 // code from parent
278
279 pScene->SetDrawOnlySelected(true);
280 pScene->SingleObjectPainter(rOut);
281 pScene->SetDrawOnlySelected(false);
282 }
283
284 // Reset selection flag
285 for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
286 {
287 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
288 if(auto pCompoundObject = dynamic_cast<E3dCompoundObject*>(pObj))
289 {
290 // related scene
291 pScene = pCompoundObject->getRootE3dSceneFromE3dObject();
292
293 if(nullptr != pScene)
294 {
295 pScene->SetSelected(false);
296 }
297 }
298 }
299 }
300 else
301 {
302 // call parent
304 }
305}
306
307// override get model, since in some 3D objects an additional scene
308// must be pushed in
309
310std::unique_ptr<SdrModel> E3dView::CreateMarkedObjModel() const
311{
312 // Does 3D objects exist which scenes are not selected?
313 bool bSpecialHandling(false);
314 const size_t nCount(GetMarkedObjectCount());
315 E3dScene *pScene = nullptr;
316
317 for(size_t nObjs = 0; nObjs < nCount; ++nObjs)
318 {
319 const SdrObject* pObj = GetMarkedObjectByIndex(nObjs);
320
321 if(!bSpecialHandling)
322 if(auto pCompoundObj = dynamic_cast< const E3dCompoundObject*>(pObj))
323 {
324 // if the object is selected, but it's scene not,
325 // we need special handling
326 pScene = pCompoundObj->getRootE3dSceneFromE3dObject();
327
328 if(nullptr != pScene && !IsObjMarked(pScene))
329 {
330 bSpecialHandling = true;
331 }
332 }
333
334 if(auto p3dObject = dynamic_cast< const E3dObject*>(pObj))
335 {
336 // reset all selection flags at 3D objects
337 pScene = p3dObject->getRootE3dSceneFromE3dObject();
338
339 if(nullptr != pScene)
340 {
341 pScene->SetSelected(false);
342 }
343 }
344 }
345
346 if(!bSpecialHandling)
347 {
348 // call parent
350 }
351
352 std::unique_ptr<SdrModel> pNewModel;
353 tools::Rectangle aSelectedSnapRect;
354
355 // set 3d selection flags at all directly selected objects
356 // and collect SnapRect of selected objects
357 for(size_t nObjs = 0; nObjs < nCount; ++nObjs)
358 {
359 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
360
361 if(auto p3DObj = dynamic_cast<E3dCompoundObject*>(pObj))
362 {
363 // mark object, but not scenes
364 p3DObj->SetSelected(true);
365 aSelectedSnapRect.Union(p3DObj->GetSnapRect());
366 }
367 }
368
369 // create new mark list which contains all indirectly selected3d
370 // scenes as selected objects
372 SdrMarkList aNewML;
373 SdrMarkList& rCurrentMarkList = const_cast<E3dView*>(this)->GetMarkedObjectListWriteAccess();
374 rCurrentMarkList = aNewML;
375
376 for(size_t nObjs = 0; nObjs < nCount; ++nObjs)
377 {
378 SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj();
379
380 if(auto p3dObject = dynamic_cast< E3dObject* >(pObj))
381 {
382 pScene = p3dObject->getRootE3dSceneFromE3dObject();
383
384 if(nullptr != pScene && !IsObjMarked(pScene) && GetSdrPageView())
385 {
386 const_cast<E3dView*>(this)->MarkObj(pScene, GetSdrPageView(), false, true);
387 }
388 }
389 }
390
391 // call parent. This will copy all scenes and the selection flags at the 3D objects. So
392 // it will be possible to delete all non-selected 3d objects from the cloned 3d scenes
393 pNewModel = SdrView::CreateMarkedObjModel();
394
395 if(pNewModel)
396 {
397 for(sal_uInt16 nPg(0); nPg < pNewModel->GetPageCount(); nPg++)
398 {
399 const SdrPage* pSrcPg=pNewModel->GetPage(nPg);
400 const size_t nObjCount(pSrcPg->GetObjCount());
401
402 for(size_t nOb = 0; nOb < nObjCount; ++nOb)
403 {
404 const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
405
406 if(auto p3dscene = dynamic_cast< const E3dScene* >( pSrcOb))
407 {
408 pScene = const_cast<E3dScene*>(p3dscene);
409
410 // delete all not intentionally cloned 3d objects
412
413 // reset select flags and set SnapRect of all selected objects
414 pScene->SetSelected(false);
415 pScene->SetSnapRect(aSelectedSnapRect);
416 }
417 }
418 }
419 }
420
421 // restore old selection
422 rCurrentMarkList = aOldML;
423
424 return pNewModel;
425}
426
427// When pasting objects have to integrated if a scene is inserted, but
428// not the scene itself
429
431 const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, SdrInsertFlags nOptions)
432{
433 bool bRetval = false;
434
435 // Get list
436 Point aPos(rPos);
437 SdrObjList* pDstList = pLst;
438 ImpGetPasteObjList(aPos, pDstList);
439
440 if(!pDstList)
441 return false;
442
443 // Get owner of the list
444 E3dScene* pDstScene(dynamic_cast< E3dScene* >(pDstList->getSdrObjectFromSdrObjList()));
445
446 if(nullptr != pDstScene)
447 {
448 BegUndo(SvxResId(RID_SVX_3D_UNDO_EXCHANGE_PASTE));
449
450 // Copy all objects from E3dScenes and insert them directly
451 for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++)
452 {
453 const SdrPage* pSrcPg=rMod.GetPage(nPg);
454 const size_t nObjCount(pSrcPg->GetObjCount());
455
456 // calculate offset for paste
458 Point aDist(aPos - aR.Center());
459
460 // Insert sub-objects for scenes
461 for(size_t nOb = 0; nOb < nObjCount; ++nOb)
462 {
463 const SdrObject* pSrcOb = pSrcPg->GetObj(nOb);
464 if(auto p3dscene = dynamic_cast< const E3dScene* >(pSrcOb))
465 {
466 E3dScene* pSrcScene = const_cast<E3dScene*>(p3dscene);
467 ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist);
468 }
469 }
470 }
471 EndUndo();
472 }
473 else
474 {
475 // call parent
476 bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions);
477 }
478
479 return bRetval;
480}
481
482// Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
483bool E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene const * pSrcScene, E3dScene* pDstScene, Point /*aOffset*/)
484{
485 bool bRetval(false);
486
487 if(pSrcScene && pDstScene)
488 {
489 for(size_t i = 0; i < pSrcScene->GetSubList()->GetObjCount(); ++i)
490 {
491 E3dCompoundObject* pCompoundObj = dynamic_cast< E3dCompoundObject* >(pSrcScene->GetSubList()->GetObj(i));
492
493 if(pCompoundObj)
494 {
495 rtl::Reference<E3dCompoundObject> pNewCompoundObj = SdrObject::Clone(*pCompoundObj, pDstScene->getSdrModelFromSdrObject());
496
497 if(pNewCompoundObj)
498 {
499 // get dest scene's current range in 3D world coordinates
500 const basegfx::B3DHomMatrix aSceneToWorldTrans(pDstScene->GetFullTransform());
501 basegfx::B3DRange aSceneRange(pDstScene->GetBoundVolume());
502 aSceneRange.transform(aSceneToWorldTrans);
503
504 // get new object's implied object transformation
505 const basegfx::B3DHomMatrix aNewObjectTrans(pNewCompoundObj->GetTransform());
506
507 // get new object's range in 3D world coordinates in dest scene
508 // as if it were already added
509 const basegfx::B3DHomMatrix aObjectToWorldTrans(aSceneToWorldTrans * aNewObjectTrans);
510 basegfx::B3DRange aObjectRange(pNewCompoundObj->GetBoundVolume());
511 aObjectRange.transform(aObjectToWorldTrans);
512
513 // get scale adaptation
514 const basegfx::B3DVector aSceneScale(aSceneRange.getRange());
515 const basegfx::B3DVector aObjectScale(aObjectRange.getRange());
516 double fScale(1.0);
517
518 // if new object's size in X,Y or Z is bigger that 80% of dest scene, adapt scale
519 // to not change the scene by the inserted object
520 const double fSizeFactor(0.5);
521
522 if(aObjectScale.getX() * fScale > aSceneScale.getX() * fSizeFactor)
523 {
524 const double fObjSize(aObjectScale.getX() * fScale);
525 const double fFactor((aSceneScale.getX() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
526 fScale *= fFactor;
527 }
528
529 if(aObjectScale.getY() * fScale > aSceneScale.getY() * fSizeFactor)
530 {
531 const double fObjSize(aObjectScale.getY() * fScale);
532 const double fFactor((aSceneScale.getY() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
533 fScale *= fFactor;
534 }
535
536 if(aObjectScale.getZ() * fScale > aSceneScale.getZ() * fSizeFactor)
537 {
538 const double fObjSize(aObjectScale.getZ() * fScale);
539 const double fFactor((aSceneScale.getZ() * fSizeFactor) / (basegfx::fTools::equalZero(fObjSize) ? 1.0 : fObjSize));
540 fScale *= fFactor;
541 }
542
543 // get translation adaptation
544 const basegfx::B3DPoint aSceneCenter(aSceneRange.getCenter());
545 const basegfx::B3DPoint aObjectCenter(aObjectRange.getCenter());
546
547 // build full modification transform. The object's transformation
548 // shall be modified, so start at object coordinates; transform to 3d world coor
549 basegfx::B3DHomMatrix aModifyingTransform(aObjectToWorldTrans);
550
551 // translate to absolute center in 3d world coor
552 aModifyingTransform.translate(-aObjectCenter.getX(), -aObjectCenter.getY(), -aObjectCenter.getZ());
553
554 // scale to dest size in 3d world coor
555 aModifyingTransform.scale(fScale, fScale, fScale);
556
557 // translate to dest scene center in 3d world coor
558 aModifyingTransform.translate(aSceneCenter.getX(), aSceneCenter.getY(), aSceneCenter.getZ());
559
560 // transform from 3d world to dest object coordinates
561 basegfx::B3DHomMatrix aWorldToObject(aObjectToWorldTrans);
562 aWorldToObject.invert();
563 aModifyingTransform = aWorldToObject * aModifyingTransform;
564
565 // correct implied object transform by applying changing one in object coor
566 pNewCompoundObj->SetTransform(aModifyingTransform * aNewObjectTrans);
567
568 // fill and insert new object
569 pNewCompoundObj->NbcSetLayer(pCompoundObj->GetLayer());
570 pNewCompoundObj->NbcSetStyleSheet(pCompoundObj->GetStyleSheet(), true);
571 pDstScene->InsertObject(pNewCompoundObj.get());
572 bRetval = true;
573
574 // Create undo
575 if( GetModel()->IsUndoEnabled() )
576 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNewCompoundObj));
577 }
578 }
579 }
580 }
581
582 return bRetval;
583}
584
586{
587 bool bAny3D(false);
588 bool bGroupSelected(false);
589 bool bRetval(true);
590
591 for(size_t a=0; !bAny3D && a<GetMarkedObjectCount(); ++a)
592 {
594 if(pObj)
595 {
596 ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected);
597 }
598 }
599
600 bRetval = !bAny3D
601 && (
605 return bRetval;
606}
607
608void E3dView::ImpIsConvertTo3DPossible(SdrObject const * pObj, bool& rAny3D,
609 bool& rGroupSelected) const
610{
611 if(!pObj)
612 return;
613
614 if(dynamic_cast< const E3dObject* >(pObj) != nullptr)
615 {
616 rAny3D = true;
617 }
618 else
619 {
620 if(pObj->IsGroupObject())
621 {
623 while(aIter.IsMore())
624 {
625 SdrObject* pNewObj = aIter.Next();
626 ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected);
627 }
628 rGroupSelected = true;
629 }
630 }
631}
632
634{
635 if(dynamic_cast<const SdrTextObj*>( pObj) == nullptr)
636 return;
637
638 const SfxItemSet& rSet = pObj->GetMergedItemSet();
639 const SvxColorItem& rTextColorItem = rSet.Get(EE_CHAR_COLOR);
640 if(rTextColorItem.GetValue() != COL_BLACK)
641 return;
642
643 //For black text objects, the color set to gray
644 if(pObj->getSdrPageFromSdrObject())
645 {
646 // if black is only default attribute from
647 // pattern set it hard so that it is used in undo.
649
650 // add undo now
651 if( GetModel()->IsUndoEnabled() )
652 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj));
653 }
654
656}
657
659{
660 auto pPathObj = dynamic_cast<const SdrPathObj*>( pObj);
661 if(!pPathObj)
662 return;
663
664 const SfxItemSet& rSet = pObj->GetMergedItemSet();
665 sal_Int32 nLineWidth = rSet.Get(XATTR_LINEWIDTH).GetValue();
666 drawing::LineStyle eLineStyle = rSet.Get(XATTR_LINESTYLE).GetValue();
667 drawing::FillStyle eFillStyle = rSet.Get(XATTR_FILLSTYLE).GetValue();
668
669 if(pPathObj->IsClosed()
670 && eLineStyle == drawing::LineStyle_SOLID
671 && !nLineWidth
672 && eFillStyle != drawing::FillStyle_NONE)
673 {
675 {
676 AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj));
677 }
678
679 pObj->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
681 }
682}
683
684void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, bool bExtrude, double fDepth, basegfx::B2DHomMatrix const & rLatheMat)
685{
686 // Single PathObject, transform this
687 SdrPathObj* pPath = dynamic_cast<SdrPathObj*>( pObj );
688
689 if(!pPath)
690 return;
691
692 E3dDefaultAttributes aDefault = Get3DDefaultAttributes();
693
694 if(bExtrude)
695 {
696 aDefault.SetDefaultExtrudeCharacterMode(true);
697 }
698 else
699 {
700 aDefault.SetDefaultLatheCharacterMode(true);
701 }
702
703 // Get Itemset of the original object
704 SfxItemSet aSet(pObj->GetMergedItemSet());
705
706 drawing::FillStyle eFillStyle = aSet.Get(XATTR_FILLSTYLE).GetValue();
707
708 // line style turned off
709 aSet.Put(XLineStyleItem(drawing::LineStyle_NONE));
710
711 //Determining if FILL_Attribute is set.
712 if(!pPath->IsClosed() || eFillStyle == drawing::FillStyle_NONE)
713 {
714 // This SdrPathObj is not filled, leave the front and rear face out.
715 // Moreover, a two-sided representation necessary.
716 aDefault.SetDefaultExtrudeCloseFront(false);
717 aDefault.SetDefaultExtrudeCloseBack(false);
718
719 aSet.Put(makeSvx3DDoubleSidedItem(true));
720
721 // Set fill attribute
722 aSet.Put(XFillStyleItem(drawing::FillStyle_SOLID));
723
724 // Fill color must be the color line, because the object was
725 // previously just a line
726 Color aColorLine = aSet.Get(XATTR_LINECOLOR).GetColorValue();
727 aSet.Put(XFillColorItem(OUString(), aColorLine));
728 }
729
730 // Create a new extrude object
732 if(bExtrude)
733 {
734 p3DObj = new E3dExtrudeObj(pObj->getSdrModelFromSdrObject(), aDefault, pPath->GetPathPoly(), fDepth);
735 }
736 else
737 {
738 // rLatheMat expects coordinates with y-axis up, pPath uses y-axis down
739 basegfx::B2DHomMatrix aFlipVerticalMat(1.0, 0.0, 0.0, 0.0, -1.0, 0.0);
740 basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly());
741 aPolyPoly2D.transform(aFlipVerticalMat);
742 aPolyPoly2D.transform(rLatheMat);
743 // ctor E3dLatheObj expects coordinates with y-axis down
744 aPolyPoly2D.transform(aFlipVerticalMat);
745 p3DObj = new E3dLatheObj(pObj->getSdrModelFromSdrObject(), aDefault, std::move(aPolyPoly2D));
746 }
747
748 // Set attribute
749 p3DObj->NbcSetLayer(pObj->GetLayer());
750
751 p3DObj->SetMergedItemSet(aSet);
752
753 p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), true);
754
755 // Insert a new extrude object
756 pScene->InsertObject(p3DObj.get());
757}
758
759void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, bool bExtrude, double fDepth, basegfx::B2DHomMatrix const & rLatheMat)
760{
761 if(!pObj)
762 return;
763
764 // change text color attribute for not so dark colors
765 if(pObj->IsGroupObject())
766 {
768 while(aIter.IsMore())
769 {
770 SdrObject* pGroupMember = aIter.Next();
772 }
773 }
774 else
776
777 // convert completely to path objects
778 rtl::Reference<SdrObject> pNewObj1 = pObj->ConvertToPolyObj(false, false);
779
780 if(!pNewObj1)
781 return;
782
783 // change text color attribute for not so dark colors
784 if(pNewObj1->IsGroupObject())
785 {
787 while(aIter.IsMore())
788 {
789 SdrObject* pGroupMember = aIter.Next();
791 }
792 }
793 else
795
796 // convert completely to path objects
797 rtl::Reference<SdrObject> pNewObj2 = pObj->ConvertToContourObj(pNewObj1.get(), true);
798
799 if(pNewObj2)
800 {
801 // add all to flat scene
802 if(pNewObj2->IsGroupObject())
803 {
805 while(aIter.IsMore())
806 {
807 SdrObject* pGroupMember = aIter.Next();
808 ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat);
809 }
810 }
811 else
812 ImpCreateSingle3DObjectFlat(pScene, pNewObj2.get(), bExtrude, fDepth, rLatheMat);
813 }
814}
815
816void E3dView::ConvertMarkedObjTo3D(bool bExtrude, const basegfx::B2DPoint& rPnt1, const basegfx::B2DPoint& rPnt2)
817{
818 if(!AreObjectsMarked())
819 return;
820
821 // Create undo
822 if(bExtrude)
823 BegUndo(SvxResId(RID_SVX_3D_UNDO_EXTRUDE));
824 else
825 BegUndo(SvxResId(RID_SVX_3D_UNDO_LATHE));
826
827 SdrModel& rSdrModel(GetSdrMarkByIndex(0)->GetMarkedSdrObj()->getSdrModelFromSdrObject());
828
829 // Create a new scene for the created 3D object
830 rtl::Reference<E3dScene> pScene = new E3dScene(rSdrModel);
831
832 // Determine rectangle and possibly correct it
834 if(aRect.GetWidth() <= 1)
835 aRect.SetSize(Size(500, aRect.GetHeight()));
836 if(aRect.GetHeight() <= 1)
837 aRect.SetSize(Size(aRect.GetWidth(), 500));
838
839 // Determine the depth relative to the size of the selection
840 double fDepth = 0.0;
841 double fRot3D = 0.0;
842 basegfx::B2DHomMatrix aLatheMat;
843
844 if(bExtrude)
845 {
846 double fW = static_cast<double>(aRect.GetWidth());
847 double fH = static_cast<double>(aRect.GetHeight());
848 fDepth = sqrt(fW*fW + fH*fH) / 6.0;
849 }
850 if(!bExtrude)
851 {
852 // Create transformation for the polygons rotating body
853 if (rPnt1 != rPnt2)
854 {
855 // Rotation around control point #1 with set angle
856 // for 3D coordinates
857 basegfx::B2DPoint aDiff(rPnt1 - rPnt2);
858 fRot3D = atan2(aDiff.getY(), aDiff.getX()) - M_PI_2;
859
860 if(basegfx::fTools::equalZero(fabs(fRot3D)))
861 fRot3D = 0.0;
862
863 if(fRot3D != 0.0)
864 {
865 aLatheMat = basegfx::utils::createRotateAroundPoint(rPnt2, -fRot3D)
866 * aLatheMat;
867 }
868 }
869
870 if (rPnt2.getX() != 0.0)
871 {
872 // Translation to Y=0 - axis
873 aLatheMat.translate(-rPnt2.getX(), 0.0);
874 }
875 else
876 {
877 aLatheMat.translate(static_cast<double>(-aRect.Left()), 0.0);
878 }
879
880 // Form the inverse matrix to determine the target expansion
881 basegfx::B2DHomMatrix aInvLatheMat(aLatheMat);
882 aInvLatheMat.invert();
883
884 // SnapRect extension enables mirroring in the axis of rotation
885 for(size_t a=0; a<GetMarkedObjectCount(); ++a)
886 {
887 SdrMark* pMark = GetSdrMarkByIndex(a);
888 SdrObject* pObj = pMark->GetMarkedSdrObj();
889 tools::Rectangle aTurnRect = pObj->GetSnapRect();
891 Point aRotPnt;
892
893 aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top());
894 aRot *= aLatheMat;
895 aRot.setX(-aRot.getX());
896 aRot *= aInvLatheMat;
897 aRotPnt = Point(static_cast<tools::Long>(aRot.getX() + 0.5), static_cast<tools::Long>(-aRot.getY() - 0.5));
898 aRect.Union(tools::Rectangle(aRotPnt, aRotPnt));
899
900 aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom());
901 aRot *= aLatheMat;
902 aRot.setX(-aRot.getX());
903 aRot *= aInvLatheMat;
904 aRotPnt = Point(static_cast<tools::Long>(aRot.getX() + 0.5), static_cast<tools::Long>(-aRot.getY() - 0.5));
905 aRect.Union(tools::Rectangle(aRotPnt, aRotPnt));
906
907 aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top());
908 aRot *= aLatheMat;
909 aRot.setX(-aRot.getX());
910 aRot *= aInvLatheMat;
911 aRotPnt = Point(static_cast<tools::Long>(aRot.getX() + 0.5), static_cast<tools::Long>(-aRot.getY() - 0.5));
912 aRect.Union(tools::Rectangle(aRotPnt, aRotPnt));
913
914 aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom());
915 aRot *= aLatheMat;
916 aRot.setX(-aRot.getX());
917 aRot *= aInvLatheMat;
918 aRotPnt = Point(static_cast<tools::Long>(aRot.getX() + 0.5), static_cast<tools::Long>(-aRot.getY() - 0.5));
919 aRect.Union(tools::Rectangle(aRotPnt, aRotPnt));
920 }
921 }
922
923 // Walk through the selection and convert it into 3D, complete with
924 // Conversion to SdrPathObject, also fonts
925 for(size_t a=0; a<GetMarkedObjectCount(); ++a)
926 {
927 SdrMark* pMark = GetSdrMarkByIndex(a);
928 SdrObject* pObj = pMark->GetMarkedSdrObj();
929
930 ImpCreate3DObject(pScene.get(), pObj, bExtrude, fDepth, aLatheMat);
931 }
932
933 if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0)
934 {
935 // Arrange all created objects by depth
936 if(bExtrude)
937 DoDepthArrange(pScene.get(), fDepth);
938
939 // Center 3D objects in the middle of the overall rectangle
940 basegfx::B3DPoint aCenter(pScene->GetBoundVolume().getCenter());
941 basegfx::B3DHomMatrix aMatrix;
942
943 aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ());
944 pScene->SetTransform(aMatrix * pScene->GetTransform());
945
946 // Initialize scene
947 pScene->NbcSetSnapRect(aRect);
948 basegfx::B3DRange aBoundVol = pScene->GetBoundVolume();
949 InitScene(pScene.get(), static_cast<double>(aRect.GetWidth()), static_cast<double>(aRect.GetHeight()), aBoundVol.getDepth());
950
951 // Insert scene instead of the first selected object and throw away
952 // all the old objects
953 SdrObject* pRepObj = GetMarkedObjectByIndex(0);
955 MarkObj(pRepObj, pPV, true);
956 ReplaceObjectAtView(pRepObj, *pPV, pScene.get(), false);
957 DeleteMarked();
958 MarkObj(pScene.get(), pPV);
959
960 // Rotate Rotation body around the axis of rotation
961 if(!bExtrude && fRot3D != 0.0)
962 {
963 basegfx::B3DHomMatrix aRotate;
964 aRotate.rotate(0.0, 0.0, fRot3D);
965 pScene->SetTransform(aRotate * pScene->GetTransform());
966 }
967
968 // Set default rotation
969 {
970 basegfx::B3DHomMatrix aRotate;
971 aRotate.rotate(basegfx::deg2rad(20.0), 0.0, 0.0);
972 // E3DModifySceneSnapRectUpdater updates the 2D representation of the scene.
973 // It prepares things in ctor and acts in dtor.
974 E3DModifySceneSnapRectUpdater aUpdater(pScene->getSdrObjectFromSdrObjList());
975 pScene->SetTransform(aRotate * pScene->GetTransform());
976 }
977 }
978 else
979 pScene.clear();
980
981 EndUndo();
982}
983
984//Arrange all created extrude objects by depth
985
986namespace {
987
988struct E3dDepthNeighbour
989{
990 E3dExtrudeObj* mpObj;
991 basegfx::B2DPolyPolygon maPreparedPolyPolygon;
992
993 E3dDepthNeighbour(E3dExtrudeObj* pObj, basegfx::B2DPolyPolygon aPreparedPolyPolygon)
994 : mpObj(pObj),
995 maPreparedPolyPolygon(std::move(aPreparedPolyPolygon))
996 {
997 }
998};
999
1000struct E3dDepthLayer
1001{
1002 E3dDepthLayer* mpDown;
1003 std::vector<E3dDepthNeighbour> mvNeighbours;
1004
1005 E3dDepthLayer()
1006 : mpDown(nullptr)
1007 {
1008 }
1009};
1010
1011}
1012
1013void E3dView::DoDepthArrange(E3dScene const * pScene, double fDepth)
1014{
1015 if(!(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1))
1016 return;
1017
1018 SdrObjList* pSubList = pScene->GetSubList();
1019 SdrObjListIter aIter(pSubList, SdrIterMode::Flat);
1020 E3dDepthLayer* pBaseLayer = nullptr;
1021 E3dDepthLayer* pLayer = nullptr;
1022 sal_Int32 nNumLayers = 0;
1023
1024 while(aIter.IsMore())
1025 {
1026 E3dExtrudeObj* pExtrudeObj = dynamic_cast< E3dExtrudeObj* >(aIter.Next());
1027
1028 if(pExtrudeObj)
1029 {
1030 const basegfx::B2DPolyPolygon aExtrudePoly(
1031 basegfx::utils::prepareForPolygonOperation(pExtrudeObj->GetExtrudePolygon()));
1032 const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet();
1033 const drawing::FillStyle eLocalFillStyle = rLocalSet.Get(XATTR_FILLSTYLE).GetValue();
1034 const Color aLocalColor = rLocalSet.Get(XATTR_FILLCOLOR).GetColorValue();
1035
1036 // sort in ExtrudeObj
1037 if(pLayer)
1038 {
1039 // do we have overlap with an object of this layer?
1040 bool bOverlap(false);
1041
1042 for(const auto& rAct : pLayer->mvNeighbours)
1043 {
1044 // do rAct.mpObj and pExtrudeObj overlap? Check by
1045 // using logical AND clipping
1046 const basegfx::B2DPolyPolygon aAndPolyPolygon(
1048 aExtrudePoly,
1049 rAct.maPreparedPolyPolygon));
1050
1051 if(aAndPolyPolygon.count() != 0)
1052 {
1053 // second criteria: is another fillstyle or color used?
1054 const SfxItemSet& rCompareSet = rAct.mpObj->GetMergedItemSet();
1055
1056 drawing::FillStyle eCompareFillStyle = rCompareSet.Get(XATTR_FILLSTYLE).GetValue();
1057
1058 if(eLocalFillStyle == eCompareFillStyle)
1059 {
1060 if(eLocalFillStyle == drawing::FillStyle_SOLID)
1061 {
1062 Color aCompareColor = rCompareSet.Get(XATTR_FILLCOLOR).GetColorValue();
1063
1064 if(aCompareColor == aLocalColor)
1065 {
1066 continue;
1067 }
1068 }
1069 else if(eLocalFillStyle == drawing::FillStyle_NONE)
1070 {
1071 continue;
1072 }
1073 }
1074
1075 bOverlap = true;
1076 break;
1077 }
1078 }
1079
1080 if(bOverlap)
1081 {
1082 // yes, start a new layer
1083 pLayer->mpDown = new E3dDepthLayer;
1084 pLayer = pLayer->mpDown;
1085 nNumLayers++;
1086 pLayer->mvNeighbours.emplace_back(pExtrudeObj, aExtrudePoly);
1087 }
1088 else
1089 {
1090 // no, add to current layer
1091 pLayer->mvNeighbours.emplace(pLayer->mvNeighbours.begin(), pExtrudeObj, aExtrudePoly);
1092 }
1093 }
1094 else
1095 {
1096 // first layer ever
1097 pBaseLayer = new E3dDepthLayer;
1098 pLayer = pBaseLayer;
1099 nNumLayers++;
1100 pLayer->mvNeighbours.emplace_back(pExtrudeObj, aExtrudePoly);
1101 }
1102 }
1103 }
1104
1105 // number of layers is done
1106 if(nNumLayers > 1)
1107 {
1108 // need to be arranged
1109 double fMinDepth = fDepth * 0.8;
1110 double fStep = (fDepth - fMinDepth) / static_cast<double>(nNumLayers);
1111 pLayer = pBaseLayer;
1112
1113 while(pLayer)
1114 {
1115 // move along layer
1116 for(auto& rAct : pLayer->mvNeighbours)
1117 {
1118 // adapt extrude value
1119 rAct.mpObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5)));
1120 }
1121
1122 // next layer
1123 pLayer = pLayer->mpDown;
1124 fMinDepth += fStep;
1125 }
1126 }
1127
1128 // cleanup
1129 while(pBaseLayer)
1130 {
1131 pLayer = pBaseLayer->mpDown;
1132 delete pBaseLayer;
1133 pBaseLayer = pLayer;
1134 }
1135}
1136
1137// Start drag, create for 3D objects before possibly drag method
1138
1139bool E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut,
1140 SdrHdl* pHdl, short nMinMov,
1141 SdrDragMethod* pForcedMeth)
1142{
1144 {
1145 // Determine all selected polygons and return the mirrored helper overlay
1146 mpMirrorOverlay->SetMirrorAxis(maRef1, maRef2);
1147 }
1148 else
1149 {
1150 bool bOwnActionNecessary;
1151 if (pHdl == nullptr)
1152 {
1153 bOwnActionNecessary = true;
1154 }
1155 else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl())
1156 {
1157 bOwnActionNecessary = true;
1158 }
1159 else
1160 {
1161 bOwnActionNecessary = false;
1162 }
1163
1164 if(bOwnActionNecessary && GetMarkedObjectCount() > 0)
1165 {
1167 bool bThereAreRootScenes = false;
1168 bool bThereAre3DObjects = false;
1169 const size_t nCnt = GetMarkedObjectCount();
1170 for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
1171 {
1172 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1173 if(pObj)
1174 {
1175 if( auto pScene = dynamic_cast< const E3dScene* >(pObj) )
1176 if( pScene->getRootE3dSceneFromE3dObject() == pObj )
1177 bThereAreRootScenes = true;
1178
1179 if(dynamic_cast< const E3dObject* >(pObj) != nullptr)
1180 {
1181 bThereAre3DObjects = true;
1182 }
1183 }
1184 }
1185 if( bThereAre3DObjects )
1186 {
1187 meDragHdl = ( pHdl == nullptr ? SdrHdlKind::Move : pHdl->GetKind() );
1188 switch ( meDragMode )
1189 {
1191 case SdrDragMode::Shear:
1192 {
1193 switch ( meDragHdl )
1194 {
1195 case SdrHdlKind::Left:
1196 case SdrHdlKind::Right:
1197 {
1198 eConstraint = E3dDragConstraint::X;
1199 }
1200 break;
1201
1202 case SdrHdlKind::Upper:
1203 case SdrHdlKind::Lower:
1204 {
1205 eConstraint = E3dDragConstraint::Y;
1206 }
1207 break;
1208
1213 {
1214 eConstraint = E3dDragConstraint::Z;
1215 }
1216 break;
1217 default: break;
1218 }
1219
1220 // do not mask the allowed rotations
1221 eConstraint &= E3dDragConstraint::XYZ;
1222 pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint, IsSolidDragging());
1223 }
1224 break;
1225
1226 case SdrDragMode::Move:
1227 {
1228 if(!bThereAreRootScenes)
1229 {
1230 pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), meDragHdl, eConstraint, IsSolidDragging());
1231 }
1232 }
1233 break;
1234
1235 // later on
1237 case SdrDragMode::Crook:
1240 default:
1241 {
1242 }
1243 break;
1244 }
1245 }
1246 }
1247 }
1248 return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth);
1249}
1250
1251// Set current 3D drawing object, create the scene for this
1253{
1254 DBG_ASSERT(p3DObj != nullptr, "Who puts in a NULL-pointer here");
1255
1256 // get transformed BoundVolume of the object
1257 basegfx::B3DRange aVolume(p3DObj->GetBoundVolume());
1258 aVolume.transform(p3DObj->GetTransform());
1259 double fW(aVolume.getWidth());
1260 double fH(aVolume.getHeight());
1261
1262 tools::Rectangle aRect(0,0, static_cast<tools::Long>(fW), static_cast<tools::Long>(fH));
1263
1265
1266 InitScene(pScene.get(), fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0));
1267
1268 pScene->InsertObject(p3DObj);
1269 pScene->NbcSetSnapRect(aRect);
1270
1271 return pScene;
1272}
1273
1274void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ)
1275{
1276 Camera3D aCam(pScene->GetCamera());
1277
1278 aCam.SetAutoAdjustProjection(false);
1279 aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1280 basegfx::B3DPoint aLookAt;
1281
1282 double fDefaultCamPosZ = GetDefaultCamPosZ();
1283 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1284
1285 aCam.SetPosAndLookAt(aCamPos, aLookAt);
1287 pScene->SetCamera(aCam);
1288}
1289
1291{
1292 if (!GetMarkedObjectCount())
1293 return;
1294
1295 //positioned
1296 tools::Long nOutMin = 0;
1297 tools::Long nOutMax = 0;
1298 tools::Long nMinLen = 0;
1299 tools::Long nObjDst = 0;
1300 tools::Long nOutHgt = 0;
1302
1303 // first determine representation boundaries
1304 if (pOut != nullptr)
1305 {
1306 nMinLen = pOut->PixelToLogic(Size(0,50)).Height();
1307 nObjDst = pOut->PixelToLogic(Size(0,20)).Height();
1308
1309 tools::Long nDst = pOut->PixelToLogic(Size(0,10)).Height();
1310
1311 nOutMin = -pOut->GetMapMode().GetOrigin().Y();
1312 nOutMax = pOut->GetOutputSize().Height() - 1 + nOutMin;
1313 nOutMin += nDst;
1314 nOutMax -= nDst;
1315
1316 if (nOutMax - nOutMin < nDst)
1317 {
1318 nOutMin += nOutMax + 1;
1319 nOutMin /= 2;
1320 nOutMin -= (nDst + 1) / 2;
1321 nOutMax = nOutMin + nDst;
1322 }
1323
1324 nOutHgt = nOutMax - nOutMin;
1325
1326 tools::Long nTemp = nOutHgt / 4;
1327 if (nTemp > nMinLen) nMinLen = nTemp;
1328 }
1329
1330 // and then attach the marks at the top and bottom of the object
1332 for(size_t nMark = 0; nMark < GetMarkedObjectCount(); ++nMark)
1333 {
1334 SdrObject* pMark = GetMarkedObjectByIndex(nMark);
1335 basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly());
1337 }
1338
1339 basegfx::B2DPoint aCenter(aR.getCenter());
1340 tools::Long nMarkHgt = basegfx::fround(aR.getHeight()) - 1;
1341 tools::Long nHgt = nMarkHgt + nObjDst * 2;
1342
1343 if (nHgt < nMinLen) nHgt = nMinLen;
1344
1345 tools::Long nY1 = basegfx::fround(aCenter.getY()) - (nHgt + 1) / 2;
1346 tools::Long nY2 = nY1 + nHgt;
1347
1348 if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt;
1349 if (pOut)
1350 {
1351 if (nY1 < nOutMin)
1352 {
1353 nY1 = nOutMin;
1354 if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen;
1355 }
1356 if (nY2 > nOutMax)
1357 {
1358 nY2 = nOutMax;
1359 if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen;
1360 }
1361 }
1362
1363 maRef1.setX( basegfx::fround(aR.getMinX()) ); // Initial move axis 2/100mm to the left
1364 maRef1.setY( nY1 );
1365 maRef2.setX( maRef1.X() );
1366 maRef2.setY( nY2 );
1367
1368 // Turn on marks
1369 SetMarkHandles(nullptr);
1370
1371 //HMHif (bVis) ShowMarkHdl();
1373
1374 // Show mirror polygon IMMEDIATELY
1375 const SdrHdlList &aHdlList = GetHdlList();
1377 mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(SdrHdlKind::Ref1)->GetPos(), aHdlList.GetHdl(SdrHdlKind::Ref2)->GetPos());
1378}
1379
1380// what happens with a mouse movement when the object is created?
1381
1382void E3dView::MovAction(const Point& rPnt)
1383{
1385 {
1386 SdrHdl* pHdl = GetDragHdl();
1387
1388 if (pHdl)
1389 {
1390 SdrHdlKind eHdlKind = pHdl->GetKind();
1391
1392 // reacts only due to a mirror axis
1393 if ((eHdlKind == SdrHdlKind::Ref1) ||
1394 (eHdlKind == SdrHdlKind::Ref2) ||
1395 (eHdlKind == SdrHdlKind::MirrorAxis))
1396 {
1397 const SdrHdlList &aHdlList = GetHdlList ();
1398
1399 // delete the mirrored polygon, mirrors the original and draws
1400 // it anew
1401 SdrView::MovAction (rPnt);
1402 mpMirrorOverlay->SetMirrorAxis(
1403 aHdlList.GetHdl (SdrHdlKind::Ref1)->GetPos(),
1404 aHdlList.GetHdl (SdrHdlKind::Ref2)->GetPos());
1405 }
1406 }
1407 else
1408 {
1409 SdrView::MovAction (rPnt);
1410 }
1411 }
1412 else
1413 {
1414 SdrView::MovAction (rPnt);
1415 }
1416}
1417
1418// The End. Create object and any child objects through ImpCreate3DLathe.
1419// With the parameter value sal_True (SDefault: sal_False) is simply a
1420// rotation body created, without letting the user set the position of the
1421// axis. It is sufficient with this call, if an object is selected.
1422// (No initialization necessary)
1423
1424void E3dView::End3DCreation(bool bUseDefaultValuesForMirrorAxes)
1425{
1427
1428 if(!AreObjectsMarked())
1429 return;
1430
1431 if(bUseDefaultValuesForMirrorAxes)
1432 {
1434 if(aRect.GetWidth() <= 1)
1435 aRect.SetSize(Size(500, aRect.GetHeight()));
1436 if(aRect.GetHeight() <= 1)
1437 aRect.SetSize(Size(aRect.GetWidth(), 500));
1438
1439 basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top());
1440 basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom());
1441
1442 ConvertMarkedObjTo3D(false, aPnt1, aPnt2);
1443 }
1444 else
1445 {
1446 // Turn off helper overlay
1447 // Determine from the handle positions and the displacement of
1448 // the points
1449 const SdrHdlList &aHdlList = GetHdlList();
1450 Point aMirrorRef1 = aHdlList.GetHdl(SdrHdlKind::Ref1)->GetPos();
1451 Point aMirrorRef2 = aHdlList.GetHdl(SdrHdlKind::Ref2)->GetPos();
1452
1453 basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y());
1454 basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y());
1455
1456 ConvertMarkedObjTo3D(false, aPnt1, aPnt2);
1457 }
1458}
1459
1461{
1462}
1463
1465{
1466 mpMirrorOverlay.reset();
1467}
1468
1470{
1471 mpMirrorOverlay = nullptr;
1472}
1473
1475{
1476 const size_t nCount = GetMarkedObjectCount();
1477
1478 if (nCount > 0)
1479 {
1480 for (size_t i = 0; i < nCount; ++i)
1481 {
1483
1484 if (auto p3dObject = dynamic_cast< E3dObject* >(pObj))
1485 {
1486 if(!p3dObject->IsBreakObjPossible())
1487 return false;
1488 }
1489 else
1490 {
1491 return false;
1492 }
1493 }
1494 }
1495 else
1496 {
1497 return false;
1498 }
1499
1500 return true;
1501}
1502
1504{
1506 return;
1507
1508 // ALL selected objects are changed
1509 const size_t nCount = GetMarkedObjectCount();
1510
1511 BegUndo(SvxResId(RID_SVX_3D_UNDO_BREAK_LATHE));
1512 for(size_t a=0; a<nCount; ++a)
1513 {
1514 E3dObject* pObj = static_cast<E3dObject*>(GetMarkedObjectByIndex(a));
1515 BreakSingle3DObj(pObj);
1516 }
1517 DeleteMarked();
1518 EndUndo();
1519}
1520
1522{
1523 if(dynamic_cast< const E3dScene* >(pObj) != nullptr)
1524 {
1525 SdrObjList* pSubList = pObj->GetSubList();
1526 SdrObjListIter aIter(pSubList, SdrIterMode::Flat);
1527
1528 while(aIter.IsMore())
1529 {
1530 E3dObject* pSubObj = static_cast<E3dObject*>(aIter.Next());
1531 BreakSingle3DObj(pSubObj);
1532 }
1533 }
1534 else
1535 {
1536 rtl::Reference<SdrAttrObj> pNewObj = pObj->GetBreakObj();
1537 if (pNewObj)
1538 {
1540 {
1541 pNewObj->SetChanged();
1542 pNewObj->BroadcastObjectChange();
1543 }
1544 }
1545 }
1546}
1547
1549{
1550 // call parent
1552
1553 // Set other flags
1555 return;
1556
1557 const size_t nMarkCnt = GetMarkedObjectCount();
1558 bool bCompound = false;
1559 bool b3DObject = false;
1560 for(size_t nObjs = 0; (nObjs < nMarkCnt) && !bCompound; ++nObjs)
1561 {
1562 SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
1563 if(dynamic_cast< const E3dCompoundObject* >(pObj))
1564 bCompound = true;
1565 if(dynamic_cast< const E3dObject* >(pObj))
1566 b3DObject = true;
1567 }
1568
1569 // So far: there are two or more of any objects selected. See if
1570 // compound objects are involved. If yes, ban grouping.
1571 if(m_bGroupPossible && bCompound)
1572 m_bGroupPossible = false;
1573
1574 if(m_bUnGroupPossible && b3DObject)
1575 m_bUnGroupPossible = false;
1576
1577 if(m_bGrpEnterPossible && bCompound)
1578 m_bGrpEnterPossible = false;
1579}
1580
1581/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 nLineWidth
SlideSorterView & mrView
void SetAutoAdjustProjection(bool bAdjust)
Definition: camera3d.hxx:62
void SetFocalLength(double fLen)
Definition: camera3d.cxx:172
void SetPosAndLookAt(const basegfx::B3DPoint &rNewPos, const basegfx::B3DPoint &rNewLookAt)
Definition: camera3d.cxx:69
void SetViewWindow(double fX, double fY, double fW, double fH)
Definition: camera3d.cxx:41
Helper for 3d object changes affecting 2d geometry.
const basegfx::B3DRange & GetBoundVolume() const
Definition: obj3d.cxx:310
const basegfx::B3DHomMatrix & GetTransform() const
Definition: obj3d.hxx:112
const basegfx::B3DHomMatrix & GetFullTransform() const
Definition: obj3d.cxx:334
virtual rtl::Reference< SdrAttrObj > GetBreakObj()
Definition: obj3d.cxx:98
virtual E3dScene * getRootE3dSceneFromE3dObject() const override
Definition: scene3d.cxx:387
virtual void SetSelected(bool bNew) override
Definition: scene3d.cxx:725
void removeAllNonSelectedObjects()
Definition: scene3d.cxx:399
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE) override
Definition: scene3d.cxx:760
virtual SdrObjList * GetSubList() const override
Definition: scene3d.cxx:856
void SetDrawOnlySelected(bool bNew)
Definition: scene3d.hxx:113
void SetCamera(const Camera3D &rNewCamera)
Definition: scene3d.cxx:343
const Camera3D & GetCamera() const
Definition: scene3d.hxx:125
Derived class of SdrView to edit 3D objects.
Definition: view3d.hxx:42
E3dDefaultAttributes & Get3DDefaultAttributes()
Definition: view3d.hxx:72
void ConvertMarkedObjTo3D(bool bExtrude=true, const basegfx::B2DPoint &rPnt1=basegfx::B2DPoint(0.0, 0.0), const basegfx::B2DPoint &rPnt2=basegfx::B2DPoint(0.0, 1.0))
Definition: view3d.cxx:816
void End3DCreation(bool bUseDefaultValuesForMirrorAxes=false)
Definition: view3d.cxx:1424
void InitView()
Definition: view3d.cxx:1469
void Break3DObj()
Definition: view3d.cxx:1503
virtual bool BegDragObj(const Point &rPnt, OutputDevice *pOut, SdrHdl *pHdl, short nMinMov=-3, SdrDragMethod *pForcedMeth=nullptr) override
Definition: view3d.cxx:1139
bool IsConvertTo3DObjPossible() const
Definition: view3d.cxx:585
bool Is3DRotationCreationActive() const
Definition: view3d.hxx:101
virtual void DrawMarkedObj(OutputDevice &rOut) const override
Definition: view3d.cxx:212
void BreakSingle3DObj(E3dObject *pObj)
Definition: view3d.cxx:1521
bool IsBreak3DObjPossible() const
Definition: view3d.cxx:1474
E3dView(SdrModel &rSdrModel, OutputDevice *pOut)
Definition: view3d.cxx:201
std::unique_ptr< Impl3DMirrorConstructOverlay > mpMirrorOverlay
Definition: view3d.hxx:47
virtual void CheckPossibilities() override
Definition: view3d.cxx:1548
void ImpCreateSingle3DObjectFlat(E3dScene *pScene, SdrObject *pObj, bool bExtrude, double fDepth, basegfx::B2DHomMatrix const &rLatheMat)
Definition: view3d.cxx:684
static void DoDepthArrange(E3dScene const *pScene, double fDepth)
Definition: view3d.cxx:1013
void ImpChangeSomeAttributesFor3DConversion(SdrObject *pObj)
Definition: view3d.cxx:633
void ImpIsConvertTo3DPossible(SdrObject const *pObj, bool &rAny3D, bool &rGroupSelected) const
Definition: view3d.cxx:608
void ImpChangeSomeAttributesFor3DConversion2(SdrObject *pObj)
Definition: view3d.cxx:658
void Start3DCreation()
Definition: view3d.cxx:1290
virtual ~E3dView() override
Definition: view3d.cxx:1460
rtl::Reference< E3dScene > SetCurrent3DObj(E3dObject *p3DObj)
Definition: view3d.cxx:1252
bool ImpCloneAll3DObjectsToDestScene(E3dScene const *pSrcScene, E3dScene *pDstScene, Point aOffset)
Definition: view3d.cxx:483
double GetDefaultCamFocal()
Definition: view3d1.cxx:172
void InitScene(E3dScene *pScene, double fW, double fH, double fCamZ)
Definition: view3d.cxx:1274
void ResetCreationActive()
Definition: view3d.cxx:1464
void ImpCreate3DObject(E3dScene *pScene, SdrObject *pObj, bool bExtrude, double fDepth, basegfx::B2DHomMatrix const &rLatheMat)
Definition: view3d.cxx:759
virtual bool Paste(const SdrModel &rMod, const Point &rPos, SdrObjList *pLst, SdrInsertFlags nOptions) override
Definition: view3d.cxx:430
virtual void MovAction(const Point &rPnt) override
Definition: view3d.cxx:1382
double GetDefaultCamPosZ()
Definition: view3d1.cxx:167
virtual std::unique_ptr< SdrModel > CreateMarkedObjModel() const override
Definition: view3d.cxx:310
const E3dView & mrView
Definition: view3d.cxx:67
void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
Definition: view3d.cxx:136
sdr::overlay::OverlayObjectList maObjects
Definition: view3d.cxx:64
drawinglayer::primitive2d::Primitive2DContainer maFullOverlay
Definition: view3d.cxx:76
Impl3DMirrorConstructOverlay(const Impl3DMirrorConstructOverlay &)=delete
Impl3DMirrorConstructOverlay & operator=(const Impl3DMirrorConstructOverlay &)=delete
basegfx::B2DPolyPolygon * mpPolygons
Definition: view3d.cxx:73
virtual void MovAction(const Point &rPnt) override
Definition: svdcrtv.cxx:206
virtual bool BegDragObj(const Point &rPnt, OutputDevice *pOut, SdrHdl *pHdl, short nMinMov=-3, SdrDragMethod *pForcedMeth=nullptr)
Definition: svddrgv.cxx:183
bool IsSolidDragging() const
Definition: svddrgv.cxx:912
SdrHdlKind meDragHdl
Definition: svddrgv.hxx:46
virtual void SetMarkHandles(SfxViewShell *pOtherShell) override
Definition: svddrgv.cxx:896
SdrHdl * GetDragHdl() const
Definition: svddrgv.hxx:104
virtual void CheckPossibilities()
Definition: svdedtv.cxx:475
bool IsConvertToPolyObjPossible() const
Definition: svdedtv.hxx:351
bool m_bGroupPossible
Definition: svdedtv.hxx:82
void ReplaceObjectAtView(SdrObject *pOldObj, SdrPageView &rPV, SdrObject *pNewObj, bool bMark=true)
Definition: svdedtv.cxx:1023
bool IsUndoEnabled() const
Definition: svdedtv.cxx:1059
bool IsConvertToPathObjPossible() const
Definition: svdedtv.hxx:350
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svdedtv.hxx:182
void BegUndo()
Definition: svdedtv.hxx:178
bool InsertObjectAtView(SdrObject *pObj, SdrPageView &rPV, SdrInsertFlags nOptions=SdrInsertFlags::NONE)
Definition: svdedtv.cxx:981
bool IsImportMtfPossible() const
Definition: svdedtv.hxx:409
bool m_bGrpEnterPossible
Definition: svdedtv.hxx:84
bool m_bUnGroupPossible
Definition: svdedtv.hxx:83
void EndUndo()
Definition: svdedtv.cxx:295
void ImpGetPasteObjList(Point &rPos, SdrObjList *&rpLst)
Definition: svdxcgv.cxx:97
virtual void DrawMarkedObj(OutputDevice &rOut) const
Definition: svdxcgv.cxx:702
virtual bool Paste(const SdrModel &rMod, const Point &rPos, SdrObjList *pLst, SdrInsertFlags nOptions)
Definition: svdxcgv.cxx:231
virtual std::unique_ptr< SdrModel > CreateMarkedObjModel() const
Definition: svdxcgv.cxx:716
SdrHdl * GetHdl(size_t nNum) const
Definition: svdhdl.hxx:460
SdrHdlKind GetKind() const
Definition: svdhdl.hxx:194
bool IsVertexHdl() const
Definition: svdhdl.hxx:213
bool IsCornerHdl() const
Definition: svdhdl.hxx:212
const Point & GetPos() const
Definition: svdhdl.hxx:197
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:230
bool IsObjMarked(SdrObject const *pObj) const
Definition: svdmrkv.cxx:2195
const SdrMarkList & GetMarkedObjectList() const
Definition: svdmrkv.hxx:258
bool AreObjectsMarked() const
Definition: svdmrkv.hxx:266
void SortMarkedObjects() const
Definition: svdmrkv.hxx:265
SdrObject * GetMarkedObjectByIndex(size_t nNum) const
Definition: svdmrkv.hxx:263
const SdrHdlList & GetHdlList() const
Definition: svdmrkv.hxx:360
SdrMarkList & GetMarkedObjectListWriteAccess()
Definition: svdmrkv.hxx:254
size_t GetMarkedObjectCount() const
Definition: svdmrkv.hxx:264
Point maRef1
Definition: svdmrkv.hxx:105
SdrDragMode meDragMode
Definition: svdmrkv.hxx:118
SdrMark * GetSdrMarkByIndex(size_t nNum) const
Definition: svdmrkv.hxx:262
Point maRef2
Definition: svdmrkv.hxx:106
SdrPageView * GetSdrPageViewOfMarkedByIndex(size_t nNum) const
Definition: svdmrkv.hxx:261
const tools::Rectangle & GetAllMarkedRect() const
Definition: svdmrkv.hxx:426
bool MarkObj(const Point &rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false)
Definition: svdmrkv.cxx:1928
Everything a View needs to know about a selected object.
Definition: svdmark.hxx:45
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:68
bool IsUndoEnabled() const
returns true if undo is currently enabled This returns false if undo was disabled using EnableUndo( f...
Definition: svdmodel.cxx:525
const SdrPage * GetPage(sal_uInt16 nPgNum) const
Definition: svdmodel.cxx:1790
sal_uInt16 GetPageCount() const
Definition: svdmodel.cxx:1800
virtual void MarkListHasChanged() override
Definition: svdedxv.cxx:2506
SdrObject * Next()
Definition: svditer.hxx:63
bool IsMore() const
Definition: svditer.hxx:62
const tools::Rectangle & GetAllObjBoundRect() const
Definition: svdpage.cxx:740
SdrObject * GetObj(size_t nNum) const
Definition: svdpage.cxx:822
size_t GetObjCount() const
Definition: svdpage.cxx:816
virtual SdrObject * getSdrObjectFromSdrObjList() const
Definition: svdpage.cxx:128
Abstract DrawObject.
Definition: svdobj.hxx:257
virtual basegfx::B2DPolyPolygon TakeXorPoly() const
The Xor-Polygon is required by the View to drag the object.
Definition: svdobj.cxx:1091
void SingleObjectPainter(OutputDevice &rOut) const
Definition: svdobj.cxx:1019
virtual SdrObjList * GetSubList() const
Definition: svdobj.cxx:710
rtl::Reference< SdrObject > ConvertToPolyObj(bool bBezier, bool bLineToArea) const
Definition: svdobj.cxx:2618
static rtl::Reference< T > Clone(T const &rObj, SdrModel &rTargetModel)
Definition: svdobj.hxx:445
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:284
virtual const tools::Rectangle & GetSnapRect() const
Definition: svdobj.cxx:1660
SfxStyleSheet * GetStyleSheet() const
Definition: svdobj.cxx:2242
bool IsGroupObject() const
Definition: svdobj.cxx:705
SdrPage * getSdrPageFromSdrObject() const
Definition: svdobj.cxx:274
virtual void SetSnapRect(const tools::Rectangle &rRect)
Definition: svdobj.cxx:1685
rtl::Reference< SdrObject > ConvertToContourObj(SdrObject *pRet, bool bForceLineDash=false) const
Definition: svdobj.cxx:2579
const SfxItemSet & GetMergedItemSet() const
Definition: svdobj.cxx:1972
virtual SdrLayerID GetLayer() const
Definition: svdobj.cxx:640
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1982
sal_uInt32 PageWindowCount() const
Definition: svdpagv.hxx:89
A SdrPage contains exactly one SdrObjList and a description of the physical page dimensions (size / m...
Definition: svdpage.hxx:377
SdrPaintWindow * GetPaintWindow(sal_uInt32 nIndex) const
Definition: svdpntv.cxx:75
OutputDevice * GetFirstOutputDevice() const
Definition: svdpntv.cxx:91
SdrModel * GetModel() const
Definition: svdpntv.hxx:261
sal_uInt32 PaintWindowCount() const
Definition: svdpntv.hxx:219
SdrPageView * GetSdrPageView() const
Definition: svdpntv.hxx:300
rtl::Reference< sdr::overlay::OverlayManager > const & GetOverlayManager() const
const basegfx::B2DPolyPolygon & GetPathPoly() const
Definition: svdopath.hxx:141
bool IsClosed() const
Definition: svdopath.hxx:146
virtual void DeleteMarked()
Definition: svdview.cxx:1409
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
const Color & GetValue() const
void rotate(double fRadiant)
void translate(double fX, double fY)
void scale(double fX, double fY)
bool isIdentity() const
void transform(const basegfx::B2DHomMatrix &rMatrix)
sal_uInt32 count() const
B2DPoint getCenter() const
void rotate(double fAngleX, double fAngleY, double fAngleZ)
void translate(double fX, double fY, double fZ)
void scale(double fX, double fY, double fZ)
BASEGFX_DLLPUBLIC void transform(const B3DHomMatrix &rMatrix)
B3DVector getRange() const
double getHeight() const
double getMaxZ() const
double getDepth() const
double getWidth() const
B3DPoint getCenter() const
TYPE getMinX() const
void expand(const Tuple2D< TYPE > &rTuple)
TYPE getHeight() const
TYPE getX() const
TYPE getY() const
void setX(TYPE fX)
TYPE getX() const
TYPE getZ() const
TYPE getY() const
void append(std::unique_ptr< OverlayObject > pOverlayObject)
constexpr Point Center() const
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
void SetSize(const Size &)
constexpr tools::Long Right() const
constexpr tools::Long GetHeight() const
tools::Rectangle & Union(const tools::Rectangle &rRect)
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
int nCount
#define DBG_ASSERT(sCon, aError)
E3dDragConstraint
Definition: def3d.hxx:28
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
std::size_t mnCount
constexpr TypedWhichId< SvxColorItem > EE_CHAR_COLOR(EE_CHAR_START+0)
EmbeddedObjectRef * pObject
uno_Any a
bool equalZero(const T &rfVal)
B2DPolyPolygon prepareForPolygonOperation(const B2DPolygon &rCandidate)
B2DHomMatrix createRotateAroundPoint(double fPointX, double fPointY, double fRadiant)
B2DPolyPolygon solvePolygonOperationAnd(const B2DPolyPolygon &rCandidateA, const B2DPolyPolygon &rCandidateB)
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
B2DRange getRange(const B2DPolygon &rCandidate)
B2IRange fround(const B2DRange &rRange)
constexpr double deg2rad(double v)
int i
long Long
static SfxItemSet & rSet
constexpr TypedWhichId< SfxUInt32Item > SDRATTR_3DOBJ_DEPTH(SDRATTR_3DOBJ_FIRST+2)
SdrInsertFlags
Definition: svdedtv.hxx:59
SdrHdlKind
Definition: svdhdl.hxx:53
SfxBoolItem makeSvx3DDoubleSidedItem(bool bVal)
Definition: svx3ditems.hxx:58
oslFileHandle & pOut
constexpr TypedWhichId< XFillColorItem > XATTR_FILLCOLOR(XATTR_FILL_FIRST+1)
constexpr TypedWhichId< XLineColorItem > XATTR_LINECOLOR(XATTR_LINE_FIRST+3)
constexpr TypedWhichId< XLineWidthItem > XATTR_LINEWIDTH(XATTR_LINE_FIRST+2)
constexpr TypedWhichId< XLineStyleItem > XATTR_LINESTYLE(XATTR_LINE_FIRST)
constexpr TypedWhichId< XFillStyleItem > XATTR_FILLSTYLE(XATTR_FILL_FIRST)