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/def3d.hxx>
22 #include <svx/dlgctl3d.hxx>
23 #include <svx/strings.hrc>
24 #include <svx/view3d.hxx>
25 #include <svx/fmmodel.hxx>
26 #include <svl/itempool.hxx>
27 #include <svx/fmpage.hxx>
28 #include <svx/sphere3d.hxx>
29 #include <svx/cube3d.hxx>
30 #include <svx/scene3d.hxx>
31 #include <vcl/svapp.hxx>
32 #include <svx/helperhittest3d.hxx>
33 #include <basegfx/polygon/b2dpolygontools.hxx>
34 #include <polygn3d.hxx>
35 #include <svx/xfillit0.hxx>
36 #include <svx/xflclit.hxx>
37 #include <svx/xlineit0.hxx>
38 #include <svx/xlnclit.hxx>
39 #include <svx/xlnwtit.hxx>
41 #include <svx/dialmgr.hxx>
42 #include <tools/helpers.hxx>
43 #include <vcl/settings.hxx>
45 using namespace com::sun::star
;
47 Svx3DPreviewControl::Svx3DPreviewControl()
51 , mnObjectType(SvxPreviewObjectType::SPHERE
)
55 void Svx3DPreviewControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
57 Size
aSize(pDrawingArea
->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont
)));
58 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
59 CustomWidgetController::SetDrawingArea(pDrawingArea
);
60 SetOutputSizePixel(aSize
);
65 Svx3DPreviewControl::~Svx3DPreviewControl()
71 void Svx3DPreviewControl::Construct()
73 // Do never mirror the preview window. This explicitly includes right
74 // to left writing environments.
76 OutputDevice
& rDevice
= GetDrawingArea()->get_ref_device();
77 rDevice
.SetMapMode(MapMode(MapUnit::Map100thMM
));
80 mpModel
.reset(new FmFormModel());
81 mpModel
->GetItemPool().FreezeIdRanges();
84 mpFmPage
= new FmFormPage( *mpModel
);
85 mpModel
->InsertPage( mpFmPage
, 0 );
88 mp3DView
.reset(new E3dView(*mpModel
, &rDevice
));
89 mp3DView
->SetBufferedOutputAllowed(true);
90 mp3DView
->SetBufferedOverlayAllowed(true);
93 mpScene
= new E3dScene(*mpModel
);
95 // initially create object
96 SetObjectType(SvxPreviewObjectType::SPHERE
);
98 // camera and perspective
99 Camera3D rCamera
= mpScene
->GetCamera();
100 const basegfx::B3DRange
& rVolume
= mpScene
->GetBoundVolume();
101 double fW
= rVolume
.getWidth();
102 double fH
= rVolume
.getHeight();
103 double fCamZ
= rVolume
.getMaxZ() + ((fW
+ fH
) / 2.0);
105 rCamera
.SetAutoAdjustProjection(false);
106 rCamera
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
107 basegfx::B3DPoint aLookAt
;
108 double fDefaultCamPosZ
= mp3DView
->GetDefaultCamPosZ();
109 basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
110 rCamera
.SetPosAndLookAt(aCamPos
, aLookAt
);
111 double fDefaultCamFocal
= mp3DView
->GetDefaultCamFocal();
112 rCamera
.SetFocalLength(fDefaultCamFocal
);
114 mpScene
->SetCamera( rCamera
);
115 mpFmPage
->InsertObject( mpScene
);
117 basegfx::B3DHomMatrix aRotation
;
118 aRotation
.rotate(DEG2RAD( 25 ), 0.0, 0.0);
119 aRotation
.rotate(0.0, DEG2RAD( 40 ), 0.0);
120 mpScene
->SetTransform(aRotation
* mpScene
->GetTransform());
122 // invalidate SnapRects of objects
123 mpScene
->SetRectsDirty();
125 SfxItemSet
aSet( mpModel
->GetItemPool(),
126 svl::Items
<XATTR_LINESTYLE
, XATTR_LINESTYLE
,
127 XATTR_FILL_FIRST
, XATTR_FILLBITMAP
>{} );
128 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
129 aSet
.Put( XFillStyleItem( drawing::FillStyle_SOLID
) );
130 aSet
.Put( XFillColorItem( "", COL_WHITE
) );
132 mpScene
->SetMergedItemSet(aSet
);
135 SdrPageView
* pPageView
= mp3DView
->ShowSdrPage( mpFmPage
);
136 mp3DView
->hideMarkHandles();
139 mp3DView
->MarkObj( mpScene
, pPageView
);
142 void Svx3DPreviewControl::Resize()
145 Size
aSize(GetOutputSizePixel());
146 aSize
= GetDrawingArea()->get_ref_device().PixelToLogic(aSize
);
147 mpFmPage
->SetSize(aSize
);
150 Size
aObjSize( aSize
.Width()*5/6, aSize
.Height()*5/6 );
151 Point
aObjPoint( (aSize
.Width() - aObjSize
.Width()) / 2,
152 (aSize
.Height() - aObjSize
.Height()) / 2);
153 tools::Rectangle
aRect( aObjPoint
, aObjSize
);
154 mpScene
->SetSnapRect( aRect
);
157 void Svx3DPreviewControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
159 mp3DView
->CompleteRedraw(&rRenderContext
, vcl::Region(rRect
));
162 bool Svx3DPreviewControl::MouseButtonDown(const MouseEvent
& rMEvt
)
164 if (rMEvt
.IsShift() && rMEvt
.IsMod1())
166 if(SvxPreviewObjectType::SPHERE
== GetObjectType())
168 SetObjectType(SvxPreviewObjectType::CUBE
);
172 SetObjectType(SvxPreviewObjectType::SPHERE
);
178 void Svx3DPreviewControl::SetObjectType(SvxPreviewObjectType nType
)
180 if(mnObjectType
== nType
&& mp3DObj
)
183 SfxItemSet
aSet(mpModel
->GetItemPool(), svl::Items
<SDRATTR_START
, SDRATTR_END
>{});
184 mnObjectType
= nType
;
188 aSet
.Put(mp3DObj
->GetMergedItemSet());
189 mpScene
->RemoveObject( mp3DObj
->GetOrdNum() );
190 // always use SdrObject::Free(...) for SdrObjects (!)
191 SdrObject
* pTemp(mp3DObj
);
192 SdrObject::Free(pTemp
);
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
);
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 : maChangeCallback(),
249 maSelectionChangeCallback(),
250 maSelectedLight(NO_LIGHT_SELECTED
),
251 mpExpansionObject(nullptr),
252 mpLampBottomObject(nullptr),
253 mpLampShaftObject(nullptr),
254 maLightObjects(MAX_NUMBER_LIGHTS
, nullptr),
258 maActionStartPoint(),
259 mfSaveActionStartHor(0.0),
260 mfSaveActionStartVer(0.0),
261 mfSaveActionStartRotZ(0.0),
263 mbMouseCaptured(false),
264 mbGeometrySelected(false)
268 void Svx3DLightControl::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
270 Svx3DPreviewControl::SetDrawingArea(pDrawingArea
);
274 void Svx3DLightControl::Construct2()
277 // hide all page stuff, use control background (normally gray)
278 const Color
aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
279 mp3DView
->SetPageVisible(false);
280 mp3DView
->SetApplicationBackgroundColor(aDialogColor
);
281 mp3DView
->SetApplicationDocumentColor(aDialogColor
);
285 // create invisible expansion object
286 const double fMaxExpansion(RADIUS_LAMP_BIG
+ RADIUS_LAMP_PREVIEW_SIZE
);
287 mpExpansionObject
= new E3dCubeObj(
289 mp3DView
->Get3DDefaultAttributes(),
290 basegfx::B3DPoint(-fMaxExpansion
, -fMaxExpansion
, -fMaxExpansion
),
291 basegfx::B3DVector(2.0 * fMaxExpansion
, 2.0 * fMaxExpansion
, 2.0 * fMaxExpansion
));
292 mpScene
->InsertObject( mpExpansionObject
);
293 SfxItemSet
aSet(mpModel
->GetItemPool());
294 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
295 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
296 mpExpansionObject
->SetMergedItemSet(aSet
);
300 // create lamp control object (Yellow lined object)
302 const basegfx::B2DPolygon
a2DCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE
));
303 basegfx::B3DPolygon
a3DCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DCircle
));
304 basegfx::B3DHomMatrix aTransform
;
306 aTransform
.rotate(F_PI2
, 0.0, 0.0);
307 aTransform
.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE
, 0.0);
308 a3DCircle
.transform(aTransform
);
310 // create object for it
311 mpLampBottomObject
= new E3dPolygonObj(
313 basegfx::B3DPolyPolygon(a3DCircle
));
314 mpScene
->InsertObject( mpLampBottomObject
);
316 // half circle with stand
317 basegfx::B2DPolygon a2DHalfCircle
;
318 a2DHalfCircle
.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE
, 0.0));
319 a2DHalfCircle
.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE
, -RADIUS_LAMP_PREVIEW_SIZE
));
320 a2DHalfCircle
.append(basegfx::utils::createPolygonFromEllipseSegment(
321 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE
, RADIUS_LAMP_PREVIEW_SIZE
, F_2PI
- F_PI2
, F_PI2
));
322 basegfx::B3DPolygon
a3DHalfCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DHalfCircle
));
324 // create object for it
325 mpLampShaftObject
= new E3dPolygonObj(
327 basegfx::B3DPolyPolygon(a3DHalfCircle
));
328 mpScene
->InsertObject( mpLampShaftObject
);
330 // initially invisible
331 SfxItemSet
aSet(mpModel
->GetItemPool());
332 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
333 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
335 mpLampBottomObject
->SetMergedItemSet(aSet
);
336 mpLampShaftObject
->SetMergedItemSet(aSet
);
340 // change camera settings
341 Camera3D rCamera
= mpScene
->GetCamera();
342 const basegfx::B3DRange
& rVolume
= mpScene
->GetBoundVolume();
343 double fW
= rVolume
.getWidth();
344 double fH
= rVolume
.getHeight();
345 double fCamZ
= rVolume
.getMaxZ() + ((fW
+ fH
) / 2.0);
347 rCamera
.SetAutoAdjustProjection(false);
348 rCamera
.SetViewWindow(- fW
/ 2, - fH
/ 2, fW
, fH
);
349 basegfx::B3DPoint aLookAt
;
350 double fDefaultCamPosZ
= mp3DView
->GetDefaultCamPosZ();
351 basegfx::B3DPoint
aCamPos(0.0, 0.0, fCamZ
< fDefaultCamPosZ
? fDefaultCamPosZ
: fCamZ
);
352 rCamera
.SetPosAndLookAt(aCamPos
, aLookAt
);
353 double fDefaultCamFocal
= mp3DView
->GetDefaultCamFocal();
354 rCamera
.SetFocalLength(fDefaultCamFocal
);
356 mpScene
->SetCamera( rCamera
);
358 basegfx::B3DHomMatrix aNeutral
;
359 mpScene
->SetTransform(aNeutral
);
362 // invalidate SnapRects of objects
363 mpScene
->SetRectsDirty();
366 void Svx3DLightControl::ConstructLightObjects()
368 for(sal_uInt32
a(0); a
< MAX_NUMBER_LIGHTS
; a
++)
370 // get rid of possible existing light object
371 if(maLightObjects
[a
])
373 mpScene
->RemoveObject(maLightObjects
[a
]->GetOrdNum());
374 // always use SdrObject::Free(...) for SdrObjects (!)
375 SdrObject
* pTemp(maLightObjects
[a
]);
376 SdrObject::Free(pTemp
);
377 maLightObjects
[a
] = nullptr;
382 const bool bIsSelectedLight(a
== maSelectedLight
);
383 basegfx::B3DVector
aDirection(GetLightDirection(a
));
384 aDirection
.normalize();
385 aDirection
*= RADIUS_LAMP_PREVIEW_SIZE
;
387 const double fLampSize(bIsSelectedLight
? RADIUS_LAMP_BIG
: RADIUS_LAMP_SMALL
);
388 E3dObject
* pNewLight
= new E3dSphereObj(
390 mp3DView
->Get3DDefaultAttributes(),
391 basegfx::B3DPoint( 0, 0, 0 ),
392 basegfx::B3DVector( fLampSize
, fLampSize
, fLampSize
));
393 mpScene
->InsertObject(pNewLight
);
395 basegfx::B3DHomMatrix aTransform
;
396 aTransform
.translate(aDirection
.getX(), aDirection
.getY(), aDirection
.getZ());
397 pNewLight
->SetTransform(aTransform
);
399 SfxItemSet
aSet(mpModel
->GetItemPool());
400 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
401 aSet
.Put( XFillStyleItem( drawing::FillStyle_SOLID
) );
402 aSet
.Put( XFillColorItem(OUString(), GetLightColor(a
)));
403 pNewLight
->SetMergedItemSet(aSet
);
405 maLightObjects
[a
] = pNewLight
;
410 void Svx3DLightControl::AdaptToSelectedLight()
412 if(NO_LIGHT_SELECTED
== maSelectedLight
)
414 // make mpLampBottomObject/mpLampShaftObject invisible
415 SfxItemSet
aSet(mpModel
->GetItemPool());
416 aSet
.Put( XLineStyleItem( drawing::LineStyle_NONE
) );
417 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
418 mpLampBottomObject
->SetMergedItemSet(aSet
);
419 mpLampShaftObject
->SetMergedItemSet(aSet
);
423 basegfx::B3DVector
aDirection(GetLightDirection(maSelectedLight
));
424 aDirection
.normalize();
426 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
427 SfxItemSet
aSet(mpModel
->GetItemPool());
428 aSet
.Put( XLineStyleItem( drawing::LineStyle_SOLID
) );
429 aSet
.Put( XLineColorItem(OUString(), COL_YELLOW
));
430 aSet
.Put( XLineWidthItem(0));
431 aSet
.Put( XFillStyleItem( drawing::FillStyle_NONE
) );
432 mpLampBottomObject
->SetMergedItemSet(aSet
);
433 mpLampShaftObject
->SetMergedItemSet(aSet
);
435 // adapt transformation of mpLampShaftObject
436 basegfx::B3DHomMatrix aTransform
;
437 double fRotateY(0.0);
439 if(!basegfx::fTools::equalZero(aDirection
.getZ()) || !basegfx::fTools::equalZero(aDirection
.getX()))
441 fRotateY
= atan2(-aDirection
.getZ(), aDirection
.getX());
444 aTransform
.rotate(0.0, fRotateY
, 0.0);
445 mpLampShaftObject
->SetTransform(aTransform
);
447 // adapt transformation of selected light
448 E3dObject
* pSelectedLight
= maLightObjects
[sal_Int32(maSelectedLight
)];
452 aTransform
.identity();
453 aTransform
.translate(
454 aDirection
.getX() * RADIUS_LAMP_PREVIEW_SIZE
,
455 aDirection
.getY() * RADIUS_LAMP_PREVIEW_SIZE
,
456 aDirection
.getZ() * RADIUS_LAMP_PREVIEW_SIZE
);
457 pSelectedLight
->SetTransform(aTransform
);
462 void Svx3DLightControl::TrySelection(Point aPosPixel
)
467 const Point
aPosLogic(GetDrawingArea()->get_ref_device().PixelToLogic(aPosPixel
));
468 const basegfx::B2DPoint
aPoint(aPosLogic
.X(), aPosLogic
.Y());
469 std::vector
< const E3dCompoundObject
* > aResult
;
470 getAllHit3DObjectsSortedFrontToBack(aPoint
, *mpScene
, aResult
);
475 // exclude expansion object which will be part of
476 // the hits. It's invisible, but for HitTest, it's included
477 const E3dCompoundObject
* pResult
= nullptr;
479 for(auto const & b
: aResult
)
481 if(b
&& b
!= mpExpansionObject
)
488 if(pResult
== mp3DObj
)
490 if(!mbGeometrySelected
)
492 mbGeometrySelected
= true;
493 maSelectedLight
= NO_LIGHT_SELECTED
;
494 ConstructLightObjects();
495 AdaptToSelectedLight();
498 if(maSelectionChangeCallback
.IsSet())
500 maSelectionChangeCallback
.Call(this);
506 sal_uInt32
aNewSelectedLight(NO_LIGHT_SELECTED
);
508 for(sal_uInt32
a(0); a
< MAX_NUMBER_LIGHTS
; a
++)
510 if(maLightObjects
[a
] && maLightObjects
[a
] == pResult
)
512 aNewSelectedLight
= a
;
516 if(aNewSelectedLight
!= maSelectedLight
)
518 SelectLight(aNewSelectedLight
);
520 if(maSelectionChangeCallback
.IsSet())
522 maSelectionChangeCallback
.Call(this);
528 void Svx3DLightControl::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
530 Svx3DPreviewControl::Paint(rRenderContext
, rRect
);
533 tools::Rectangle
Svx3DLightControl::GetFocusRect()
536 return tools::Rectangle();
537 Size aFocusSize
= GetOutputSizePixel();
538 aFocusSize
.AdjustWidth( -4 );
539 aFocusSize
.AdjustHeight( -4 );
540 return tools::Rectangle(Point(2, 2), aFocusSize
);
543 bool Svx3DLightControl::MouseButtonDown( const MouseEvent
& rMEvt
)
545 bool bCallParent(true);
550 if(IsSelectionValid() || mbGeometrySelected
)
552 mbMouseMoved
= false;
554 maActionStartPoint
= rMEvt
.GetPosPixel();
556 mbMouseCaptured
= true;
560 // Single click without moving much trying to do a selection
561 TrySelection(rMEvt
.GetPosPixel());
568 return Svx3DPreviewControl::MouseButtonDown(rMEvt
);
572 bool Svx3DLightControl::MouseMove(const MouseEvent
& rMEvt
)
574 if (!mbMouseCaptured
)
577 Point aDeltaPos
= rMEvt
.GetPosPixel() - maActionStartPoint
;
581 if(sal_Int32(aDeltaPos
.X() * aDeltaPos
.X() + aDeltaPos
.Y() * aDeltaPos
.Y()) > g_nInteractionStartDistance
)
583 if(mbGeometrySelected
)
585 GetRotation(mfSaveActionStartVer
, mfSaveActionStartHor
, mfSaveActionStartRotZ
);
589 // interaction start, save values
590 GetPosition(mfSaveActionStartHor
, mfSaveActionStartVer
);
599 if(mbGeometrySelected
)
601 double fNewRotX
= mfSaveActionStartVer
- basegfx::deg2rad(aDeltaPos
.Y());
602 double fNewRotY
= mfSaveActionStartHor
+ basegfx::deg2rad(aDeltaPos
.X());
605 while(fNewRotY
< 0.0)
610 while(fNewRotY
>= F_2PI
)
616 if(fNewRotX
< -F_PI2
)
626 SetRotation(fNewRotX
, fNewRotY
, mfSaveActionStartRotZ
);
628 if(maChangeCallback
.IsSet())
630 maChangeCallback
.Call(this);
635 // interaction in progress
636 double fNewPosHor
= mfSaveActionStartHor
+ static_cast<double>(aDeltaPos
.X());
637 double fNewPosVer
= mfSaveActionStartVer
- static_cast<double>(aDeltaPos
.Y());
640 fNewPosHor
= NormAngle360(fNewPosHor
);
643 if(fNewPosVer
< -90.0)
648 if(fNewPosVer
> 90.0)
653 SetPosition(fNewPosHor
, fNewPosVer
);
655 if(maChangeCallback
.IsSet())
657 maChangeCallback
.Call(this);
664 bool Svx3DLightControl::MouseButtonUp(const MouseEvent
& rMEvt
)
666 if (!mbMouseCaptured
)
669 mbMouseCaptured
= false;
673 // was change interactively
677 // simple click without much movement, try selection
678 TrySelection(rMEvt
.GetPosPixel());
684 void Svx3DLightControl::Resize()
687 const Size
aSize(GetDrawingArea()->get_ref_device().PixelToLogic(GetOutputSizePixel()));
688 mpFmPage
->SetSize(aSize
);
690 // set position and size of scene
691 mpScene
->SetSnapRect(tools::Rectangle(Point(0, 0), aSize
));
694 void Svx3DLightControl::SetObjectType(SvxPreviewObjectType nType
)
697 Svx3DPreviewControl::SetObjectType(nType
);
699 // apply object rotation
702 basegfx::B3DHomMatrix aObjectRotation
;
703 aObjectRotation
.rotate(mfRotateX
, mfRotateY
, mfRotateZ
);
704 mp3DObj
->SetTransform(aObjectRotation
);
708 bool Svx3DLightControl::IsSelectionValid()
710 return (NO_LIGHT_SELECTED
!= maSelectedLight
) && GetLightOnOff(maSelectedLight
);
713 void Svx3DLightControl::GetPosition(double& rHor
, double& rVer
)
715 if(IsSelectionValid())
717 basegfx::B3DVector
aDirection(GetLightDirection(maSelectedLight
));
718 aDirection
.normalize();
719 rHor
= basegfx::rad2deg(atan2(-aDirection
.getX(), -aDirection
.getZ()) + F_PI
); // 0..360.0
720 rVer
= basegfx::rad2deg(atan2(aDirection
.getY(), aDirection
.getXZLength())); // -90.0..90.0
722 if(IsGeometrySelected())
724 rHor
= basegfx::rad2deg(mfRotateY
); // 0..360.0
725 rVer
= basegfx::rad2deg(mfRotateX
); // -90.0..90.0
729 void Svx3DLightControl::SetPosition(double fHor
, double fVer
)
731 if(IsSelectionValid())
733 // set selected light's direction
734 fHor
= basegfx::deg2rad(fHor
) - F_PI
; // -PI..PI
735 fVer
= basegfx::deg2rad(fVer
); // -PI2..PI2
736 basegfx::B3DVector
aDirection(cos(fVer
) * -sin(fHor
), sin(fVer
), cos(fVer
) * -cos(fHor
));
737 aDirection
.normalize();
739 if(!aDirection
.equal(GetLightDirection(maSelectedLight
)))
741 // set changed light direction at SdrScene
742 SfxItemSet
aSet(mpModel
->GetItemPool());
744 switch(maSelectedLight
)
746 case 0: aSet
.Put(makeSvx3DLightDirection1Item(aDirection
)); break;
747 case 1: aSet
.Put(makeSvx3DLightDirection2Item(aDirection
)); break;
748 case 2: aSet
.Put(makeSvx3DLightDirection3Item(aDirection
)); break;
749 case 3: aSet
.Put(makeSvx3DLightDirection4Item(aDirection
)); break;
750 case 4: aSet
.Put(makeSvx3DLightDirection5Item(aDirection
)); break;
751 case 5: aSet
.Put(makeSvx3DLightDirection6Item(aDirection
)); break;
752 case 6: aSet
.Put(makeSvx3DLightDirection7Item(aDirection
)); break;
754 case 7: aSet
.Put(makeSvx3DLightDirection8Item(aDirection
)); break;
757 mpScene
->SetMergedItemSet(aSet
);
759 // correct 3D light's and LampFrame's geometries
760 AdaptToSelectedLight();
764 if(!IsGeometrySelected())
767 if(mfRotateX
== fVer
&& mfRotateY
== fHor
)
770 mfRotateX
= basegfx::deg2rad(fVer
);
771 mfRotateY
= basegfx::deg2rad(fHor
);
775 basegfx::B3DHomMatrix aObjectRotation
;
776 aObjectRotation
.rotate(mfRotateX
, mfRotateY
, mfRotateZ
);
777 mp3DObj
->SetTransform(aObjectRotation
);
783 void Svx3DLightControl::SetRotation(double fRotX
, double fRotY
, double fRotZ
)
785 if(!IsGeometrySelected())
788 if(fRotX
== mfRotateX
&& fRotY
== mfRotateY
&& fRotZ
== mfRotateZ
)
797 basegfx::B3DHomMatrix aObjectRotation
;
798 aObjectRotation
.rotate(mfRotateX
, mfRotateY
, mfRotateZ
);
799 mp3DObj
->SetTransform(aObjectRotation
);
805 void Svx3DLightControl::GetRotation(double& rRotX
, double& rRotY
, double& rRotZ
)
812 void Svx3DLightControl::Set3DAttributes( const SfxItemSet
& rAttr
)
815 Svx3DPreviewControl::Set3DAttributes(rAttr
);
817 if(maSelectedLight
!= NO_LIGHT_SELECTED
&& !GetLightOnOff(maSelectedLight
))
819 // selected light is no more active, select new one
820 maSelectedLight
= NO_LIGHT_SELECTED
;
824 ConstructLightObjects();
825 AdaptToSelectedLight();
829 void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber
)
833 nLightNumber
= NO_LIGHT_SELECTED
;
836 if(NO_LIGHT_SELECTED
!= nLightNumber
)
838 if(!GetLightOnOff(nLightNumber
))
840 nLightNumber
= NO_LIGHT_SELECTED
;
844 if(nLightNumber
!= maSelectedLight
)
846 maSelectedLight
= nLightNumber
;
847 mbGeometrySelected
= false;
848 ConstructLightObjects();
849 AdaptToSelectedLight();
854 bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum
) const
858 const SfxItemSet
aLightItemSet(Get3DAttributes());
862 case 0 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_1
).GetValue();
863 case 1 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_2
).GetValue();
864 case 2 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_3
).GetValue();
865 case 3 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_4
).GetValue();
866 case 4 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_5
).GetValue();
867 case 5 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_6
).GetValue();
868 case 6 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_7
).GetValue();
869 case 7 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTON_8
).GetValue();
876 Color
Svx3DLightControl::GetLightColor(sal_uInt32 nNum
) const
880 const SfxItemSet
aLightItemSet(Get3DAttributes());
884 case 0 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1
).GetValue();
885 case 1 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2
).GetValue();
886 case 2 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3
).GetValue();
887 case 3 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4
).GetValue();
888 case 4 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5
).GetValue();
889 case 5 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6
).GetValue();
890 case 6 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7
).GetValue();
891 case 7 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8
).GetValue();
898 basegfx::B3DVector
Svx3DLightControl::GetLightDirection(sal_uInt32 nNum
) const
902 const SfxItemSet
aLightItemSet(Get3DAttributes());
906 case 0 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1
).GetValue();
907 case 1 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2
).GetValue();
908 case 2 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3
).GetValue();
909 case 3 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4
).GetValue();
910 case 4 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5
).GetValue();
911 case 5 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6
).GetValue();
912 case 6 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7
).GetValue();
913 case 7 : return aLightItemSet
.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8
).GetValue();
917 return basegfx::B3DVector();
920 SvxLightCtl3D::SvxLightCtl3D(Svx3DLightControl
& rLightControl
, weld::Scale
& rHori
,
921 weld::Scale
& rVert
, weld::Button
& rSwitcher
)
922 : mrLightControl(rLightControl
)
923 , mrHorScroller(rHori
)
924 , mrVerScroller(rVert
)
925 , mrSwitcher(rSwitcher
)
931 void SvxLightCtl3D::Init()
933 Size
aSize(mrLightControl
.GetDrawingArea()->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont
)));
934 mrLightControl
.set_size_request(aSize
.Width(), aSize
.Height());
936 // #i58240# set HelpIDs for scrollbars and switcher
937 mrHorScroller
.set_help_id(HID_CTRL3D_HSCROLL
);
938 mrVerScroller
.set_help_id(HID_CTRL3D_VSCROLL
);
939 mrSwitcher
.set_help_id(HID_CTRL3D_SWITCHER
);
940 mrSwitcher
.set_accessible_name(SvxResId(STR_SWITCH
));
943 mrLightControl
.Show();
944 mrLightControl
.SetChangeCallback( LINK(this, SvxLightCtl3D
, InternalInteractiveChange
) );
945 mrLightControl
.SetSelectionChangeCallback( LINK(this, SvxLightCtl3D
, InternalSelectionChange
) );
948 mrHorScroller
.show();
949 mrHorScroller
.set_range(0, 36000);
950 mrHorScroller
.connect_value_changed( LINK(this, SvxLightCtl3D
, ScrollBarMove
) );
953 mrVerScroller
.show();
954 mrVerScroller
.set_range(0, 18000);
955 mrVerScroller
.connect_value_changed( LINK(this, SvxLightCtl3D
, ScrollBarMove
) );
959 mrSwitcher
.connect_clicked( LINK(this, SvxLightCtl3D
, ButtonPress
) );
961 weld::DrawingArea
* pArea
= mrLightControl
.GetDrawingArea();
962 pArea
->connect_key_press(Link
<const KeyEvent
&, bool>()); //acknowledge we first remove the old one
963 pArea
->connect_key_press(LINK(this, SvxLightCtl3D
, KeyInput
));
965 pArea
->connect_focus_in(Link
<weld::Widget
&, void>()); //acknowledge we first remove the old one
966 pArea
->connect_focus_in(LINK(this, SvxLightCtl3D
, FocusIn
));
972 SvxLightCtl3D::~SvxLightCtl3D()
976 void SvxLightCtl3D::CheckSelection()
978 const bool bSelectionValid(mrLightControl
.IsSelectionValid() || mrLightControl
.IsGeometrySelected());
979 mrHorScroller
.set_sensitive(bSelectionValid
);
980 mrVerScroller
.set_sensitive(bSelectionValid
);
984 double fHor(0.0), fVer(0.0);
985 mrLightControl
.GetPosition(fHor
, fVer
);
986 mrHorScroller
.set_value( sal_Int32(fHor
* 100.0) );
987 mrVerScroller
.set_value( 18000 - sal_Int32((fVer
+ 90.0) * 100.0) );
991 void SvxLightCtl3D::move( double fDeltaHor
, double fDeltaVer
)
993 double fHor(0.0), fVer(0.0);
995 mrLightControl
.GetPosition(fHor
, fVer
);
1005 mrLightControl
.SetPosition(fHor
, fVer
);
1006 mrHorScroller
.set_value( sal_Int32(fHor
* 100.0) );
1007 mrVerScroller
.set_value( 18000 - sal_Int32((fVer
+ 90.0) * 100.0) );
1009 if(maUserInteractiveChangeCallback
.IsSet())
1011 maUserInteractiveChangeCallback
.Call(this);
1015 IMPL_LINK(SvxLightCtl3D
, KeyInput
, const KeyEvent
&, rKEvt
, bool)
1017 const vcl::KeyCode
aCode(rKEvt
.GetKeyCode());
1019 if (aCode
.GetModifier())
1022 bool bHandled
= true;
1024 switch ( aCode
.GetCode() )
1032 move( -4.0, 0.0 ); // #i58242# changed move direction in X
1037 move( 4.0, 0.0 ); // #i58242# changed move direction in X
1052 sal_Int32
nLight(mrLightControl
.GetSelectedLight() - 1);
1054 while((nLight
>= 0) && !mrLightControl
.GetLightOnOff(nLight
))
1063 while((nLight
>= 0) && !mrLightControl
.GetLightOnOff(nLight
))
1071 mrLightControl
.SelectLight(nLight
);
1074 if(maUserSelectionChangeCallback
.IsSet())
1076 maUserSelectionChangeCallback
.Call(this);
1084 sal_Int32
nLight(mrLightControl
.GetSelectedLight() - 1);
1086 while(nLight
<= 7 && !mrLightControl
.GetLightOnOff(nLight
))
1095 while(nLight
<= 7 && !mrLightControl
.GetLightOnOff(nLight
))
1103 mrLightControl
.SelectLight(nLight
);
1106 if(maUserSelectionChangeCallback
.IsSet())
1108 maUserSelectionChangeCallback
.Call(this);
1123 IMPL_LINK_NOARG(SvxLightCtl3D
, FocusIn
, weld::Widget
&, void)
1125 if (mrLightControl
.IsEnabled())
1131 IMPL_LINK_NOARG(SvxLightCtl3D
, ScrollBarMove
, weld::Scale
&, void)
1133 const sal_Int32
nHor(mrHorScroller
.get_value());
1134 const sal_Int32
nVer(mrVerScroller
.get_value());
1136 mrLightControl
.SetPosition(
1137 static_cast<double>(nHor
) / 100.0,
1138 static_cast<double>((18000 - nVer
) - 9000) / 100.0);
1140 if (maUserInteractiveChangeCallback
.IsSet())
1142 maUserInteractiveChangeCallback
.Call(this);
1146 IMPL_LINK_NOARG(SvxLightCtl3D
, ButtonPress
, weld::Button
&, void)
1148 if(SvxPreviewObjectType::SPHERE
== GetSvx3DLightControl().GetObjectType())
1150 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::CUBE
);
1154 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::SPHERE
);
1158 IMPL_LINK_NOARG(SvxLightCtl3D
, InternalInteractiveChange
, Svx3DLightControl
*, void)
1160 double fHor(0.0), fVer(0.0);
1162 mrLightControl
.GetPosition(fHor
, fVer
);
1163 mrHorScroller
.set_value( sal_Int32(fHor
* 100.0) );
1164 mrVerScroller
.set_value( 18000 - sal_Int32((fVer
+ 90.0) * 100.0) );
1166 if(maUserInteractiveChangeCallback
.IsSet())
1168 maUserInteractiveChangeCallback
.Call(this);
1172 IMPL_LINK_NOARG(SvxLightCtl3D
, InternalSelectionChange
, Svx3DLightControl
*, void)
1176 if(maUserSelectionChangeCallback
.IsSet())
1178 maUserSelectionChangeCallback
.Call(this);
1182 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */