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 <svx/dlgctl3d.hxx>
22 #include <svx/strings.hrc>
23 #include <svx/view3d.hxx>
24 #include <svx/fmmodel.hxx>
25 #include <svl/itempool.hxx>
26 #include <svx/fmpage.hxx>
27 #include <svx/sphere3d.hxx>
28 #include <svx/cube3d.hxx>
29 #include <svx/scene3d.hxx>
30 #include <vcl/svapp.hxx>
31 #include <svx/helperhittest3d.hxx>
32 #include <basegfx/polygon/b2dpolygontools.hxx>
33 #include <polygn3d.hxx>
34 #include <svx/xfillit0.hxx>
35 #include <svx/xflclit.hxx>
36 #include <svx/xlineit0.hxx>
37 #include <svx/xlnclit.hxx>
38 #include <svx/xlnwtit.hxx>
40 #include <svx/dialmgr.hxx>
41 #include <tools/helpers.hxx>
42 #include <vcl/settings.hxx>
44 using namespace com::sun::star
;
46 Svx3DPreviewControl::Svx3DPreviewControl()
47 : mnObjectType(SvxPreviewObjectType::SPHERE
)
51 void Svx3DPreviewControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
53 Size
aSize(pDrawingArea
->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont
)));
54 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
55 CustomWidgetController::SetDrawingArea(pDrawingArea
);
56 SetOutputSizePixel(aSize
);
61 void Svx3DPreviewControl::ClearPageView()
63 mp3DView
->ClearPageView();
66 Svx3DPreviewControl::~Svx3DPreviewControl()
75 void Svx3DPreviewControl::Construct()
77 // Do never mirror the preview window. This explicitly includes right
78 // to left writing environments.
80 OutputDevice
& rDevice
= GetDrawingArea()->get_ref_device();
81 rDevice
.SetMapMode(MapMode(MapUnit::Map100thMM
));
84 mpModel
.reset(new FmFormModel());
87 mxFmPage
= new FmFormPage( *mpModel
);
88 mpModel
->InsertPage( mxFmPage
.get(), 0 );
91 mp3DView
.reset(new E3dView(*mpModel
, &rDevice
));
92 mp3DView
->SetBufferedOutputAllowed(true);
93 mp3DView
->SetBufferedOverlayAllowed(true);
96 mpScene
= new E3dScene(*mpModel
);
98 // initially create object
99 SetObjectType(SvxPreviewObjectType::SPHERE
);
101 // camera and perspective
102 Camera3D rCamera
= mpScene
->GetCamera();
103 const basegfx::B3DRange
& rVolume
= mpScene
->GetBoundVolume();
104 double fW
= rVolume
.getWidth();
105 double fH
= rVolume
.getHeight();
106 double fCamZ
= rVolume
.getMaxZ() + ((fW
+ fH
) / 2.0);
108 rCamera
.SetAutoAdjustProjection(false);
109 rCamera
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
110 basegfx::B3DPoint aLookAt
;
111 double fDefaultCamPosZ
= mp3DView
->GetDefaultCamPosZ();
112 basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
113 rCamera
.SetPosAndLookAt(aCamPos
, aLookAt
);
114 double fDefaultCamFocal
= mp3DView
->GetDefaultCamFocal();
115 rCamera
.SetFocalLength(fDefaultCamFocal
);
117 mpScene
->SetCamera( rCamera
);
118 mxFmPage
->InsertObject( mpScene
.get() );
120 basegfx::B3DHomMatrix aRotation
;
121 aRotation
.rotate(basegfx::deg2rad( 25 ), 0.0, 0.0);
122 aRotation
.rotate(0.0, basegfx::deg2rad( 40 ), 0.0);
123 mpScene
->SetTransform(aRotation
* mpScene
->GetTransform());
125 // invalidate SnapRects of objects
126 mpScene
->SetBoundAndSnapRectsDirty();
128 SfxItemSetFixed
<XATTR_LINESTYLE
, XATTR_LINESTYLE
,
129 XATTR_FILL_FIRST
, XATTR_FILLBITMAP
> aSet( mpModel
->GetItemPool() );
130 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
131 aSet
.Put( XFillStyleItem( drawing::FillStyle_SOLID
) );
132 aSet
.Put( XFillColorItem( u
""_ustr
, COL_WHITE
) );
134 mpScene
->SetMergedItemSet(aSet
);
137 SdrPageView
* pPageView
= mp3DView
->ShowSdrPage( mxFmPage
.get() );
138 mp3DView
->hideMarkHandles();
141 mp3DView
->MarkObj( mpScene
.get(), pPageView
);
144 void Svx3DPreviewControl::Resize()
147 Size
aSize(GetOutputSizePixel());
148 aSize
= GetDrawingArea()->get_ref_device().PixelToLogic(aSize
);
149 mxFmPage
->SetSize(aSize
);
152 Size
aObjSize( aSize
.Width()*5/6, aSize
.Height()*5/6 );
153 Point
aObjPoint( (aSize
.Width() - aObjSize
.Width()) / 2,
154 (aSize
.Height() - aObjSize
.Height()) / 2);
155 tools::Rectangle
aRect( aObjPoint
, aObjSize
);
156 mpScene
->SetSnapRect( aRect
);
159 void Svx3DPreviewControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
161 mp3DView
->CompleteRedraw(&rRenderContext
, vcl::Region(rRect
));
164 bool Svx3DPreviewControl::MouseButtonDown(const MouseEvent
& rMEvt
)
166 if (rMEvt
.IsShift() && rMEvt
.IsMod1())
168 if(SvxPreviewObjectType::SPHERE
== GetObjectType())
170 SetObjectType(SvxPreviewObjectType::CUBE
);
174 SetObjectType(SvxPreviewObjectType::SPHERE
);
180 void Svx3DPreviewControl::SetObjectType(SvxPreviewObjectType nType
)
182 if(mnObjectType
== nType
&& mp3DObj
)
185 SfxItemSetFixed
<SDRATTR_START
, SDRATTR_END
> aSet(mpModel
->GetItemPool());
186 mnObjectType
= nType
;
190 aSet
.Put(mp3DObj
->GetMergedItemSet());
191 mpScene
->RemoveObject( mp3DObj
->GetOrdNum() );
197 case SvxPreviewObjectType::SPHERE
:
199 mp3DObj
= new E3dSphereObj(
201 mp3DView
->Get3DDefaultAttributes(),
202 basegfx::B3DPoint( 0, 0, 0 ),
203 basegfx::B3DVector( 5000, 5000, 5000 ));
207 case SvxPreviewObjectType::CUBE
:
209 mp3DObj
= new E3dCubeObj(
211 mp3DView
->Get3DDefaultAttributes(),
212 basegfx::B3DPoint( -2500, -2500, -2500 ),
213 basegfx::B3DVector( 5000, 5000, 5000 ));
220 mpScene
->InsertObject( mp3DObj
.get() );
221 mp3DObj
->SetMergedItemSet(aSet
);
227 SfxItemSet
const & Svx3DPreviewControl::Get3DAttributes() const
229 return mp3DObj
->GetMergedItemSet();
232 void Svx3DPreviewControl::Set3DAttributes( const SfxItemSet
& rAttr
)
234 mp3DObj
->SetMergedItemSet(rAttr
, true);
239 #define RADIUS_LAMP_PREVIEW_SIZE (4500.0)
240 #define RADIUS_LAMP_SMALL (600.0)
241 #define RADIUS_LAMP_BIG (1000.0)
242 #define NO_LIGHT_SELECTED (0xffffffff)
243 #define MAX_NUMBER_LIGHTS (8)
245 const sal_Int32 g_nInteractionStartDistance
= 5 * 5 * 2;
247 Svx3DLightControl::Svx3DLightControl()
248 : maSelectedLight(NO_LIGHT_SELECTED
),
249 maLightObjects(MAX_NUMBER_LIGHTS
, nullptr),
253 mfSaveActionStartHor(0.0),
254 mfSaveActionStartVer(0.0),
255 mfSaveActionStartRotZ(0.0),
257 mbMouseCaptured(false),
258 mbGeometrySelected(false)
262 void Svx3DLightControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
264 Svx3DPreviewControl::SetDrawingArea(pDrawingArea
);
268 void Svx3DLightControl::Construct2()
271 // hide all page stuff, use control background (normally gray)
272 const Color
aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
273 mp3DView
->SetPageVisible(false);
274 mp3DView
->SetApplicationBackgroundColor(aDialogColor
);
275 mp3DView
->SetApplicationDocumentColor(aDialogColor
);
279 // create invisible expansion object
280 const double fMaxExpansion(RADIUS_LAMP_BIG
+ RADIUS_LAMP_PREVIEW_SIZE
);
281 mpExpansionObject
= new E3dCubeObj(
283 mp3DView
->Get3DDefaultAttributes(),
284 basegfx::B3DPoint(-fMaxExpansion
, -fMaxExpansion
, -fMaxExpansion
),
285 basegfx::B3DVector(2.0 * fMaxExpansion
, 2.0 * fMaxExpansion
, 2.0 * fMaxExpansion
));
286 mpScene
->InsertObject( mpExpansionObject
.get() );
287 SfxItemSet
aSet(mpModel
->GetItemPool());
288 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
289 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
290 mpExpansionObject
->SetMergedItemSet(aSet
);
294 // create lamp control object (Yellow lined object)
296 const basegfx::B2DPolygon
a2DCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE
));
297 basegfx::B3DPolygon
a3DCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DCircle
));
298 basegfx::B3DHomMatrix aTransform
;
300 aTransform
.rotate(M_PI_2
, 0.0, 0.0);
301 aTransform
.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE
, 0.0);
302 a3DCircle
.transform(aTransform
);
304 // create object for it
305 mpLampBottomObject
= new E3dPolygonObj(
307 basegfx::B3DPolyPolygon(a3DCircle
));
308 mpScene
->InsertObject( mpLampBottomObject
.get() );
310 // half circle with stand
311 basegfx::B2DPolygon a2DHalfCircle
;
312 a2DHalfCircle
.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE
, 0.0));
313 a2DHalfCircle
.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE
, -RADIUS_LAMP_PREVIEW_SIZE
));
314 a2DHalfCircle
.append(basegfx::utils::createPolygonFromEllipseSegment(
315 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE
, RADIUS_LAMP_PREVIEW_SIZE
, 2 * M_PI
- M_PI_2
, M_PI_2
));
316 basegfx::B3DPolygon
a3DHalfCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DHalfCircle
));
318 // create object for it
319 mpLampShaftObject
= new E3dPolygonObj(
321 basegfx::B3DPolyPolygon(a3DHalfCircle
));
322 mpScene
->InsertObject( mpLampShaftObject
.get() );
324 // initially invisible
325 SfxItemSet
aSet(mpModel
->GetItemPool());
326 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
327 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
329 mpLampBottomObject
->SetMergedItemSet(aSet
);
330 mpLampShaftObject
->SetMergedItemSet(aSet
);
334 // change camera settings
335 Camera3D rCamera
= mpScene
->GetCamera();
336 const basegfx::B3DRange
& rVolume
= mpScene
->GetBoundVolume();
337 double fW
= rVolume
.getWidth();
338 double fH
= rVolume
.getHeight();
339 double fCamZ
= rVolume
.getMaxZ() + ((fW
+ fH
) / 2.0);
341 rCamera
.SetAutoAdjustProjection(false);
342 rCamera
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
343 basegfx::B3DPoint aLookAt
;
344 double fDefaultCamPosZ
= mp3DView
->GetDefaultCamPosZ();
345 basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
346 rCamera
.SetPosAndLookAt(aCamPos
, aLookAt
);
347 double fDefaultCamFocal
= mp3DView
->GetDefaultCamFocal();
348 rCamera
.SetFocalLength(fDefaultCamFocal
);
350 mpScene
->SetCamera( rCamera
);
352 basegfx::B3DHomMatrix aNeutral
;
353 mpScene
->SetTransform(aNeutral
);
356 // invalidate SnapRects of objects
357 mpScene
->SetBoundAndSnapRectsDirty();
360 void Svx3DLightControl::ConstructLightObjects()
362 for(sal_uInt32
a(0); a
< MAX_NUMBER_LIGHTS
; a
++)
364 // get rid of possible existing light object
365 if(maLightObjects
[a
])
367 mpScene
->RemoveObject(maLightObjects
[a
]->GetOrdNum());
368 maLightObjects
[a
] = nullptr;
373 const bool bIsSelectedLight(a
== maSelectedLight
);
374 basegfx::B3DVector
aDirection(GetLightDirection(a
));
375 aDirection
.normalize();
376 aDirection
*= RADIUS_LAMP_PREVIEW_SIZE
;
378 const double fLampSize(bIsSelectedLight
? RADIUS_LAMP_BIG
: RADIUS_LAMP_SMALL
);
379 rtl::Reference
<E3dObject
> pNewLight
= new E3dSphereObj(
381 mp3DView
->Get3DDefaultAttributes(),
382 basegfx::B3DPoint( 0, 0, 0 ),
383 basegfx::B3DVector( fLampSize
, fLampSize
, fLampSize
));
384 mpScene
->InsertObject(pNewLight
.get());
386 basegfx::B3DHomMatrix aTransform
;
387 aTransform
.translate(aDirection
.getX(), aDirection
.getY(), aDirection
.getZ());
388 pNewLight
->SetTransform(aTransform
);
390 SfxItemSet
aSet(mpModel
->GetItemPool());
391 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
392 aSet
.Put( XFillStyleItem( drawing::FillStyle_SOLID
) );
393 aSet
.Put( XFillColorItem(OUString(), GetLightColor(a
)));
394 pNewLight
->SetMergedItemSet(aSet
);
396 maLightObjects
[a
] = pNewLight
.get();
401 void Svx3DLightControl::AdaptToSelectedLight()
403 if(NO_LIGHT_SELECTED
== maSelectedLight
)
405 // make mpLampBottomObject/mpLampShaftObject invisible
406 SfxItemSet
aSet(mpModel
->GetItemPool());
407 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
408 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
409 mpLampBottomObject
->SetMergedItemSet(aSet
);
410 mpLampShaftObject
->SetMergedItemSet(aSet
);
414 basegfx::B3DVector
aDirection(GetLightDirection(maSelectedLight
));
415 aDirection
.normalize();
417 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
418 SfxItemSet
aSet(mpModel
->GetItemPool());
419 aSet
.Put( XLineStyleItem( drawing::LineStyle_SOLID
) );
420 aSet
.Put( XLineColorItem(OUString(), COL_YELLOW
));
421 aSet
.Put( XLineWidthItem(0));
422 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
423 mpLampBottomObject
->SetMergedItemSet(aSet
);
424 mpLampShaftObject
->SetMergedItemSet(aSet
);
426 // adapt transformation of mpLampShaftObject
427 basegfx::B3DHomMatrix aTransform
;
428 double fRotateY(0.0);
430 if(!basegfx::fTools::equalZero(aDirection
.getZ()) || !basegfx::fTools::equalZero(aDirection
.getX()))
432 fRotateY
= atan2(-aDirection
.getZ(), aDirection
.getX());
435 aTransform
.rotate(0.0, fRotateY
, 0.0);
436 mpLampShaftObject
->SetTransform(aTransform
);
438 // adapt transformation of selected light
439 E3dObject
* pSelectedLight
= maLightObjects
[sal_Int32(maSelectedLight
)];
443 aTransform
.identity();
444 aTransform
.translate(
445 aDirection
.getX() * RADIUS_LAMP_PREVIEW_SIZE
,
446 aDirection
.getY() * RADIUS_LAMP_PREVIEW_SIZE
,
447 aDirection
.getZ() * RADIUS_LAMP_PREVIEW_SIZE
);
448 pSelectedLight
->SetTransform(aTransform
);
453 void Svx3DLightControl::TrySelection(Point aPosPixel
)
458 const Point
aPosLogic(GetDrawingArea()->get_ref_device().PixelToLogic(aPosPixel
));
459 const basegfx::B2DPoint
aPoint(aPosLogic
.X(), aPosLogic
.Y());
460 std::vector
< const E3dCompoundObject
* > aResult
;
461 getAllHit3DObjectsSortedFrontToBack(aPoint
, *mpScene
, aResult
);
466 // exclude expansion object which will be part of
467 // the hits. It's invisible, but for HitTest, it's included
468 const E3dCompoundObject
* pResult
= nullptr;
470 for(auto const & b
: aResult
)
472 if(b
&& b
!= mpExpansionObject
.get())
479 if(pResult
== mp3DObj
.get())
481 if(!mbGeometrySelected
)
483 mbGeometrySelected
= true;
484 maSelectedLight
= NO_LIGHT_SELECTED
;
485 ConstructLightObjects();
486 AdaptToSelectedLight();
489 if(maSelectionChangeCallback
.IsSet())
491 maSelectionChangeCallback
.Call(this);
497 sal_uInt32
aNewSelectedLight(NO_LIGHT_SELECTED
);
499 for(sal_uInt32
a(0); a
< MAX_NUMBER_LIGHTS
; a
++)
501 if(maLightObjects
[a
] && maLightObjects
[a
] == pResult
)
503 aNewSelectedLight
= a
;
507 if(aNewSelectedLight
!= maSelectedLight
)
509 SelectLight(aNewSelectedLight
);
511 if(maSelectionChangeCallback
.IsSet())
513 maSelectionChangeCallback
.Call(this);
519 void Svx3DLightControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
521 Svx3DPreviewControl::Paint(rRenderContext
, rRect
);
524 tools::Rectangle
Svx3DLightControl::GetFocusRect()
527 return tools::Rectangle();
528 Size aFocusSize
= GetOutputSizePixel();
529 aFocusSize
.AdjustWidth( -4 );
530 aFocusSize
.AdjustHeight( -4 );
531 return tools::Rectangle(Point(2, 2), aFocusSize
);
534 bool Svx3DLightControl::MouseButtonDown( const MouseEvent
& rMEvt
)
536 bool bCallParent(true);
541 if(IsSelectionValid() || mbGeometrySelected
)
543 mbMouseMoved
= false;
545 maActionStartPoint
= rMEvt
.GetPosPixel();
547 mbMouseCaptured
= true;
551 // Single click without moving much trying to do a selection
552 TrySelection(rMEvt
.GetPosPixel());
559 return Svx3DPreviewControl::MouseButtonDown(rMEvt
);
563 bool Svx3DLightControl::MouseMove(const MouseEvent
& rMEvt
)
565 if (!mbMouseCaptured
)
568 Point aDeltaPos
= rMEvt
.GetPosPixel() - maActionStartPoint
;
572 if(sal_Int32(aDeltaPos
.X() * aDeltaPos
.X() + aDeltaPos
.Y() * aDeltaPos
.Y()) > g_nInteractionStartDistance
)
574 if(mbGeometrySelected
)
576 GetRotation(mfSaveActionStartVer
, mfSaveActionStartHor
, mfSaveActionStartRotZ
);
580 // interaction start, save values
581 GetPosition(mfSaveActionStartHor
, mfSaveActionStartVer
);
590 if(mbGeometrySelected
)
592 double fNewRotX
= mfSaveActionStartVer
- basegfx::deg2rad(aDeltaPos
.Y());
593 double fNewRotY
= mfSaveActionStartHor
+ basegfx::deg2rad(aDeltaPos
.X());
596 while(fNewRotY
< 0.0)
598 fNewRotY
+= 2 * M_PI
;
601 while(fNewRotY
>= 2 * M_PI
)
603 fNewRotY
-= 2 * M_PI
;
607 if(fNewRotX
< -M_PI_2
)
612 if(fNewRotX
> M_PI_2
)
617 SetRotation(fNewRotX
, fNewRotY
, mfSaveActionStartRotZ
);
619 if(maChangeCallback
.IsSet())
621 maChangeCallback
.Call(this);
626 // interaction in progress
627 double fNewPosHor
= mfSaveActionStartHor
+ static_cast<double>(aDeltaPos
.X());
628 double fNewPosVer
= mfSaveActionStartVer
- static_cast<double>(aDeltaPos
.Y());
631 fNewPosHor
= NormAngle360(fNewPosHor
);
634 if(fNewPosVer
< -90.0)
639 if(fNewPosVer
> 90.0)
644 SetPosition(fNewPosHor
, fNewPosVer
);
646 if(maChangeCallback
.IsSet())
648 maChangeCallback
.Call(this);
655 bool Svx3DLightControl::MouseButtonUp(const MouseEvent
& rMEvt
)
657 if (!mbMouseCaptured
)
660 mbMouseCaptured
= false;
664 // was change interactively
668 // simple click without much movement, try selection
669 TrySelection(rMEvt
.GetPosPixel());
675 void Svx3DLightControl::Resize()
678 const Size
aSize(GetDrawingArea()->get_ref_device().PixelToLogic(GetOutputSizePixel()));
679 mxFmPage
->SetSize(aSize
);
681 // set position and size of scene
682 mpScene
->SetSnapRect(tools::Rectangle(Point(0, 0), aSize
));
685 void Svx3DLightControl::SetObjectType(SvxPreviewObjectType nType
)
688 Svx3DPreviewControl::SetObjectType(nType
);
690 // apply object rotation
693 basegfx::B3DHomMatrix aObjectRotation
;
694 aObjectRotation
.rotate(mfRotateX
, mfRotateY
, mfRotateZ
);
695 mp3DObj
->SetTransform(aObjectRotation
);
699 bool Svx3DLightControl::IsSelectionValid()
701 return (NO_LIGHT_SELECTED
!= maSelectedLight
) && GetLightOnOff(maSelectedLight
);
704 void Svx3DLightControl::GetPosition(double& rHor
, double& rVer
)
706 if(IsSelectionValid())
708 basegfx::B3DVector
aDirection(GetLightDirection(maSelectedLight
));
709 aDirection
.normalize();
710 rHor
= basegfx::rad2deg(atan2(-aDirection
.getX(), -aDirection
.getZ()) + M_PI
); // 0..360.0
711 rVer
= basegfx::rad2deg(atan2(aDirection
.getY(), aDirection
.getXZLength())); // -90.0..90.0
713 if(IsGeometrySelected())
715 rHor
= basegfx::rad2deg(mfRotateY
); // 0..360.0
716 rVer
= basegfx::rad2deg(mfRotateX
); // -90.0..90.0
720 void Svx3DLightControl::SetPosition(double fHor
, double fVer
)
722 if(IsSelectionValid())
724 // set selected light's direction
725 fHor
= basegfx::deg2rad(fHor
) - M_PI
; // -PI..PI
726 fVer
= basegfx::deg2rad(fVer
); // -PI2..PI2
727 basegfx::B3DVector
aDirection(cos(fVer
) * -sin(fHor
), sin(fVer
), cos(fVer
) * -cos(fHor
));
728 aDirection
.normalize();
730 if(!aDirection
.equal(GetLightDirection(maSelectedLight
)))
732 // set changed light direction at SdrScene
733 SfxItemSet
aSet(mpModel
->GetItemPool());
735 switch(maSelectedLight
)
737 case 0: aSet
.Put(makeSvx3DLightDirection1Item(aDirection
)); break;
738 case 1: aSet
.Put(makeSvx3DLightDirection2Item(aDirection
)); break;
739 case 2: aSet
.Put(makeSvx3DLightDirection3Item(aDirection
)); break;
740 case 3: aSet
.Put(makeSvx3DLightDirection4Item(aDirection
)); break;
741 case 4: aSet
.Put(makeSvx3DLightDirection5Item(aDirection
)); break;
742 case 5: aSet
.Put(makeSvx3DLightDirection6Item(aDirection
)); break;
743 case 6: aSet
.Put(makeSvx3DLightDirection7Item(aDirection
)); break;
745 case 7: aSet
.Put(makeSvx3DLightDirection8Item(aDirection
)); break;
748 mpScene
->SetMergedItemSet(aSet
);
750 // correct 3D light's and LampFrame's geometries
751 AdaptToSelectedLight();
755 if(!IsGeometrySelected())
758 if(mfRotateX
== fVer
&& mfRotateY
== fHor
)
761 mfRotateX
= basegfx::deg2rad(fVer
);
762 mfRotateY
= basegfx::deg2rad(fHor
);
766 basegfx::B3DHomMatrix aObjectRotation
;
767 aObjectRotation
.rotate(mfRotateX
, mfRotateY
, mfRotateZ
);
768 mp3DObj
->SetTransform(aObjectRotation
);
774 void Svx3DLightControl::SetRotation(double fRotX
, double fRotY
, double fRotZ
)
776 if(!IsGeometrySelected())
779 if(fRotX
== mfRotateX
&& fRotY
== mfRotateY
&& fRotZ
== mfRotateZ
)
788 basegfx::B3DHomMatrix aObjectRotation
;
789 aObjectRotation
.rotate(mfRotateX
, mfRotateY
, mfRotateZ
);
790 mp3DObj
->SetTransform(aObjectRotation
);
796 void Svx3DLightControl::GetRotation(double& rRotX
, double& rRotY
, double& rRotZ
)
803 void Svx3DLightControl::Set3DAttributes( const SfxItemSet
& rAttr
)
806 Svx3DPreviewControl::Set3DAttributes(rAttr
);
808 if(maSelectedLight
!= NO_LIGHT_SELECTED
&& !GetLightOnOff(maSelectedLight
))
810 // selected light is no more active, select new one
811 maSelectedLight
= NO_LIGHT_SELECTED
;
815 ConstructLightObjects();
816 AdaptToSelectedLight();
820 void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber
)
824 nLightNumber
= NO_LIGHT_SELECTED
;
827 if(NO_LIGHT_SELECTED
!= nLightNumber
)
829 if(!GetLightOnOff(nLightNumber
))
831 nLightNumber
= NO_LIGHT_SELECTED
;
835 if(nLightNumber
!= maSelectedLight
)
837 maSelectedLight
= nLightNumber
;
838 mbGeometrySelected
= false;
839 ConstructLightObjects();
840 AdaptToSelectedLight();
845 bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum
) const
849 const SfxItemSet
aLightItemSet(Get3DAttributes());
853 case 0 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_1
).GetValue();
854 case 1 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_2
).GetValue();
855 case 2 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_3
).GetValue();
856 case 3 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_4
).GetValue();
857 case 4 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_5
).GetValue();
858 case 5 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_6
).GetValue();
859 case 6 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_7
).GetValue();
860 case 7 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_8
).GetValue();
867 Color
Svx3DLightControl::GetLightColor(sal_uInt32 nNum
) const
871 const SfxItemSet
aLightItemSet(Get3DAttributes());
875 case 0 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1
).GetValue();
876 case 1 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2
).GetValue();
877 case 2 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3
).GetValue();
878 case 3 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4
).GetValue();
879 case 4 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5
).GetValue();
880 case 5 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6
).GetValue();
881 case 6 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7
).GetValue();
882 case 7 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8
).GetValue();
889 basegfx::B3DVector
Svx3DLightControl::GetLightDirection(sal_uInt32 nNum
) const
893 const SfxItemSet
aLightItemSet(Get3DAttributes());
897 case 0 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1
).GetValue();
898 case 1 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2
).GetValue();
899 case 2 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3
).GetValue();
900 case 3 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4
).GetValue();
901 case 4 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5
).GetValue();
902 case 5 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6
).GetValue();
903 case 6 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7
).GetValue();
904 case 7 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8
).GetValue();
908 return basegfx::B3DVector();
911 SvxLightCtl3D::SvxLightCtl3D(Svx3DLightControl
& rLightControl
, weld::Scale
& rHori
,
912 weld::Scale
& rVert
, weld::Button
& rSwitcher
)
913 : mrLightControl(rLightControl
)
914 , mrHorScroller(rHori
)
915 , mrVerScroller(rVert
)
916 , mrSwitcher(rSwitcher
)
922 void SvxLightCtl3D::Init()
924 Size
aSize(mrLightControl
.GetDrawingArea()->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont
)));
925 mrLightControl
.set_size_request(aSize
.Width(), aSize
.Height());
927 // #i58240# set HelpIDs for scrollbars and switcher
928 mrHorScroller
.set_help_id(HID_CTRL3D_HSCROLL
);
929 mrVerScroller
.set_help_id(HID_CTRL3D_VSCROLL
);
930 mrSwitcher
.set_help_id(HID_CTRL3D_SWITCHER
);
931 mrSwitcher
.set_accessible_name(SvxResId(STR_SWITCH
));
934 mrLightControl
.Show();
935 mrLightControl
.SetChangeCallback( LINK(this, SvxLightCtl3D
, InternalInteractiveChange
) );
936 mrLightControl
.SetSelectionChangeCallback( LINK(this, SvxLightCtl3D
, InternalSelectionChange
) );
939 mrHorScroller
.show();
940 mrHorScroller
.set_range(0, 36000);
941 mrHorScroller
.connect_value_changed( LINK(this, SvxLightCtl3D
, ScrollBarMove
) );
944 mrVerScroller
.show();
945 mrVerScroller
.set_range(0, 18000);
946 mrVerScroller
.connect_value_changed( LINK(this, SvxLightCtl3D
, ScrollBarMove
) );
950 mrSwitcher
.connect_clicked( LINK(this, SvxLightCtl3D
, ButtonPress
) );
952 weld::DrawingArea
* pArea
= mrLightControl
.GetDrawingArea();
953 pArea
->connect_key_press(Link
<const KeyEvent
&, bool>()); //acknowledge we first remove the old one
954 pArea
->connect_key_press(LINK(this, SvxLightCtl3D
, KeyInput
));
956 pArea
->connect_focus_in(Link
<weld::Widget
&, void>()); //acknowledge we first remove the old one
957 pArea
->connect_focus_in(LINK(this, SvxLightCtl3D
, FocusIn
));
963 void SvxLightCtl3D::CheckSelection()
965 const bool bSelectionValid(mrLightControl
.IsSelectionValid() || mrLightControl
.IsGeometrySelected());
966 mrHorScroller
.set_sensitive(bSelectionValid
);
967 mrVerScroller
.set_sensitive(bSelectionValid
);
971 double fHor(0.0), fVer(0.0);
972 mrLightControl
.GetPosition(fHor
, fVer
);
973 mrHorScroller
.set_value( sal_Int32(fHor
* 100.0) );
974 mrVerScroller
.set_value( 18000 - sal_Int32((fVer
+ 90.0) * 100.0) );
978 void SvxLightCtl3D::move( double fDeltaHor
, double fDeltaVer
)
980 double fHor(0.0), fVer(0.0);
982 mrLightControl
.GetPosition(fHor
, fVer
);
992 mrLightControl
.SetPosition(fHor
, fVer
);
993 mrHorScroller
.set_value( sal_Int32(fHor
* 100.0) );
994 mrVerScroller
.set_value( 18000 - sal_Int32((fVer
+ 90.0) * 100.0) );
996 if(maUserInteractiveChangeCallback
.IsSet())
998 maUserInteractiveChangeCallback
.Call(this);
1002 IMPL_LINK(SvxLightCtl3D
, KeyInput
, const KeyEvent
&, rKEvt
, bool)
1004 const vcl::KeyCode
aCode(rKEvt
.GetKeyCode());
1006 if (aCode
.GetModifier())
1009 bool bHandled
= true;
1011 switch ( aCode
.GetCode() )
1019 move( -4.0, 0.0 ); // #i58242# changed move direction in X
1024 move( 4.0, 0.0 ); // #i58242# changed move direction in X
1039 sal_Int32
nLight(mrLightControl
.GetSelectedLight() - 1);
1041 while((nLight
>= 0) && !mrLightControl
.GetLightOnOff(nLight
))
1050 while((nLight
>= 0) && !mrLightControl
.GetLightOnOff(nLight
))
1058 mrLightControl
.SelectLight(nLight
);
1061 if(maUserSelectionChangeCallback
.IsSet())
1063 maUserSelectionChangeCallback
.Call(this);
1071 sal_Int32
nLight(mrLightControl
.GetSelectedLight() - 1);
1073 while(nLight
<= 7 && !mrLightControl
.GetLightOnOff(nLight
))
1082 while(nLight
<= 7 && !mrLightControl
.GetLightOnOff(nLight
))
1090 mrLightControl
.SelectLight(nLight
);
1093 if(maUserSelectionChangeCallback
.IsSet())
1095 maUserSelectionChangeCallback
.Call(this);
1110 IMPL_LINK_NOARG(SvxLightCtl3D
, FocusIn
, weld::Widget
&, void)
1112 if (mrLightControl
.IsEnabled())
1118 IMPL_LINK_NOARG(SvxLightCtl3D
, ScrollBarMove
, weld::Scale
&, void)
1120 const sal_Int32
nHor(mrHorScroller
.get_value());
1121 const sal_Int32
nVer(mrVerScroller
.get_value());
1123 mrLightControl
.SetPosition(
1124 static_cast<double>(nHor
) / 100.0,
1125 static_cast<double>((18000 - nVer
) - 9000) / 100.0);
1127 if (maUserInteractiveChangeCallback
.IsSet())
1129 maUserInteractiveChangeCallback
.Call(this);
1133 IMPL_LINK_NOARG(SvxLightCtl3D
, ButtonPress
, weld::Button
&, void)
1135 if(SvxPreviewObjectType::SPHERE
== GetSvx3DLightControl().GetObjectType())
1137 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::CUBE
);
1141 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::SPHERE
);
1145 IMPL_LINK_NOARG(SvxLightCtl3D
, InternalInteractiveChange
, Svx3DLightControl
*, void)
1147 double fHor(0.0), fVer(0.0);
1149 mrLightControl
.GetPosition(fHor
, fVer
);
1150 mrHorScroller
.set_value( sal_Int32(fHor
* 100.0) );
1151 mrVerScroller
.set_value( 18000 - sal_Int32((fVer
+ 90.0) * 100.0) );
1153 if(maUserInteractiveChangeCallback
.IsSet())
1155 maUserInteractiveChangeCallback
.Call(this);
1159 IMPL_LINK_NOARG(SvxLightCtl3D
, InternalSelectionChange
, Svx3DLightControl
*, void)
1163 if(maUserSelectionChangeCallback
.IsSet())
1165 maUserSelectionChangeCallback
.Call(this);
1169 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */