1345 lines
47 KiB
C++
1345 lines
47 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* 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 .
|
|
*/
|
|
|
|
|
|
#include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
|
|
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
|
|
#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
|
|
#include <com/sun/star/drawing/ShadeMode.hpp>
|
|
#include <com/sun/star/drawing/Position3D.hpp>
|
|
#include <com/sun/star/drawing/Direction3D.hpp>
|
|
#include <com/sun/star/drawing/ProjectionMode.hpp>
|
|
#include <svx/svxids.hrc>
|
|
#include <svx/svdundo.hxx>
|
|
#include <sfx2/request.hxx>
|
|
#include <sfx2/objface.hxx>
|
|
#include <sfx2/viewsh.hxx>
|
|
#include <sfx2/bindings.hxx>
|
|
#include <svx/xsflclit.hxx>
|
|
#include <svx/dialmgr.hxx>
|
|
#include <svx/svdoashp.hxx>
|
|
#include <svx/strings.hrc>
|
|
#include <svx/svdview.hxx>
|
|
#include <editeng/colritem.hxx>
|
|
#include <svx/chrtitem.hxx>
|
|
#include <svx/sdasitm.hxx>
|
|
#include <svl/intitem.hxx>
|
|
#include <rtl/math.hxx>
|
|
#include <basegfx/numeric/ftools.hxx>
|
|
|
|
#include <svx/extrusionbar.hxx>
|
|
#include <extrusiondepthdialog.hxx>
|
|
|
|
using namespace ::svx;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::drawing;
|
|
using namespace ::com::sun::star::uno;
|
|
|
|
// Declare the default interface. (The slotmap must not be empty, so
|
|
// we enter something which never occurs here (hopefully).)
|
|
static SfxSlot aExtrusionBarSlots_Impl[] =
|
|
{
|
|
{ 0, SfxGroupId::NONE, SfxSlotMode::NONE, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr, 0, SfxDisableFlags::NONE, u""_ustr }
|
|
};
|
|
|
|
SFX_IMPL_INTERFACE(ExtrusionBar, SfxShell)
|
|
|
|
void ExtrusionBar::InitInterface_Impl()
|
|
{
|
|
GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Svx_Extrusion_Bar);
|
|
}
|
|
|
|
|
|
ExtrusionBar::ExtrusionBar(SfxViewShell* pViewShell )
|
|
: SfxShell(pViewShell)
|
|
{
|
|
DBG_ASSERT( pViewShell, "svx::ExtrusionBar::ExtrusionBar(), I need a viewshell!" );
|
|
if( pViewShell )
|
|
SetPool(&pViewShell->GetPool());
|
|
|
|
SetName(SvxResId(RID_SVX_EXTRUSION_BAR));
|
|
}
|
|
|
|
ExtrusionBar::~ExtrusionBar()
|
|
{
|
|
SetRepeatTarget(nullptr);
|
|
}
|
|
|
|
static void getLightingDirectionDefaults( const Direction3D **pLighting1Defaults, const Direction3D **pLighting2Defaults )
|
|
{
|
|
|
|
static const Direction3D aLighting1Defaults[9] =
|
|
{
|
|
Direction3D( -50000, -50000, 10000 ),
|
|
Direction3D( 0, -50000, 10000 ),
|
|
Direction3D( 50000, -50000, 10000 ),
|
|
Direction3D( -50000, 0, 10000 ),
|
|
Direction3D( 0, 0, 10000 ),
|
|
Direction3D( 50000, 0, 10000 ),
|
|
Direction3D( -50000, 50000, 10000 ),
|
|
Direction3D( 0, 50000, 10000 ),
|
|
Direction3D( 50000, 50000, 10000 )
|
|
};
|
|
|
|
static const Direction3D aLighting2Defaults[9] =
|
|
{
|
|
Direction3D( 50000,0, 10000 ),
|
|
Direction3D( 0, 50000, 10000 ),
|
|
Direction3D( -50000, 0, 10000 ),
|
|
Direction3D( 50000, 0, 10000 ),
|
|
Direction3D( 0, 0, 10000 ),
|
|
Direction3D( -50000, 0, 10000 ),
|
|
Direction3D( 50000, 0, 10000 ),
|
|
Direction3D( 0, -50000, 10000 ),
|
|
Direction3D( -50000, 0, 10000 )
|
|
};
|
|
|
|
*pLighting1Defaults = aLighting1Defaults;
|
|
*pLighting2Defaults = aLighting2Defaults;
|
|
};
|
|
|
|
static void impl_execute( SfxRequest const & rReq, SdrCustomShapeGeometryItem& rGeometryItem, SdrObject* pObj )
|
|
{
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
static constexpr OUString sRotateAngle = u"RotateAngle"_ustr;
|
|
|
|
sal_uInt16 nSID = rReq.GetSlot();
|
|
switch( nSID )
|
|
{
|
|
case SID_EXTRUSION_TOGGLE:
|
|
{
|
|
bool bOn(false);
|
|
css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if ( pAny )
|
|
{
|
|
(*pAny) >>= bOn;
|
|
bOn = !bOn;
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = sExtrusion;
|
|
aPropValue.Value <<= bOn;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
}
|
|
else
|
|
{
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = sExtrusion;
|
|
aPropValue.Value <<= true;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
bOn = true;
|
|
}
|
|
|
|
// draw:extrusion-diffusion has default 0% and c3DDiffuseAmt has default 100%. We set property
|
|
// "Diffusion" with value 100% here if it does not exist already. This forces, that the
|
|
// property is written to file in case an extrusion is newly created, and users of old
|
|
// documents, which usually do not have this property, can force the value to 100% by toggling
|
|
// the extrusion off and on.
|
|
if (bOn)
|
|
{
|
|
pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"Diffusion"_ustr);
|
|
if (!pAny)
|
|
{
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = u"Diffusion"_ustr;
|
|
aPropValue.Value <<= 100.0;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_EXTRUSION_TILT_DOWN:
|
|
case SID_EXTRUSION_TILT_UP:
|
|
case SID_EXTRUSION_TILT_LEFT:
|
|
case SID_EXTRUSION_TILT_RIGHT:
|
|
{
|
|
bool bHorizontal = ( nSID == SID_EXTRUSION_TILT_DOWN ) || ( nSID == SID_EXTRUSION_TILT_UP );
|
|
sal_Int32 nDiff = ( nSID == SID_EXTRUSION_TILT_LEFT ) || ( nSID == SID_EXTRUSION_TILT_UP ) ? 5 : -5;
|
|
EnhancedCustomShapeParameterPair aRotateAnglePropPair;
|
|
double fX = 0.0;
|
|
double fY = 0.0;
|
|
aRotateAnglePropPair.First.Value <<= fX;
|
|
aRotateAnglePropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
aRotateAnglePropPair.Second.Value <<= fY;
|
|
aRotateAnglePropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sRotateAngle );
|
|
if( pAny && ( *pAny >>= aRotateAnglePropPair ) )
|
|
{
|
|
aRotateAnglePropPair.First.Value >>= fX;
|
|
aRotateAnglePropPair.Second.Value >>= fY;
|
|
}
|
|
if ( bHorizontal )
|
|
fX += nDiff;
|
|
else
|
|
fY += nDiff;
|
|
aRotateAnglePropPair.First.Value <<= fX;
|
|
aRotateAnglePropPair.Second.Value <<= fY;
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = sRotateAngle;
|
|
aPropValue.Value <<= aRotateAnglePropPair;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
}
|
|
break;
|
|
|
|
case SID_EXTRUSION_DIRECTION:
|
|
{
|
|
const SfxInt32Item* pExtrusionItem = nullptr;
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_DIRECTION, true, &pExtrusionItem ) == SfxItemState::SET )
|
|
{
|
|
sal_Int32 nSkew = pExtrusionItem->GetValue();
|
|
|
|
Position3D aViewPoint( 3472, -3472, 25000 );
|
|
double fOriginX = 0.50;
|
|
double fOriginY = -0.50;
|
|
double fSkewAngle = nSkew;
|
|
double fSkew = 50.0;
|
|
|
|
switch( nSkew )
|
|
{
|
|
case 135:
|
|
aViewPoint.PositionY = 3472;
|
|
fOriginY = 0.50;
|
|
break;
|
|
case 90:
|
|
aViewPoint.PositionX = 0;
|
|
aViewPoint.PositionY = 3472;
|
|
fOriginX = 0;
|
|
fOriginY = 0.50;
|
|
break;
|
|
case 45:
|
|
aViewPoint.PositionX = -3472;
|
|
aViewPoint.PositionY = 3472;
|
|
fOriginX = -0.50;
|
|
fOriginY = 0.50;
|
|
break;
|
|
case 180:
|
|
aViewPoint.PositionY = 0;
|
|
fOriginY = 0;
|
|
break;
|
|
case 0:
|
|
aViewPoint.PositionX = 0;
|
|
aViewPoint.PositionY = 0;
|
|
fOriginX = 0;
|
|
fOriginY = 0;
|
|
fSkew = 0.0;
|
|
break;
|
|
case -360:
|
|
aViewPoint.PositionX = -3472;
|
|
aViewPoint.PositionY = 0;
|
|
fOriginX = -0.50;
|
|
fOriginY = 0;
|
|
break;
|
|
case -90:
|
|
aViewPoint.PositionX = 0;
|
|
fOriginX = 0;
|
|
break;
|
|
case -45:
|
|
aViewPoint.PositionX = -3472;
|
|
fOriginX = -0.50;
|
|
break;
|
|
}
|
|
|
|
css::beans::PropertyValue aPropValue;
|
|
|
|
aPropValue.Name = "ViewPoint";
|
|
aPropValue.Value <<= aViewPoint;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
|
|
EnhancedCustomShapeParameterPair aOriginPropPair;
|
|
aOriginPropPair.First.Value <<= fOriginX;
|
|
aOriginPropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
aOriginPropPair.Second.Value <<= fOriginY;
|
|
aOriginPropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
aPropValue.Name = "Origin";
|
|
aPropValue.Value <<= aOriginPropPair;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
EnhancedCustomShapeParameterPair aSkewPropPair;
|
|
aSkewPropPair.First.Value <<= fSkew;
|
|
aSkewPropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
aSkewPropPair.Second.Value <<= fSkewAngle;
|
|
aSkewPropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
aPropValue.Name = "Skew";
|
|
aPropValue.Value <<= aSkewPropPair;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
}
|
|
}
|
|
break;
|
|
case SID_EXTRUSION_PROJECTION:
|
|
{
|
|
const SfxInt32Item* pExtrusionItem = nullptr;
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_PROJECTION, true, &pExtrusionItem ) == SfxItemState::SET )
|
|
{
|
|
sal_Int32 nProjection = pExtrusionItem->GetValue();
|
|
ProjectionMode eProjectionMode = nProjection == 1 ? ProjectionMode_PARALLEL : ProjectionMode_PERSPECTIVE;
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = "ProjectionMode";
|
|
aPropValue.Value <<= eProjectionMode;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
}
|
|
}
|
|
break;
|
|
case SID_EXTRUSION_DEPTH:
|
|
{
|
|
const SvxDoubleItem* pExtrusionItem = nullptr;
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_DEPTH, true, &pExtrusionItem ) == SfxItemState::SET)
|
|
{
|
|
double fDepth = pExtrusionItem->GetValue();
|
|
EnhancedCustomShapeParameterPair aDepthPropPair;
|
|
aDepthPropPair.First.Value <<= fDepth;
|
|
aDepthPropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
aDepthPropPair.Second.Value <<= 0.0; // fraction
|
|
aDepthPropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
|
|
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = "Depth";
|
|
aPropValue.Value <<= aDepthPropPair;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
}
|
|
}
|
|
break;
|
|
case SID_EXTRUSION_3D_COLOR:
|
|
{
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_3D_COLOR ) == SfxItemState::SET)
|
|
{
|
|
Color aColor( static_cast<const SvxColorItem&>(rReq.GetArgs()->Get(SID_EXTRUSION_3D_COLOR)).GetValue() );
|
|
|
|
const bool bAuto = aColor == COL_AUTO;
|
|
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = "Color";
|
|
aPropValue.Value <<= !bAuto;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
if( bAuto )
|
|
{
|
|
pObj->ClearMergedItem( XATTR_SECONDARYFILLCOLOR );
|
|
}
|
|
else
|
|
{
|
|
pObj->SetMergedItem( XSecondaryFillColorItem( u""_ustr, aColor ) );
|
|
}
|
|
pObj->BroadcastObjectChange();
|
|
}
|
|
}
|
|
break;
|
|
case SID_EXTRUSION_SURFACE:
|
|
{
|
|
const SfxInt32Item* pExtrusionItem = nullptr;
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_SURFACE, true, &pExtrusionItem ) == SfxItemState::SET)
|
|
{
|
|
sal_Int32 nSurface = pExtrusionItem->GetValue();
|
|
|
|
// Set ShadeMode only when changing from or to wireframe, otherwise keep existing value.
|
|
ShadeMode eOldShadeMode(ShadeMode_FLAT);
|
|
css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"ShadeMode"_ustr);
|
|
if (pAny)
|
|
*pAny >>= eOldShadeMode;
|
|
ShadeMode eShadeMode(eOldShadeMode);
|
|
switch (nSurface)
|
|
{
|
|
case 0: // wireframe
|
|
eShadeMode = ShadeMode_DRAFT;
|
|
break;
|
|
case 1: // matte
|
|
case 2: // plastic
|
|
case 3: // metal ODF
|
|
case 4: // metal MS Office
|
|
if (eOldShadeMode == ShadeMode_DRAFT)
|
|
eShadeMode = ShadeMode_FLAT; // ODF default
|
|
break;
|
|
}
|
|
|
|
// ODF has no dedicated property for 'surface'. MS Office binary format uses attribute
|
|
// c3DSpecularAmt to distinguish between 'matte' (=0) and 'plastic'.
|
|
// We do the same.
|
|
double fOldSpecularity = 0.0;
|
|
pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"Specularity"_ustr);
|
|
if (pAny)
|
|
*pAny >>= fOldSpecularity;
|
|
double fSpecularity = fOldSpecularity;
|
|
switch( nSurface )
|
|
{
|
|
case 0: // wireframe
|
|
break;
|
|
case 1: // matte
|
|
fSpecularity = 0.0;
|
|
break;
|
|
case 2: // plastic
|
|
case 3: // metal ODF
|
|
case 4: // metal MS Office
|
|
if (basegfx::fTools::equalZero(fOldSpecularity, 0.0001))
|
|
// MS Office uses 80000/65536. That is currently not allowed in ODF.
|
|
// But the ODF error will be caught in xmloff.
|
|
fSpecularity = 80000.0 / 655.36; // interpreted as %
|
|
break;
|
|
}
|
|
|
|
// MS Office binary format uses attribute c3DDiffuseAmt with value =43712 (Fixed 16.16) in
|
|
// addition to the 'metal' flag. For other surface kinds default = 65536 is used.
|
|
// We toggle between 100 and 43712.0 / 655.36 here, to get better ODF -> MSO binary.
|
|
// We keep other values, those might be set outside regular UI, e.g by macro.
|
|
double fOldDiffusion = 100.0;
|
|
pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"Diffusion"_ustr);
|
|
if (pAny)
|
|
*pAny >>= fOldDiffusion;
|
|
double fDiffusion = fOldDiffusion;
|
|
if (nSurface == 4)
|
|
{
|
|
if (fOldDiffusion == 100.0)
|
|
fDiffusion = 43712.0 / 655.36; // interpreted as %
|
|
}
|
|
else
|
|
{
|
|
if (basegfx::fTools::equalZero(fOldDiffusion - 43712.0 / 655.36, 0.0001))
|
|
fDiffusion = 100.0;
|
|
}
|
|
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = "ShadeMode";
|
|
aPropValue.Value <<= eShadeMode;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
aPropValue.Name = "Metal";
|
|
aPropValue.Value <<= nSurface == 3 || nSurface == 4;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
|
|
if (nSurface == 3 || nSurface == 4)
|
|
{
|
|
aPropValue.Name = "MetalType";
|
|
aPropValue.Value <<= nSurface == 4
|
|
? EnhancedCustomShapeMetalType::MetalMSCompatible
|
|
: EnhancedCustomShapeMetalType::MetalODF;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
}
|
|
|
|
if (!basegfx::fTools::equalZero(fOldSpecularity - fSpecularity, 0.0001))
|
|
{
|
|
aPropValue.Name = "Specularity";
|
|
aPropValue.Value <<= fSpecularity;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
}
|
|
|
|
if (!basegfx::fTools::equalZero(fOldDiffusion - fDiffusion, 0.0001))
|
|
{
|
|
aPropValue.Name = "Diffusion";
|
|
aPropValue.Value <<= fDiffusion;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SID_EXTRUSION_LIGHTING_INTENSITY:
|
|
{
|
|
const SfxInt32Item* pLightItem = nullptr;
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_LIGHTING_INTENSITY, true, &pLightItem ) == SfxItemState::SET)
|
|
{
|
|
sal_Int32 nLevel = pLightItem->GetValue();
|
|
|
|
double fBrightness; // c3DAmbientIntensity in MS Office
|
|
double fLevel1; // c3DKeyIntensity in MS Office
|
|
double fLevel2; // c3DFillIntensity in MS Office
|
|
|
|
// ToDo: "bright" values are different from MS Office. Should they be kept?
|
|
switch( nLevel )
|
|
{
|
|
case 0: // bright
|
|
fBrightness = 33.0; // ODF default.
|
|
fLevel1 = 66.0; // ODF default
|
|
fLevel2 = 66.0; // ODF default
|
|
break;
|
|
case 1: // normal
|
|
fBrightness = 15.0;
|
|
fLevel1 = 67.0;
|
|
fLevel2 = 37.0;
|
|
break;
|
|
case 2: // dim
|
|
fBrightness = 6.0;
|
|
fLevel1 = 79.0;
|
|
fLevel2 = 21.0;
|
|
break;
|
|
}
|
|
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = "Brightness";
|
|
aPropValue.Value <<= fBrightness;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
aPropValue.Name = "FirstLightLevel";
|
|
aPropValue.Value <<= fLevel1;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
aPropValue.Name = "SecondLightLevel";
|
|
aPropValue.Value <<= fLevel2;
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
// If a user sets light preset 'Dim' in MS Office, MS Office sets second light to harsh.
|
|
// In other cases it is soft.
|
|
aPropValue.Name = "SecondLightHarsh";
|
|
aPropValue.Value <<= nLevel == 2;
|
|
rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
|
|
}
|
|
}
|
|
break;
|
|
case SID_EXTRUSION_LIGHTING_DIRECTION:
|
|
{
|
|
const SfxInt32Item* pLightDirectionItem = nullptr;
|
|
if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_LIGHTING_DIRECTION, true, &pLightDirectionItem ) == SfxItemState::SET)
|
|
{
|
|
sal_Int32 nDirection = pLightDirectionItem->GetValue();
|
|
|
|
if((nDirection >= 0) && (nDirection < 9))
|
|
{
|
|
const Direction3D * pLighting1Defaults;
|
|
const Direction3D * pLighting2Defaults;
|
|
|
|
getLightingDirectionDefaults( &pLighting1Defaults, &pLighting2Defaults );
|
|
|
|
css::beans::PropertyValue aPropValue;
|
|
aPropValue.Name = "FirstLightDirection";
|
|
aPropValue.Value <<= pLighting1Defaults[nDirection];
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
|
|
aPropValue.Name = "SecondLightDirection";
|
|
aPropValue.Value <<= pLighting2Defaults[nDirection];
|
|
rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void ExtrusionBar::execute( SdrView* pSdrView, SfxRequest const & rReq, SfxBindings& rBindings )
|
|
{
|
|
sal_uInt16 nSID = rReq.GetSlot();
|
|
TranslateId pStrResId;
|
|
|
|
const bool bUndo = pSdrView && pSdrView->IsUndoEnabled();
|
|
|
|
switch( nSID )
|
|
{
|
|
case SID_EXTRUSION_TOGGLE:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ON_OFF;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_TILT_DOWN:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_DOWN;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_TILT_UP:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_UP;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_TILT_LEFT:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_LEFT;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_TILT_RIGHT:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_RIGHT;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_DIRECTION:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ORIENTATION;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_PROJECTION:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_PROJECTION;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_DEPTH:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_DEPTH;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_3D_COLOR:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_COLOR;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_SURFACE:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_SURFACE;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_LIGHTING_INTENSITY:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_BRIGHTNESS;
|
|
[[fallthrough]];
|
|
}
|
|
case SID_EXTRUSION_LIGHTING_DIRECTION:
|
|
{
|
|
if ( !pStrResId )
|
|
pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_LIGHTING;
|
|
|
|
if (pSdrView)
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
if( bUndo )
|
|
{
|
|
OUString aStr( SvxResId( pStrResId ) );
|
|
pSdrView->BegUndo( aStr );
|
|
pSdrView->AddUndo( pSdrView->GetModel().GetSdrUndoFactory().CreateUndoAttrObject( *pObj ) );
|
|
}
|
|
SdrCustomShapeGeometryItem aGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
impl_execute( rReq, aGeometryItem, pObj );
|
|
pObj->SetMergedItem( aGeometryItem );
|
|
pObj->BroadcastObjectChange();
|
|
if( bUndo )
|
|
pSdrView->EndUndo();
|
|
|
|
// simulate a context change:
|
|
// force SelectionHasChanged() being called
|
|
// so that extrusion bar will be visible/hidden
|
|
pSdrView->MarkListHasChanged();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_EXTRUSION_DEPTH_DIALOG:
|
|
{
|
|
const SvxDoubleItem* pDepthItem = nullptr;
|
|
const SfxUInt16Item* pMetricItem = nullptr;
|
|
if( rReq.GetArgs() &&
|
|
(rReq.GetArgs()->GetItemState( SID_EXTRUSION_DEPTH, true, &pDepthItem ) == SfxItemState::SET) &&
|
|
(rReq.GetArgs()->GetItemState( SID_ATTR_METRIC, true, &pMetricItem ) == SfxItemState::SET))
|
|
{
|
|
double fDepth = pDepthItem->GetValue();
|
|
FieldUnit eUnit = static_cast<FieldUnit>(pMetricItem->GetValue());
|
|
|
|
ExtrusionDepthDialog aDlg(rReq.GetFrameWeld(), fDepth, eUnit);
|
|
sal_uInt16 nRet = aDlg.run();
|
|
if (nRet == RET_OK)
|
|
{
|
|
fDepth = aDlg.getDepth();
|
|
|
|
SvxDoubleItem aItem( fDepth, SID_EXTRUSION_DEPTH );
|
|
SfxPoolItem* aItems[] = { &aItem, nullptr };
|
|
rBindings.Execute( SID_EXTRUSION_DEPTH, const_cast<const SfxPoolItem**>(aItems) );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( nSID != SID_EXTRUSION_TOGGLE )
|
|
return;
|
|
|
|
static const sal_uInt16 SidArray[] = {
|
|
SID_EXTRUSION_TILT_DOWN,
|
|
SID_EXTRUSION_TILT_UP,
|
|
SID_EXTRUSION_TILT_LEFT,
|
|
SID_EXTRUSION_TILT_RIGHT,
|
|
SID_EXTRUSION_DEPTH_FLOATER,
|
|
SID_EXTRUSION_DIRECTION_FLOATER,
|
|
SID_EXTRUSION_LIGHTING_FLOATER,
|
|
SID_EXTRUSION_SURFACE_FLOATER,
|
|
SID_EXTRUSION_3D_COLOR,
|
|
SID_EXTRUSION_DEPTH,
|
|
SID_EXTRUSION_DIRECTION,
|
|
SID_EXTRUSION_PROJECTION,
|
|
SID_EXTRUSION_LIGHTING_DIRECTION,
|
|
SID_EXTRUSION_LIGHTING_INTENSITY,
|
|
SID_EXTRUSION_SURFACE,
|
|
0 };
|
|
|
|
rBindings.Invalidate( SidArray );
|
|
}
|
|
|
|
static void getExtrusionDirectionState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
double fFinalSkewAngle = -1;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
bool bParallel = true;
|
|
Position3D aViewPoint( 3472, -3472, 25000 ); // MSO default
|
|
double fSkewAngle = -135; // MSO default
|
|
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"ProjectionMode"_ustr );
|
|
sal_Int16 nProjectionMode = sal_Int16();
|
|
if( pAny && ( *pAny >>= nProjectionMode ) )
|
|
bParallel = static_cast<ProjectionMode>(nProjectionMode) == ProjectionMode_PARALLEL;
|
|
|
|
if( bParallel )
|
|
{
|
|
double fSkew = 50.0;
|
|
EnhancedCustomShapeParameterPair aSkewPropPair;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Skew"_ustr );
|
|
if( pAny && ( *pAny >>= aSkewPropPair ) )
|
|
{
|
|
aSkewPropPair.First.Value >>= fSkew;
|
|
aSkewPropPair.Second.Value >>= fSkewAngle;
|
|
}
|
|
if ( fSkew == 0.0 )
|
|
fSkewAngle = 0.0;
|
|
else if ( fSkewAngle == 0.0 )
|
|
fSkewAngle = -360.0;
|
|
}
|
|
else
|
|
{
|
|
double fOriginX = 0.50;
|
|
double fOriginY = -0.50;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"ViewPoint"_ustr );
|
|
if( pAny )
|
|
*pAny >>= aViewPoint;
|
|
|
|
EnhancedCustomShapeParameterPair aOriginPropPair;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Origin"_ustr );
|
|
if( pAny && ( *pAny >>= aOriginPropPair ) )
|
|
{
|
|
aOriginPropPair.First.Value >>= fOriginX;
|
|
aOriginPropPair.Second.Value >>= fOriginY;
|
|
}
|
|
fSkewAngle = -1;
|
|
const double e = 0.0001;
|
|
if( aViewPoint.PositionX > e )
|
|
{
|
|
if( aViewPoint.PositionY > e )
|
|
{
|
|
if( (fOriginX > e ) && ( fOriginY > e ) )
|
|
fSkewAngle = 135.0;
|
|
}
|
|
else if( aViewPoint.PositionY < -e )
|
|
{
|
|
if( ( fOriginX > e ) && ( fOriginY < -e ) )
|
|
fSkewAngle = -135.0;
|
|
}
|
|
else
|
|
{
|
|
if( ( fOriginX > e ) && ( fOriginY > -e ) && ( fOriginY < e ) )
|
|
fSkewAngle = 180.0;
|
|
}
|
|
}
|
|
else if( aViewPoint.PositionX < -e )
|
|
{
|
|
if( aViewPoint.PositionY < -e )
|
|
{
|
|
if( ( fOriginX < -e ) && ( fOriginY < -e ) )
|
|
fSkewAngle = -45.0;
|
|
}
|
|
else if( aViewPoint.PositionY > e )
|
|
{
|
|
if( ( fOriginX < -e ) && ( fOriginY > e ) )
|
|
fSkewAngle = 45.0;
|
|
}
|
|
else
|
|
{
|
|
if( ( fOriginX < e ) && ( fOriginY > -e ) && ( fOriginY < e ) )
|
|
fSkewAngle = -360.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( aViewPoint.PositionY < -e )
|
|
{
|
|
if( ( fOriginX > -e ) && ( fOriginX < e ) && ( fOriginY < -e ) )
|
|
fSkewAngle = -90.0;
|
|
}
|
|
else if( aViewPoint.PositionY > e )
|
|
{
|
|
if( ( fOriginX > -e ) && ( fOriginX < e ) && ( fOriginY > e ) )
|
|
fSkewAngle = 90.0;
|
|
}
|
|
else
|
|
{
|
|
if( ( fOriginX > -e ) && ( fOriginX < e ) && ( fOriginY > -e ) && ( fOriginY < e ) )
|
|
fSkewAngle = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( rtl::math::approxEqual(fFinalSkewAngle, -1.0) )
|
|
{
|
|
fFinalSkewAngle = fSkewAngle;
|
|
}
|
|
else if( !rtl::math::approxEqual(fSkewAngle, fFinalSkewAngle) )
|
|
{
|
|
fFinalSkewAngle = -1.0;
|
|
}
|
|
|
|
if( rtl::math::approxEqual(fFinalSkewAngle, -1.0) )
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SfxInt32Item( SID_EXTRUSION_DIRECTION, static_cast<sal_Int32>(fFinalSkewAngle) ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_DIRECTION );
|
|
}
|
|
|
|
static void getExtrusionProjectionState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
sal_Int32 nFinalProjection = -1;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
bool bParallel = true;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"ProjectionMode"_ustr );
|
|
ProjectionMode eProjectionMode;
|
|
if( pAny && ( *pAny >>= eProjectionMode ) )
|
|
bParallel = eProjectionMode == ProjectionMode_PARALLEL;
|
|
|
|
if( nFinalProjection == -1 )
|
|
{
|
|
nFinalProjection = bParallel ? 1 : 0;
|
|
}
|
|
else if( nFinalProjection != (bParallel ? 1 : 0) )
|
|
{
|
|
nFinalProjection = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SfxInt32Item( SID_EXTRUSION_PROJECTION, nFinalProjection ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_PROJECTION );
|
|
}
|
|
|
|
static void getExtrusionSurfaceState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
sal_Int32 nFinalSurface = -1;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
sal_Int32 nSurface = 0; // wire frame
|
|
|
|
ShadeMode eShadeMode( ShadeMode_FLAT );
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"ShadeMode"_ustr );
|
|
if( pAny )
|
|
*pAny >>= eShadeMode;
|
|
|
|
if (eShadeMode != ShadeMode_DRAFT)
|
|
{
|
|
bool bMetal = false;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Metal"_ustr );
|
|
if( pAny )
|
|
*pAny >>= bMetal;
|
|
|
|
if( bMetal )
|
|
{
|
|
nSurface = 3; // metal ODF
|
|
sal_Int16 eMetalType = EnhancedCustomShapeMetalType::MetalODF;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"MetalType"_ustr );
|
|
if (pAny)
|
|
{
|
|
*pAny >>= eMetalType;
|
|
if (eMetalType == EnhancedCustomShapeMetalType::MetalMSCompatible)
|
|
nSurface = 4; // metal MS Office
|
|
}
|
|
}
|
|
else
|
|
{
|
|
double fSpecularity = 0;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Specularity"_ustr );
|
|
if( pAny )
|
|
*pAny >>= fSpecularity;
|
|
|
|
const double e = 0.0001;
|
|
if( (fSpecularity > -e) && (fSpecularity < e) )
|
|
{
|
|
nSurface = 1; // matte
|
|
}
|
|
else
|
|
{
|
|
nSurface = 2; // plastic
|
|
}
|
|
}
|
|
}
|
|
|
|
if( nFinalSurface == -1 )
|
|
{
|
|
nFinalSurface = nSurface;
|
|
}
|
|
else if( nFinalSurface != nSurface )
|
|
{
|
|
nFinalSurface = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SfxInt32Item( SID_EXTRUSION_SURFACE, nFinalSurface ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_SURFACE );
|
|
}
|
|
|
|
static void getExtrusionDepthState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
double fFinalDepth = -1;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
double fDepth = 1270.0; // =36pt ODF default
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Depth"_ustr );
|
|
if( pAny )
|
|
{
|
|
EnhancedCustomShapeParameterPair aDepthPropPair;
|
|
if ( *pAny >>= aDepthPropPair )
|
|
aDepthPropPair.First.Value >>= fDepth;
|
|
}
|
|
|
|
if( fFinalDepth == -1 )
|
|
{
|
|
fFinalDepth = fDepth;
|
|
}
|
|
else if( !rtl::math::approxEqual(fFinalDepth, fDepth) )
|
|
{
|
|
fFinalDepth = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FieldUnit eUnit = pSdrView->GetModel().GetUIUnit();
|
|
rSet.Put( SfxUInt16Item( SID_ATTR_METRIC, static_cast<sal_uInt16>(eUnit) ) );
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SvxDoubleItem( fFinalDepth, SID_EXTRUSION_DEPTH ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_DEPTH );
|
|
}
|
|
|
|
static bool compare_direction( const Direction3D& d1, const Direction3D& d2 )
|
|
{
|
|
if( ((d1.DirectionX < 0) && (d2.DirectionX < 0)) || ((d1.DirectionX == 0) && (d2.DirectionX == 0)) || ((d1.DirectionX > 0) && (d2.DirectionX > 0)) )
|
|
{
|
|
if( ((d1.DirectionY < 0) && (d2.DirectionY < 0)) || ((d1.DirectionY == 0) && (d2.DirectionY == 0)) || ((d1.DirectionY > 0) && (d2.DirectionY > 0)) )
|
|
{
|
|
if( ((d1.DirectionZ < 0) && (d2.DirectionZ < 0)) || ((d1.DirectionZ == 0) && (d2.DirectionZ == 0)) || ((d1.DirectionZ > 0) && (d2.DirectionZ > 0)) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static void getExtrusionLightingDirectionState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const Direction3D * pLighting1Defaults;
|
|
const Direction3D * pLighting2Defaults;
|
|
|
|
getLightingDirectionDefaults( &pLighting1Defaults, &pLighting2Defaults );
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
int nFinalDirection = -1;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
Direction3D aFirstLightDirection( 50000, 0, 10000 );
|
|
Direction3D aSecondLightDirection( -50000, 0, 10000 );
|
|
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"FirstLightDirection"_ustr );
|
|
if( pAny )
|
|
*pAny >>= aFirstLightDirection;
|
|
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"SecondLightDirection"_ustr );
|
|
if( pAny )
|
|
*pAny >>= aSecondLightDirection;
|
|
|
|
int nDirection = -1;
|
|
|
|
int j;
|
|
for( j = 0; j < 9; j++ )
|
|
{
|
|
if( compare_direction( aFirstLightDirection, pLighting1Defaults[j] ) &&
|
|
compare_direction( aSecondLightDirection, pLighting2Defaults[j] ))
|
|
{
|
|
nDirection = j;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( nFinalDirection == -1 )
|
|
{
|
|
nFinalDirection = nDirection;
|
|
}
|
|
else if( nDirection != nFinalDirection )
|
|
{
|
|
nFinalDirection = -1;
|
|
}
|
|
|
|
if( nFinalDirection == -1 )
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SfxInt32Item( SID_EXTRUSION_LIGHTING_DIRECTION, static_cast<sal_Int32>(nFinalDirection) ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_LIGHTING_DIRECTION );
|
|
}
|
|
|
|
static void getExtrusionLightingIntensityState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
int nFinalLevel = -1;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
double fBrightness = 22178.0 / 655.36;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Brightness"_ustr );
|
|
if( pAny )
|
|
*pAny >>= fBrightness;
|
|
|
|
int nLevel;
|
|
if( fBrightness >= 30.0 )
|
|
{
|
|
nLevel = 0; // Bright
|
|
}
|
|
else if( fBrightness >= 10.0 )
|
|
{
|
|
nLevel = 1; // Normal;
|
|
}
|
|
else
|
|
{
|
|
nLevel = 2; // Dim
|
|
}
|
|
|
|
if( nFinalLevel == -1 )
|
|
{
|
|
nFinalLevel = nLevel;
|
|
}
|
|
else if( nFinalLevel != nLevel )
|
|
{
|
|
nFinalLevel = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SfxInt32Item( SID_EXTRUSION_LIGHTING_INTENSITY, nFinalLevel ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_LIGHTING_INTENSITY );
|
|
}
|
|
|
|
static void getExtrusionColorState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const css::uno::Any* pAny;
|
|
|
|
bool bInit = false;
|
|
bool bAmbigius = false;
|
|
Color aFinalColor;
|
|
bool bHasCustomShape = false;
|
|
|
|
for(size_t i=0; i<nCount; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
|
|
// see if this is an extruded customshape
|
|
if( !bHasCustomShape )
|
|
{
|
|
const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny_ )
|
|
*pAny_ >>= bHasCustomShape;
|
|
|
|
if( !bHasCustomShape )
|
|
continue;
|
|
}
|
|
|
|
Color aColor;
|
|
|
|
bool bUseColor = false;
|
|
pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Color"_ustr );
|
|
if( pAny )
|
|
*pAny >>= bUseColor;
|
|
|
|
if( bUseColor )
|
|
{
|
|
const XSecondaryFillColorItem& rItem = pObj->GetMergedItem( XATTR_SECONDARYFILLCOLOR );
|
|
aColor = rItem.GetColorValue();
|
|
}
|
|
else
|
|
{
|
|
aColor = COL_AUTO;
|
|
}
|
|
|
|
if( !bInit )
|
|
{
|
|
aFinalColor = aColor;
|
|
bInit = true;
|
|
}
|
|
else if( aFinalColor != aColor )
|
|
{
|
|
bAmbigius = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bAmbigius )
|
|
aFinalColor = COL_AUTO;
|
|
|
|
if( bHasCustomShape )
|
|
rSet.Put( SvxColorItem( aFinalColor, SID_EXTRUSION_3D_COLOR ) );
|
|
else
|
|
rSet.DisableItem( SID_EXTRUSION_3D_COLOR );
|
|
}
|
|
|
|
namespace svx {
|
|
bool checkForSelectedCustomShapes( SdrView const * pSdrView, bool bOnlyExtruded )
|
|
{
|
|
static constexpr OUString sExtrusion = u"Extrusion"_ustr;
|
|
|
|
const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
|
|
const size_t nCount = rMarkList.GetMarkCount();
|
|
bool bFound = false;
|
|
|
|
for(size_t i=0;(i<nCount) && !bFound ; ++i)
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
|
|
if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
|
|
{
|
|
if( bOnlyExtruded )
|
|
{
|
|
const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
|
|
const Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
|
|
if( pAny )
|
|
*pAny >>= bFound;
|
|
}
|
|
else
|
|
{
|
|
bFound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bFound;
|
|
}
|
|
}
|
|
|
|
void ExtrusionBar::getState( SdrView const * pSdrView, SfxItemSet& rSet )
|
|
{
|
|
getExtrusionDirectionState( pSdrView, rSet );
|
|
getExtrusionProjectionState( pSdrView, rSet );
|
|
|
|
const bool bOnlyExtrudedCustomShapes(checkForSelectedCustomShapes( pSdrView, true ));
|
|
|
|
if (! bOnlyExtrudedCustomShapes)
|
|
{
|
|
rSet.DisableItem( SID_EXTRUSION_TILT_DOWN );
|
|
rSet.DisableItem( SID_EXTRUSION_TILT_DOWN );
|
|
rSet.DisableItem( SID_EXTRUSION_TILT_UP );
|
|
rSet.DisableItem( SID_EXTRUSION_TILT_LEFT );
|
|
rSet.DisableItem( SID_EXTRUSION_TILT_RIGHT );
|
|
rSet.DisableItem( SID_EXTRUSION_3D_COLOR );
|
|
rSet.DisableItem( SID_EXTRUSION_DEPTH_FLOATER );
|
|
rSet.DisableItem( SID_EXTRUSION_DIRECTION_FLOATER );
|
|
rSet.DisableItem( SID_EXTRUSION_LIGHTING_FLOATER );
|
|
rSet.DisableItem( SID_EXTRUSION_SURFACE_FLOATER );
|
|
}
|
|
|
|
if( !checkForSelectedCustomShapes( pSdrView, false ) )
|
|
rSet.DisableItem( SID_EXTRUSION_TOGGLE );
|
|
|
|
getExtrusionDepthState( pSdrView, rSet );
|
|
getExtrusionSurfaceState( pSdrView, rSet );
|
|
getExtrusionLightingIntensityState( pSdrView, rSet );
|
|
getExtrusionLightingDirectionState( pSdrView, rSet );
|
|
getExtrusionColorState( pSdrView, rSet );
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|