1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "fucon3d.hxx"
22 #include <vcl/waitobj.hxx>
24 #include <svx/svxids.hrc>
25 #include <svl/aeitem.hxx>
26 #include <sfx2/app.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <tools/poly.hxx>
32 #include <svx/globl3d.hxx>
33 #include <svx/scene3d.hxx>
34 #include <svx/sphere3d.hxx>
35 #include <svx/cube3d.hxx>
36 #include <svx/lathe3d.hxx>
37 #include <svx/camera3d.hxx>
40 #include "res_bmp.hrc"
43 #include "ViewShell.hxx"
44 #include "drawdoc.hxx"
45 #include "ViewShellBase.hxx"
46 #include "ToolBarManager.hxx"
47 #include <svx/svx3ditems.hxx>
49 #include <svx/polysc3d.hxx>
50 #include <basegfx/polygon/b2dpolygontools.hxx>
54 TYPEINIT1( FuConstruct3dObject
, FuConstruct
);
57 FuConstruct3dObject::FuConstruct3dObject (
63 : FuConstruct(pViewSh
, pWin
, pView
, pDoc
, rReq
)
67 FunctionReference
FuConstruct3dObject::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
, bool bPermanent
)
69 FuConstruct3dObject
* pFunc
;
70 FunctionReference
xFunc( pFunc
= new FuConstruct3dObject( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
71 xFunc
->DoExecute(rReq
);
72 pFunc
->SetPermanent(bPermanent
);
76 void FuConstruct3dObject::DoExecute( SfxRequest
& rReq
)
78 FuConstruct::DoExecute( rReq
);
79 mpViewShell
->GetViewShellBase().GetToolBarManager()->SetToolBar(
80 ToolBarManager::TBG_FUNCTION
,
81 ToolBarManager::msDrawingObjectToolBar
);
85 E3dCompoundObject
* FuConstruct3dObject::ImpCreateBasic3DShape()
87 E3dCompoundObject
* p3DObj
= NULL
;
94 p3DObj
= new E3dCubeObj(
95 mpView
->Get3DDefaultAttributes(),
96 ::basegfx::B3DPoint(-2500, -2500, -2500),
97 ::basegfx::B3DVector(5000, 5000, 5000));
103 p3DObj
= new E3dSphereObj(
104 mpView
->Get3DDefaultAttributes(),
105 ::basegfx::B3DPoint(0, 0, 0),
106 ::basegfx::B3DVector(5000, 5000, 5000));
112 XPolygon
aXPoly(Point (0, 1250), 2500, 2500, 0, 900, sal_False
);
113 aXPoly
.Scale(5.0, 5.0);
115 ::basegfx::B2DPolygon
aB2DPolygon(aXPoly
.getB2DPolygon());
116 if(aB2DPolygon
.areControlPointsUsed())
118 aB2DPolygon
= ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon
);
120 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon
));
122 /* this is an open object, therefore it has to be handled double-
124 p3DObj
->SetMergedItem(Svx3DDoubleSidedItem(sal_True
));
128 case SID_3D_HALF_SPHERE
:
130 XPolygon
aXPoly(Point (0, 1250), 2500, 2500, 0, 900, sal_False
);
131 aXPoly
.Scale(5.0, 5.0);
133 aXPoly
.Insert(0, Point (2400*5, 1250*5), XPOLY_NORMAL
);
134 aXPoly
.Insert(0, Point (2000*5, 1250*5), XPOLY_NORMAL
);
135 aXPoly
.Insert(0, Point (1500*5, 1250*5), XPOLY_NORMAL
);
136 aXPoly
.Insert(0, Point (1000*5, 1250*5), XPOLY_NORMAL
);
137 aXPoly
.Insert(0, Point (500*5, 1250*5), XPOLY_NORMAL
);
138 aXPoly
.Insert(0, Point (250*5, 1250*5), XPOLY_NORMAL
);
139 aXPoly
.Insert(0, Point (50*5, 1250*5), XPOLY_NORMAL
);
140 aXPoly
.Insert(0, Point (0*5, 1250*5), XPOLY_NORMAL
);
142 ::basegfx::B2DPolygon
aB2DPolygon(aXPoly
.getB2DPolygon());
143 if(aB2DPolygon
.areControlPointsUsed())
145 aB2DPolygon
= ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon
);
147 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon
));
153 ::basegfx::B2DPolygon
aB2DPolygon(::basegfx::tools::createPolygonFromCircle(::basegfx::B2DPoint(1000.0, 0.0), 500.0));
154 if(aB2DPolygon
.areControlPointsUsed())
156 aB2DPolygon
= ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon
);
158 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon
));
162 case SID_3D_CYLINDER
:
164 ::basegfx::B2DPolygon aInnerPoly
;
166 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
167 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
168 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
169 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
170 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
171 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
172 aInnerPoly
.append(::basegfx::B2DPoint(450*5, 1000*5));
173 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
174 aInnerPoly
.append(::basegfx::B2DPoint(500*5, -1000*5));
175 aInnerPoly
.append(::basegfx::B2DPoint(450*5, -1000*5));
176 aInnerPoly
.append(::basegfx::B2DPoint(400*5, -1000*5));
177 aInnerPoly
.append(::basegfx::B2DPoint(300*5, -1000*5));
178 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -1000*5));
179 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -1000*5));
180 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -1000*5));
181 aInnerPoly
.append(::basegfx::B2DPoint(0*5, -1000*5));
182 aInnerPoly
.setClosed(true);
184 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly
));
190 ::basegfx::B2DPolygon aInnerPoly
;
192 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
193 aInnerPoly
.append(::basegfx::B2DPoint(25*5, -900*5));
194 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -800*5));
195 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -600*5));
196 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -200*5));
197 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 200*5));
198 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 600*5));
199 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
200 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
201 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
202 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
203 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
204 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
205 aInnerPoly
.append(::basegfx::B2DPoint(0*5, 1000*5));
206 aInnerPoly
.setClosed(true);
208 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly
));
214 ::basegfx::B2DPolygon aInnerPoly
;
216 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
217 aInnerPoly
.append(::basegfx::B2DPoint(25*5, -900*5));
218 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -800*5));
219 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -600*5));
220 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -200*5));
221 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 200*5));
222 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 600*5));
223 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
224 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
225 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
226 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
227 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
228 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
229 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
230 aInnerPoly
.setClosed(true);
232 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly
));
233 p3DObj
->SetMergedItem(Svx3DHorizontalSegmentsItem(4));
241 void FuConstruct3dObject::ImpPrepareBasic3DShape(E3dCompoundObject
* p3DObj
, E3dScene
*pScene
)
243 Camera3D
&aCamera
= (Camera3D
&) pScene
->GetCamera ();
245 // get transformed BoundVolume of the new object
246 basegfx::B3DRange aBoundVol
;
247 basegfx::B3DRange
aObjVol(p3DObj
->GetBoundVolume());
248 aObjVol
.transform(p3DObj
->GetTransform());
249 aBoundVol
.expand(aObjVol
);
250 double fDeepth(aBoundVol
.getDepth());
252 aCamera
.SetPRP(::basegfx::B3DPoint(0.0, 0.0, 1000.0));
253 aCamera
.SetPosition(::basegfx::B3DPoint(0.0, 0.0, mpView
->GetDefaultCamPosZ() + fDeepth
/ 2));
254 aCamera
.SetFocalLength(mpView
->GetDefaultCamFocal());
255 pScene
->SetCamera(aCamera
);
256 basegfx::B3DHomMatrix aTransformation
;
262 aTransformation
.rotate(DEG2RAD(20), 0.0, 0.0);
272 case SID_3D_HALF_SPHERE
:
274 aTransformation
.rotate(DEG2RAD(200), 0.0, 0.0);
278 case SID_3D_CYLINDER
:
287 aTransformation
.rotate(DEG2RAD(90), 0.0, 0.0);
297 pScene
->SetTransform(aTransformation
* pScene
->GetTransform());
299 SfxItemSet
aAttr (mpViewShell
->GetPool());
300 pScene
->SetMergedItemSetAndBroadcast(aAttr
);
303 sal_Bool
FuConstruct3dObject::MouseButtonDown(const MouseEvent
& rMEvt
)
305 sal_Bool bReturn
= FuConstruct::MouseButtonDown(rMEvt
);
307 if ( rMEvt
.IsLeft() && !mpView
->IsAction() )
309 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
311 mpWindow
->CaptureMouse();
312 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
314 E3dCompoundObject
* p3DObj
= NULL
;
316 WaitObject
aWait( (Window
*)mpViewShell
->GetActiveWindow() );
318 p3DObj
= ImpCreateBasic3DShape();
319 E3dScene
* pScene
= mpView
->SetCurrent3DObj(p3DObj
);
321 ImpPrepareBasic3DShape(p3DObj
, pScene
);
322 bReturn
= mpView
->BegCreatePreparedObject(aPnt
, nDrgLog
, pScene
);
324 SdrObject
* pObj
= mpView
->GetCreateObj();
328 SfxItemSet
aAttr(mpDoc
->GetPool());
329 SetStyleSheet(aAttr
, pObj
);
332 aAttr
.Put(XLineStyleItem (XLINE_NONE
));
334 pObj
->SetMergedItemSet(aAttr
);
342 sal_Bool
FuConstruct3dObject::MouseMove(const MouseEvent
& rMEvt
)
344 return FuConstruct::MouseMove(rMEvt
);
348 sal_Bool
FuConstruct3dObject::MouseButtonUp(const MouseEvent
& rMEvt
)
350 sal_Bool bReturn
= sal_False
;
352 if ( mpView
->IsCreateObj() && rMEvt
.IsLeft() )
354 mpView
->EndCreateObj(SDRCREATE_FORCEEND
);
358 bReturn
= FuConstruct::MouseButtonUp(rMEvt
) || bReturn
;
361 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SFX_CALLMODE_ASYNCHRON
);
367 * Process keyboard input
368 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
370 sal_Bool
FuConstruct3dObject::KeyInput(const KeyEvent
& rKEvt
)
372 return( FuConstruct::KeyInput(rKEvt
) );
376 void FuConstruct3dObject::Activate()
378 mpView
->SetCurrentObj(OBJ_NONE
);
380 FuConstruct::Activate();
384 void FuConstruct3dObject::Deactivate()
386 FuConstruct::Deactivate();
389 SdrObject
* FuConstruct3dObject::CreateDefaultObject(const sal_uInt16 nID
, const Rectangle
& rRectangle
)
392 E3dCompoundObject
* p3DObj
= ImpCreateBasic3DShape();
394 // E3dView::SetCurrent3DObj part
395 // get transformed BoundVolume of the object
396 basegfx::B3DRange
aObjVol(p3DObj
->GetBoundVolume());
397 aObjVol
.transform(p3DObj
->GetTransform());
398 basegfx::B3DRange
aVolume(aObjVol
);
399 double fW(aVolume
.getWidth());
400 double fH(aVolume
.getHeight());
401 Rectangle
a3DRect(0, 0, (long)fW
, (long)fH
);
402 E3dScene
* pScene
= new E3dPolyScene(mpView
->Get3DDefaultAttributes());
404 // copied code from E3dView::InitScene
405 double fCamZ(aVolume
.getMaxZ() + ((fW
+ fH
) / 4.0));
406 Camera3D
aCam(pScene
->GetCamera());
407 aCam
.SetAutoAdjustProjection(sal_False
);
408 aCam
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
409 ::basegfx::B3DPoint aLookAt
;
410 double fDefaultCamPosZ
= mpView
->GetDefaultCamPosZ();
411 ::basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
412 aCam
.SetPosAndLookAt(aCamPos
, aLookAt
);
413 aCam
.SetFocalLength(mpView
->GetDefaultCamFocal());
414 aCam
.SetDefaults(::basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ
), aLookAt
, mpView
->GetDefaultCamFocal());
415 pScene
->SetCamera(aCam
);
417 pScene
->Insert3DObj(p3DObj
);
418 pScene
->NbcSetSnapRect(a3DRect
);
419 pScene
->SetModel(mpDoc
);
421 ImpPrepareBasic3DShape(p3DObj
, pScene
);
423 SfxItemSet
aAttr(mpDoc
->GetPool());
424 SetStyleSheet(aAttr
, p3DObj
);
425 aAttr
.Put(XLineStyleItem (XLINE_NONE
));
426 p3DObj
->SetMergedItemSet(aAttr
);
428 // make object interactive at once
429 pScene
->SetRectsDirty();
431 // Take care of restrictions for the rectangle
432 Rectangle
aRect(rRectangle
);
441 ImpForceQuadratic(aRect
);
446 case SID_3D_HALF_SPHERE
:
448 // force horizontal layout
452 case SID_3D_CYLINDER
:
456 // force vertical layout
461 // use changed rectangle, not original one
462 pScene
->SetLogicRect(aRect
);
467 } // end of namespace sd
469 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */