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>
42 #include <ViewShell.hxx>
43 #include <drawdoc.hxx>
44 #include <ViewShellBase.hxx>
45 #include <ToolBarManager.hxx>
46 #include <svx/svx3ditems.hxx>
48 #include <basegfx/polygon/b2dpolygontools.hxx>
50 using namespace com::sun::star
;
55 FuConstruct3dObject::FuConstruct3dObject (
61 : FuConstruct(pViewSh
, pWin
, pView
, pDoc
, rReq
)
65 rtl::Reference
<FuPoor
> FuConstruct3dObject::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
, bool bPermanent
)
67 FuConstruct3dObject
* pFunc
;
68 rtl::Reference
<FuPoor
> xFunc( pFunc
= new FuConstruct3dObject( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
69 xFunc
->DoExecute(rReq
);
70 pFunc
->SetPermanent(bPermanent
);
74 void FuConstruct3dObject::DoExecute( SfxRequest
& rReq
)
76 FuConstruct::DoExecute( rReq
);
77 mpViewShell
->GetViewShellBase().GetToolBarManager()->SetToolBar(
78 ToolBarManager::ToolBarGroup::Function
,
79 ToolBarManager::msDrawingObjectToolBar
);
82 E3dCompoundObject
* FuConstruct3dObject::ImpCreateBasic3DShape()
84 E3dCompoundObject
* p3DObj
= nullptr;
91 p3DObj
= new E3dCubeObj(
92 mpView
->getSdrModelFromSdrView(),
93 mpView
->Get3DDefaultAttributes(),
94 ::basegfx::B3DPoint(-2500, -2500, -2500),
95 ::basegfx::B3DVector(5000, 5000, 5000));
101 p3DObj
= new E3dSphereObj(
102 mpView
->getSdrModelFromSdrView(),
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::utils::adaptiveSubdivideByAngle(aB2DPolygon
);
119 p3DObj
= new E3dLatheObj(
120 mpView
->getSdrModelFromSdrView(),
121 mpView
->Get3DDefaultAttributes(),
122 ::basegfx::B2DPolyPolygon(aB2DPolygon
));
124 /* this is an open object, therefore it has to be handled double-
126 p3DObj
->SetMergedItem(makeSvx3DDoubleSidedItem(true));
130 case SID_3D_HALF_SPHERE
:
132 XPolygon
aXPoly(Point (0, 1250), 2500, 2500, 0, 900, false);
133 aXPoly
.Scale(5.0, 5.0);
135 aXPoly
.Insert(0, Point (2400*5, 1250*5), PolyFlags::Normal
);
136 aXPoly
.Insert(0, Point (2000*5, 1250*5), PolyFlags::Normal
);
137 aXPoly
.Insert(0, Point (1500*5, 1250*5), PolyFlags::Normal
);
138 aXPoly
.Insert(0, Point (1000*5, 1250*5), PolyFlags::Normal
);
139 aXPoly
.Insert(0, Point (500*5, 1250*5), PolyFlags::Normal
);
140 aXPoly
.Insert(0, Point (250*5, 1250*5), PolyFlags::Normal
);
141 aXPoly
.Insert(0, Point (50*5, 1250*5), PolyFlags::Normal
);
142 aXPoly
.Insert(0, Point (0, 1250*5), PolyFlags::Normal
);
144 ::basegfx::B2DPolygon
aB2DPolygon(aXPoly
.getB2DPolygon());
145 if(aB2DPolygon
.areControlPointsUsed())
147 aB2DPolygon
= ::basegfx::utils::adaptiveSubdivideByAngle(aB2DPolygon
);
149 p3DObj
= new E3dLatheObj(
150 mpView
->getSdrModelFromSdrView(),
151 mpView
->Get3DDefaultAttributes(),
152 ::basegfx::B2DPolyPolygon(aB2DPolygon
));
158 ::basegfx::B2DPolygon
aB2DPolygon(::basegfx::utils::createPolygonFromCircle(::basegfx::B2DPoint(1000.0, 0.0), 500.0));
159 if(aB2DPolygon
.areControlPointsUsed())
161 aB2DPolygon
= ::basegfx::utils::adaptiveSubdivideByAngle(aB2DPolygon
);
163 p3DObj
= new E3dLatheObj(
164 mpView
->getSdrModelFromSdrView(),
165 mpView
->Get3DDefaultAttributes(),
166 ::basegfx::B2DPolyPolygon(aB2DPolygon
));
170 case SID_3D_CYLINDER
:
172 ::basegfx::B2DPolygon aInnerPoly
;
174 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
175 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
176 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
177 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
178 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
179 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
180 aInnerPoly
.append(::basegfx::B2DPoint(450*5, 1000*5));
181 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
182 aInnerPoly
.append(::basegfx::B2DPoint(500*5, -1000*5));
183 aInnerPoly
.append(::basegfx::B2DPoint(450*5, -1000*5));
184 aInnerPoly
.append(::basegfx::B2DPoint(400*5, -1000*5));
185 aInnerPoly
.append(::basegfx::B2DPoint(300*5, -1000*5));
186 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -1000*5));
187 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -1000*5));
188 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -1000*5));
189 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
190 aInnerPoly
.setClosed(true);
192 p3DObj
= new E3dLatheObj(
193 mpView
->getSdrModelFromSdrView(),
194 mpView
->Get3DDefaultAttributes(),
195 ::basegfx::B2DPolyPolygon(aInnerPoly
));
201 ::basegfx::B2DPolygon aInnerPoly
;
203 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
204 aInnerPoly
.append(::basegfx::B2DPoint(25*5, -900*5));
205 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -800*5));
206 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -600*5));
207 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -200*5));
208 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 200*5));
209 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 600*5));
210 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
211 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
212 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
213 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
214 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
215 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
216 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
217 aInnerPoly
.setClosed(true);
219 p3DObj
= new E3dLatheObj(
220 mpView
->getSdrModelFromSdrView(),
221 mpView
->Get3DDefaultAttributes(),
222 ::basegfx::B2DPolyPolygon(aInnerPoly
));
228 ::basegfx::B2DPolygon aInnerPoly
;
230 aInnerPoly
.append(::basegfx::B2DPoint(0, -1000*5));
231 aInnerPoly
.append(::basegfx::B2DPoint(25*5, -900*5));
232 aInnerPoly
.append(::basegfx::B2DPoint(50*5, -800*5));
233 aInnerPoly
.append(::basegfx::B2DPoint(100*5, -600*5));
234 aInnerPoly
.append(::basegfx::B2DPoint(200*5, -200*5));
235 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 200*5));
236 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 600*5));
237 aInnerPoly
.append(::basegfx::B2DPoint(500*5, 1000*5));
238 aInnerPoly
.append(::basegfx::B2DPoint(400*5, 1000*5));
239 aInnerPoly
.append(::basegfx::B2DPoint(300*5, 1000*5));
240 aInnerPoly
.append(::basegfx::B2DPoint(200*5, 1000*5));
241 aInnerPoly
.append(::basegfx::B2DPoint(100*5, 1000*5));
242 aInnerPoly
.append(::basegfx::B2DPoint(50*5, 1000*5));
243 aInnerPoly
.append(::basegfx::B2DPoint(0, 1000*5));
244 aInnerPoly
.setClosed(true);
246 p3DObj
= new E3dLatheObj(
247 mpView
->getSdrModelFromSdrView(),
248 mpView
->Get3DDefaultAttributes(),
249 ::basegfx::B2DPolyPolygon(aInnerPoly
));
250 p3DObj
->SetMergedItem(makeSvx3DHorizontalSegmentsItem(4));
258 void FuConstruct3dObject::ImpPrepareBasic3DShape(E3dCompoundObject
const * p3DObj
, E3dScene
*pScene
)
260 Camera3D aCamera
= pScene
->GetCamera ();
262 // get transformed BoundVolume of the new object
263 basegfx::B3DRange aBoundVol
;
264 basegfx::B3DRange
aObjVol(p3DObj
->GetBoundVolume());
265 aObjVol
.transform(p3DObj
->GetTransform());
266 aBoundVol
.expand(aObjVol
);
267 double fDeepth(aBoundVol
.getDepth());
269 aCamera
.SetPRP(::basegfx::B3DPoint(0.0, 0.0, 1000.0));
270 aCamera
.SetPosition(::basegfx::B3DPoint(0.0, 0.0, mpView
->GetDefaultCamPosZ() + fDeepth
/ 2));
271 aCamera
.SetFocalLength(mpView
->GetDefaultCamFocal());
272 pScene
->SetCamera(aCamera
);
273 basegfx::B3DHomMatrix aTransformation
;
279 aTransformation
.rotate(DEG2RAD(20), 0.0, 0.0);
289 case SID_3D_HALF_SPHERE
:
291 aTransformation
.rotate(DEG2RAD(200), 0.0, 0.0);
295 case SID_3D_CYLINDER
:
304 aTransformation
.rotate(DEG2RAD(90), 0.0, 0.0);
314 pScene
->SetTransform(aTransformation
* pScene
->GetTransform());
316 SfxItemSet
aAttr (mpViewShell
->GetPool());
317 pScene
->SetMergedItemSetAndBroadcast(aAttr
);
320 bool FuConstruct3dObject::MouseButtonDown(const MouseEvent
& rMEvt
)
322 bool bReturn
= FuConstruct::MouseButtonDown(rMEvt
);
324 if ( rMEvt
.IsLeft() && !mpView
->IsAction() )
326 Point
aPnt( mpWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
328 mpWindow
->CaptureMouse();
329 sal_uInt16 nDrgLog
= sal_uInt16 ( mpWindow
->PixelToLogic(Size(DRGPIX
,0)).Width() );
331 E3dCompoundObject
* p3DObj
= nullptr;
333 WaitObject
aWait( static_cast<vcl::Window
*>(mpViewShell
->GetActiveWindow()) );
335 p3DObj
= ImpCreateBasic3DShape();
336 E3dScene
* pScene
= mpView
->SetCurrent3DObj(p3DObj
);
338 ImpPrepareBasic3DShape(p3DObj
, pScene
);
339 bReturn
= mpView
->BegCreatePreparedObject(aPnt
, nDrgLog
, pScene
);
341 SdrObject
* pObj
= mpView
->GetCreateObj();
345 SfxItemSet
aAttr(mpDoc
->GetPool());
346 SetStyleSheet(aAttr
, pObj
);
349 aAttr
.Put(XLineStyleItem (drawing::LineStyle_NONE
));
351 pObj
->SetMergedItemSet(aAttr
);
358 bool FuConstruct3dObject::MouseButtonUp(const MouseEvent
& rMEvt
)
360 bool bReturn
= false;
362 if ( mpView
->IsCreateObj() && rMEvt
.IsLeft() )
364 mpView
->EndCreateObj(SdrCreateCmd::ForceEnd
);
368 bReturn
= FuConstruct::MouseButtonUp(rMEvt
) || bReturn
;
371 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
);
376 void FuConstruct3dObject::Activate()
378 mpView
->SetCurrentObj(OBJ_NONE
);
380 FuConstruct::Activate();
383 SdrObject
* FuConstruct3dObject::CreateDefaultObject(const sal_uInt16 nID
, const ::tools::Rectangle
& rRectangle
)
386 E3dCompoundObject
* p3DObj
= ImpCreateBasic3DShape();
388 // E3dView::SetCurrent3DObj part
389 // get transformed BoundVolume of the object
390 basegfx::B3DRange
aObjVol(p3DObj
->GetBoundVolume());
391 aObjVol
.transform(p3DObj
->GetTransform());
392 basegfx::B3DRange
aVolume(aObjVol
);
393 double fW(aVolume
.getWidth());
394 double fH(aVolume
.getHeight());
395 ::tools::Rectangle
a3DRect(0, 0, static_cast<long>(fW
), static_cast<long>(fH
));
396 E3dScene
* pScene
= new E3dScene(*mpDoc
);
398 // copied code from E3dView::InitScene
399 double fCamZ(aVolume
.getMaxZ() + ((fW
+ fH
) / 4.0));
400 Camera3D
aCam(pScene
->GetCamera());
401 aCam
.SetAutoAdjustProjection(false);
402 aCam
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
403 ::basegfx::B3DPoint aLookAt
;
404 double fDefaultCamPosZ
= mpView
->GetDefaultCamPosZ();
405 ::basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
406 aCam
.SetPosAndLookAt(aCamPos
, aLookAt
);
407 aCam
.SetFocalLength(mpView
->GetDefaultCamFocal());
408 aCam
.SetDefaults(::basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ
), aLookAt
);
409 pScene
->SetCamera(aCam
);
410 pScene
->Insert3DObj(p3DObj
);
411 pScene
->NbcSetSnapRect(a3DRect
);
412 ImpPrepareBasic3DShape(p3DObj
, pScene
);
413 SfxItemSet
aAttr(mpDoc
->GetPool());
414 SetStyleSheet(aAttr
, p3DObj
);
415 aAttr
.Put(XLineStyleItem (drawing::LineStyle_NONE
));
416 p3DObj
->SetMergedItemSet(aAttr
);
418 // make object interactive at once
419 pScene
->SetRectsDirty();
421 // Take care of restrictions for the rectangle
422 ::tools::Rectangle
aRect(rRectangle
);
431 ImpForceQuadratic(aRect
);
436 case SID_3D_HALF_SPHERE
:
438 // force horizontal layout
442 case SID_3D_CYLINDER
:
446 // force vertical layout
451 // use changed rectangle, not original one
452 pScene
->SetLogicRect(aRect
);
457 } // end of namespace sd
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */