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 "svx/svdstr.hrc" 32 #include "svx/svdglob.hxx" 33 #include "svx/svditer.hxx" 34 35 #if defined( UNX ) || defined( ICC ) 36 #include <stdlib.h> 37 #endif 38 #include "svx/globl3d.hxx" 39 #include <svx/svdpage.hxx> 40 #include <svl/style.hxx> 41 #include <svx/scene3d.hxx> 42 #include <svx/e3dundo.hxx> 43 #include <svx/svdtrans.hxx> 44 #include <svx/svxids.hrc> 45 #include <editeng/colritem.hxx> 46 #include <svx/e3ditem.hxx> 47 #include <svx/xlntrit.hxx> 48 #include <svx/xfltrit.hxx> 49 #include <svx/svx3ditems.hxx> 50 #include <svl/whiter.hxx> 51 #include <svx/xflftrit.hxx> 52 #include <svx/sdr/properties/e3dsceneproperties.hxx> 53 #include <svx/sdr/contact/viewcontactofe3dscene.hxx> 54 #include <svx/svddrag.hxx> 55 #include <helperminimaldepth3d.hxx> 56 #include <algorithm> 57 #include <drawinglayer/geometry/viewinformation3d.hxx> 58 #include <basegfx/polygon/b2dpolypolygontools.hxx> 59 #include <svx/e3dsceneupdater.hxx> 60 61 #define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() 62 63 ////////////////////////////////////////////////////////////////////////////// 64 // #110988# 65 66 class ImpRemap3DDepth 67 { 68 sal_uInt32 mnOrdNum; 69 double mfMinimalDepth; 70 71 // bitfield 72 unsigned mbIsScene : 1; 73 74 public: 75 ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth); 76 ImpRemap3DDepth(sal_uInt32 nOrdNum); 77 ~ImpRemap3DDepth(); 78 79 // for ::std::sort 80 bool operator<(const ImpRemap3DDepth& rComp) const; 81 82 sal_uInt32 GetOrdNum() const { return mnOrdNum; } 83 sal_Bool IsScene() const { return mbIsScene; } 84 }; 85 86 ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth) 87 : mnOrdNum(nOrdNum), 88 mfMinimalDepth(fMinimalDepth), 89 mbIsScene(sal_False) 90 { 91 } 92 93 ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum) 94 : mnOrdNum(nOrdNum), 95 mbIsScene(sal_True) 96 { 97 } 98 99 ImpRemap3DDepth::~ImpRemap3DDepth() 100 { 101 } 102 103 bool ImpRemap3DDepth::operator<(const ImpRemap3DDepth& rComp) const 104 { 105 if(IsScene()) 106 { 107 return sal_False; 108 } 109 else 110 { 111 if(rComp.IsScene()) 112 { 113 return sal_True; 114 } 115 else 116 { 117 return mfMinimalDepth < rComp.mfMinimalDepth; 118 } 119 } 120 } 121 122 // typedefs for a vector of ImpRemap3DDepths 123 typedef ::std::vector< ImpRemap3DDepth > ImpRemap3DDepthVector; 124 125 ////////////////////////////////////////////////////////////////////////////// 126 // #110988# 127 128 class Imp3DDepthRemapper 129 { 130 ImpRemap3DDepthVector maVector; 131 132 public: 133 Imp3DDepthRemapper(E3dScene& rScene); 134 ~Imp3DDepthRemapper(); 135 136 sal_uInt32 RemapOrdNum(sal_uInt32 nOrdNum) const; 137 }; 138 139 Imp3DDepthRemapper::Imp3DDepthRemapper(E3dScene& rScene) 140 { 141 // only called when rScene.GetSubList() and nObjCount > 1L 142 SdrObjList* pList = rScene.GetSubList(); 143 const sal_uInt32 nObjCount(pList->GetObjCount()); 144 145 for(sal_uInt32 a(0L); a < nObjCount; a++) 146 { 147 SdrObject* pCandidate = pList->GetObj(a); 148 149 if(pCandidate) 150 { 151 if(pCandidate->ISA(E3dCompoundObject)) 152 { 153 // single 3d object, calc depth 154 const double fMinimalDepth(getMinimalDepthInViewCoordinates(static_cast< const E3dCompoundObject& >(*pCandidate))); 155 ImpRemap3DDepth aEntry(a, fMinimalDepth); 156 maVector.push_back(aEntry); 157 } 158 else 159 { 160 // scene, use standard entry for scene 161 ImpRemap3DDepth aEntry(a); 162 maVector.push_back(aEntry); 163 } 164 } 165 } 166 167 // now, we need to sort the maVector by it's members minimal depth. The 168 // smaller, the nearer to the viewer. 169 ::std::sort(maVector.begin(), maVector.end()); 170 } 171 172 Imp3DDepthRemapper::~Imp3DDepthRemapper() 173 { 174 } 175 176 sal_uInt32 Imp3DDepthRemapper::RemapOrdNum(sal_uInt32 nOrdNum) const 177 { 178 if(nOrdNum < maVector.size()) 179 { 180 nOrdNum = maVector[(maVector.size() - 1) - nOrdNum].GetOrdNum(); 181 } 182 183 return nOrdNum; 184 } 185 186 ////////////////////////////////////////////////////////////////////////////// 187 // BaseProperties section 188 189 sdr::properties::BaseProperties* E3dScene::CreateObjectSpecificProperties() 190 { 191 return new sdr::properties::E3dSceneProperties(*this); 192 } 193 194 ////////////////////////////////////////////////////////////////////////////// 195 // #110094# DrawContact section 196 197 sdr::contact::ViewContact* E3dScene::CreateObjectSpecificViewContact() 198 { 199 return new sdr::contact::ViewContactOfE3dScene(*this); 200 } 201 202 //////////////////////////////////////////////////////////////////////////////////////////////////// 203 204 TYPEINIT1(E3dScene, E3dObject); 205 206 /************************************************************************* 207 |* 208 |* E3dScene-Konstruktor 209 |* 210 \************************************************************************/ 211 212 E3dScene::E3dScene() 213 : E3dObject(), 214 aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()), 215 mp3DDepthRemapper(0L), 216 bDrawOnlySelected(false) 217 { 218 // Defaults setzen 219 E3dDefaultAttributes aDefault; 220 SetDefaultAttributes(aDefault); 221 } 222 223 E3dScene::E3dScene(E3dDefaultAttributes& rDefault) 224 : E3dObject(), 225 aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()), 226 mp3DDepthRemapper(0L), 227 bDrawOnlySelected(false) 228 { 229 // Defaults setzen 230 SetDefaultAttributes(rDefault); 231 } 232 233 void E3dScene::SetDefaultAttributes(E3dDefaultAttributes& /*rDefault*/) 234 { 235 // Fuer OS/2 die FP-Exceptions abschalten 236 #if defined(OS2) 237 #define SC_FPEXCEPTIONS_ON() _control87( MCW_EM, 0 ) 238 #define SC_FPEXCEPTIONS_OFF() _control87( MCW_EM, MCW_EM ) 239 SC_FPEXCEPTIONS_OFF(); 240 #endif 241 242 // Fuer WIN95/NT die FP-Exceptions abschalten 243 #if defined(WNT) 244 #define SC_FPEXCEPTIONS_ON() _control87( _MCW_EM, 0 ) 245 #define SC_FPEXCEPTIONS_OFF() _control87( _MCW_EM, _MCW_EM ) 246 SC_FPEXCEPTIONS_OFF(); 247 #endif 248 249 // Defaults setzen 250 aCamera.SetViewWindow(-2, -2, 4, 4); 251 aCameraSet.SetDeviceRectangle(-2, 2, -2, 2); 252 aCamera.SetDeviceWindow(Rectangle(0, 0, 10, 10)); 253 Rectangle aRect(0, 0, 10, 10); 254 aCameraSet.SetViewportRectangle(aRect); 255 256 // set defaults for Camera from ItemPool 257 aCamera.SetProjection(GetPerspective()); 258 basegfx::B3DPoint aActualPosition(aCamera.GetPosition()); 259 double fNew = GetDistance(); 260 261 if(fabs(fNew - aActualPosition.getZ()) > 1.0) 262 { 263 aCamera.SetPosition( basegfx::B3DPoint( aActualPosition.getX(), aActualPosition.getY(), fNew) ); 264 } 265 266 fNew = GetFocalLength() / 100.0; 267 aCamera.SetFocalLength(fNew); 268 } 269 270 /************************************************************************* 271 |* 272 |* Destruktor 273 |* 274 \************************************************************************/ 275 276 E3dScene::~E3dScene() 277 { 278 // #110988# 279 ImpCleanup3DDepthMapper(); 280 } 281 282 basegfx::B2DPolyPolygon E3dScene::TakeXorPoly() const 283 { 284 const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(GetViewContact()); 285 const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); 286 const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe()); 287 288 basegfx::B2DPolyPolygon aRetval(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon, 289 aViewInfo3D.getObjectToView())); 290 aRetval.transform(rVCScene.getObjectTransformation()); 291 292 return aRetval; 293 } 294 295 // #110988# 296 void E3dScene::ImpCleanup3DDepthMapper() 297 { 298 if(mp3DDepthRemapper) 299 { 300 delete mp3DDepthRemapper; 301 mp3DDepthRemapper = 0L; 302 } 303 } 304 305 // #110988# 306 sal_uInt32 E3dScene::RemapOrdNum(sal_uInt32 nNewOrdNum) const 307 { 308 if(!mp3DDepthRemapper) 309 { 310 const sal_uInt32 nObjCount(GetSubList() ? GetSubList()->GetObjCount() : 0L); 311 312 if(nObjCount > 1L) 313 { 314 ((E3dScene*)this)->mp3DDepthRemapper = new Imp3DDepthRemapper((E3dScene&)(*this)); 315 } 316 } 317 318 if(mp3DDepthRemapper) 319 { 320 return mp3DDepthRemapper->RemapOrdNum(nNewOrdNum); 321 } 322 323 return nNewOrdNum; 324 } 325 326 /************************************************************************* 327 |* 328 |* Identifier zurueckgeben 329 |* 330 \************************************************************************/ 331 332 sal_uInt16 E3dScene::GetObjIdentifier() const 333 { 334 return E3D_SCENE_ID; 335 } 336 337 void E3dScene::SetBoundRectDirty() 338 { 339 E3dScene* pScene = GetScene(); 340 341 if(pScene == this) 342 { 343 // avoid resetting aOutRect which in case of a 3D scene used as 2d object 344 // is model data,not re-creatable view data 345 } 346 else 347 { 348 // if not the outmost scene it is used as group in 3d, call parent 349 E3dObject::SetBoundRectDirty(); 350 } 351 } 352 353 /************************************************************************* 354 |* 355 |* SetSnapRect 356 |* 357 \************************************************************************/ 358 359 void E3dScene::NbcSetSnapRect(const Rectangle& rRect) 360 { 361 SetRectsDirty(); 362 E3dObject::NbcSetSnapRect(rRect); 363 aCamera.SetDeviceWindow(rRect); 364 aCameraSet.SetViewportRectangle((Rectangle&)rRect); 365 366 // #110988# 367 ImpCleanup3DDepthMapper(); 368 } 369 370 /************************************************************************* 371 |* 372 |* Objekt verschieben 373 |* 374 \************************************************************************/ 375 376 void E3dScene::NbcMove(const Size& rSize) 377 { 378 Rectangle aNewSnapRect = GetSnapRect(); 379 MoveRect(aNewSnapRect, rSize); 380 NbcSetSnapRect(aNewSnapRect); 381 } 382 383 /************************************************************************* 384 |* 385 |* Objekt Resizen 386 |* 387 \************************************************************************/ 388 389 void E3dScene::NbcResize(const Point& rRef, const Fraction& rXFact, 390 const Fraction& rYFact) 391 { 392 Rectangle aNewSnapRect = GetSnapRect(); 393 ResizeRect(aNewSnapRect, rRef, rXFact, rYFact); 394 NbcSetSnapRect(aNewSnapRect); 395 } 396 397 /************************************************************************* 398 |* 399 |* Neue Kamera setzen, und dabei die Szene und ggf. das BoundVolume 400 |* als geaendert markieren 401 |* 402 \************************************************************************/ 403 404 void E3dScene::SetCamera(const Camera3D& rNewCamera) 405 { 406 // Alte Kamera setzen 407 aCamera = rNewCamera; 408 ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera(); 409 410 SetRectsDirty(); 411 412 // Neue Kamera aus alter fuellen 413 Camera3D& rCam = (Camera3D&)GetCamera(); 414 415 // Ratio abschalten 416 if(rCam.GetAspectMapping() == AS_NO_MAPPING) 417 GetCameraSet().SetRatio(0.0); 418 419 // Abbildungsgeometrie setzen 420 basegfx::B3DPoint aVRP(rCam.GetViewPoint()); 421 basegfx::B3DVector aVPN(aVRP - rCam.GetVRP()); 422 basegfx::B3DVector aVUV(rCam.GetVUV()); 423 424 // #91047# use SetViewportValues() to set VRP, VPN and VUV as vectors, too. 425 // Else these values would not be exported/imported correctly. 426 GetCameraSet().SetViewportValues(aVRP, aVPN, aVUV); 427 428 // Perspektive setzen 429 GetCameraSet().SetPerspective(rCam.GetProjection() == PR_PERSPECTIVE); 430 GetCameraSet().SetViewportRectangle((Rectangle&)rCam.GetDeviceWindow()); 431 432 // #110988# 433 ImpCleanup3DDepthMapper(); 434 } 435 436 /************************************************************************* 437 |* 438 |* 3D-Objekt einfuegen 439 |* 440 \************************************************************************/ 441 442 void E3dScene::NewObjectInserted(const E3dObject* p3DObj) 443 { 444 E3dObject::NewObjectInserted(p3DObj); 445 446 if ( p3DObj == this ) 447 return; 448 449 // #110988# 450 ImpCleanup3DDepthMapper(); 451 } 452 453 /************************************************************************* 454 |* 455 |* Parent ueber Aenderung eines Childs informieren 456 |* 457 \************************************************************************/ 458 459 void E3dScene::StructureChanged() 460 { 461 E3dObject::StructureChanged(); 462 SetRectsDirty(); 463 464 // #110988# 465 ImpCleanup3DDepthMapper(); 466 } 467 468 /************************************************************************* 469 |* 470 |* Uebergeordnetes Szenenobjekt bestimmen 471 |* 472 \************************************************************************/ 473 474 E3dScene* E3dScene::GetScene() const 475 { 476 if(GetParentObj()) 477 return GetParentObj()->GetScene(); 478 else 479 return (E3dScene*)this; 480 } 481 482 void E3dScene::removeAllNonSelectedObjects() 483 { 484 E3DModifySceneSnapRectUpdater aUpdater(this); 485 486 for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) 487 { 488 SdrObject* pObj = maSubList.GetObj(a); 489 490 if(pObj) 491 { 492 bool bRemoveObject(false); 493 494 if(pObj->ISA(E3dScene)) 495 { 496 E3dScene* pScene = (E3dScene*)pObj; 497 498 // iterate over this sub-scene 499 pScene->removeAllNonSelectedObjects(); 500 501 // check object count. Empty scenes can be deleted 502 const sal_uInt32 nObjCount(pScene->GetSubList() ? pScene->GetSubList()->GetObjCount() : 0); 503 504 if(!nObjCount) 505 { 506 // all objects removed, scene can be removed, too 507 bRemoveObject = true; 508 } 509 } 510 else if(pObj->ISA(E3dCompoundObject)) 511 { 512 E3dCompoundObject* pCompound = (E3dCompoundObject*)pObj; 513 514 if(!pCompound->GetSelected()) 515 { 516 bRemoveObject = true; 517 } 518 } 519 520 if(bRemoveObject) 521 { 522 maSubList.NbcRemoveObject(pObj->GetOrdNum()); 523 a--; 524 SdrObject::Free(pObj); 525 } 526 } 527 } 528 } 529 530 /************************************************************************* 531 |* 532 |* Zuweisungsoperator 533 |* 534 \************************************************************************/ 535 536 void E3dScene::operator=(const SdrObject& rObj) 537 { 538 E3dObject::operator=(rObj); 539 540 const E3dScene& r3DObj = (const E3dScene&) rObj; 541 aCamera = r3DObj.aCamera; 542 543 // neu ab 377: 544 aCameraSet = r3DObj.aCameraSet; 545 ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera(); 546 547 // SetSnapRect(r3DObj.GetSnapRect()); 548 InvalidateBoundVolume(); 549 RebuildLists(); 550 SetRectsDirty(); 551 552 // #110988# 553 ImpCleanup3DDepthMapper(); 554 555 // #i101941# 556 // After a Scene as model object is cloned, the used 557 // ViewContactOfE3dScene is created and partially used 558 // to calculate Bound/SnapRects, but - since quite some 559 // values are buffered at the VC - not really well 560 // initialized. It would be possible to always watch for 561 // preconditions of buffered data, but this would be expensive 562 // and would create a lot of short living data structures. 563 // It is currently better to flush that data, e.g. by using 564 // ActionChanged at the VC which will for this class 565 // flush that cached data and initalize it's valid reconstruction 566 GetViewContact().ActionChanged(); 567 } 568 569 /************************************************************************* 570 |* 571 |* Licht- und Labelobjektlisten neu aufbauen (nach Laden, Zuweisung) 572 |* 573 \************************************************************************/ 574 575 void E3dScene::RebuildLists() 576 { 577 // zuerst loeschen 578 SdrLayerID nCurrLayerID = GetLayer(); 579 580 SdrObjListIter a3DIterator(maSubList, IM_FLAT); 581 582 // dann alle Objekte in der Szene pruefen 583 while ( a3DIterator.IsMore() ) 584 { 585 E3dObject* p3DObj = (E3dObject*) a3DIterator.Next(); 586 p3DObj->NbcSetLayer(nCurrLayerID); 587 NewObjectInserted(p3DObj); 588 } 589 } 590 591 /************************************************************************* 592 |* 593 |* erstelle neues GeoData-Objekt 594 |* 595 \************************************************************************/ 596 597 SdrObjGeoData *E3dScene::NewGeoData() const 598 { 599 return new E3DSceneGeoData; 600 } 601 602 /************************************************************************* 603 |* 604 |* uebergebe aktuelle werte an das GeoData-Objekt 605 |* 606 \************************************************************************/ 607 608 void E3dScene::SaveGeoData(SdrObjGeoData& rGeo) const 609 { 610 E3dObject::SaveGeoData (rGeo); 611 612 ((E3DSceneGeoData &) rGeo).aCamera = aCamera; 613 } 614 615 /************************************************************************* 616 |* 617 |* uebernehme werte aus dem GeoData-Objekt 618 |* 619 \************************************************************************/ 620 621 void E3dScene::RestGeoData(const SdrObjGeoData& rGeo) 622 { 623 // #i94832# removed E3DModifySceneSnapRectUpdater here. 624 // It should not be needed, is already part of E3dObject::RestGeoData 625 E3dObject::RestGeoData (rGeo); 626 SetCamera (((E3DSceneGeoData &) rGeo).aCamera); 627 } 628 629 /************************************************************************* 630 |* 631 |* Am StyleSheet wurde etwas geaendert, also Scene aendern 632 |* 633 \************************************************************************/ 634 635 void E3dScene::Notify(SfxBroadcaster &rBC, const SfxHint &rHint) 636 { 637 SetRectsDirty(); 638 E3dObject::Notify(rBC, rHint); 639 } 640 641 /************************************************************************* 642 |* 643 \************************************************************************/ 644 645 void E3dScene::RotateScene (const Point& rRef, long /*nWink*/, double sn, double cs) 646 { 647 Point UpperLeft, LowerRight, Center, NewCenter; 648 649 UpperLeft = aOutRect.TopLeft(); 650 LowerRight = aOutRect.BottomRight(); 651 652 long dxOutRectHalf = labs(UpperLeft.X() - LowerRight.X()); 653 dxOutRectHalf /= 2; 654 long dyOutRectHalf = labs(UpperLeft.Y() - LowerRight.Y()); 655 dyOutRectHalf /= 2; 656 657 Rectangle RectQuelle(aOutRect), RectZiel(aOutRect); 658 659 // Nur der Mittelpunkt wird bewegt. Die Ecken werden von NbcMove bewegt. 660 // Fuer das Drehen wird von mir ein kartesisches Koordinatensystem verwendet in dem der Drehpunkt 661 // der Nullpunkt ist und die Y- Achse nach oben ansteigt, die X-Achse nach rechts. 662 // Dies muss bei den Y-Werten beachtet werden. (Auf dem Blatt zeigt die Y-Achse nach unten 663 Center.X() = (UpperLeft.X() + dxOutRectHalf) - rRef.X(); 664 Center.Y() = -((UpperLeft.Y() + dyOutRectHalf) - rRef.Y()); 665 // Ein paar Spezialfaelle zuerst abhandeln (n*90 Grad n ganzzahlig) 666 if (sn==1.0 && cs==0.0) { // 90deg 667 NewCenter.X() = -Center.Y(); 668 NewCenter.Y() = -Center.X(); 669 } else if (sn==0.0 && cs==-1.0) { // 180deg 670 NewCenter.X() = -Center.X(); 671 NewCenter.Y() = -Center.Y(); 672 } else if (sn==-1.0 && cs==0.0) { // 270deg 673 NewCenter.X() = Center.Y(); 674 NewCenter.Y() = -Center.X(); 675 } 676 else // Hier wird um einen beliebigen Winkel in mathematisch positiver Richtung gedreht! 677 { // xneu = x * cos(alpha) - y * sin(alpha) 678 // yneu = x * sin(alpha) + y * cos(alpha) 679 // Unten Rechts wird nicht gedreht: die Seiten von RectQuelle muessen parallel 680 // zu den Koordinatenachsen bleiben. 681 NewCenter.X() = (long) (Center.X() * cs - Center.Y() * sn); 682 NewCenter.Y() = (long) (Center.X() * sn + Center.Y() * cs); 683 } 684 685 Size Differenz; 686 Point DiffPoint = (NewCenter - Center); 687 Differenz.Width() = DiffPoint.X(); 688 Differenz.Height() = -DiffPoint.Y(); // Man beachte dass die Y-Achse nach unten positiv gezaehlt wird. 689 NbcMove (Differenz); // fuehrt die eigentliche Koordinatentransformation durch. 690 } 691 692 /************************************************************************* 693 |* 694 |* Get the name of the object (singular) 695 |* 696 \************************************************************************/ 697 698 void E3dScene::TakeObjNameSingul(XubString& rName) const 699 { 700 rName=ImpGetResStr(STR_ObjNameSingulScene3d); 701 702 String aName( GetName() ); 703 if(aName.Len()) 704 { 705 rName += sal_Unicode(' '); 706 rName += sal_Unicode('\''); 707 rName += aName; 708 rName += sal_Unicode('\''); 709 } 710 } 711 712 /************************************************************************* 713 |* 714 |* Get the name of the object (plural) 715 |* 716 \************************************************************************/ 717 718 void E3dScene::TakeObjNamePlural(XubString& rName) const 719 { 720 rName=ImpGetResStr(STR_ObjNamePluralScene3d); 721 } 722 723 /************************************************************************* 724 |* 725 |* Die NbcRotate-Routine ueberlaedt die des SdrObject. Die Idee ist die Scene 726 |* drehen zu koennen und relativ zur Lage der Scene dann auch die Objekte 727 |* in der Scene 728 |* 729 \************************************************************************/ 730 731 void E3dScene::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix) 732 { 733 if(maTransformation != rMatrix) 734 { 735 // call parent 736 E3dObject::NbcSetTransform(rMatrix); 737 } 738 } 739 740 void E3dScene::SetTransform(const basegfx::B3DHomMatrix& rMatrix) 741 { 742 if(rMatrix != maTransformation) 743 { 744 // call parent 745 E3dObject::SetTransform(rMatrix); 746 } 747 } 748 749 void E3dScene::NbcRotate(const Point& rRef, long nWink, double sn, double cs) 750 { 751 // Also derzeit sind die Klebepunkte relativ zum aOutRect der Szene definiert. Vor dem Drehen 752 // werden die Klebepunkte relativ zur Seite definiert. Sie nehmen an der Drehung der Szene noch nicht Teil 753 // dafuer gibt es den 754 SetGlueReallyAbsolute(sal_True); 755 756 // So dass war die Szene, ab jetzt kommen die Objekte in der Szene 757 // 3D-Objekte gibt es nur ein einziges das kann zwar mehrere Flaechen haben aber die Flaechen 758 // muessen ja nicht zusammenhaengend sein 759 // es ermoeglicht den Zugriff auf Kindobjekte 760 // Ich gehe also die gesamte Liste durch und rotiere um die Z-Achse die durch den 761 // Mittelpunkt von aOutRect geht (Satz von Steiner), also RotateZ 762 763 RotateScene (rRef, nWink, sn, cs); // Rotiert die Szene 764 double fWinkelInRad = nWink/100 * F_PI180; 765 766 basegfx::B3DHomMatrix aRotation; 767 aRotation.rotate(0.0, 0.0, fWinkelInRad); 768 NbcSetTransform(aRotation * GetTransform()); 769 770 SetRectsDirty(); // Veranlasst eine Neuberechnung aller BoundRects 771 NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotiert die Klebepunkte (die haben noch Koordinaten relativ 772 // zum Urpsung des Blattes 773 SetGlueReallyAbsolute(sal_False); // ab jetzt sind sie wieder relativ zum BoundRect (also dem aOutRect definiert) 774 SetRectsDirty(); 775 } 776 777 /************************************************************************* 778 |* 779 |* SnapRect berechnen 780 |* 781 \************************************************************************/ 782 783 void E3dScene::RecalcSnapRect() 784 { 785 E3dScene* pScene = GetScene(); 786 787 if(pScene == this) 788 { 789 // Szene wird als 2D-Objekt benutzt, nimm SnapRect aus der 790 // 2D Bildschrimdarstellung 791 Camera3D& rCam = (Camera3D&)pScene->GetCamera(); 792 maSnapRect = rCam.GetDeviceWindow(); 793 } 794 else 795 { 796 // Szene ist selbst Mitglied einer anderen Szene, hole das 797 // SnapRect als zusammengesetztes Objekt 798 E3dObject::RecalcSnapRect(); 799 } 800 } 801 802 /************************************************************************* 803 |* 804 |* Aufbrechen 805 |* 806 \************************************************************************/ 807 808 sal_Bool E3dScene::IsBreakObjPossible() 809 { 810 // Szene ist aufzubrechen, wenn alle Mitglieder aufzubrechen sind 811 SdrObjListIter a3DIterator(maSubList, IM_DEEPWITHGROUPS); 812 813 while ( a3DIterator.IsMore() ) 814 { 815 E3dObject* pObj = (E3dObject*) a3DIterator.Next(); 816 DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!"); 817 if(!pObj->IsBreakObjPossible()) 818 return sal_False; 819 } 820 821 return sal_True; 822 } 823 824 basegfx::B3DVector E3dScene::GetShadowPlaneDirection() const 825 { 826 double fWink = (double)GetShadowSlant() * F_PI180; 827 basegfx::B3DVector aShadowPlaneDir(0.0, sin(fWink), cos(fWink)); 828 aShadowPlaneDir.normalize(); 829 return aShadowPlaneDir; 830 } 831 832 void E3dScene::SetShadowPlaneDirection(const basegfx::B3DVector& rVec) 833 { 834 sal_uInt16 nSceneShadowSlant = (sal_uInt16)((atan2(rVec.getY(), rVec.getZ()) / F_PI180) + 0.5); 835 GetProperties().SetObjectItemDirect(Svx3DShadowSlantItem(nSceneShadowSlant)); 836 } 837 838 basegfx::B2DPolyPolygon E3dScene::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const 839 { 840 return TakeXorPoly(); 841 } 842 843 FASTBOOL E3dScene::BegCreate(SdrDragStat& rStat) 844 { 845 rStat.SetOrtho4Possible(); 846 Rectangle aRect1(rStat.GetStart(), rStat.GetNow()); 847 aRect1.Justify(); 848 rStat.SetActionRect(aRect1); 849 NbcSetSnapRect(aRect1); 850 return sal_True; 851 } 852 853 FASTBOOL E3dScene::MovCreate(SdrDragStat& rStat) 854 { 855 Rectangle aRect1; 856 rStat.TakeCreateRect(aRect1); 857 aRect1.Justify(); 858 rStat.SetActionRect(aRect1); 859 NbcSetSnapRect(aRect1); 860 SetBoundRectDirty(); 861 bSnapRectDirty=sal_True; 862 return sal_True; 863 } 864 865 FASTBOOL E3dScene::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) 866 { 867 Rectangle aRect1; 868 rStat.TakeCreateRect(aRect1); 869 aRect1.Justify(); 870 NbcSetSnapRect(aRect1); 871 SetRectsDirty(); 872 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); 873 } 874 875 FASTBOOL E3dScene::BckCreate(SdrDragStat& /*rStat*/) 876 { 877 return sal_False; 878 } 879 880 void E3dScene::BrkCreate(SdrDragStat& /*rStat*/) 881 { 882 } 883 884 // eof 885