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