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_sd.hxx" 30 31 #include "fucon3d.hxx" 32 #include <vcl/waitobj.hxx> 33 34 #include <svx/svxids.hrc> 35 #include <svl/aeitem.hxx> 36 #include <sfx2/app.hxx> 37 #include <sfx2/dispatch.hxx> 38 #include <sfx2/viewfrm.hxx> 39 #include <tools/poly.hxx> 40 41 #include <math.h> 42 #include <svx/globl3d.hxx> 43 #include <svx/scene3d.hxx> 44 #include <svx/sphere3d.hxx> 45 #include <svx/cube3d.hxx> 46 #include <svx/lathe3d.hxx> 47 #include <svx/camera3d.hxx> 48 49 #include "app.hrc" 50 #include "res_bmp.hrc" 51 #include "View.hxx" 52 #include "Window.hxx" 53 #include "ViewShell.hxx" 54 #include "drawdoc.hxx" 55 #include "ViewShellBase.hxx" 56 #include "ToolBarManager.hxx" 57 #include <svx/svx3ditems.hxx> 58 59 // #97016# 60 #include <svx/polysc3d.hxx> 61 #include <basegfx/polygon/b2dpolygontools.hxx> 62 63 namespace sd { 64 65 TYPEINIT1( FuConstruct3dObject, FuConstruct ); 66 67 /************************************************************************* 68 |* 69 |* Konstruktor 70 |* 71 \************************************************************************/ 72 73 FuConstruct3dObject::FuConstruct3dObject ( 74 ViewShell* pViewSh, 75 ::sd::Window* pWin, 76 ::sd::View* pView, 77 SdDrawDocument* pDoc, 78 SfxRequest& rReq) 79 : FuConstruct(pViewSh, pWin, pView, pDoc, rReq) 80 { 81 } 82 83 FunctionReference FuConstruct3dObject::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq, bool bPermanent ) 84 { 85 FuConstruct3dObject* pFunc; 86 FunctionReference xFunc( pFunc = new FuConstruct3dObject( pViewSh, pWin, pView, pDoc, rReq ) ); 87 xFunc->DoExecute(rReq); 88 pFunc->SetPermanent(bPermanent); 89 return xFunc; 90 } 91 92 void FuConstruct3dObject::DoExecute( SfxRequest& rReq ) 93 { 94 FuConstruct::DoExecute( rReq ); 95 mpViewShell->GetViewShellBase().GetToolBarManager()->SetToolBar( 96 ToolBarManager::TBG_FUNCTION, 97 ToolBarManager::msDrawingObjectToolBar); 98 } 99 100 /************************************************************************* 101 |* 102 |* MouseButtonDown-event 103 |* 104 \************************************************************************/ 105 106 // #97016# 107 E3dCompoundObject* FuConstruct3dObject::ImpCreateBasic3DShape() 108 { 109 E3dCompoundObject* p3DObj = NULL; 110 111 switch (nSlotId) 112 { 113 default: 114 case SID_3D_CUBE: 115 { 116 p3DObj = new E3dCubeObj( 117 mpView->Get3DDefaultAttributes(), 118 ::basegfx::B3DPoint(-2500, -2500, -2500), 119 ::basegfx::B3DVector(5000, 5000, 5000)); 120 break; 121 } 122 123 case SID_3D_SPHERE: 124 { 125 p3DObj = new E3dSphereObj( 126 mpView->Get3DDefaultAttributes(), 127 ::basegfx::B3DPoint(0, 0, 0), 128 ::basegfx::B3DVector(5000, 5000, 5000)); 129 break; 130 } 131 132 case SID_3D_SHELL: 133 { 134 XPolygon aXPoly(Point (0, 1250), 2500, 2500, 0, 900, sal_False); 135 aXPoly.Scale(5.0, 5.0); 136 137 ::basegfx::B2DPolygon aB2DPolygon(aXPoly.getB2DPolygon()); 138 if(aB2DPolygon.areControlPointsUsed()) 139 { 140 aB2DPolygon = ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon); 141 } 142 p3DObj = new E3dLatheObj(mpView->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon)); 143 144 // Dies ist ein offenes Objekt, muss daher defaultmaessig 145 // doppelseitig behandelt werden 146 p3DObj->SetMergedItem(Svx3DDoubleSidedItem(sal_True)); 147 break; 148 } 149 150 case SID_3D_HALF_SPHERE: 151 { 152 XPolygon aXPoly(Point (0, 1250), 2500, 2500, 0, 900, sal_False); 153 aXPoly.Scale(5.0, 5.0); 154 155 aXPoly.Insert(0, Point (2400*5, 1250*5), XPOLY_NORMAL); 156 aXPoly.Insert(0, Point (2000*5, 1250*5), XPOLY_NORMAL); 157 aXPoly.Insert(0, Point (1500*5, 1250*5), XPOLY_NORMAL); 158 aXPoly.Insert(0, Point (1000*5, 1250*5), XPOLY_NORMAL); 159 aXPoly.Insert(0, Point (500*5, 1250*5), XPOLY_NORMAL); 160 aXPoly.Insert(0, Point (250*5, 1250*5), XPOLY_NORMAL); 161 aXPoly.Insert(0, Point (50*5, 1250*5), XPOLY_NORMAL); 162 aXPoly.Insert(0, Point (0*5, 1250*5), XPOLY_NORMAL); 163 164 ::basegfx::B2DPolygon aB2DPolygon(aXPoly.getB2DPolygon()); 165 if(aB2DPolygon.areControlPointsUsed()) 166 { 167 aB2DPolygon = ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon); 168 } 169 p3DObj = new E3dLatheObj(mpView->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon)); 170 break; 171 } 172 173 case SID_3D_TORUS: 174 { 175 ::basegfx::B2DPolygon aB2DPolygon(::basegfx::tools::createPolygonFromCircle(::basegfx::B2DPoint(1000.0, 0.0), 500.0)); 176 if(aB2DPolygon.areControlPointsUsed()) 177 { 178 aB2DPolygon = ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon); 179 } 180 p3DObj = new E3dLatheObj(mpView->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon)); 181 break; 182 } 183 184 case SID_3D_CYLINDER: 185 { 186 ::basegfx::B2DPolygon aInnerPoly; 187 188 aInnerPoly.append(::basegfx::B2DPoint(0, 1000*5)); 189 aInnerPoly.append(::basegfx::B2DPoint(50*5, 1000*5)); 190 aInnerPoly.append(::basegfx::B2DPoint(100*5, 1000*5)); 191 aInnerPoly.append(::basegfx::B2DPoint(200*5, 1000*5)); 192 aInnerPoly.append(::basegfx::B2DPoint(300*5, 1000*5)); 193 aInnerPoly.append(::basegfx::B2DPoint(400*5, 1000*5)); 194 aInnerPoly.append(::basegfx::B2DPoint(450*5, 1000*5)); 195 aInnerPoly.append(::basegfx::B2DPoint(500*5, 1000*5)); 196 aInnerPoly.append(::basegfx::B2DPoint(500*5, -1000*5)); 197 aInnerPoly.append(::basegfx::B2DPoint(450*5, -1000*5)); 198 aInnerPoly.append(::basegfx::B2DPoint(400*5, -1000*5)); 199 aInnerPoly.append(::basegfx::B2DPoint(300*5, -1000*5)); 200 aInnerPoly.append(::basegfx::B2DPoint(200*5, -1000*5)); 201 aInnerPoly.append(::basegfx::B2DPoint(100*5, -1000*5)); 202 aInnerPoly.append(::basegfx::B2DPoint(50*5, -1000*5)); 203 aInnerPoly.append(::basegfx::B2DPoint(0*5, -1000*5)); 204 aInnerPoly.setClosed(true); 205 206 p3DObj = new E3dLatheObj(mpView->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly)); 207 break; 208 } 209 210 case SID_3D_CONE: 211 { 212 ::basegfx::B2DPolygon aInnerPoly; 213 214 aInnerPoly.append(::basegfx::B2DPoint(0, -1000*5)); 215 aInnerPoly.append(::basegfx::B2DPoint(25*5, -900*5)); 216 aInnerPoly.append(::basegfx::B2DPoint(50*5, -800*5)); 217 aInnerPoly.append(::basegfx::B2DPoint(100*5, -600*5)); 218 aInnerPoly.append(::basegfx::B2DPoint(200*5, -200*5)); 219 aInnerPoly.append(::basegfx::B2DPoint(300*5, 200*5)); 220 aInnerPoly.append(::basegfx::B2DPoint(400*5, 600*5)); 221 aInnerPoly.append(::basegfx::B2DPoint(500*5, 1000*5)); 222 aInnerPoly.append(::basegfx::B2DPoint(400*5, 1000*5)); 223 aInnerPoly.append(::basegfx::B2DPoint(300*5, 1000*5)); 224 aInnerPoly.append(::basegfx::B2DPoint(200*5, 1000*5)); 225 aInnerPoly.append(::basegfx::B2DPoint(100*5, 1000*5)); 226 aInnerPoly.append(::basegfx::B2DPoint(50*5, 1000*5)); 227 aInnerPoly.append(::basegfx::B2DPoint(0*5, 1000*5)); 228 aInnerPoly.setClosed(true); 229 230 p3DObj = new E3dLatheObj(mpView->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly)); 231 break; 232 } 233 234 case SID_3D_PYRAMID: 235 { 236 ::basegfx::B2DPolygon aInnerPoly; 237 238 aInnerPoly.append(::basegfx::B2DPoint(0, -1000*5)); 239 aInnerPoly.append(::basegfx::B2DPoint(25*5, -900*5)); 240 aInnerPoly.append(::basegfx::B2DPoint(50*5, -800*5)); 241 aInnerPoly.append(::basegfx::B2DPoint(100*5, -600*5)); 242 aInnerPoly.append(::basegfx::B2DPoint(200*5, -200*5)); 243 aInnerPoly.append(::basegfx::B2DPoint(300*5, 200*5)); 244 aInnerPoly.append(::basegfx::B2DPoint(400*5, 600*5)); 245 aInnerPoly.append(::basegfx::B2DPoint(500*5, 1000*5)); 246 aInnerPoly.append(::basegfx::B2DPoint(400*5, 1000*5)); 247 aInnerPoly.append(::basegfx::B2DPoint(300*5, 1000*5)); 248 aInnerPoly.append(::basegfx::B2DPoint(200*5, 1000*5)); 249 aInnerPoly.append(::basegfx::B2DPoint(100*5, 1000*5)); 250 aInnerPoly.append(::basegfx::B2DPoint(50*5, 1000*5)); 251 aInnerPoly.append(::basegfx::B2DPoint(0, 1000*5)); 252 aInnerPoly.setClosed(true); 253 254 p3DObj = new E3dLatheObj(mpView->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly)); 255 p3DObj->SetMergedItem(Svx3DHorizontalSegmentsItem(4)); 256 break; 257 } 258 } 259 260 return p3DObj; 261 } 262 263 // #97016# 264 void FuConstruct3dObject::ImpPrepareBasic3DShape(E3dCompoundObject* p3DObj, E3dScene *pScene) 265 { 266 Camera3D &aCamera = (Camera3D&) pScene->GetCamera (); 267 268 // get transformed BoundVolume of the new object 269 basegfx::B3DRange aBoundVol; 270 basegfx::B3DRange aObjVol(p3DObj->GetBoundVolume()); 271 aObjVol.transform(p3DObj->GetTransform()); 272 aBoundVol.expand(aObjVol); 273 double fDeepth(aBoundVol.getDepth()); 274 275 aCamera.SetPRP(::basegfx::B3DPoint(0.0, 0.0, 1000.0)); 276 aCamera.SetPosition(::basegfx::B3DPoint(0.0, 0.0, mpView->GetDefaultCamPosZ() + fDeepth / 2)); 277 aCamera.SetFocalLength(mpView->GetDefaultCamFocal()); 278 pScene->SetCamera(aCamera); 279 basegfx::B3DHomMatrix aTransformation; 280 281 switch (nSlotId) 282 { 283 case SID_3D_CUBE: 284 { 285 aTransformation.rotate(DEG2RAD(20), 0.0, 0.0); 286 } 287 break; 288 289 case SID_3D_SPHERE: 290 { 291 // pScene->RotateX(DEG2RAD(60)); 292 } 293 break; 294 295 case SID_3D_SHELL: 296 case SID_3D_HALF_SPHERE: 297 { 298 aTransformation.rotate(DEG2RAD(200), 0.0, 0.0); 299 } 300 break; 301 302 case SID_3D_CYLINDER: 303 case SID_3D_CONE: 304 case SID_3D_PYRAMID: 305 { 306 // pScene->RotateX(DEG2RAD(25)); 307 } 308 break; 309 310 case SID_3D_TORUS: 311 { 312 // pScene->RotateX(DEG2RAD(15)); 313 aTransformation.rotate(DEG2RAD(90), 0.0, 0.0); 314 } 315 break; 316 317 default: 318 { 319 } 320 break; 321 } 322 323 pScene->SetTransform(aTransformation * pScene->GetTransform()); 324 325 SfxItemSet aAttr (mpViewShell->GetPool()); 326 pScene->SetMergedItemSetAndBroadcast(aAttr); 327 } 328 329 sal_Bool FuConstruct3dObject::MouseButtonDown(const MouseEvent& rMEvt) 330 { 331 sal_Bool bReturn = FuConstruct::MouseButtonDown(rMEvt); 332 333 if ( rMEvt.IsLeft() && !mpView->IsAction() ) 334 { 335 Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); 336 337 mpWindow->CaptureMouse(); 338 sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); 339 340 E3dCompoundObject* p3DObj = NULL; 341 342 WaitObject aWait( (Window*)mpViewShell->GetActiveWindow() ); 343 344 // #97016# 345 p3DObj = ImpCreateBasic3DShape(); 346 E3dScene* pScene = mpView->SetCurrent3DObj(p3DObj); 347 348 // #97016# 349 ImpPrepareBasic3DShape(p3DObj, pScene); 350 bReturn = mpView->BegCreatePreparedObject(aPnt, nDrgLog, pScene); 351 352 SdrObject* pObj = mpView->GetCreateObj(); 353 354 if (pObj) 355 { 356 SfxItemSet aAttr(mpDoc->GetPool()); 357 SetStyleSheet(aAttr, pObj); 358 359 // LineStyle rausnehmen 360 aAttr.Put(XLineStyleItem (XLINE_NONE)); 361 362 pObj->SetMergedItemSet(aAttr); 363 } 364 } 365 366 return bReturn; 367 } 368 369 /************************************************************************* 370 |* 371 |* MouseMove-event 372 |* 373 \************************************************************************/ 374 375 sal_Bool FuConstruct3dObject::MouseMove(const MouseEvent& rMEvt) 376 { 377 return FuConstruct::MouseMove(rMEvt); 378 } 379 380 /************************************************************************* 381 |* 382 |* MouseButtonUp-event 383 |* 384 \************************************************************************/ 385 386 sal_Bool FuConstruct3dObject::MouseButtonUp(const MouseEvent& rMEvt) 387 { 388 sal_Bool bReturn = sal_False; 389 390 if ( mpView->IsCreateObj() && rMEvt.IsLeft() ) 391 { 392 Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); 393 mpView->EndCreateObj(SDRCREATE_FORCEEND); 394 bReturn = sal_True; 395 } 396 397 bReturn = FuConstruct::MouseButtonUp(rMEvt) || bReturn; 398 399 if (!bPermanent) 400 mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SFX_CALLMODE_ASYNCHRON); 401 402 return bReturn; 403 } 404 405 /************************************************************************* 406 |* 407 |* Tastaturereignisse bearbeiten 408 |* 409 |* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls 410 |* sal_False. 411 |* 412 \************************************************************************/ 413 414 sal_Bool FuConstruct3dObject::KeyInput(const KeyEvent& rKEvt) 415 { 416 return( FuConstruct::KeyInput(rKEvt) ); 417 } 418 419 /************************************************************************* 420 |* 421 |* Function aktivieren 422 |* 423 \************************************************************************/ 424 425 void FuConstruct3dObject::Activate() 426 { 427 mpView->SetCurrentObj(OBJ_NONE); 428 429 FuConstruct::Activate(); 430 } 431 432 /************************************************************************* 433 |* 434 |* Function deaktivieren 435 |* 436 \************************************************************************/ 437 438 void FuConstruct3dObject::Deactivate() 439 { 440 FuConstruct::Deactivate(); 441 } 442 443 // #97016# 444 SdrObject* FuConstruct3dObject::CreateDefaultObject(const sal_uInt16 nID, const Rectangle& rRectangle) 445 { 446 // case SID_3D_CUBE: 447 // case SID_3D_SHELL: 448 // case SID_3D_SPHERE: 449 // case SID_3D_TORUS: 450 // case SID_3D_HALF_SPHERE: 451 // case SID_3D_CYLINDER: 452 // case SID_3D_CONE: 453 // case SID_3D_PYRAMID: 454 455 E3dCompoundObject* p3DObj = ImpCreateBasic3DShape(); 456 457 // E3dView::SetCurrent3DObj part 458 // get transformed BoundVolume of the object 459 basegfx::B3DRange aObjVol(p3DObj->GetBoundVolume()); 460 aObjVol.transform(p3DObj->GetTransform()); 461 basegfx::B3DRange aVolume(aObjVol); 462 double fW(aVolume.getWidth()); 463 double fH(aVolume.getHeight()); 464 Rectangle a3DRect(0, 0, (long)fW, (long)fH); 465 E3dScene* pScene = new E3dPolyScene(mpView->Get3DDefaultAttributes()); 466 467 // mpView->InitScene(pScene, fW, fH, aVolume.MaxVec().Z() + ((fW + fH) / 4.0)); 468 // copied code from E3dView::InitScene 469 double fCamZ(aVolume.getMaxZ() + ((fW + fH) / 4.0)); 470 Camera3D aCam(pScene->GetCamera()); 471 aCam.SetAutoAdjustProjection(sal_False); 472 aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH); 473 ::basegfx::B3DPoint aLookAt; 474 double fDefaultCamPosZ = mpView->GetDefaultCamPosZ(); 475 ::basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ); 476 aCam.SetPosAndLookAt(aCamPos, aLookAt); 477 aCam.SetFocalLength(mpView->GetDefaultCamFocal()); 478 aCam.SetDefaults(::basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, mpView->GetDefaultCamFocal()); 479 pScene->SetCamera(aCam); 480 481 pScene->Insert3DObj(p3DObj); 482 pScene->NbcSetSnapRect(a3DRect); 483 pScene->SetModel(mpDoc); 484 485 ImpPrepareBasic3DShape(p3DObj, pScene); 486 487 SfxItemSet aAttr(mpDoc->GetPool()); 488 SetStyleSheet(aAttr, p3DObj); 489 aAttr.Put(XLineStyleItem (XLINE_NONE)); 490 p3DObj->SetMergedItemSet(aAttr); 491 492 // make object interactive at once 493 pScene->SetRectsDirty(); 494 495 // Take care of restrictions for the rectangle 496 Rectangle aRect(rRectangle); 497 498 switch(nID) 499 { 500 case SID_3D_CUBE: 501 case SID_3D_SPHERE: 502 case SID_3D_TORUS: 503 { 504 // force quadratic 505 ImpForceQuadratic(aRect); 506 break; 507 } 508 509 case SID_3D_SHELL: 510 case SID_3D_HALF_SPHERE: 511 { 512 // force horizontal layout 513 break; 514 } 515 516 case SID_3D_CYLINDER: 517 case SID_3D_CONE: 518 case SID_3D_PYRAMID: 519 { 520 // force vertical layout 521 break; 522 } 523 } 524 525 // #97016#, #98245# use changed rectangle, not original one 526 pScene->SetLogicRect(aRect); 527 528 return pScene; 529 } 530 531 } // end of namespace sd 532