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 .
20 #include "fucon3d.hxx"
21 #include <vcl/waitobj.hxx>
23 #include <svx/svxids.hrc>
24 #include <svl/aeitem.hxx>
25 #include <sfx2/app.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <tools/poly.hxx>
31 #include <svx/globl3d.hxx>
32 #include <svx/scene3d.hxx>
33 #include <svx/sphere3d.hxx>
34 #include <svx/cube3d.hxx>
35 #include <svx/lathe3d.hxx>
36 #include <svx/camera3d.hxx>
39 #include "res_bmp.hrc"
42 #include "ViewShell.hxx"
43 #include "drawdoc.hxx"
44 #include "ViewShellBase.hxx"
45 #include "ToolBarManager.hxx"
46 #include <svx/svx3ditems.hxx>
48 #include <svx/polysc3d.hxx>
49 #include <basegfx/polygon/b2dpolygontools.hxx>
51 using namespace com::sun::star
;
55 TYPEINIT1( FuConstruct3dObject
, FuConstruct
);
57 FuConstruct3dObject::FuConstruct3dObject (
63 : FuConstruct(pViewSh
, pWin
, pView
, pDoc
, rReq
)
67 rtl::Reference
<FuPoor
> FuConstruct3dObject::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
, bool bPermanent
)
69 FuConstruct3dObject
* pFunc
;
70 rtl::Reference
<FuPoor
> 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
);
84 E3dCompoundObject
* FuConstruct3dObject::ImpCreateBasic3DShape()
86 E3dCompoundObject
* p3DObj
= NULL
;
93 p3DObj
= new E3dCubeObj(
94 mpView
->Get3DDefaultAttributes(),
95 ::basegfx::B3DPoint(-2500, -2500, -2500),
96 ::basegfx::B3DVector(5000, 5000, 5000));
102 p3DObj
= new E3dSphereObj(
103 mpView
->Get3DDefaultAttributes(),
104 ::basegfx::B3DPoint(0, 0, 0),
105 ::basegfx::B3DVector(5000, 5000, 5000));
111 XPolygon
aXPoly(Point (0, 1250), 2500, 2500, 0, 900, false);
112 aXPoly
.Scale(5.0, 5.0);
114 ::basegfx::B2DPolygon
aB2DPolygon(aXPoly
.getB2DPolygon());
115 if(aB2DPolygon
.areControlPointsUsed())
117 aB2DPolygon
= ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon
);
119 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon
));
121 /* this is an open object, therefore it has to be handled double-
123 p3DObj
->SetMergedItem(makeSvx3DDoubleSidedItem(true));
127 case SID_3D_HALF_SPHERE
:
129 XPolygon
aXPoly(Point (0, 1250), 2500, 2500, 0, 900, false);
130 aXPoly
.Scale(5.0, 5.0);
132 aXPoly
.Insert(0, Point (2400*5, 1250*5), XPOLY_NORMAL
);
133 aXPoly
.Insert(0, Point (2000*5, 1250*5), XPOLY_NORMAL
);
134 aXPoly
.Insert(0, Point (1500*5, 1250*5), XPOLY_NORMAL
);
135 aXPoly
.Insert(0, Point (1000*5, 1250*5), XPOLY_NORMAL
);
136 aXPoly
.Insert(0, Point (500*5, 1250*5), XPOLY_NORMAL
);
137 aXPoly
.Insert(0, Point (250*5, 1250*5), XPOLY_NORMAL
);
138 aXPoly
.Insert(0, Point (50*5, 1250*5), XPOLY_NORMAL
);
139 aXPoly
.Insert(0, Point (0*5, 1250*5), XPOLY_NORMAL
);
141 ::basegfx::B2DPolygon
aB2DPolygon(aXPoly
.getB2DPolygon());
142 if(aB2DPolygon
.areControlPointsUsed())
144 aB2DPolygon
= ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon
);
146 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon
));
152 ::basegfx::B2DPolygon
aB2DPolygon(::basegfx::tools::createPolygonFromCircle(::basegfx::B2DPoint(1000.0, 0.0), 500.0));
153 if(aB2DPolygon
.areControlPointsUsed())
155 aB2DPolygon
= ::basegfx::tools::adaptiveSubdivideByAngle(aB2DPolygon
);
157 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aB2DPolygon
));
161 case SID_3D_CYLINDER
:
163 ::basegfx::B2DPolygon aInnerPoly
;
165 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
166 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
167 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
168 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
169 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
170 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
171 aInnerPoly
.append(::basegfx::B2DPoint(450*5, 1000*5));
172 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
173 aInnerPoly
.append(::basegfx::B2DPoint(500*5, -1000*5));
174 aInnerPoly
.append(::basegfx::B2DPoint(450*5, -1000*5));
175 aInnerPoly
.append(::basegfx::B2DPoint(400*5, -1000*5));
176 aInnerPoly
.append(::basegfx::B2DPoint(300*5, -1000*5));
177 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -1000*5));
178 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -1000*5));
179 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -1000*5));
180 aInnerPoly
.append(::basegfx::B2DPoint(0*5, -1000*5));
181 aInnerPoly
.setClosed(true);
183 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly
));
189 ::basegfx::B2DPolygon aInnerPoly
;
191 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
192 aInnerPoly
.append(::basegfx::B2DPoint(25*5, -900*5));
193 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -800*5));
194 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -600*5));
195 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -200*5));
196 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 200*5));
197 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 600*5));
198 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
199 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
200 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
201 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
202 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
203 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
204 aInnerPoly
.append(::basegfx::B2DPoint(0*5, 1000*5));
205 aInnerPoly
.setClosed(true);
207 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly
));
213 ::basegfx::B2DPolygon aInnerPoly
;
215 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
216 aInnerPoly
.append(::basegfx::B2DPoint(25*5, -900*5));
217 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -800*5));
218 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -600*5));
219 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -200*5));
220 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 200*5));
221 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 600*5));
222 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
223 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
224 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
225 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
226 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
227 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
228 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
229 aInnerPoly
.setClosed(true);
231 p3DObj
= new E3dLatheObj(mpView
->Get3DDefaultAttributes(), ::basegfx::B2DPolyPolygon(aInnerPoly
));
232 p3DObj
->SetMergedItem(makeSvx3DHorizontalSegmentsItem(4));
240 void FuConstruct3dObject::ImpPrepareBasic3DShape(E3dCompoundObject
* p3DObj
, E3dScene
*pScene
)
242 Camera3D
&aCamera
= (Camera3D
&) pScene
->GetCamera ();
244 // get transformed BoundVolume of the new object
245 basegfx::B3DRange aBoundVol
;
246 basegfx::B3DRange
aObjVol(p3DObj
->GetBoundVolume());
247 aObjVol
.transform(p3DObj
->GetTransform());
248 aBoundVol
.expand(aObjVol
);
249 double fDeepth(aBoundVol
.getDepth());
251 aCamera
.SetPRP(::basegfx::B3DPoint(0.0, 0.0, 1000.0));
252 aCamera
.SetPosition(::basegfx::B3DPoint(0.0, 0.0, mpView
->GetDefaultCamPosZ() + fDeepth
/ 2));
253 aCamera
.SetFocalLength(mpView
->GetDefaultCamFocal());
254 pScene
->SetCamera(aCamera
);
255 basegfx::B3DHomMatrix aTransformation
;
261 aTransformation
.rotate(DEG2RAD(20), 0.0, 0.0);
271 case SID_3D_HALF_SPHERE
:
273 aTransformation
.rotate(DEG2RAD(200), 0.0, 0.0);
277 case SID_3D_CYLINDER
:
286 aTransformation
.rotate(DEG2RAD(90), 0.0, 0.0);
296 pScene
->SetTransform(aTransformation
* pScene
->GetTransform());
298 SfxItemSet
aAttr (mpViewShell
->GetPool());
299 pScene
->SetMergedItemSetAndBroadcast(aAttr
);
302 bool FuConstruct3dObject::MouseButtonDown(const MouseEvent
& rMEvt
)
304 bool bReturn
= FuConstruct::MouseButtonDown(rMEvt
);
306 if ( rMEvt
.IsLeft() && !mpView
->IsAction() )
308 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
310 mpWindow
->CaptureMouse();
311 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
313 E3dCompoundObject
* p3DObj
= NULL
;
315 WaitObject
aWait( (vcl::Window
*)mpViewShell
->GetActiveWindow() );
317 p3DObj
= ImpCreateBasic3DShape();
318 E3dScene
* pScene
= mpView
->SetCurrent3DObj(p3DObj
);
320 ImpPrepareBasic3DShape(p3DObj
, pScene
);
321 bReturn
= mpView
->BegCreatePreparedObject(aPnt
, nDrgLog
, pScene
);
323 SdrObject
* pObj
= mpView
->GetCreateObj();
327 SfxItemSet
aAttr(mpDoc
->GetPool());
328 SetStyleSheet(aAttr
, pObj
);
331 aAttr
.Put(XLineStyleItem (drawing::LineStyle_NONE
));
333 pObj
->SetMergedItemSet(aAttr
);
340 bool FuConstruct3dObject::MouseMove(const MouseEvent
& rMEvt
)
342 return FuConstruct::MouseMove(rMEvt
);
345 bool FuConstruct3dObject::MouseButtonUp(const MouseEvent
& rMEvt
)
347 bool bReturn
= false;
349 if ( mpView
->IsCreateObj() && rMEvt
.IsLeft() )
351 mpView
->EndCreateObj(SDRCREATE_FORCEEND
);
355 bReturn
= FuConstruct::MouseButtonUp(rMEvt
) || bReturn
;
358 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
);
364 * Process keyboard input
365 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
367 bool FuConstruct3dObject::KeyInput(const KeyEvent
& rKEvt
)
369 return FuConstruct::KeyInput(rKEvt
);
372 void FuConstruct3dObject::Activate()
374 mpView
->SetCurrentObj(OBJ_NONE
);
376 FuConstruct::Activate();
379 void FuConstruct3dObject::Deactivate()
381 FuConstruct::Deactivate();
384 SdrObject
* FuConstruct3dObject::CreateDefaultObject(const sal_uInt16 nID
, const Rectangle
& rRectangle
)
387 E3dCompoundObject
* p3DObj
= ImpCreateBasic3DShape();
389 // E3dView::SetCurrent3DObj part
390 // get transformed BoundVolume of the object
391 basegfx::B3DRange
aObjVol(p3DObj
->GetBoundVolume());
392 aObjVol
.transform(p3DObj
->GetTransform());
393 basegfx::B3DRange
aVolume(aObjVol
);
394 double fW(aVolume
.getWidth());
395 double fH(aVolume
.getHeight());
396 Rectangle
a3DRect(0, 0, (long)fW
, (long)fH
);
397 E3dScene
* pScene
= new E3dPolyScene(mpView
->Get3DDefaultAttributes());
399 // copied code from E3dView::InitScene
400 double fCamZ(aVolume
.getMaxZ() + ((fW
+ fH
) / 4.0));
401 Camera3D
aCam(pScene
->GetCamera());
402 aCam
.SetAutoAdjustProjection(false);
403 aCam
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
404 ::basegfx::B3DPoint aLookAt
;
405 double fDefaultCamPosZ
= mpView
->GetDefaultCamPosZ();
406 ::basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
407 aCam
.SetPosAndLookAt(aCamPos
, aLookAt
);
408 aCam
.SetFocalLength(mpView
->GetDefaultCamFocal());
409 aCam
.SetDefaults(::basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ
), aLookAt
, mpView
->GetDefaultCamFocal());
410 pScene
->SetCamera(aCam
);
412 pScene
->Insert3DObj(p3DObj
);
413 pScene
->NbcSetSnapRect(a3DRect
);
414 pScene
->SetModel(mpDoc
);
416 ImpPrepareBasic3DShape(p3DObj
, pScene
);
418 SfxItemSet
aAttr(mpDoc
->GetPool());
419 SetStyleSheet(aAttr
, p3DObj
);
420 aAttr
.Put(XLineStyleItem (drawing::LineStyle_NONE
));
421 p3DObj
->SetMergedItemSet(aAttr
);
423 // make object interactive at once
424 pScene
->SetRectsDirty();
426 // Take care of restrictions for the rectangle
427 Rectangle
aRect(rRectangle
);
436 ImpForceQuadratic(aRect
);
441 case SID_3D_HALF_SPHERE
:
443 // force horizontal layout
447 case SID_3D_CYLINDER
:
451 // force vertical layout
456 // use changed rectangle, not original one
457 pScene
->SetLogicRect(aRect
);
462 } // end of namespace sd
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */