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