1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
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 <vcl/builderfactory.hxx>
33 #include <svx/helperhittest3d.hxx>
34 #include <basegfx/polygon/b2dpolygontools.hxx>
35 #include <svx/polygn3d.hxx>
36 #include <svx/xfillit0.hxx>
37 #include <svx/xflclit.hxx>
38 #include <svx/xlineit0.hxx>
39 #include <svx/xlnclit.hxx>
40 #include <svx/xlnwtit.hxx>
41 #include <helpids.h>
42 #include <algorithm>
43 #include <svx/dialmgr.hxx>
44 #include <tools/helpers.hxx>
45 #include <vcl/settings.hxx>
46
47 using namespace com::sun::star;
48
Svx3DPreviewControl(vcl::Window * pParent,WinBits nStyle)49 Svx3DPreviewControl::Svx3DPreviewControl(vcl::Window* pParent, WinBits nStyle)
50 : Control(pParent, nStyle),
51 mpFmPage(nullptr),
52 mpScene(nullptr),
53 mp3DObj(nullptr),
54 mnObjectType(SvxPreviewObjectType::SPHERE)
55 {
56 Construct();
57
58 // do not paint background self, DrawingLayer paints this buffered and as page
59 SetControlBackground();
60 SetBackground();
61 }
62
GetOptimalSize() const63 Size Svx3DPreviewControl::GetOptimalSize() const
64 {
65 return LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont));
66 }
67
VCL_BUILDER_FACTORY(Svx3DPreviewControl)68 VCL_BUILDER_FACTORY(Svx3DPreviewControl)
69
70 Svx3DPreviewControl::~Svx3DPreviewControl()
71 {
72 disposeOnce();
73 }
74
dispose()75 void Svx3DPreviewControl::dispose()
76 {
77 mp3DView.reset();
78 mpModel.reset();
79 Control::dispose();
80 }
81
Construct()82 void Svx3DPreviewControl::Construct()
83 {
84 // Do never mirror the preview window. This explicitly includes right
85 // to left writing environments.
86 EnableRTL (false);
87 SetMapMode(MapMode(MapUnit::Map100thMM));
88
89 // Model
90 mpModel.reset(new FmFormModel());
91 mpModel->GetItemPool().FreezeIdRanges();
92
93 // Page
94 mpFmPage = new FmFormPage( *mpModel );
95 mpModel->InsertPage( mpFmPage, 0 );
96
97 // 3D View
98 mp3DView.reset(new E3dView(*mpModel, this ));
99 mp3DView->SetBufferedOutputAllowed(true);
100 mp3DView->SetBufferedOverlayAllowed(true);
101
102 // 3D Scene
103 mpScene = new E3dScene(*mpModel);
104
105 // initially create object
106 SetObjectType(SvxPreviewObjectType::SPHERE);
107
108 // camera and perspective
109 Camera3D rCamera = mpScene->GetCamera();
110 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
111 double fW = rVolume.getWidth();
112 double fH = rVolume.getHeight();
113 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
114
115 rCamera.SetAutoAdjustProjection(false);
116 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
117 basegfx::B3DPoint aLookAt;
118 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
119 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
120 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
121 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
122 rCamera.SetFocalLength(fDefaultCamFocal);
123
124 mpScene->SetCamera( rCamera );
125 mpFmPage->InsertObject( mpScene );
126
127 basegfx::B3DHomMatrix aRotation;
128 aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
129 aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
130 mpScene->SetTransform(aRotation * mpScene->GetTransform());
131
132 // invalidate SnapRects of objects
133 mpScene->SetRectsDirty();
134
135 SfxItemSet aSet( mpModel->GetItemPool(),
136 svl::Items<XATTR_LINESTYLE, XATTR_LINESTYLE,
137 XATTR_FILL_FIRST, XATTR_FILLBITMAP>{} );
138 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
139 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
140 aSet.Put( XFillColorItem( "", COL_WHITE ) );
141
142 mpScene->SetMergedItemSet(aSet);
143
144 // PageView
145 SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
146 mp3DView->hideMarkHandles();
147
148 // mark scene
149 mp3DView->MarkObj( mpScene, pPageView );
150 }
151
Resize()152 void Svx3DPreviewControl::Resize()
153 {
154 // size of page
155 Size aSize( GetSizePixel() );
156 aSize = PixelToLogic( aSize );
157 mpFmPage->SetSize( aSize );
158
159 // set size
160 Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
161 Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
162 (aSize.Height() - aObjSize.Height()) / 2);
163 tools::Rectangle aRect( aObjPoint, aObjSize);
164 mpScene->SetSnapRect( aRect );
165 }
166
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect)167 void Svx3DPreviewControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
168 {
169 mp3DView->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
170 }
171
MouseButtonDown(const MouseEvent & rMEvt)172 void Svx3DPreviewControl::MouseButtonDown(const MouseEvent& rMEvt)
173 {
174 Control::MouseButtonDown(rMEvt);
175
176 if( rMEvt.IsShift() && rMEvt.IsMod1() )
177 {
178 if(SvxPreviewObjectType::SPHERE == GetObjectType())
179 {
180 SetObjectType(SvxPreviewObjectType::CUBE);
181 }
182 else
183 {
184 SetObjectType(SvxPreviewObjectType::SPHERE);
185 }
186 }
187 }
188
SetObjectType(SvxPreviewObjectType nType)189 void Svx3DPreviewControl::SetObjectType(SvxPreviewObjectType nType)
190 {
191 if( mnObjectType != nType || !mp3DObj)
192 {
193 SfxItemSet aSet(mpModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{});
194 mnObjectType = nType;
195
196 if( mp3DObj )
197 {
198 aSet.Put(mp3DObj->GetMergedItemSet());
199 mpScene->RemoveObject( mp3DObj->GetOrdNum() );
200 // always use SdrObject::Free(...) for SdrObjects (!)
201 SdrObject* pTemp(mp3DObj);
202 SdrObject::Free(pTemp);
203 }
204
205 switch( nType )
206 {
207 case SvxPreviewObjectType::SPHERE:
208 {
209 mp3DObj = new E3dSphereObj(
210 *mpModel,
211 mp3DView->Get3DDefaultAttributes(),
212 basegfx::B3DPoint( 0, 0, 0 ),
213 basegfx::B3DVector( 5000, 5000, 5000 ));
214 }
215 break;
216
217 case SvxPreviewObjectType::CUBE:
218 {
219 mp3DObj = new E3dCubeObj(
220 *mpModel,
221 mp3DView->Get3DDefaultAttributes(),
222 basegfx::B3DPoint( -2500, -2500, -2500 ),
223 basegfx::B3DVector( 5000, 5000, 5000 ));
224 }
225 break;
226 }
227
228 if (mp3DObj)
229 {
230 mpScene->InsertObject( mp3DObj );
231 mp3DObj->SetMergedItemSet(aSet);
232 }
233
234 Resize();
235 }
236 }
237
Get3DAttributes() const238 SfxItemSet const & Svx3DPreviewControl::Get3DAttributes() const
239 {
240 return mp3DObj->GetMergedItemSet();
241 }
242
Set3DAttributes(const SfxItemSet & rAttr)243 void Svx3DPreviewControl::Set3DAttributes( const SfxItemSet& rAttr )
244 {
245 mp3DObj->SetMergedItemSet(rAttr, true);
246 Resize();
247 }
248
PreviewControl3D()249 PreviewControl3D::PreviewControl3D()
250 : mpFmPage(nullptr)
251 , mpScene(nullptr)
252 , mp3DObj(nullptr)
253 , mnObjectType(SvxPreviewObjectType::SPHERE)
254 {
255 }
256
SetDrawingArea(weld::DrawingArea * pDrawingArea)257 void PreviewControl3D::SetDrawingArea(weld::DrawingArea* pDrawingArea)
258 {
259 Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont)));
260 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
261 CustomWidgetController::SetDrawingArea(pDrawingArea);
262 SetOutputSizePixel(aSize);
263
264 Construct();
265 }
266
~PreviewControl3D()267 PreviewControl3D::~PreviewControl3D()
268 {
269 mp3DView.reset();
270 mpModel.reset();
271 }
272
Construct()273 void PreviewControl3D::Construct()
274 {
275 // Do never mirror the preview window. This explicitly includes right
276 // to left writing environments.
277 EnableRTL (false);
278 OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
279 rDevice.SetMapMode(MapMode(MapUnit::Map100thMM));
280
281 // Model
282 mpModel.reset(new FmFormModel());
283 mpModel->GetItemPool().FreezeIdRanges();
284
285 // Page
286 mpFmPage = new FmFormPage( *mpModel );
287 mpModel->InsertPage( mpFmPage, 0 );
288
289 // 3D View
290 mp3DView.reset(new E3dView(*mpModel, &rDevice));
291 mp3DView->SetBufferedOutputAllowed(true);
292 mp3DView->SetBufferedOverlayAllowed(true);
293
294 // 3D Scene
295 mpScene = new E3dScene(*mpModel);
296
297 // initially create object
298 SetObjectType(SvxPreviewObjectType::SPHERE);
299
300 // camera and perspective
301 Camera3D rCamera = mpScene->GetCamera();
302 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
303 double fW = rVolume.getWidth();
304 double fH = rVolume.getHeight();
305 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
306
307 rCamera.SetAutoAdjustProjection(false);
308 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
309 basegfx::B3DPoint aLookAt;
310 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
311 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
312 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
313 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
314 rCamera.SetFocalLength(fDefaultCamFocal);
315
316 mpScene->SetCamera( rCamera );
317 mpFmPage->InsertObject( mpScene );
318
319 basegfx::B3DHomMatrix aRotation;
320 aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
321 aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
322 mpScene->SetTransform(aRotation * mpScene->GetTransform());
323
324 // invalidate SnapRects of objects
325 mpScene->SetRectsDirty();
326
327 SfxItemSet aSet( mpModel->GetItemPool(),
328 svl::Items<XATTR_LINESTYLE, XATTR_LINESTYLE,
329 XATTR_FILL_FIRST, XATTR_FILLBITMAP>{} );
330 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
331 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
332 aSet.Put( XFillColorItem( "", COL_WHITE ) );
333
334 mpScene->SetMergedItemSet(aSet);
335
336 // PageView
337 SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
338 mp3DView->hideMarkHandles();
339
340 // mark scene
341 mp3DView->MarkObj( mpScene, pPageView );
342 }
343
Resize()344 void PreviewControl3D::Resize()
345 {
346 // size of page
347 Size aSize(GetOutputSizePixel());
348 aSize = GetDrawingArea()->get_ref_device().PixelToLogic(aSize);
349 mpFmPage->SetSize(aSize);
350
351 // set size
352 Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
353 Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
354 (aSize.Height() - aObjSize.Height()) / 2);
355 tools::Rectangle aRect( aObjPoint, aObjSize);
356 mpScene->SetSnapRect( aRect );
357 }
358
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect)359 void PreviewControl3D::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
360 {
361 mp3DView->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
362 }
363
MouseButtonDown(const MouseEvent & rMEvt)364 bool PreviewControl3D::MouseButtonDown(const MouseEvent& rMEvt)
365 {
366 if (rMEvt.IsShift() && rMEvt.IsMod1())
367 {
368 if(SvxPreviewObjectType::SPHERE == GetObjectType())
369 {
370 SetObjectType(SvxPreviewObjectType::CUBE);
371 }
372 else
373 {
374 SetObjectType(SvxPreviewObjectType::SPHERE);
375 }
376 }
377 return false;
378 }
379
SetObjectType(SvxPreviewObjectType nType)380 void PreviewControl3D::SetObjectType(SvxPreviewObjectType nType)
381 {
382 if( mnObjectType != nType || !mp3DObj)
383 {
384 SfxItemSet aSet(mpModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{});
385 mnObjectType = nType;
386
387 if( mp3DObj )
388 {
389 aSet.Put(mp3DObj->GetMergedItemSet());
390 mpScene->RemoveObject( mp3DObj->GetOrdNum() );
391 // always use SdrObject::Free(...) for SdrObjects (!)
392 SdrObject* pTemp(mp3DObj);
393 SdrObject::Free(pTemp);
394 }
395
396 switch( nType )
397 {
398 case SvxPreviewObjectType::SPHERE:
399 {
400 mp3DObj = new E3dSphereObj(
401 *mpModel,
402 mp3DView->Get3DDefaultAttributes(),
403 basegfx::B3DPoint( 0, 0, 0 ),
404 basegfx::B3DVector( 5000, 5000, 5000 ));
405 }
406 break;
407
408 case SvxPreviewObjectType::CUBE:
409 {
410 mp3DObj = new E3dCubeObj(
411 *mpModel,
412 mp3DView->Get3DDefaultAttributes(),
413 basegfx::B3DPoint( -2500, -2500, -2500 ),
414 basegfx::B3DVector( 5000, 5000, 5000 ));
415 }
416 break;
417 }
418
419 if (mp3DObj)
420 {
421 mpScene->InsertObject( mp3DObj );
422 mp3DObj->SetMergedItemSet(aSet);
423 }
424
425 Invalidate();
426 }
427 }
428
Get3DAttributes() const429 SfxItemSet const & PreviewControl3D::Get3DAttributes() const
430 {
431 return mp3DObj->GetMergedItemSet();
432 }
433
Set3DAttributes(const SfxItemSet & rAttr)434 void PreviewControl3D::Set3DAttributes( const SfxItemSet& rAttr )
435 {
436 mp3DObj->SetMergedItemSet(rAttr, true);
437 Resize();
438 }
439
440 #define RADIUS_LAMP_PREVIEW_SIZE (4500.0)
441 #define RADIUS_LAMP_SMALL (600.0)
442 #define RADIUS_LAMP_BIG (1000.0)
443 #define NO_LIGHT_SELECTED (0xffffffff)
444 #define MAX_NUMBER_LIGHTS (8)
445
446 static const sal_Int32 g_nInteractionStartDistance = 5 * 5 * 2;
447
Svx3DLightControl(vcl::Window * pParent,WinBits nStyle)448 Svx3DLightControl::Svx3DLightControl(vcl::Window* pParent, WinBits nStyle)
449 : Svx3DPreviewControl(pParent, nStyle),
450 maChangeCallback(),
451 maSelectionChangeCallback(),
452 maSelectedLight(NO_LIGHT_SELECTED),
453 mpExpansionObject(nullptr),
454 mpLampBottomObject(nullptr),
455 mpLampShaftObject(nullptr),
456 maLightObjects(MAX_NUMBER_LIGHTS, nullptr),
457 mfRotateX(-20.0),
458 mfRotateY(45.0),
459 mfRotateZ(0.0),
460 maActionStartPoint(),
461 mfSaveActionStartHor(0.0),
462 mfSaveActionStartVer(0.0),
463 mfSaveActionStartRotZ(0.0),
464 mbMouseMoved(false),
465 mbGeometrySelected(false)
466 {
467 Construct2();
468 }
469
Construct2()470 void Svx3DLightControl::Construct2()
471 {
472 {
473 // hide all page stuff, use control background (normally gray)
474 const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
475 mp3DView->SetPageVisible(false);
476 mp3DView->SetApplicationBackgroundColor(aDialogColor);
477 mp3DView->SetApplicationDocumentColor(aDialogColor);
478 }
479
480 {
481 // create invisible expansion object
482 const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
483 mpExpansionObject = new E3dCubeObj(
484 *mpModel,
485 mp3DView->Get3DDefaultAttributes(),
486 basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
487 basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
488 mpScene->InsertObject( mpExpansionObject );
489 SfxItemSet aSet(mpModel->GetItemPool());
490 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
491 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
492 mpExpansionObject->SetMergedItemSet(aSet);
493 }
494
495 {
496 // create lamp control object (Yellow lined object)
497 // base circle
498 const basegfx::B2DPolygon a2DCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
499 basegfx::B3DPolygon a3DCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DCircle));
500 basegfx::B3DHomMatrix aTransform;
501
502 aTransform.rotate(F_PI2, 0.0, 0.0);
503 aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
504 a3DCircle.transform(aTransform);
505
506 // create object for it
507 mpLampBottomObject = new E3dPolygonObj(
508 *mpModel,
509 basegfx::B3DPolyPolygon(a3DCircle));
510 mpScene->InsertObject( mpLampBottomObject );
511
512 // half circle with stand
513 basegfx::B2DPolygon a2DHalfCircle;
514 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
515 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
516 a2DHalfCircle.append(basegfx::utils::createPolygonFromEllipseSegment(
517 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
518 basegfx::B3DPolygon a3DHalfCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
519
520 // create object for it
521 mpLampShaftObject = new E3dPolygonObj(
522 *mpModel,
523 basegfx::B3DPolyPolygon(a3DHalfCircle));
524 mpScene->InsertObject( mpLampShaftObject );
525
526 // initially invisible
527 SfxItemSet aSet(mpModel->GetItemPool());
528 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
529 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
530
531 mpLampBottomObject->SetMergedItemSet(aSet);
532 mpLampShaftObject->SetMergedItemSet(aSet);
533 }
534
535 {
536 // change camera settings
537 Camera3D rCamera = mpScene->GetCamera();
538 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
539 double fW = rVolume.getWidth();
540 double fH = rVolume.getHeight();
541 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
542
543 rCamera.SetAutoAdjustProjection(false);
544 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
545 basegfx::B3DPoint aLookAt;
546 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
547 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
548 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
549 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
550 rCamera.SetFocalLength(fDefaultCamFocal);
551
552 mpScene->SetCamera( rCamera );
553
554 basegfx::B3DHomMatrix aNeutral;
555 mpScene->SetTransform(aNeutral);
556 }
557
558 // invalidate SnapRects of objects
559 mpScene->SetRectsDirty();
560 }
561
ConstructLightObjects()562 void Svx3DLightControl::ConstructLightObjects()
563 {
564 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
565 {
566 // get rid of possible existing light object
567 if(maLightObjects[a])
568 {
569 mpScene->RemoveObject(maLightObjects[a]->GetOrdNum());
570 // always use SdrObject::Free(...) for SdrObjects (!)
571 SdrObject* pTemp(maLightObjects[a]);
572 SdrObject::Free(pTemp);
573 maLightObjects[a] = nullptr;
574 }
575
576 if(GetLightOnOff(a))
577 {
578 const bool bIsSelectedLight(a == maSelectedLight);
579 basegfx::B3DVector aDirection(GetLightDirection(a));
580 aDirection.normalize();
581 aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
582
583 const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
584 E3dObject* pNewLight = new E3dSphereObj(
585 *mpModel,
586 mp3DView->Get3DDefaultAttributes(),
587 basegfx::B3DPoint( 0, 0, 0 ),
588 basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
589 mpScene->InsertObject(pNewLight);
590
591 basegfx::B3DHomMatrix aTransform;
592 aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
593 pNewLight->SetTransform(aTransform);
594
595 SfxItemSet aSet(mpModel->GetItemPool());
596 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
597 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
598 aSet.Put( XFillColorItem(OUString(), GetLightColor(a)));
599 pNewLight->SetMergedItemSet(aSet);
600
601 maLightObjects[a] = pNewLight;
602 }
603 }
604 }
605
AdaptToSelectedLight()606 void Svx3DLightControl::AdaptToSelectedLight()
607 {
608 if(NO_LIGHT_SELECTED == maSelectedLight)
609 {
610 // make mpLampBottomObject/mpLampShaftObject invisible
611 SfxItemSet aSet(mpModel->GetItemPool());
612 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
613 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
614 mpLampBottomObject->SetMergedItemSet(aSet);
615 mpLampShaftObject->SetMergedItemSet(aSet);
616 }
617 else
618 {
619 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
620 aDirection.normalize();
621
622 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
623 SfxItemSet aSet(mpModel->GetItemPool());
624 aSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) );
625 aSet.Put( XLineColorItem(OUString(), COL_YELLOW));
626 aSet.Put( XLineWidthItem(0));
627 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
628 mpLampBottomObject->SetMergedItemSet(aSet);
629 mpLampShaftObject->SetMergedItemSet(aSet);
630
631 // adapt transformation of mpLampShaftObject
632 basegfx::B3DHomMatrix aTransform;
633 double fRotateY(0.0);
634
635 if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
636 {
637 fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
638 }
639
640 aTransform.rotate(0.0, fRotateY, 0.0);
641 mpLampShaftObject->SetTransform(aTransform);
642
643 // adapt transformation of selected light
644 E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
645
646 if(pSelectedLight)
647 {
648 aTransform.identity();
649 aTransform.translate(
650 aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
651 aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
652 aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
653 pSelectedLight->SetTransform(aTransform);
654 }
655 }
656 }
657
TrySelection(Point aPosPixel)658 void Svx3DLightControl::TrySelection(Point aPosPixel)
659 {
660 if(mpScene)
661 {
662 const Point aPosLogic(PixelToLogic(aPosPixel));
663 const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
664 std::vector< const E3dCompoundObject* > aResult;
665 getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
666
667 if(!aResult.empty())
668 {
669 // exclude expansion object which will be part of
670 // the hits. It's invisible, but for HitTest, it's included
671 const E3dCompoundObject* pResult = nullptr;
672
673 for(auto const & b: aResult)
674 {
675 if(b && b != mpExpansionObject)
676 {
677 pResult = b;
678 break;
679 }
680 }
681
682 if(pResult == mp3DObj)
683 {
684 if(!mbGeometrySelected)
685 {
686 mbGeometrySelected = true;
687 maSelectedLight = NO_LIGHT_SELECTED;
688 ConstructLightObjects();
689 AdaptToSelectedLight();
690 Invalidate();
691
692 if(maSelectionChangeCallback.IsSet())
693 {
694 maSelectionChangeCallback.Call(this);
695 }
696 }
697 }
698 else
699 {
700 sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
701
702 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
703 {
704 if(maLightObjects[a] && maLightObjects[a] == pResult)
705 {
706 aNewSelectedLight = a;
707 }
708 }
709
710 if(aNewSelectedLight != maSelectedLight)
711 {
712 SelectLight(aNewSelectedLight);
713
714 if(maSelectionChangeCallback.IsSet())
715 {
716 maSelectionChangeCallback.Call(this);
717 }
718 }
719 }
720 }
721 }
722 }
723
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect)724 void Svx3DLightControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
725 {
726 Svx3DPreviewControl::Paint(rRenderContext, rRect);
727 }
728
MouseButtonDown(const MouseEvent & rMEvt)729 void Svx3DLightControl::MouseButtonDown( const MouseEvent& rMEvt )
730 {
731 bool bCallParent(true);
732
733 // switch state
734 if(rMEvt.IsLeft())
735 {
736 if(IsSelectionValid() || mbGeometrySelected)
737 {
738 mbMouseMoved = false;
739 bCallParent = false;
740 maActionStartPoint = rMEvt.GetPosPixel();
741 StartTracking();
742 }
743 else
744 {
745 // Single click without moving much trying to do a selection
746 TrySelection(rMEvt.GetPosPixel());
747 bCallParent = false;
748 }
749 }
750
751 // call parent
752 if(bCallParent)
753 {
754 Svx3DPreviewControl::MouseButtonDown(rMEvt);
755 }
756 }
757
Tracking(const TrackingEvent & rTEvt)758 void Svx3DLightControl::Tracking( const TrackingEvent& rTEvt )
759 {
760 if(rTEvt.IsTrackingEnded())
761 {
762 if(rTEvt.IsTrackingCanceled())
763 {
764 if(mbMouseMoved)
765 {
766 // interrupt tracking
767 mbMouseMoved = false;
768
769 if(mbGeometrySelected)
770 {
771 SetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
772 }
773 else
774 {
775 SetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
776 }
777
778 if(maChangeCallback.IsSet())
779 {
780 maChangeCallback.Call(this);
781 }
782 }
783 }
784 else
785 {
786 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
787
788 if(mbMouseMoved)
789 {
790 // was change interactively
791 }
792 else
793 {
794 // simple click without much movement, try selection
795 TrySelection(rMEvt.GetPosPixel());
796 }
797 }
798 }
799 else
800 {
801 const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
802 Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
803
804 if(!mbMouseMoved)
805 {
806 if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > g_nInteractionStartDistance)
807 {
808 if(mbGeometrySelected)
809 {
810 GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
811 }
812 else
813 {
814 // interaction start, save values
815 GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
816 }
817
818 mbMouseMoved = true;
819 }
820 }
821
822 if(mbMouseMoved)
823 {
824 if(mbGeometrySelected)
825 {
826 double fNewRotX = mfSaveActionStartVer - basegfx::deg2rad(aDeltaPos.Y());
827 double fNewRotY = mfSaveActionStartHor + basegfx::deg2rad(aDeltaPos.X());
828
829 // cut horizontal
830 while(fNewRotY < 0.0)
831 {
832 fNewRotY += F_2PI;
833 }
834
835 while(fNewRotY >= F_2PI)
836 {
837 fNewRotY -= F_2PI;
838 }
839
840 // cut vertical
841 if(fNewRotX < -F_PI2)
842 {
843 fNewRotX = -F_PI2;
844 }
845
846 if(fNewRotX > F_PI2)
847 {
848 fNewRotX = F_PI2;
849 }
850
851 SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
852
853 if(maChangeCallback.IsSet())
854 {
855 maChangeCallback.Call(this);
856 }
857 }
858 else
859 {
860 // interaction in progress
861 double fNewPosHor = mfSaveActionStartHor + static_cast<double>(aDeltaPos.X());
862 double fNewPosVer = mfSaveActionStartVer - static_cast<double>(aDeltaPos.Y());
863
864 // cut horizontal
865 fNewPosHor = NormAngle360(fNewPosHor);
866
867 // cut vertical
868 if(fNewPosVer < -90.0)
869 {
870 fNewPosVer = -90.0;
871 }
872
873 if(fNewPosVer > 90.0)
874 {
875 fNewPosVer = 90.0;
876 }
877
878 SetPosition(fNewPosHor, fNewPosVer);
879
880 if(maChangeCallback.IsSet())
881 {
882 maChangeCallback.Call(this);
883 }
884 }
885 }
886 }
887 }
888
Resize()889 void Svx3DLightControl::Resize()
890 {
891 // set size of page
892 const Size aSize(PixelToLogic(GetSizePixel()));
893 mpFmPage->SetSize(aSize);
894
895 // set position and size of scene
896 mpScene->SetSnapRect(tools::Rectangle(Point(0, 0), aSize));
897 }
898
SetObjectType(SvxPreviewObjectType nType)899 void Svx3DLightControl::SetObjectType(SvxPreviewObjectType nType)
900 {
901 // call parent
902 Svx3DPreviewControl::SetObjectType(nType);
903
904 // apply object rotation
905 if(mp3DObj)
906 {
907 basegfx::B3DHomMatrix aObjectRotation;
908 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
909 mp3DObj->SetTransform(aObjectRotation);
910 }
911 }
912
IsSelectionValid()913 bool Svx3DLightControl::IsSelectionValid()
914 {
915 return (NO_LIGHT_SELECTED != maSelectedLight) && GetLightOnOff(maSelectedLight);
916 }
917
GetPosition(double & rHor,double & rVer)918 void Svx3DLightControl::GetPosition(double& rHor, double& rVer)
919 {
920 if(IsSelectionValid())
921 {
922 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
923 aDirection.normalize();
924 rHor = basegfx::rad2deg(atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI); // 0..360.0
925 rVer = basegfx::rad2deg(atan2(aDirection.getY(), aDirection.getXZLength())); // -90.0..90.0
926 }
927 if(IsGeometrySelected())
928 {
929 rHor = basegfx::rad2deg(mfRotateY); // 0..360.0
930 rVer = basegfx::rad2deg(mfRotateX); // -90.0..90.0
931 }
932 }
933
SetPosition(double fHor,double fVer)934 void Svx3DLightControl::SetPosition(double fHor, double fVer)
935 {
936 if(IsSelectionValid())
937 {
938 // set selected light's direction
939 fHor = basegfx::deg2rad(fHor) - F_PI; // -PI..PI
940 fVer = basegfx::deg2rad(fVer); // -PI2..PI2
941 basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
942 aDirection.normalize();
943
944 if(!aDirection.equal(GetLightDirection(maSelectedLight)))
945 {
946 // set changed light direction at SdrScene
947 SfxItemSet aSet(mpModel->GetItemPool());
948
949 switch(maSelectedLight)
950 {
951 case 0: aSet.Put(makeSvx3DLightDirection1Item(aDirection)); break;
952 case 1: aSet.Put(makeSvx3DLightDirection2Item(aDirection)); break;
953 case 2: aSet.Put(makeSvx3DLightDirection3Item(aDirection)); break;
954 case 3: aSet.Put(makeSvx3DLightDirection4Item(aDirection)); break;
955 case 4: aSet.Put(makeSvx3DLightDirection5Item(aDirection)); break;
956 case 5: aSet.Put(makeSvx3DLightDirection6Item(aDirection)); break;
957 case 6: aSet.Put(makeSvx3DLightDirection7Item(aDirection)); break;
958 default:
959 case 7: aSet.Put(makeSvx3DLightDirection8Item(aDirection)); break;
960 }
961
962 mpScene->SetMergedItemSet(aSet);
963
964 // correct 3D light's and LampFrame's geometries
965 AdaptToSelectedLight();
966 Invalidate();
967 }
968 }
969 if(IsGeometrySelected())
970 {
971 if(mfRotateX != fVer || mfRotateY != fHor)
972 {
973 mfRotateX = basegfx::deg2rad(fVer);
974 mfRotateY = basegfx::deg2rad(fHor);
975
976 if(mp3DObj)
977 {
978 basegfx::B3DHomMatrix aObjectRotation;
979 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
980 mp3DObj->SetTransform(aObjectRotation);
981
982 Invalidate();
983 }
984 }
985 }
986 }
987
SetRotation(double fRotX,double fRotY,double fRotZ)988 void Svx3DLightControl::SetRotation(double fRotX, double fRotY, double fRotZ)
989 {
990 if(IsGeometrySelected())
991 {
992 if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
993 {
994 mfRotateX = fRotX;
995 mfRotateY = fRotY;
996 mfRotateZ = fRotZ;
997
998 if(mp3DObj)
999 {
1000 basegfx::B3DHomMatrix aObjectRotation;
1001 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1002 mp3DObj->SetTransform(aObjectRotation);
1003
1004 Invalidate();
1005 }
1006 }
1007 }
1008 }
1009
GetRotation(double & rRotX,double & rRotY,double & rRotZ)1010 void Svx3DLightControl::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
1011 {
1012 rRotX = mfRotateX;
1013 rRotY = mfRotateY;
1014 rRotZ = mfRotateZ;
1015 }
1016
Set3DAttributes(const SfxItemSet & rAttr)1017 void Svx3DLightControl::Set3DAttributes( const SfxItemSet& rAttr )
1018 {
1019 // call parent
1020 Svx3DPreviewControl::Set3DAttributes(rAttr);
1021
1022 if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
1023 {
1024 // selected light is no more active, select new one
1025 maSelectedLight = NO_LIGHT_SELECTED;
1026 }
1027
1028 // local updates
1029 ConstructLightObjects();
1030 AdaptToSelectedLight();
1031 Invalidate();
1032 }
1033
SelectLight(sal_uInt32 nLightNumber)1034 void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber)
1035 {
1036 if(nLightNumber > 7)
1037 {
1038 nLightNumber = NO_LIGHT_SELECTED;
1039 }
1040
1041 if(NO_LIGHT_SELECTED != nLightNumber)
1042 {
1043 if(!GetLightOnOff(nLightNumber))
1044 {
1045 nLightNumber = NO_LIGHT_SELECTED;
1046 }
1047 }
1048
1049 if(nLightNumber != maSelectedLight)
1050 {
1051 maSelectedLight = nLightNumber;
1052 mbGeometrySelected = false;
1053 ConstructLightObjects();
1054 AdaptToSelectedLight();
1055 Invalidate();
1056 }
1057 }
1058
GetLightOnOff(sal_uInt32 nNum) const1059 bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum) const
1060 {
1061 if(nNum <= 7)
1062 {
1063 const SfxItemSet aLightItemSet(Get3DAttributes());
1064
1065 switch(nNum)
1066 {
1067 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue();
1068 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue();
1069 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue();
1070 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue();
1071 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue();
1072 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue();
1073 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue();
1074 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue();
1075 }
1076 }
1077
1078 return false;
1079 }
1080
GetLightColor(sal_uInt32 nNum) const1081 Color Svx3DLightControl::GetLightColor(sal_uInt32 nNum) const
1082 {
1083 if(nNum <= 7)
1084 {
1085 const SfxItemSet aLightItemSet(Get3DAttributes());
1086
1087 switch(nNum)
1088 {
1089 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue();
1090 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue();
1091 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue();
1092 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue();
1093 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue();
1094 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue();
1095 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue();
1096 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue();
1097 }
1098 }
1099
1100 return COL_BLACK;
1101 }
1102
GetLightDirection(sal_uInt32 nNum) const1103 basegfx::B3DVector Svx3DLightControl::GetLightDirection(sal_uInt32 nNum) const
1104 {
1105 if(nNum <= 7)
1106 {
1107 const SfxItemSet aLightItemSet(Get3DAttributes());
1108
1109 switch(nNum)
1110 {
1111 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue();
1112 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue();
1113 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue();
1114 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue();
1115 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue();
1116 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue();
1117 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue();
1118 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue();
1119 }
1120 }
1121
1122 return basegfx::B3DVector();
1123 }
1124
LightControl3D()1125 LightControl3D::LightControl3D()
1126 : maChangeCallback(),
1127 maSelectionChangeCallback(),
1128 maSelectedLight(NO_LIGHT_SELECTED),
1129 mpExpansionObject(nullptr),
1130 mpLampBottomObject(nullptr),
1131 mpLampShaftObject(nullptr),
1132 maLightObjects(MAX_NUMBER_LIGHTS, nullptr),
1133 mfRotateX(-20.0),
1134 mfRotateY(45.0),
1135 mfRotateZ(0.0),
1136 maActionStartPoint(),
1137 mfSaveActionStartHor(0.0),
1138 mfSaveActionStartVer(0.0),
1139 mfSaveActionStartRotZ(0.0),
1140 mbMouseMoved(false),
1141 mbMouseCaptured(false),
1142 mbGeometrySelected(false)
1143 {
1144 }
1145
SetDrawingArea(weld::DrawingArea * pDrawingArea)1146 void LightControl3D::SetDrawingArea(weld::DrawingArea* pDrawingArea)
1147 {
1148 PreviewControl3D::SetDrawingArea(pDrawingArea);
1149 Construct2();
1150 }
1151
Construct2()1152 void LightControl3D::Construct2()
1153 {
1154 {
1155 // hide all page stuff, use control background (normally gray)
1156 const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
1157 mp3DView->SetPageVisible(false);
1158 mp3DView->SetApplicationBackgroundColor(aDialogColor);
1159 mp3DView->SetApplicationDocumentColor(aDialogColor);
1160 }
1161
1162 {
1163 // create invisible expansion object
1164 const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
1165 mpExpansionObject = new E3dCubeObj(
1166 *mpModel,
1167 mp3DView->Get3DDefaultAttributes(),
1168 basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
1169 basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
1170 mpScene->InsertObject( mpExpansionObject );
1171 SfxItemSet aSet(mpModel->GetItemPool());
1172 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1173 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1174 mpExpansionObject->SetMergedItemSet(aSet);
1175 }
1176
1177 {
1178 // create lamp control object (Yellow lined object)
1179 // base circle
1180 const basegfx::B2DPolygon a2DCircle(basegfx::utils::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
1181 basegfx::B3DPolygon a3DCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DCircle));
1182 basegfx::B3DHomMatrix aTransform;
1183
1184 aTransform.rotate(F_PI2, 0.0, 0.0);
1185 aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
1186 a3DCircle.transform(aTransform);
1187
1188 // create object for it
1189 mpLampBottomObject = new E3dPolygonObj(
1190 *mpModel,
1191 basegfx::B3DPolyPolygon(a3DCircle));
1192 mpScene->InsertObject( mpLampBottomObject );
1193
1194 // half circle with stand
1195 basegfx::B2DPolygon a2DHalfCircle;
1196 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
1197 a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
1198 a2DHalfCircle.append(basegfx::utils::createPolygonFromEllipseSegment(
1199 basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
1200 basegfx::B3DPolygon a3DHalfCircle(basegfx::utils::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
1201
1202 // create object for it
1203 mpLampShaftObject = new E3dPolygonObj(
1204 *mpModel,
1205 basegfx::B3DPolyPolygon(a3DHalfCircle));
1206 mpScene->InsertObject( mpLampShaftObject );
1207
1208 // initially invisible
1209 SfxItemSet aSet(mpModel->GetItemPool());
1210 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1211 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1212
1213 mpLampBottomObject->SetMergedItemSet(aSet);
1214 mpLampShaftObject->SetMergedItemSet(aSet);
1215 }
1216
1217 {
1218 // change camera settings
1219 Camera3D rCamera = mpScene->GetCamera();
1220 const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
1221 double fW = rVolume.getWidth();
1222 double fH = rVolume.getHeight();
1223 double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
1224
1225 rCamera.SetAutoAdjustProjection(false);
1226 rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
1227 basegfx::B3DPoint aLookAt;
1228 double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
1229 basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
1230 rCamera.SetPosAndLookAt(aCamPos, aLookAt);
1231 double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
1232 rCamera.SetFocalLength(fDefaultCamFocal);
1233
1234 mpScene->SetCamera( rCamera );
1235
1236 basegfx::B3DHomMatrix aNeutral;
1237 mpScene->SetTransform(aNeutral);
1238 }
1239
1240 // invalidate SnapRects of objects
1241 mpScene->SetRectsDirty();
1242 }
1243
ConstructLightObjects()1244 void LightControl3D::ConstructLightObjects()
1245 {
1246 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
1247 {
1248 // get rid of possible existing light object
1249 if(maLightObjects[a])
1250 {
1251 mpScene->RemoveObject(maLightObjects[a]->GetOrdNum());
1252 // always use SdrObject::Free(...) for SdrObjects (!)
1253 SdrObject* pTemp(maLightObjects[a]);
1254 SdrObject::Free(pTemp);
1255 maLightObjects[a] = nullptr;
1256 }
1257
1258 if(GetLightOnOff(a))
1259 {
1260 const bool bIsSelectedLight(a == maSelectedLight);
1261 basegfx::B3DVector aDirection(GetLightDirection(a));
1262 aDirection.normalize();
1263 aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
1264
1265 const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
1266 E3dObject* pNewLight = new E3dSphereObj(
1267 *mpModel,
1268 mp3DView->Get3DDefaultAttributes(),
1269 basegfx::B3DPoint( 0, 0, 0 ),
1270 basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
1271 mpScene->InsertObject(pNewLight);
1272
1273 basegfx::B3DHomMatrix aTransform;
1274 aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
1275 pNewLight->SetTransform(aTransform);
1276
1277 SfxItemSet aSet(mpModel->GetItemPool());
1278 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1279 aSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
1280 aSet.Put( XFillColorItem(OUString(), GetLightColor(a)));
1281 pNewLight->SetMergedItemSet(aSet);
1282
1283 maLightObjects[a] = pNewLight;
1284 }
1285 }
1286 }
1287
AdaptToSelectedLight()1288 void LightControl3D::AdaptToSelectedLight()
1289 {
1290 if(NO_LIGHT_SELECTED == maSelectedLight)
1291 {
1292 // make mpLampBottomObject/mpLampShaftObject invisible
1293 SfxItemSet aSet(mpModel->GetItemPool());
1294 aSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1295 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1296 mpLampBottomObject->SetMergedItemSet(aSet);
1297 mpLampShaftObject->SetMergedItemSet(aSet);
1298 }
1299 else
1300 {
1301 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
1302 aDirection.normalize();
1303
1304 // make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
1305 SfxItemSet aSet(mpModel->GetItemPool());
1306 aSet.Put( XLineStyleItem( drawing::LineStyle_SOLID ) );
1307 aSet.Put( XLineColorItem(OUString(), COL_YELLOW));
1308 aSet.Put( XLineWidthItem(0));
1309 aSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1310 mpLampBottomObject->SetMergedItemSet(aSet);
1311 mpLampShaftObject->SetMergedItemSet(aSet);
1312
1313 // adapt transformation of mpLampShaftObject
1314 basegfx::B3DHomMatrix aTransform;
1315 double fRotateY(0.0);
1316
1317 if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
1318 {
1319 fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
1320 }
1321
1322 aTransform.rotate(0.0, fRotateY, 0.0);
1323 mpLampShaftObject->SetTransform(aTransform);
1324
1325 // adapt transformation of selected light
1326 E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
1327
1328 if(pSelectedLight)
1329 {
1330 aTransform.identity();
1331 aTransform.translate(
1332 aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
1333 aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
1334 aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
1335 pSelectedLight->SetTransform(aTransform);
1336 }
1337 }
1338 }
1339
TrySelection(Point aPosPixel)1340 void LightControl3D::TrySelection(Point aPosPixel)
1341 {
1342 if(mpScene)
1343 {
1344 const Point aPosLogic(GetDrawingArea()->get_ref_device().PixelToLogic(aPosPixel));
1345 const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
1346 std::vector< const E3dCompoundObject* > aResult;
1347 getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
1348
1349 if(!aResult.empty())
1350 {
1351 // exclude expansion object which will be part of
1352 // the hits. It's invisible, but for HitTest, it's included
1353 const E3dCompoundObject* pResult = nullptr;
1354
1355 for(auto const & b: aResult)
1356 {
1357 if(b && b != mpExpansionObject)
1358 {
1359 pResult = b;
1360 break;
1361 }
1362 }
1363
1364 if(pResult == mp3DObj)
1365 {
1366 if(!mbGeometrySelected)
1367 {
1368 mbGeometrySelected = true;
1369 maSelectedLight = NO_LIGHT_SELECTED;
1370 ConstructLightObjects();
1371 AdaptToSelectedLight();
1372 Invalidate();
1373
1374 if(maSelectionChangeCallback.IsSet())
1375 {
1376 maSelectionChangeCallback.Call(this);
1377 }
1378 }
1379 }
1380 else
1381 {
1382 sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
1383
1384 for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
1385 {
1386 if(maLightObjects[a] && maLightObjects[a] == pResult)
1387 {
1388 aNewSelectedLight = a;
1389 }
1390 }
1391
1392 if(aNewSelectedLight != maSelectedLight)
1393 {
1394 SelectLight(aNewSelectedLight);
1395
1396 if(maSelectionChangeCallback.IsSet())
1397 {
1398 maSelectionChangeCallback.Call(this);
1399 }
1400 }
1401 }
1402 }
1403 }
1404 }
1405
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect)1406 void LightControl3D::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
1407 {
1408 PreviewControl3D::Paint(rRenderContext, rRect);
1409 }
1410
GetFocusRect()1411 tools::Rectangle LightControl3D::GetFocusRect()
1412 {
1413 if (!HasFocus())
1414 return tools::Rectangle();
1415 Size aFocusSize = GetOutputSizePixel();
1416 aFocusSize.AdjustWidth( -4 );
1417 aFocusSize.AdjustHeight( -4 );
1418 return tools::Rectangle(Point(2, 2), aFocusSize);
1419 }
1420
MouseButtonDown(const MouseEvent & rMEvt)1421 bool LightControl3D::MouseButtonDown( const MouseEvent& rMEvt )
1422 {
1423 bool bCallParent(true);
1424
1425 // switch state
1426 if(rMEvt.IsLeft())
1427 {
1428 if(IsSelectionValid() || mbGeometrySelected)
1429 {
1430 mbMouseMoved = false;
1431 bCallParent = false;
1432 maActionStartPoint = rMEvt.GetPosPixel();
1433 CaptureMouse();
1434 mbMouseCaptured = true;
1435 }
1436 else
1437 {
1438 // Single click without moving much trying to do a selection
1439 TrySelection(rMEvt.GetPosPixel());
1440 bCallParent = false;
1441 }
1442 }
1443
1444 // call parent
1445 if (bCallParent)
1446 return PreviewControl3D::MouseButtonDown(rMEvt);
1447 return true;
1448 }
1449
MouseMove(const MouseEvent & rMEvt)1450 bool LightControl3D::MouseMove(const MouseEvent& rMEvt)
1451 {
1452 if (!mbMouseCaptured)
1453 return false;
1454
1455 Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
1456
1457 if(!mbMouseMoved)
1458 {
1459 if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > g_nInteractionStartDistance)
1460 {
1461 if(mbGeometrySelected)
1462 {
1463 GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
1464 }
1465 else
1466 {
1467 // interaction start, save values
1468 GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
1469 }
1470
1471 mbMouseMoved = true;
1472 }
1473 }
1474
1475 if(mbMouseMoved)
1476 {
1477 if(mbGeometrySelected)
1478 {
1479 double fNewRotX = mfSaveActionStartVer - basegfx::deg2rad(aDeltaPos.Y());
1480 double fNewRotY = mfSaveActionStartHor + basegfx::deg2rad(aDeltaPos.X());
1481
1482 // cut horizontal
1483 while(fNewRotY < 0.0)
1484 {
1485 fNewRotY += F_2PI;
1486 }
1487
1488 while(fNewRotY >= F_2PI)
1489 {
1490 fNewRotY -= F_2PI;
1491 }
1492
1493 // cut vertical
1494 if(fNewRotX < -F_PI2)
1495 {
1496 fNewRotX = -F_PI2;
1497 }
1498
1499 if(fNewRotX > F_PI2)
1500 {
1501 fNewRotX = F_PI2;
1502 }
1503
1504 SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
1505
1506 if(maChangeCallback.IsSet())
1507 {
1508 maChangeCallback.Call(this);
1509 }
1510 }
1511 else
1512 {
1513 // interaction in progress
1514 double fNewPosHor = mfSaveActionStartHor + static_cast<double>(aDeltaPos.X());
1515 double fNewPosVer = mfSaveActionStartVer - static_cast<double>(aDeltaPos.Y());
1516
1517 // cut horizontal
1518 fNewPosHor = NormAngle360(fNewPosHor);
1519
1520 // cut vertical
1521 if(fNewPosVer < -90.0)
1522 {
1523 fNewPosVer = -90.0;
1524 }
1525
1526 if(fNewPosVer > 90.0)
1527 {
1528 fNewPosVer = 90.0;
1529 }
1530
1531 SetPosition(fNewPosHor, fNewPosVer);
1532
1533 if(maChangeCallback.IsSet())
1534 {
1535 maChangeCallback.Call(this);
1536 }
1537 }
1538 }
1539 return true;
1540 }
1541
MouseButtonUp(const MouseEvent & rMEvt)1542 bool LightControl3D::MouseButtonUp(const MouseEvent& rMEvt)
1543 {
1544 if (!mbMouseCaptured)
1545 return false;
1546 ReleaseMouse();
1547 mbMouseCaptured = false;
1548
1549 if (mbMouseMoved)
1550 {
1551 // was change interactively
1552 }
1553 else
1554 {
1555 // simple click without much movement, try selection
1556 TrySelection(rMEvt.GetPosPixel());
1557 }
1558
1559 return true;
1560 }
1561
Resize()1562 void LightControl3D::Resize()
1563 {
1564 // set size of page
1565 const Size aSize(GetDrawingArea()->get_ref_device().PixelToLogic(GetOutputSizePixel()));
1566 mpFmPage->SetSize(aSize);
1567
1568 // set position and size of scene
1569 mpScene->SetSnapRect(tools::Rectangle(Point(0, 0), aSize));
1570 }
1571
SetObjectType(SvxPreviewObjectType nType)1572 void LightControl3D::SetObjectType(SvxPreviewObjectType nType)
1573 {
1574 // call parent
1575 PreviewControl3D::SetObjectType(nType);
1576
1577 // apply object rotation
1578 if(mp3DObj)
1579 {
1580 basegfx::B3DHomMatrix aObjectRotation;
1581 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1582 mp3DObj->SetTransform(aObjectRotation);
1583 }
1584 }
1585
IsSelectionValid()1586 bool LightControl3D::IsSelectionValid()
1587 {
1588 return (NO_LIGHT_SELECTED != maSelectedLight) && GetLightOnOff(maSelectedLight);
1589 }
1590
GetPosition(double & rHor,double & rVer)1591 void LightControl3D::GetPosition(double& rHor, double& rVer)
1592 {
1593 if(IsSelectionValid())
1594 {
1595 basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
1596 aDirection.normalize();
1597 rHor = basegfx::rad2deg(atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI); // 0..360.0
1598 rVer = basegfx::rad2deg(atan2(aDirection.getY(), aDirection.getXZLength())); // -90.0..90.0
1599 }
1600 if(IsGeometrySelected())
1601 {
1602 rHor = basegfx::rad2deg(mfRotateY); // 0..360.0
1603 rVer = basegfx::rad2deg(mfRotateX); // -90.0..90.0
1604 }
1605 }
1606
SetPosition(double fHor,double fVer)1607 void LightControl3D::SetPosition(double fHor, double fVer)
1608 {
1609 if(IsSelectionValid())
1610 {
1611 // set selected light's direction
1612 fHor = basegfx::deg2rad(fHor) - F_PI; // -PI..PI
1613 fVer = basegfx::deg2rad(fVer); // -PI2..PI2
1614 basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
1615 aDirection.normalize();
1616
1617 if(!aDirection.equal(GetLightDirection(maSelectedLight)))
1618 {
1619 // set changed light direction at SdrScene
1620 SfxItemSet aSet(mpModel->GetItemPool());
1621
1622 switch(maSelectedLight)
1623 {
1624 case 0: aSet.Put(makeSvx3DLightDirection1Item(aDirection)); break;
1625 case 1: aSet.Put(makeSvx3DLightDirection2Item(aDirection)); break;
1626 case 2: aSet.Put(makeSvx3DLightDirection3Item(aDirection)); break;
1627 case 3: aSet.Put(makeSvx3DLightDirection4Item(aDirection)); break;
1628 case 4: aSet.Put(makeSvx3DLightDirection5Item(aDirection)); break;
1629 case 5: aSet.Put(makeSvx3DLightDirection6Item(aDirection)); break;
1630 case 6: aSet.Put(makeSvx3DLightDirection7Item(aDirection)); break;
1631 default:
1632 case 7: aSet.Put(makeSvx3DLightDirection8Item(aDirection)); break;
1633 }
1634
1635 mpScene->SetMergedItemSet(aSet);
1636
1637 // correct 3D light's and LampFrame's geometries
1638 AdaptToSelectedLight();
1639 Invalidate();
1640 }
1641 }
1642 if(IsGeometrySelected())
1643 {
1644 if(mfRotateX != fVer || mfRotateY != fHor)
1645 {
1646 mfRotateX = basegfx::deg2rad(fVer);
1647 mfRotateY = basegfx::deg2rad(fHor);
1648
1649 if(mp3DObj)
1650 {
1651 basegfx::B3DHomMatrix aObjectRotation;
1652 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1653 mp3DObj->SetTransform(aObjectRotation);
1654
1655 Invalidate();
1656 }
1657 }
1658 }
1659 }
1660
SetRotation(double fRotX,double fRotY,double fRotZ)1661 void LightControl3D::SetRotation(double fRotX, double fRotY, double fRotZ)
1662 {
1663 if(IsGeometrySelected())
1664 {
1665 if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
1666 {
1667 mfRotateX = fRotX;
1668 mfRotateY = fRotY;
1669 mfRotateZ = fRotZ;
1670
1671 if(mp3DObj)
1672 {
1673 basegfx::B3DHomMatrix aObjectRotation;
1674 aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
1675 mp3DObj->SetTransform(aObjectRotation);
1676
1677 Invalidate();
1678 }
1679 }
1680 }
1681 }
1682
GetRotation(double & rRotX,double & rRotY,double & rRotZ)1683 void LightControl3D::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
1684 {
1685 rRotX = mfRotateX;
1686 rRotY = mfRotateY;
1687 rRotZ = mfRotateZ;
1688 }
1689
Set3DAttributes(const SfxItemSet & rAttr)1690 void LightControl3D::Set3DAttributes( const SfxItemSet& rAttr )
1691 {
1692 // call parent
1693 PreviewControl3D::Set3DAttributes(rAttr);
1694
1695 if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
1696 {
1697 // selected light is no more active, select new one
1698 maSelectedLight = NO_LIGHT_SELECTED;
1699 }
1700
1701 // local updates
1702 ConstructLightObjects();
1703 AdaptToSelectedLight();
1704 Invalidate();
1705 }
1706
SelectLight(sal_uInt32 nLightNumber)1707 void LightControl3D::SelectLight(sal_uInt32 nLightNumber)
1708 {
1709 if(nLightNumber > 7)
1710 {
1711 nLightNumber = NO_LIGHT_SELECTED;
1712 }
1713
1714 if(NO_LIGHT_SELECTED != nLightNumber)
1715 {
1716 if(!GetLightOnOff(nLightNumber))
1717 {
1718 nLightNumber = NO_LIGHT_SELECTED;
1719 }
1720 }
1721
1722 if(nLightNumber != maSelectedLight)
1723 {
1724 maSelectedLight = nLightNumber;
1725 mbGeometrySelected = false;
1726 ConstructLightObjects();
1727 AdaptToSelectedLight();
1728 Invalidate();
1729 }
1730 }
1731
GetLightOnOff(sal_uInt32 nNum) const1732 bool LightControl3D::GetLightOnOff(sal_uInt32 nNum) const
1733 {
1734 if(nNum <= 7)
1735 {
1736 const SfxItemSet aLightItemSet(Get3DAttributes());
1737
1738 switch(nNum)
1739 {
1740 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue();
1741 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue();
1742 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue();
1743 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue();
1744 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue();
1745 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue();
1746 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue();
1747 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue();
1748 }
1749 }
1750
1751 return false;
1752 }
1753
GetLightColor(sal_uInt32 nNum) const1754 Color LightControl3D::GetLightColor(sal_uInt32 nNum) const
1755 {
1756 if(nNum <= 7)
1757 {
1758 const SfxItemSet aLightItemSet(Get3DAttributes());
1759
1760 switch(nNum)
1761 {
1762 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue();
1763 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue();
1764 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue();
1765 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue();
1766 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue();
1767 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue();
1768 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue();
1769 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue();
1770 }
1771 }
1772
1773 return COL_BLACK;
1774 }
1775
GetLightDirection(sal_uInt32 nNum) const1776 basegfx::B3DVector LightControl3D::GetLightDirection(sal_uInt32 nNum) const
1777 {
1778 if(nNum <= 7)
1779 {
1780 const SfxItemSet aLightItemSet(Get3DAttributes());
1781
1782 switch(nNum)
1783 {
1784 case 0 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue();
1785 case 1 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue();
1786 case 2 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue();
1787 case 3 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue();
1788 case 4 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue();
1789 case 5 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue();
1790 case 6 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue();
1791 case 7 : return aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue();
1792 }
1793 }
1794
1795 return basegfx::B3DVector();
1796 }
1797
SvxLightCtl3D(vcl::Window * pParent)1798 SvxLightCtl3D::SvxLightCtl3D( vcl::Window* pParent)
1799 : Control(pParent, WB_BORDER | WB_TABSTOP),
1800 maLightControl(VclPtr<Svx3DLightControl>::Create(this, 0)),
1801 maHorScroller(VclPtr<ScrollBar>::Create(this, WB_HORZ | WB_DRAG)),
1802 maVerScroller(VclPtr<ScrollBar>::Create(this, WB_VERT | WB_DRAG)),
1803 maSwitcher(VclPtr<PushButton>::Create(this, 0))
1804 {
1805 // init members
1806 Init();
1807 }
1808
GetOptimalSize() const1809 Size SvxLightCtl3D::GetOptimalSize() const
1810 {
1811 return LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont));
1812 }
1813
VCL_BUILDER_FACTORY(SvxLightCtl3D)1814 VCL_BUILDER_FACTORY(SvxLightCtl3D)
1815
1816 void SvxLightCtl3D::Init()
1817 {
1818 // #i58240# set HelpIDs for scrollbars and switcher
1819 maHorScroller->SetHelpId(HID_CTRL3D_HSCROLL);
1820 maVerScroller->SetHelpId(HID_CTRL3D_VSCROLL);
1821 maSwitcher->SetHelpId(HID_CTRL3D_SWITCHER);
1822 maSwitcher->SetAccessibleName(SvxResId(STR_SWITCH));
1823
1824 // Light preview
1825 maLightControl->Show();
1826 maLightControl->SetChangeCallback( LINK(this, SvxLightCtl3D, InternalInteractiveChange) );
1827 maLightControl->SetSelectionChangeCallback( LINK(this, SvxLightCtl3D, InternalSelectionChange) );
1828
1829 // Horiz Scrollbar
1830 maHorScroller->Show();
1831 maHorScroller->SetRange(Range(0, 36000));
1832 maHorScroller->SetLineSize(100);
1833 maHorScroller->SetPageSize(1000);
1834 maHorScroller->SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1835
1836 // Vert Scrollbar
1837 maVerScroller->Show();
1838 maVerScroller->SetRange(Range(0, 18000));
1839 maVerScroller->SetLineSize(100);
1840 maVerScroller->SetPageSize(1000);
1841 maVerScroller->SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
1842
1843 // Switch Button
1844 maSwitcher->Show();
1845 maSwitcher->SetClickHdl( LINK(this, SvxLightCtl3D, ButtonPress) );
1846
1847 // check selection
1848 CheckSelection();
1849
1850 // new layout
1851 NewLayout();
1852 }
1853
~SvxLightCtl3D()1854 SvxLightCtl3D::~SvxLightCtl3D()
1855 {
1856 disposeOnce();
1857 }
1858
dispose()1859 void SvxLightCtl3D::dispose()
1860 {
1861 maLightControl.disposeAndClear();
1862 maHorScroller.disposeAndClear();
1863 maVerScroller.disposeAndClear();
1864 maSwitcher.disposeAndClear();
1865 Control::dispose();
1866 }
1867
Resize()1868 void SvxLightCtl3D::Resize()
1869 {
1870 // call parent
1871 Control::Resize();
1872
1873 // new layout
1874 NewLayout();
1875 }
1876
NewLayout()1877 void SvxLightCtl3D::NewLayout()
1878 {
1879 // Layout members
1880 const Size aSize(GetOutputSizePixel());
1881 const sal_Int32 nScrollSize(maHorScroller->GetSizePixel().Height());
1882
1883 // Preview control
1884 Point aPoint(0, 0);
1885 Size aDestSize(aSize.Width() - nScrollSize, aSize.Height() - nScrollSize);
1886 maLightControl->SetPosSizePixel(aPoint, aDestSize);
1887
1888 // hor scrollbar
1889 aPoint.setY( aSize.Height() - nScrollSize );
1890 aDestSize.setHeight( nScrollSize );
1891 maHorScroller->SetPosSizePixel(aPoint, aDestSize);
1892
1893 // vert scrollbar
1894 aPoint.setX( aSize.Width() - nScrollSize );
1895 aPoint.setY( 0 );
1896 aDestSize.setWidth( nScrollSize );
1897 aDestSize.setHeight( aSize.Height() - nScrollSize );
1898 maVerScroller->SetPosSizePixel(aPoint, aDestSize);
1899
1900 // button
1901 aPoint.setY( aSize.Height() - nScrollSize );
1902 aDestSize.setHeight( nScrollSize );
1903 maSwitcher->SetPosSizePixel(aPoint, aDestSize);
1904 }
1905
CheckSelection()1906 void SvxLightCtl3D::CheckSelection()
1907 {
1908 const bool bSelectionValid(maLightControl->IsSelectionValid() || maLightControl->IsGeometrySelected());
1909 maHorScroller->Enable(bSelectionValid);
1910 maVerScroller->Enable(bSelectionValid);
1911
1912 if(bSelectionValid)
1913 {
1914 double fHor(0.0), fVer(0.0);
1915 maLightControl->GetPosition(fHor, fVer);
1916 maHorScroller->SetThumbPos( sal_Int32(fHor * 100.0) );
1917 maVerScroller->SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1918 }
1919 }
1920
move(double fDeltaHor,double fDeltaVer)1921 void SvxLightCtl3D::move( double fDeltaHor, double fDeltaVer )
1922 {
1923 double fHor(0.0), fVer(0.0);
1924
1925 maLightControl->GetPosition(fHor, fVer);
1926 fHor += fDeltaHor;
1927 fVer += fDeltaVer;
1928
1929 if( fVer > 90.0 )
1930 return;
1931
1932 if ( fVer < -90.0 )
1933 return;
1934
1935 maLightControl->SetPosition(fHor, fVer);
1936 maHorScroller->SetThumbPos( sal_Int32(fHor * 100.0) );
1937 maVerScroller->SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
1938 }
1939
KeyInput(const KeyEvent & rKEvt)1940 void SvxLightCtl3D::KeyInput( const KeyEvent& rKEvt )
1941 {
1942 const vcl::KeyCode aCode(rKEvt.GetKeyCode());
1943
1944 if( aCode.GetModifier() )
1945 {
1946 Control::KeyInput( rKEvt );
1947 return;
1948 }
1949
1950 switch ( aCode.GetCode() )
1951 {
1952 case KEY_SPACE:
1953 {
1954 break;
1955 }
1956 case KEY_LEFT:
1957 {
1958 move( -4.0, 0.0 ); // #i58242# changed move direction in X
1959 break;
1960 }
1961 case KEY_RIGHT:
1962 {
1963 move( 4.0, 0.0 ); // #i58242# changed move direction in X
1964 break;
1965 }
1966 case KEY_UP:
1967 {
1968 move( 0.0, 4.0 );
1969 break;
1970 }
1971 case KEY_DOWN:
1972 {
1973 move( 0.0, -4.0 );
1974 break;
1975 }
1976 case KEY_PAGEUP:
1977 {
1978 sal_Int32 nLight(maLightControl->GetSelectedLight() - 1);
1979
1980 while((nLight >= 0) && !maLightControl->GetLightOnOff(nLight))
1981 {
1982 nLight--;
1983 }
1984
1985 if(nLight < 0)
1986 {
1987 nLight = 7;
1988
1989 while((nLight >= 0) && !maLightControl->GetLightOnOff(nLight))
1990 {
1991 nLight--;
1992 }
1993 }
1994
1995 if(nLight >= 0)
1996 {
1997 maLightControl->SelectLight(nLight);
1998 CheckSelection();
1999
2000 if(maUserSelectionChangeCallback.IsSet())
2001 {
2002 maUserSelectionChangeCallback.Call(this);
2003 }
2004 }
2005
2006 break;
2007 }
2008 case KEY_PAGEDOWN:
2009 {
2010 sal_Int32 nLight(maLightControl->GetSelectedLight() - 1);
2011
2012 while(nLight <= 7 && !maLightControl->GetLightOnOff(nLight))
2013 {
2014 nLight++;
2015 }
2016
2017 if(nLight > 7)
2018 {
2019 nLight = 0;
2020
2021 while(nLight <= 7 && !maLightControl->GetLightOnOff(nLight))
2022 {
2023 nLight++;
2024 }
2025 }
2026
2027 if(nLight <= 7)
2028 {
2029 maLightControl->SelectLight(nLight);
2030 CheckSelection();
2031
2032 if(maUserSelectionChangeCallback.IsSet())
2033 {
2034 maUserSelectionChangeCallback.Call(this);
2035 }
2036 }
2037
2038 break;
2039 }
2040 default:
2041 {
2042 Control::KeyInput( rKEvt );
2043 break;
2044 }
2045 }
2046 }
2047
GetFocus()2048 void SvxLightCtl3D::GetFocus()
2049 {
2050 Control::GetFocus();
2051
2052 if(HasFocus() && IsEnabled())
2053 {
2054 CheckSelection();
2055
2056 Size aFocusSize = maLightControl->GetOutputSizePixel();
2057
2058 aFocusSize.AdjustWidth( -4 );
2059 aFocusSize.AdjustHeight( -4 );
2060
2061 tools::Rectangle aFocusRect( Point( 2, 2 ), aFocusSize );
2062
2063 aFocusRect = maLightControl->PixelToLogic( aFocusRect );
2064
2065 maLightControl->ShowFocus( aFocusRect );
2066 }
2067 }
2068
LoseFocus()2069 void SvxLightCtl3D::LoseFocus()
2070 {
2071 Control::LoseFocus();
2072
2073 maLightControl->HideFocus();
2074 }
2075
IMPL_LINK_NOARG(SvxLightCtl3D,ScrollBarMove,ScrollBar *,void)2076 IMPL_LINK_NOARG(SvxLightCtl3D, ScrollBarMove, ScrollBar*, void)
2077 {
2078 const sal_Int32 nHor(maHorScroller->GetThumbPos());
2079 const sal_Int32 nVer(maVerScroller->GetThumbPos());
2080
2081 maLightControl->SetPosition(
2082 static_cast<double>(nHor) / 100.0,
2083 static_cast<double>((18000 - nVer) - 9000) / 100.0);
2084 }
2085
IMPL_LINK_NOARG(SvxLightCtl3D,ButtonPress,Button *,void)2086 IMPL_LINK_NOARG(SvxLightCtl3D, ButtonPress, Button*, void)
2087 {
2088 if(SvxPreviewObjectType::SPHERE == GetSvx3DLightControl().GetObjectType())
2089 {
2090 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::CUBE);
2091 }
2092 else
2093 {
2094 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::SPHERE);
2095 }
2096 }
2097
IMPL_LINK_NOARG(SvxLightCtl3D,InternalInteractiveChange,Svx3DLightControl *,void)2098 IMPL_LINK_NOARG(SvxLightCtl3D, InternalInteractiveChange, Svx3DLightControl*, void)
2099 {
2100 double fHor(0.0), fVer(0.0);
2101
2102 maLightControl->GetPosition(fHor, fVer);
2103 maHorScroller->SetThumbPos( sal_Int32(fHor * 100.0) );
2104 maVerScroller->SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2105 }
2106
IMPL_LINK_NOARG(SvxLightCtl3D,InternalSelectionChange,Svx3DLightControl *,void)2107 IMPL_LINK_NOARG(SvxLightCtl3D, InternalSelectionChange, Svx3DLightControl*, void)
2108 {
2109 CheckSelection();
2110
2111 if(maUserSelectionChangeCallback.IsSet())
2112 {
2113 maUserSelectionChangeCallback.Call(this);
2114 }
2115 }
2116
LightCtl3D(LightControl3D & rLightControl,weld::Scale & rHori,weld::Scale & rVert,weld::Button & rSwitcher)2117 LightCtl3D::LightCtl3D(LightControl3D& rLightControl, weld::Scale& rHori,
2118 weld::Scale& rVert, weld::Button& rSwitcher)
2119 : mrLightControl(rLightControl)
2120 , mrHorScroller(rHori)
2121 , mrVerScroller(rVert)
2122 , mrSwitcher(rSwitcher)
2123 {
2124 // init members
2125 Init();
2126 }
2127
Init()2128 void LightCtl3D::Init()
2129 {
2130 Size aSize(mrLightControl.GetDrawingArea()->get_ref_device().LogicToPixel(Size(80, 100), MapMode(MapUnit::MapAppFont)));
2131 mrLightControl.set_size_request(aSize.Width(), aSize.Height());
2132
2133 // #i58240# set HelpIDs for scrollbars and switcher
2134 mrHorScroller.set_help_id(HID_CTRL3D_HSCROLL);
2135 mrVerScroller.set_help_id(HID_CTRL3D_VSCROLL);
2136 mrSwitcher.set_help_id(HID_CTRL3D_SWITCHER);
2137 mrSwitcher.set_accessible_name(SvxResId(STR_SWITCH));
2138
2139 // Light preview
2140 mrLightControl.Show();
2141 mrLightControl.SetChangeCallback( LINK(this, LightCtl3D, InternalInteractiveChange) );
2142 mrLightControl.SetSelectionChangeCallback( LINK(this, LightCtl3D, InternalSelectionChange) );
2143
2144 // Horiz Scrollbar
2145 mrHorScroller.show();
2146 mrHorScroller.set_range(0, 36000);
2147 mrHorScroller.connect_value_changed( LINK(this, LightCtl3D, ScrollBarMove) );
2148
2149 // Vert Scrollbar
2150 mrVerScroller.show();
2151 mrVerScroller.set_range(0, 18000);
2152 mrVerScroller.connect_value_changed( LINK(this, LightCtl3D, ScrollBarMove) );
2153
2154 // Switch Button
2155 mrSwitcher.show();
2156 mrSwitcher.connect_clicked( LINK(this, LightCtl3D, ButtonPress) );
2157
2158 weld::DrawingArea* pArea = mrLightControl.GetDrawingArea();
2159 pArea->connect_key_press(Link<const KeyEvent&, bool>()); //acknowledge we first remove the old one
2160 pArea->connect_key_press(LINK(this, LightCtl3D, KeyInput));
2161
2162 pArea->connect_focus_in(Link<weld::Widget&, void>()); //acknowledge we first remove the old one
2163 pArea->connect_focus_in(LINK(this, LightCtl3D, FocusIn));
2164
2165 // check selection
2166 CheckSelection();
2167 }
2168
~LightCtl3D()2169 LightCtl3D::~LightCtl3D()
2170 {
2171 }
2172
CheckSelection()2173 void LightCtl3D::CheckSelection()
2174 {
2175 const bool bSelectionValid(mrLightControl.IsSelectionValid() || mrLightControl.IsGeometrySelected());
2176 mrHorScroller.set_sensitive(bSelectionValid);
2177 mrVerScroller.set_sensitive(bSelectionValid);
2178
2179 if (bSelectionValid)
2180 {
2181 double fHor(0.0), fVer(0.0);
2182 mrLightControl.GetPosition(fHor, fVer);
2183 mrHorScroller.set_value( sal_Int32(fHor * 100.0) );
2184 mrVerScroller.set_value( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2185 }
2186 }
2187
move(double fDeltaHor,double fDeltaVer)2188 void LightCtl3D::move( double fDeltaHor, double fDeltaVer )
2189 {
2190 double fHor(0.0), fVer(0.0);
2191
2192 mrLightControl.GetPosition(fHor, fVer);
2193 fHor += fDeltaHor;
2194 fVer += fDeltaVer;
2195
2196 if( fVer > 90.0 )
2197 return;
2198
2199 if ( fVer < -90.0 )
2200 return;
2201
2202 mrLightControl.SetPosition(fHor, fVer);
2203 mrHorScroller.set_value( sal_Int32(fHor * 100.0) );
2204 mrVerScroller.set_value( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2205
2206 if(maUserInteractiveChangeCallback.IsSet())
2207 {
2208 maUserInteractiveChangeCallback.Call(this);
2209 }
2210 }
2211
IMPL_LINK(LightCtl3D,KeyInput,const KeyEvent &,rKEvt,bool)2212 IMPL_LINK(LightCtl3D, KeyInput, const KeyEvent&, rKEvt, bool)
2213 {
2214 const vcl::KeyCode aCode(rKEvt.GetKeyCode());
2215
2216 if (aCode.GetModifier())
2217 return false;
2218
2219 bool bHandled = true;
2220
2221 switch ( aCode.GetCode() )
2222 {
2223 case KEY_SPACE:
2224 {
2225 break;
2226 }
2227 case KEY_LEFT:
2228 {
2229 move( -4.0, 0.0 ); // #i58242# changed move direction in X
2230 break;
2231 }
2232 case KEY_RIGHT:
2233 {
2234 move( 4.0, 0.0 ); // #i58242# changed move direction in X
2235 break;
2236 }
2237 case KEY_UP:
2238 {
2239 move( 0.0, 4.0 );
2240 break;
2241 }
2242 case KEY_DOWN:
2243 {
2244 move( 0.0, -4.0 );
2245 break;
2246 }
2247 case KEY_PAGEUP:
2248 {
2249 sal_Int32 nLight(mrLightControl.GetSelectedLight() - 1);
2250
2251 while((nLight >= 0) && !mrLightControl.GetLightOnOff(nLight))
2252 {
2253 nLight--;
2254 }
2255
2256 if(nLight < 0)
2257 {
2258 nLight = 7;
2259
2260 while((nLight >= 0) && !mrLightControl.GetLightOnOff(nLight))
2261 {
2262 nLight--;
2263 }
2264 }
2265
2266 if(nLight >= 0)
2267 {
2268 mrLightControl.SelectLight(nLight);
2269 CheckSelection();
2270
2271 if(maUserSelectionChangeCallback.IsSet())
2272 {
2273 maUserSelectionChangeCallback.Call(this);
2274 }
2275 }
2276
2277 break;
2278 }
2279 case KEY_PAGEDOWN:
2280 {
2281 sal_Int32 nLight(mrLightControl.GetSelectedLight() - 1);
2282
2283 while(nLight <= 7 && !mrLightControl.GetLightOnOff(nLight))
2284 {
2285 nLight++;
2286 }
2287
2288 if(nLight > 7)
2289 {
2290 nLight = 0;
2291
2292 while(nLight <= 7 && !mrLightControl.GetLightOnOff(nLight))
2293 {
2294 nLight++;
2295 }
2296 }
2297
2298 if(nLight <= 7)
2299 {
2300 mrLightControl.SelectLight(nLight);
2301 CheckSelection();
2302
2303 if(maUserSelectionChangeCallback.IsSet())
2304 {
2305 maUserSelectionChangeCallback.Call(this);
2306 }
2307 }
2308
2309 break;
2310 }
2311 default:
2312 {
2313 bHandled = false;
2314 break;
2315 }
2316 }
2317 return bHandled;
2318 }
2319
IMPL_LINK_NOARG(LightCtl3D,FocusIn,weld::Widget &,void)2320 IMPL_LINK_NOARG(LightCtl3D, FocusIn, weld::Widget&, void)
2321 {
2322 if (mrLightControl.IsEnabled())
2323 {
2324 CheckSelection();
2325 }
2326 }
2327
IMPL_LINK_NOARG(LightCtl3D,ScrollBarMove,weld::Scale &,void)2328 IMPL_LINK_NOARG(LightCtl3D, ScrollBarMove, weld::Scale&, void)
2329 {
2330 const sal_Int32 nHor(mrHorScroller.get_value());
2331 const sal_Int32 nVer(mrVerScroller.get_value());
2332
2333 mrLightControl.SetPosition(
2334 static_cast<double>(nHor) / 100.0,
2335 static_cast<double>((18000 - nVer) - 9000) / 100.0);
2336
2337 if (maUserInteractiveChangeCallback.IsSet())
2338 {
2339 maUserInteractiveChangeCallback.Call(this);
2340 }
2341 }
2342
IMPL_LINK_NOARG(LightCtl3D,ButtonPress,weld::Button &,void)2343 IMPL_LINK_NOARG(LightCtl3D, ButtonPress, weld::Button&, void)
2344 {
2345 if(SvxPreviewObjectType::SPHERE == GetSvx3DLightControl().GetObjectType())
2346 {
2347 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::CUBE);
2348 }
2349 else
2350 {
2351 GetSvx3DLightControl().SetObjectType(SvxPreviewObjectType::SPHERE);
2352 }
2353 }
2354
IMPL_LINK_NOARG(LightCtl3D,InternalInteractiveChange,LightControl3D *,void)2355 IMPL_LINK_NOARG(LightCtl3D, InternalInteractiveChange, LightControl3D*, void)
2356 {
2357 double fHor(0.0), fVer(0.0);
2358
2359 mrLightControl.GetPosition(fHor, fVer);
2360 mrHorScroller.set_value( sal_Int32(fHor * 100.0) );
2361 mrVerScroller.set_value( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
2362
2363 if(maUserInteractiveChangeCallback.IsSet())
2364 {
2365 maUserInteractiveChangeCallback.Call(this);
2366 }
2367 }
2368
IMPL_LINK_NOARG(LightCtl3D,InternalSelectionChange,LightControl3D *,void)2369 IMPL_LINK_NOARG(LightCtl3D, InternalSelectionChange, LightControl3D*, void)
2370 {
2371 CheckSelection();
2372
2373 if(maUserSelectionChangeCallback.IsSet())
2374 {
2375 maUserSelectionChangeCallback.Call(this);
2376 }
2377 }
2378
2379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2380