blob: 44bf6bc8e79c5cd6d732b2583af77b644ffad958 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <svx/dlgctl3d.hxx>
#include <svx/dialogs.hrc>
#include <svx/view3d.hxx>
#include <svx/fmmodel.hxx>
#include <svl/itempool.hxx>
#include <svx/fmpage.hxx>
#include <svx/polysc3d.hxx>
#include <svx/sphere3d.hxx>
#include <svx/cube3d.hxx>
#include <vcl/svapp.hxx>
#include <svx/helperhittest3d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <svx/polygn3d.hxx>
#include <svx/xlnclit.hxx>
#include <svx/xlnwtit.hxx>
#include "helpid.hrc"
#include <algorithm>
#include <svx/dialmgr.hxx>
//////////////////////////////////////////////////////////////////////////////
Svx3DPreviewControl::Svx3DPreviewControl(Window* pParent, const ResId& rResId)
: Control(pParent, rResId),
mpModel(0),
mpFmPage(0),
mp3DView(0),
mpScene(0),
mp3DObj(0),
mnObjectType(PREVIEW_OBJECTTYPE_SPHERE)
{
Construct();
// do not paint background self, DrawingLayer paints this buffered and as page
SetControlBackground();
SetBackground();
}
Svx3DPreviewControl::Svx3DPreviewControl(Window* pParent, WinBits nStyle)
: Control(pParent, nStyle),
mpModel(0),
mpFmPage(0),
mp3DView(0),
mpScene(0),
mp3DObj(0),
mnObjectType(PREVIEW_OBJECTTYPE_SPHERE)
{
Construct();
// do not paint background self, DrawingLayer paints this buffered and as page
SetControlBackground();
SetBackground();
}
Svx3DPreviewControl::~Svx3DPreviewControl()
{
delete mp3DView;
delete mpModel;
}
void Svx3DPreviewControl::Construct()
{
// Do never mirror the preview window. This explicitly includes right
// to left writing environments.
EnableRTL (sal_False);
SetMapMode( MAP_100TH_MM );
// Model
mpModel = new FmFormModel();
mpModel->GetItemPool().FreezeIdRanges();
// Page
mpFmPage = new FmFormPage( *mpModel, NULL );
mpModel->InsertPage( mpFmPage, 0 );
// 3D View
mp3DView = new E3dView( mpModel, this );
mp3DView->SetBufferedOutputAllowed(true);
mp3DView->SetBufferedOverlayAllowed(true);
// 3D Scene
mpScene = new E3dPolyScene(mp3DView->Get3DDefaultAttributes());
// initially create object
SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
// camera and perspective
Camera3D& rCamera = (Camera3D&) mpScene->GetCamera();
const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
double fW = rVolume.getWidth();
double fH = rVolume.getHeight();
double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
rCamera.SetAutoAdjustProjection(sal_False);
rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
basegfx::B3DPoint aLookAt;
double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
rCamera.SetPosAndLookAt(aCamPos, aLookAt);
double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
rCamera.SetFocalLength(fDefaultCamFocal);
rCamera.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, fDefaultCamFocal);
mpScene->SetCamera( rCamera );
mpFmPage->InsertObject( mpScene );
basegfx::B3DHomMatrix aRotation;
aRotation.rotate(DEG2RAD( 25 ), 0.0, 0.0);
aRotation.rotate(0.0, DEG2RAD( 40 ), 0.0);
mpScene->SetTransform(aRotation * mpScene->GetTransform());
// invalidate SnapRects of objects
mpScene->SetRectsDirty();
SfxItemSet aSet( mpModel->GetItemPool(),
XATTR_LINESTYLE, XATTR_LINESTYLE,
XATTR_FILL_FIRST, XATTR_FILLBITMAP,
0, 0 );
aSet.Put( XLineStyleItem( XLINE_NONE ) );
aSet.Put( XFillStyleItem( XFILL_SOLID ) );
aSet.Put( XFillColorItem( String(), Color( COL_WHITE ) ) );
mpScene->SetMergedItemSet(aSet);
// PageView
SdrPageView* pPageView = mp3DView->ShowSdrPage( mpFmPage );
mp3DView->hideMarkHandles();
// mark scene
mp3DView->MarkObj( mpScene, pPageView );
}
void Svx3DPreviewControl::Resize()
{
// size of page
Size aSize( GetSizePixel() );
aSize = PixelToLogic( aSize );
mpFmPage->SetSize( aSize );
// set size
Size aObjSize( aSize.Width()*5/6, aSize.Height()*5/6 );
Point aObjPoint( (aSize.Width() - aObjSize.Width()) / 2,
(aSize.Height() - aObjSize.Height()) / 2);
Rectangle aRect( aObjPoint, aObjSize);
mpScene->SetSnapRect( aRect );
}
void Svx3DPreviewControl::Paint(const Rectangle& rRect)
{
mp3DView->CompleteRedraw(this, Region(rRect));
}
void Svx3DPreviewControl::MouseButtonDown(const MouseEvent& rMEvt)
{
Control::MouseButtonDown(rMEvt);
if( rMEvt.IsShift() && rMEvt.IsMod1() )
{
if(PREVIEW_OBJECTTYPE_SPHERE == GetObjectType())
{
SetObjectType(PREVIEW_OBJECTTYPE_CUBE);
}
else
{
SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
}
}
}
void Svx3DPreviewControl::SetObjectType(sal_uInt16 nType)
{
if( mnObjectType != nType || !mp3DObj)
{
SfxItemSet aSet(mpModel->GetItemPool(), SDRATTR_START, SDRATTR_END, 0, 0);
mnObjectType = nType;
if( mp3DObj )
{
aSet.Put(mp3DObj->GetMergedItemSet());
mpScene->Remove3DObj( mp3DObj );
delete mp3DObj;
mp3DObj = NULL;
}
switch( nType )
{
case PREVIEW_OBJECTTYPE_SPHERE:
{
mp3DObj = new E3dSphereObj(
mp3DView->Get3DDefaultAttributes(),
basegfx::B3DPoint( 0, 0, 0 ),
basegfx::B3DVector( 5000, 5000, 5000 ));
}
break;
case PREVIEW_OBJECTTYPE_CUBE:
{
mp3DObj = new E3dCubeObj(
mp3DView->Get3DDefaultAttributes(),
basegfx::B3DPoint( -2500, -2500, -2500 ),
basegfx::B3DVector( 5000, 5000, 5000 ));
}
break;
}
mpScene->Insert3DObj( mp3DObj );
mp3DObj->SetMergedItemSet(aSet);
Resize();
}
}
SfxItemSet Svx3DPreviewControl::Get3DAttributes() const
{
return mp3DObj->GetMergedItemSet();
}
void Svx3DPreviewControl::Set3DAttributes( const SfxItemSet& rAttr )
{
mp3DObj->SetMergedItemSet(rAttr, true);
Resize();
}
//////////////////////////////////////////////////////////////////////////////
#define RADIUS_LAMP_PREVIEW_SIZE (4500.0)
#define RADIUS_LAMP_SMALL (600.0)
#define RADIUS_LAMP_BIG (1000.0)
#define NO_LIGHT_SELECTED (0xffffffff)
#define MAX_NUMBER_LIGHTS (8)
Svx3DLightControl::Svx3DLightControl(Window* pParent, const ResId& rResId)
: Svx3DPreviewControl(pParent, rResId),
maUserInteractiveChangeCallback(),
maUserSelectionChangeCallback(),
maChangeCallback(),
maSelectionChangeCallback(),
maSelectedLight(NO_LIGHT_SELECTED),
mpExpansionObject(0),
mpLampBottomObject(0),
mpLampShaftObject(0),
maLightObjects(MAX_NUMBER_LIGHTS, (E3dObject*)0),
mfRotateX(-20.0),
mfRotateY(45.0),
mfRotateZ(0.0),
maActionStartPoint(),
mnInteractionStartDistance(5 * 5 * 2),
mfSaveActionStartHor(0.0),
mfSaveActionStartVer(0.0),
mfSaveActionStartRotZ(0.0),
mbMouseMoved(false),
mbGeometrySelected(false)
{
Construct2();
}
Svx3DLightControl::Svx3DLightControl(Window* pParent, WinBits nStyle)
: Svx3DPreviewControl(pParent, nStyle),
maUserInteractiveChangeCallback(),
maUserSelectionChangeCallback(),
maChangeCallback(),
maSelectionChangeCallback(),
maSelectedLight(NO_LIGHT_SELECTED),
mpExpansionObject(0),
mpLampBottomObject(0),
mpLampShaftObject(0),
maLightObjects(MAX_NUMBER_LIGHTS, (E3dObject*)0),
mfRotateX(-20.0),
mfRotateY(45.0),
mfRotateZ(0.0),
maActionStartPoint(),
mnInteractionStartDistance(5 * 5 * 2),
mfSaveActionStartHor(0.0),
mfSaveActionStartVer(0.0),
mfSaveActionStartRotZ(0.0),
mbMouseMoved(false),
mbGeometrySelected(false)
{
Construct2();
}
Svx3DLightControl::~Svx3DLightControl()
{
// SdrObjects like mpExpansionObject and mpLampBottomObject/mpLampShaftObject get deleted
// with deletion of the DrawingLayer and model
}
void Svx3DLightControl::Construct2()
{
{
// hide all page stuff, use control background (normally gray)
const Color aDialogColor(Application::GetSettings().GetStyleSettings().GetDialogColor());
mp3DView->SetPageVisible(false);
mp3DView->SetApplicationBackgroundColor(aDialogColor);
mp3DView->SetApplicationDocumentColor(aDialogColor);
}
{
// create invisible expansion object
const double fMaxExpansion(RADIUS_LAMP_BIG + RADIUS_LAMP_PREVIEW_SIZE);
mpExpansionObject = new E3dCubeObj(
mp3DView->Get3DDefaultAttributes(),
basegfx::B3DPoint(-fMaxExpansion, -fMaxExpansion, -fMaxExpansion),
basegfx::B3DVector(2.0 * fMaxExpansion, 2.0 * fMaxExpansion, 2.0 * fMaxExpansion));
mpScene->Insert3DObj( mpExpansionObject );
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put( XLineStyleItem( XLINE_NONE ) );
aSet.Put( XFillStyleItem( XFILL_NONE ) );
mpExpansionObject->SetMergedItemSet(aSet);
}
{
// create lamp control object (Yellow lined object)
// base circle
const basegfx::B2DPolygon a2DCircle(basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE));
basegfx::B3DPolygon a3DCircle(basegfx::tools::createB3DPolygonFromB2DPolygon(a2DCircle));
basegfx::B3DHomMatrix aTransform;
aTransform.rotate(F_PI2, 0.0, 0.0);
aTransform.translate(0.0, -RADIUS_LAMP_PREVIEW_SIZE, 0.0);
a3DCircle.transform(aTransform);
// create object for it
mpLampBottomObject = new E3dPolygonObj(
mp3DView->Get3DDefaultAttributes(),
basegfx::B3DPolyPolygon(a3DCircle),
true);
mpScene->Insert3DObj( mpLampBottomObject );
// half circle with stand
basegfx::B2DPolygon a2DHalfCircle;
a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, 0.0));
a2DHalfCircle.append(basegfx::B2DPoint(RADIUS_LAMP_PREVIEW_SIZE, -RADIUS_LAMP_PREVIEW_SIZE));
a2DHalfCircle.append(basegfx::tools::createPolygonFromEllipseSegment(
basegfx::B2DPoint(0.0, 0.0), RADIUS_LAMP_PREVIEW_SIZE, RADIUS_LAMP_PREVIEW_SIZE, F_2PI - F_PI2, F_PI2));
basegfx::B3DPolygon a3DHalfCircle(basegfx::tools::createB3DPolygonFromB2DPolygon(a2DHalfCircle));
// create object for it
mpLampShaftObject = new E3dPolygonObj(
mp3DView->Get3DDefaultAttributes(),
basegfx::B3DPolyPolygon(a3DHalfCircle),
true);
mpScene->Insert3DObj( mpLampShaftObject );
// initially invisible
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put( XLineStyleItem( XLINE_NONE ) );
aSet.Put( XFillStyleItem( XFILL_NONE ) );
mpLampBottomObject->SetMergedItemSet(aSet);
mpLampShaftObject->SetMergedItemSet(aSet);
}
{
// change camera settings
Camera3D& rCamera = (Camera3D&) mpScene->GetCamera();
const basegfx::B3DRange& rVolume = mpScene->GetBoundVolume();
double fW = rVolume.getWidth();
double fH = rVolume.getHeight();
double fCamZ = rVolume.getMaxZ() + ((fW + fH) / 2.0);
rCamera.SetAutoAdjustProjection(sal_False);
rCamera.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
basegfx::B3DPoint aLookAt;
double fDefaultCamPosZ = mp3DView->GetDefaultCamPosZ();
basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
rCamera.SetPosAndLookAt(aCamPos, aLookAt);
double fDefaultCamFocal = mp3DView->GetDefaultCamFocal();
rCamera.SetFocalLength(fDefaultCamFocal);
rCamera.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, fDefaultCamFocal);
mpScene->SetCamera( rCamera );
basegfx::B3DHomMatrix aNeutral;
mpScene->SetTransform(aNeutral);
}
// invalidate SnapRects of objects
mpScene->SetRectsDirty();
}
void Svx3DLightControl::ConstructLightObjects()
{
for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
{
// get rid of evtl. existing light object
if(maLightObjects[a])
{
mpScene->Remove3DObj(maLightObjects[a]);
delete maLightObjects[a];
maLightObjects[a] = 0;
}
if(GetLightOnOff(a))
{
const bool bIsSelectedLight(a == maSelectedLight);
basegfx::B3DVector aDirection(GetLightDirection(a));
aDirection.normalize();
aDirection *= RADIUS_LAMP_PREVIEW_SIZE;
const double fLampSize(bIsSelectedLight ? RADIUS_LAMP_BIG : RADIUS_LAMP_SMALL);
E3dObject* pNewLight = new E3dSphereObj(
mp3DView->Get3DDefaultAttributes(),
basegfx::B3DPoint( 0, 0, 0 ),
basegfx::B3DVector( fLampSize, fLampSize, fLampSize));
mpScene->Insert3DObj(pNewLight);
basegfx::B3DHomMatrix aTransform;
aTransform.translate(aDirection.getX(), aDirection.getY(), aDirection.getZ());
pNewLight->SetTransform(aTransform);
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put( XLineStyleItem( XLINE_NONE ) );
aSet.Put( XFillStyleItem( XFILL_SOLID ) );
aSet.Put( XFillColorItem(String(), GetLightColor(a)));
pNewLight->SetMergedItemSet(aSet);
maLightObjects[a] = pNewLight;
}
}
}
void Svx3DLightControl::AdaptToSelectedLight()
{
if(NO_LIGHT_SELECTED == maSelectedLight)
{
// make mpLampBottomObject/mpLampShaftObject invisible
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put( XLineStyleItem( XLINE_NONE ) );
aSet.Put( XFillStyleItem( XFILL_NONE ) );
mpLampBottomObject->SetMergedItemSet(aSet);
mpLampShaftObject->SetMergedItemSet(aSet);
}
else
{
basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
aDirection.normalize();
// make mpLampBottomObject/mpLampShaftObject visible (yellow hairline)
SfxItemSet aSet(mpModel->GetItemPool());
aSet.Put( XLineStyleItem( XLINE_SOLID ) );
aSet.Put( XLineColorItem(String(), COL_YELLOW));
aSet.Put( XLineWidthItem(0));
aSet.Put( XFillStyleItem( XFILL_NONE ) );
mpLampBottomObject->SetMergedItemSet(aSet);
mpLampShaftObject->SetMergedItemSet(aSet);
// adapt transformation of mpLampShaftObject
basegfx::B3DHomMatrix aTransform;
double fRotateY(0.0);
if(!basegfx::fTools::equalZero(aDirection.getZ()) || !basegfx::fTools::equalZero(aDirection.getX()))
{
fRotateY = atan2(-aDirection.getZ(), aDirection.getX());
}
aTransform.rotate(0.0, fRotateY, 0.0);
mpLampShaftObject->SetTransform(aTransform);
// adapt transformation of selected light
E3dObject* pSelectedLight = maLightObjects[sal_Int32(maSelectedLight)];
if(pSelectedLight)
{
aTransform.identity();
aTransform.translate(
aDirection.getX() * RADIUS_LAMP_PREVIEW_SIZE,
aDirection.getY() * RADIUS_LAMP_PREVIEW_SIZE,
aDirection.getZ() * RADIUS_LAMP_PREVIEW_SIZE);
pSelectedLight->SetTransform(aTransform);
}
}
}
void Svx3DLightControl::TrySelection(Point aPosPixel)
{
if(mpScene)
{
const Point aPosLogic(PixelToLogic(aPosPixel));
const basegfx::B2DPoint aPoint(aPosLogic.X(), aPosLogic.Y());
std::vector< const E3dCompoundObject* > aResult;
getAllHit3DObjectsSortedFrontToBack(aPoint, *mpScene, aResult);
if(!aResult.empty())
{
// exclude expansion object which will be part of
// the hits. It's invisible, but for HitTest, it's included
const E3dCompoundObject* pResult = 0;
for(sal_uInt32 b(0); !pResult && b < aResult.size(); b++)
{
if(aResult[b] && aResult[b] != mpExpansionObject)
{
pResult = aResult[b];
}
}
if(pResult == mp3DObj)
{
if(!mbGeometrySelected)
{
mbGeometrySelected = true;
maSelectedLight = NO_LIGHT_SELECTED;
ConstructLightObjects();
AdaptToSelectedLight();
Invalidate();
if(maSelectionChangeCallback.IsSet())
{
maSelectionChangeCallback.Call(this);
}
}
}
else
{
sal_uInt32 aNewSelectedLight(NO_LIGHT_SELECTED);
for(sal_uInt32 a(0); a < MAX_NUMBER_LIGHTS; a++)
{
if(maLightObjects[a] && maLightObjects[a] == pResult)
{
aNewSelectedLight = a;
}
}
if(aNewSelectedLight != maSelectedLight)
{
SelectLight(aNewSelectedLight);
if(maSelectionChangeCallback.IsSet())
{
maSelectionChangeCallback.Call(this);
}
}
}
}
}
}
void Svx3DLightControl::Paint(const Rectangle& rRect)
{
Svx3DPreviewControl::Paint(rRect);
}
void Svx3DLightControl::MouseButtonDown( const MouseEvent& rMEvt )
{
bool bCallParent(true);
// switch state
if(rMEvt.IsLeft())
{
if(IsSelectionValid() || mbGeometrySelected)
{
mbMouseMoved = false;
bCallParent = false;
maActionStartPoint = rMEvt.GetPosPixel();
StartTracking();
}
else
{
// Einfacher Click ohne viel Bewegen, versuche eine
// Selektion
TrySelection(rMEvt.GetPosPixel());
bCallParent = false;
}
}
// call parent
if(bCallParent)
{
Svx3DPreviewControl::MouseButtonDown(rMEvt);
}
}
void Svx3DLightControl::Tracking( const TrackingEvent& rTEvt )
{
if(rTEvt.IsTrackingEnded())
{
if(rTEvt.IsTrackingCanceled())
{
if(mbMouseMoved)
{
// interrupt tracking
mbMouseMoved = false;
if(mbGeometrySelected)
{
SetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
}
else
{
SetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
}
if(maChangeCallback.IsSet())
{
maChangeCallback.Call(this);
}
}
}
else
{
const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
if(mbMouseMoved)
{
// was change dinteractively
}
else
{
// simple click without much movement, try selection
TrySelection(rMEvt.GetPosPixel());
}
}
}
else
{
const MouseEvent& rMEvt = rTEvt.GetMouseEvent();
Point aDeltaPos = rMEvt.GetPosPixel() - maActionStartPoint;
if(!mbMouseMoved)
{
if(sal_Int32(aDeltaPos.X() * aDeltaPos.X() + aDeltaPos.Y() * aDeltaPos.Y()) > mnInteractionStartDistance)
{
if(mbGeometrySelected)
{
GetRotation(mfSaveActionStartVer, mfSaveActionStartHor, mfSaveActionStartRotZ);
}
else
{
// intercation start, save values
GetPosition(mfSaveActionStartHor, mfSaveActionStartVer);
}
mbMouseMoved = true;
}
}
if(mbMouseMoved)
{
if(mbGeometrySelected)
{
double fNewRotX = mfSaveActionStartVer - ((double)aDeltaPos.Y() * F_PI180);
double fNewRotY = mfSaveActionStartHor + ((double)aDeltaPos.X() * F_PI180);
// cut horizontal
while(fNewRotY < 0.0)
{
fNewRotY += F_2PI;
}
while(fNewRotY >= F_2PI)
{
fNewRotY -= F_2PI;
}
// cut vertical
if(fNewRotX < -F_PI2)
{
fNewRotX = -F_PI2;
}
if(fNewRotX > F_PI2)
{
fNewRotX = F_PI2;
}
SetRotation(fNewRotX, fNewRotY, mfSaveActionStartRotZ);
if(maChangeCallback.IsSet())
{
maChangeCallback.Call(this);
}
}
else
{
// interaction in progress
double fNewPosHor = mfSaveActionStartHor + ((double)aDeltaPos.X());
double fNewPosVer = mfSaveActionStartVer - ((double)aDeltaPos.Y());
// cut horizontal
while(fNewPosHor < 0.0)
{
fNewPosHor += 360.0;
}
while(fNewPosHor >= 360.0)
{
fNewPosHor -= 360.0;
}
// cut vertical
if(fNewPosVer < -90.0)
{
fNewPosVer = -90.0;
}
if(fNewPosVer > 90.0)
{
fNewPosVer = 90.0;
}
SetPosition(fNewPosHor, fNewPosVer);
if(maChangeCallback.IsSet())
{
maChangeCallback.Call(this);
}
}
}
}
}
void Svx3DLightControl::Resize()
{
// set size of page
const Size aSize(PixelToLogic(GetSizePixel()));
mpFmPage->SetSize(aSize);
// set position and size of scene
mpScene->SetSnapRect(Rectangle(Point(0, 0), aSize));
}
void Svx3DLightControl::SetObjectType(sal_uInt16 nType)
{
// call parent
Svx3DPreviewControl::SetObjectType(nType);
// apply object rotation
if(mp3DObj)
{
basegfx::B3DHomMatrix aObjectRotation;
aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
mp3DObj->SetTransform(aObjectRotation);
}
}
bool Svx3DLightControl::IsSelectionValid()
{
if((NO_LIGHT_SELECTED != maSelectedLight) && (GetLightOnOff(maSelectedLight)))
{
return true;
}
return false;
}
void Svx3DLightControl::GetPosition(double& rHor, double& rVer)
{
if(IsSelectionValid())
{
basegfx::B3DVector aDirection(GetLightDirection(maSelectedLight));
aDirection.normalize();
rHor = atan2(-aDirection.getX(), -aDirection.getZ()) + F_PI; // 0..2PI
rVer = atan2(aDirection.getY(), aDirection.getXZLength()); // -PI2..PI2
rHor /= F_PI180; // 0..360.0
rVer /= F_PI180; // -90.0..90.0
}
if(IsGeometrySelected())
{
rHor = mfRotateY / F_PI180; // 0..360.0
rVer = mfRotateX / F_PI180; // -90.0..90.0
}
}
void Svx3DLightControl::SetPosition(double fHor, double fVer)
{
if(IsSelectionValid())
{
// set selected light's direction
fHor = (fHor * F_PI180) - F_PI; // -PI..PI
fVer *= F_PI180; // -PI2..PI2
basegfx::B3DVector aDirection(cos(fVer) * -sin(fHor), sin(fVer), cos(fVer) * -cos(fHor));
aDirection.normalize();
if(!aDirection.equal(GetLightDirection(maSelectedLight)))
{
// set changed light direction at SdrScene
SfxItemSet aSet(mpModel->GetItemPool());
switch(maSelectedLight)
{
case 0: aSet.Put(Svx3DLightDirection1Item(aDirection)); break;
case 1: aSet.Put(Svx3DLightDirection2Item(aDirection)); break;
case 2: aSet.Put(Svx3DLightDirection3Item(aDirection)); break;
case 3: aSet.Put(Svx3DLightDirection4Item(aDirection)); break;
case 4: aSet.Put(Svx3DLightDirection5Item(aDirection)); break;
case 5: aSet.Put(Svx3DLightDirection6Item(aDirection)); break;
case 6: aSet.Put(Svx3DLightDirection7Item(aDirection)); break;
default:
case 7: aSet.Put(Svx3DLightDirection8Item(aDirection)); break;
}
mpScene->SetMergedItemSet(aSet);
// correct 3D light's and LampFrame's geometries
AdaptToSelectedLight();
Invalidate();
}
}
if(IsGeometrySelected())
{
if(mfRotateX != fVer || mfRotateY != fHor)
{
mfRotateX = fVer * F_PI180;
mfRotateY = fHor * F_PI180;
if(mp3DObj)
{
basegfx::B3DHomMatrix aObjectRotation;
aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
mp3DObj->SetTransform(aObjectRotation);
Invalidate();
}
}
}
}
void Svx3DLightControl::SetRotation(double fRotX, double fRotY, double fRotZ)
{
if(IsGeometrySelected())
{
if(fRotX != mfRotateX || fRotY != mfRotateY || fRotZ != mfRotateZ)
{
mfRotateX = fRotX;
mfRotateY = fRotY;
mfRotateZ = fRotZ;
if(mp3DObj)
{
basegfx::B3DHomMatrix aObjectRotation;
aObjectRotation.rotate(mfRotateX, mfRotateY, mfRotateZ);
mp3DObj->SetTransform(aObjectRotation);
Invalidate();
}
}
}
}
void Svx3DLightControl::GetRotation(double& rRotX, double& rRotY, double& rRotZ)
{
rRotX = mfRotateX;
rRotY = mfRotateY;
rRotZ = mfRotateZ;
}
void Svx3DLightControl::Set3DAttributes( const SfxItemSet& rAttr )
{
// call parent
Svx3DPreviewControl::Set3DAttributes(rAttr);
if(maSelectedLight != NO_LIGHT_SELECTED && !GetLightOnOff(maSelectedLight))
{
// selected light is no more active, select new one
maSelectedLight = NO_LIGHT_SELECTED;
}
// local updates
ConstructLightObjects();
AdaptToSelectedLight();
Invalidate();
}
void Svx3DLightControl::SelectLight(sal_uInt32 nLightNumber)
{
if(nLightNumber > 7)
{
nLightNumber = NO_LIGHT_SELECTED;
}
if(NO_LIGHT_SELECTED != nLightNumber)
{
if(!GetLightOnOff(nLightNumber))
{
nLightNumber = NO_LIGHT_SELECTED;
}
}
if(nLightNumber != maSelectedLight)
{
maSelectedLight = nLightNumber;
mbGeometrySelected = false;
ConstructLightObjects();
AdaptToSelectedLight();
Invalidate();
}
}
bool Svx3DLightControl::GetLightOnOff(sal_uInt32 nNum) const
{
if(nNum <= 7)
{
const SfxItemSet aLightItemSet(Get3DAttributes());
switch(nNum)
{
case 0 : return ((const Svx3DLightOnOff1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_1)).GetValue();
case 1 : return ((const Svx3DLightOnOff2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_2)).GetValue();
case 2 : return ((const Svx3DLightOnOff3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_3)).GetValue();
case 3 : return ((const Svx3DLightOnOff4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_4)).GetValue();
case 4 : return ((const Svx3DLightOnOff5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_5)).GetValue();
case 5 : return ((const Svx3DLightOnOff6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_6)).GetValue();
case 6 : return ((const Svx3DLightOnOff7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_7)).GetValue();
case 7 : return ((const Svx3DLightOnOff8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTON_8)).GetValue();
}
}
return false;
}
Color Svx3DLightControl::GetLightColor(sal_uInt32 nNum) const
{
if(nNum <= 7)
{
const SfxItemSet aLightItemSet(Get3DAttributes());
switch(nNum)
{
case 0 : return ((const Svx3DLightcolor1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1)).GetValue();
case 1 : return ((const Svx3DLightcolor2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2)).GetValue();
case 2 : return ((const Svx3DLightcolor3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3)).GetValue();
case 3 : return ((const Svx3DLightcolor4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4)).GetValue();
case 4 : return ((const Svx3DLightcolor5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5)).GetValue();
case 5 : return ((const Svx3DLightcolor6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6)).GetValue();
case 6 : return ((const Svx3DLightcolor7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7)).GetValue();
case 7 : return ((const Svx3DLightcolor8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8)).GetValue();
}
}
return Color(COL_BLACK);
}
basegfx::B3DVector Svx3DLightControl::GetLightDirection(sal_uInt32 nNum) const
{
if(nNum <= 7)
{
const SfxItemSet aLightItemSet(Get3DAttributes());
switch(nNum)
{
case 0 : return ((const Svx3DLightDirection1Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1)).GetValue();
case 1 : return ((const Svx3DLightDirection2Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2)).GetValue();
case 2 : return ((const Svx3DLightDirection3Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3)).GetValue();
case 3 : return ((const Svx3DLightDirection4Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4)).GetValue();
case 4 : return ((const Svx3DLightDirection5Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5)).GetValue();
case 5 : return ((const Svx3DLightDirection6Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6)).GetValue();
case 6 : return ((const Svx3DLightDirection7Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7)).GetValue();
case 7 : return ((const Svx3DLightDirection8Item&)aLightItemSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8)).GetValue();
}
}
return basegfx::B3DVector();
}
//////////////////////////////////////////////////////////////////////////////
SvxLightCtl3D::SvxLightCtl3D( Window* pParent, const ResId& rResId)
: Control(pParent, rResId),
maLightControl(this, 0),
maHorScroller(this, WB_HORZ | WB_DRAG),
maVerScroller(this, WB_VERT | WB_DRAG),
maSwitcher(this, 0)
{
// init members
Init();
}
SvxLightCtl3D::SvxLightCtl3D( Window* pParent, WinBits nStyle )
: Control(pParent, nStyle),
maLightControl(this, 0),
maHorScroller(this, WB_HORZ | WB_DRAG),
maVerScroller(this, WB_VERT | WB_DRAG),
maSwitcher(this, 0)
{
// init members
Init();
}
void SvxLightCtl3D::Init()
{
// #i58240# set HelpIDs for scrollbars and switcher
maHorScroller.SetHelpId(HID_CTRL3D_HSCROLL);
maVerScroller.SetHelpId(HID_CTRL3D_VSCROLL);
maSwitcher.SetHelpId(HID_CTRL3D_SWITCHER);
maSwitcher.SetAccessibleName(String(SVX_RES(STR_SWITCH)));
// Light preview
maLightControl.Show();
maLightControl.SetChangeCallback( LINK(this, SvxLightCtl3D, InternalInteractiveChange) );
maLightControl.SetSelectionChangeCallback( LINK(this, SvxLightCtl3D, InternalSelectionChange) );
// Horiz Scrollbar
maHorScroller.Show();
maHorScroller.SetRange(Range(0, 36000));
maHorScroller.SetLineSize(100);
maHorScroller.SetPageSize(1000);
maHorScroller.SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
// Vert Scrollbar
maVerScroller.Show();
maVerScroller.SetRange(Range(0, 18000));
maVerScroller.SetLineSize(100);
maVerScroller.SetPageSize(1000);
maVerScroller.SetScrollHdl( LINK(this, SvxLightCtl3D, ScrollBarMove) );
// Switch Button
maSwitcher.Show();
maSwitcher.SetClickHdl( LINK(this, SvxLightCtl3D, ButtonPress) );
// check selection
CheckSelection();
// new layout
NewLayout();
}
SvxLightCtl3D::~SvxLightCtl3D()
{
}
void SvxLightCtl3D::Resize()
{
// call parent
Control::Resize();
// new layout
NewLayout();
}
void SvxLightCtl3D::NewLayout()
{
// Layout members
const Size aSize(GetOutputSizePixel());
const sal_Int32 nScrollSize(maHorScroller.GetSizePixel().Height());
// Preview control
Point aPoint(0, 0);
Size aDestSize(aSize.Width() - nScrollSize, aSize.Height() - nScrollSize);
maLightControl.SetPosSizePixel(aPoint, aDestSize);
// hor scrollbar
aPoint.Y() = aSize.Height() - nScrollSize;
aDestSize.Height() = nScrollSize;
maHorScroller.SetPosSizePixel(aPoint, aDestSize);
// vert scrollbar
aPoint.X() = aSize.Width() - nScrollSize;
aPoint.Y() = 0;
aDestSize.Width() = nScrollSize;
aDestSize.Height() = aSize.Height() - nScrollSize;
maVerScroller.SetPosSizePixel(aPoint, aDestSize);
// button
aPoint.Y() = aSize.Height() - nScrollSize;
aDestSize.Height() = nScrollSize;
maSwitcher.SetPosSizePixel(aPoint, aDestSize);
}
void SvxLightCtl3D::CheckSelection()
{
const bool bSelectionValid(maLightControl.IsSelectionValid() || maLightControl.IsGeometrySelected());
maHorScroller.Enable(bSelectionValid);
maVerScroller.Enable(bSelectionValid);
if(bSelectionValid)
{
double fHor, fVer;
maLightControl.GetPosition(fHor, fVer);
maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
}
}
void SvxLightCtl3D::move( double fDeltaHor, double fDeltaVer )
{
double fHor, fVer;
maLightControl.GetPosition(fHor, fVer);
fHor += fDeltaHor;
fVer += fDeltaVer;
if( fVer > 90.0 )
return;
if ( fVer < -90.0 )
return;
maLightControl.SetPosition(fHor, fVer);
maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
if(maUserInteractiveChangeCallback.IsSet())
{
maUserInteractiveChangeCallback.Call(this);
}
}
void SvxLightCtl3D::KeyInput( const KeyEvent& rKEvt )
{
const KeyCode aCode(rKEvt.GetKeyCode());
if( aCode.GetModifier() )
{
Control::KeyInput( rKEvt );
return;
}
switch ( aCode.GetCode() )
{
case KEY_SPACE:
{
break;
}
case KEY_LEFT:
{
move( -4.0, 0.0 ); // #i58242# changed move direction in X
break;
}
case KEY_RIGHT:
{
move( 4.0, 0.0 ); // #i58242# changed move direction in X
break;
}
case KEY_UP:
{
move( 0.0, 4.0 );
break;
}
case KEY_DOWN:
{
move( 0.0, -4.0 );
break;
}
case KEY_PAGEUP:
{
sal_Int32 nLight(maLightControl.GetSelectedLight() - 1);
while((nLight >= 0) && !maLightControl.GetLightOnOff(nLight))
{
nLight--;
}
if(nLight < 0)
{
nLight = 7;
while((nLight >= 0) && !maLightControl.GetLightOnOff(nLight))
{
nLight--;
}
}
if(nLight >= 0)
{
maLightControl.SelectLight(nLight);
CheckSelection();
if(maUserSelectionChangeCallback.IsSet())
{
maUserSelectionChangeCallback.Call(this);
}
}
break;
}
case KEY_PAGEDOWN:
{
sal_Int32 nLight(maLightControl.GetSelectedLight() - 1);
while(nLight <= 7 && !maLightControl.GetLightOnOff(nLight))
{
nLight++;
}
if(nLight > 7)
{
nLight = 0;
while(nLight <= 7 && !maLightControl.GetLightOnOff(nLight))
{
nLight++;
}
}
if(nLight <= 7)
{
maLightControl.SelectLight(nLight);
CheckSelection();
if(maUserSelectionChangeCallback.IsSet())
{
maUserSelectionChangeCallback.Call(this);
}
}
break;
}
default:
{
Control::KeyInput( rKEvt );
break;
}
}
}
void SvxLightCtl3D::GetFocus()
{
Control::GetFocus();
if(HasFocus() && IsEnabled())
{
CheckSelection();
Size aFocusSize = maLightControl.GetOutputSizePixel();
aFocusSize.Width() -= 4;
aFocusSize.Height() -= 4;
Rectangle aFocusRect( Point( 2, 2 ), aFocusSize );
aFocusRect = maLightControl.PixelToLogic( aFocusRect );
maLightControl.ShowFocus( aFocusRect );
}
}
void SvxLightCtl3D::LoseFocus()
{
Control::LoseFocus();
maLightControl.HideFocus();
}
IMPL_LINK( SvxLightCtl3D, ScrollBarMove, void*, EMPTYARG)
{
const sal_Int32 nHor(maHorScroller.GetThumbPos());
const sal_Int32 nVer(maVerScroller.GetThumbPos());
maLightControl.SetPosition(
((double)nHor) / 100.0,
((double)((18000 - nVer) - 9000)) / 100.0);
if(maUserInteractiveChangeCallback.IsSet())
{
maUserInteractiveChangeCallback.Call(this);
}
return 0;
}
IMPL_LINK( SvxLightCtl3D, ButtonPress, void*, EMPTYARG)
{
if(PREVIEW_OBJECTTYPE_SPHERE == GetSvx3DLightControl().GetObjectType())
{
GetSvx3DLightControl().SetObjectType(PREVIEW_OBJECTTYPE_CUBE);
}
else
{
GetSvx3DLightControl().SetObjectType(PREVIEW_OBJECTTYPE_SPHERE);
}
return 0;
}
IMPL_LINK( SvxLightCtl3D, InternalInteractiveChange, void*, EMPTYARG)
{
double fHor, fVer;
maLightControl.GetPosition(fHor, fVer);
maHorScroller.SetThumbPos( sal_Int32(fHor * 100.0) );
maVerScroller.SetThumbPos( 18000 - sal_Int32((fVer + 90.0) * 100.0) );
if(maUserInteractiveChangeCallback.IsSet())
{
maUserInteractiveChangeCallback.Call(this);
}
return 0;
}
IMPL_LINK( SvxLightCtl3D, InternalSelectionChange, void*, EMPTYARG)
{
CheckSelection();
if(maUserSelectionChangeCallback.IsSet())
{
maUserSelectionChangeCallback.Call(this);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
// eof