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