mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
674 lines
26 KiB
C++
674 lines
26 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platform/platform.h"
|
|
#include "gui/buttons/guiBitmapButtonCtrl.h"
|
|
#include "core/util/path.h"
|
|
#include "console/console.h"
|
|
#include "console/consoleTypes.h"
|
|
#include "console/engineAPI.h"
|
|
#include "gui/core/guiCanvas.h"
|
|
#include "gui/core/guiDefaultControlRender.h"
|
|
#include "gfx/gfxDrawUtil.h"
|
|
#include "gfx/gfxTextureManager.h"
|
|
#include "gui/editor/inspector/group.h"
|
|
#include "gui/editor/inspector/field.h"
|
|
#include "gui/editor/guiInspector.h"
|
|
|
|
|
|
ImplementEnumType( GuiBitmapMode,
|
|
"Rendering behavior when placing bitmaps in controls.\n\n"
|
|
"@ingroup GuiImages" )
|
|
{ GuiBitmapButtonCtrl::BitmapStretched, "Stretched", "Stretch bitmap to fit control extents." },
|
|
{ GuiBitmapButtonCtrl::BitmapCentered, "Centered", "Center bitmap in control." },
|
|
EndImplementEnumType;
|
|
|
|
|
|
//=============================================================================
|
|
// GuiBitmapButtonCtrl
|
|
//=============================================================================
|
|
|
|
IMPLEMENT_CONOBJECT(GuiBitmapButtonCtrl);
|
|
|
|
ConsoleDocClass( GuiBitmapButtonCtrl,
|
|
"@brief A button that renders its various states (mouse over, pushed, etc.) from separate bitmaps.\n\n"
|
|
|
|
"A bitmapped button is a push button that uses one or more texture images for rendering its individual states.\n\n"
|
|
|
|
"To find the individual textures associated with the button, a naming scheme is used. For each state "
|
|
"a suffix is appended to the texture file name given in the GuiBitmapButtonCtrl::bitmap field:\n"
|
|
|
|
"- \"_n\": Normal state. This one will be active when no other state applies.\n"
|
|
"- \"_h\": Highlighted state. This applies when the mouse is hovering over the button.\n"
|
|
"- \"_d\": Depressed state. This applies when the left mouse button has been clicked on the button but not yet released.\n"
|
|
"- \"_i\": Inactive state. This applies when the button control has been deactivated (GuiControl::setActive())\n\n"
|
|
|
|
"If a bitmap for a particular state cannot be found, the default bitmap will be used. To disable all state-based "
|
|
"bitmap functionality, set useStates to false which will make the control solely render from the bitmap specified "
|
|
"in the bitmap field.\n\n"
|
|
|
|
"@section guibitmapbutton_modifiers Per-Modifier Button Actions\n"
|
|
|
|
"If GuiBitmapButtonCtrl::useModifiers is set to true, per-modifier button actions and textures are enabled. This functionality "
|
|
"allows to associate different images and different actions with a button depending on which modifiers are pressed "
|
|
"on the keyboard by the user.\n\n"
|
|
|
|
"When enabled, this functionality alters the texture lookup above by prepending the following strings to the "
|
|
"suffixes listed above:\n"
|
|
|
|
"- \"\": Default. No modifier is pressed.\n"
|
|
"- \"_ctrl\": Image to use when CTRL/CMD is down.\n"
|
|
"- \"_alt\": Image to use when ALT is down.\n"
|
|
"- \"_shift\": Image to use when SHIFT is down\n\n"
|
|
|
|
"When this functionality is enabled, a new set of callbacks is used:\n"
|
|
|
|
"- onDefaultClick: Button was clicked without a modifier being presssed.\n"
|
|
"- onCtrlClick: Button was clicked with the CTRL/CMD key down.\n"
|
|
"- onAltClick: Button was clicked with the ALT key down.\n"
|
|
"- onShiftClick: Button was clicked with the SHIFT key down.\n\n"
|
|
|
|
"GuiControl::command or GuiControl::onAction() still work as before when per-modifier functionality is enabled.\n\n"
|
|
|
|
"Note that modifiers cannot be mixed. If two or more modifiers are pressed, a single one will take precedence over "
|
|
"the remaining modifiers. The order of precedence corresponds to the order listed above.\n\n"
|
|
|
|
"@tsexample\n"
|
|
"// Create an OK button that will trigger an onOk() call on its parent when clicked:\n"
|
|
"%okButton = new GuiBitmapButtonCtrl()\n"
|
|
"{\n"
|
|
" bitmap = \"art/gui/okButton\";\n"
|
|
" autoFitExtents = true;\n"
|
|
" command = \"$ThisControl.getParent().onOk();\";\n"
|
|
"};\n"
|
|
"@endtsexample\n\n"
|
|
|
|
"@ingroup GuiButtons"
|
|
);
|
|
|
|
IMPLEMENT_CALLBACK( GuiBitmapButtonCtrl, onDefaultClick, void, (), (),
|
|
"Called when per-modifier functionality is enabled and the user clicks on the button without any modifier pressed.\n"
|
|
"@ref guibitmapbutton_modifiers" );
|
|
IMPLEMENT_CALLBACK( GuiBitmapButtonCtrl, onCtrlClick, void, (), (),
|
|
"Called when per-modifier functionality is enabled and the user clicks on the button with the CTRL key pressed.\n"
|
|
"@ref guibitmapbutton_modifiers" );
|
|
IMPLEMENT_CALLBACK( GuiBitmapButtonCtrl, onAltClick, void, (), (),
|
|
"Called when per-modifier functionality is enabled and the user clicks on the button with the ALT key pressed.\n"
|
|
"@ref guibitmapbutton_modifiers" );
|
|
IMPLEMENT_CALLBACK( GuiBitmapButtonCtrl, onShiftClick, void, (), (),
|
|
"Called when per-modifier functionality is enabled and the user clicks on the button with the SHIFT key pressed.\n"
|
|
"@ref guibitmapbutton_modifiers" );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
GuiBitmapButtonCtrl::GuiBitmapButtonCtrl()
|
|
{
|
|
mBitmapMode = BitmapStretched;
|
|
mAutoFitExtents = false;
|
|
mUseModifiers = false;
|
|
mUseStates = true;
|
|
setExtent( 140, 30 );
|
|
mMasked = false;
|
|
mColor = ColorI::WHITE;
|
|
INIT_ASSET(Bitmap);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::initPersistFields()
|
|
{
|
|
docsURL;
|
|
addGroup( "Bitmap" );
|
|
|
|
addProtectedField("Bitmap", TypeImageFilename, Offset(mBitmapName, GuiBitmapButtonCtrl), _setBitmapFieldData, &defaultProtectedGetFn, "Texture file to display on this button.\n"
|
|
"If useStates is false, this will be the file that renders on the control. Otherwise, this will "
|
|
"specify the default texture name to which the various state and modifier suffixes are appended "
|
|
"to find the per-state and per-modifier (if enabled) textures.", AbstractClassRep::FIELD_HideInInspectors); \
|
|
addProtectedField("BitmapAsset", TypeImageAssetId, Offset(mBitmapAssetId, GuiBitmapButtonCtrl), _setBitmapFieldData, &defaultProtectedGetFn, "Texture file to display on this button.\n"
|
|
"If useStates is false, this will be the file that renders on the control. Otherwise, this will "
|
|
"specify the default texture name to which the various state and modifier suffixes are appended "
|
|
"to find the per-state and per-modifier (if enabled) textures.");
|
|
|
|
addField("color", TypeColorI, Offset(mColor, GuiBitmapButtonCtrl), "color mul");
|
|
|
|
addField( "bitmapMode", TYPEID< BitmapMode >(), Offset( mBitmapMode, GuiBitmapButtonCtrl ),
|
|
"Behavior for fitting the bitmap to the control extents.\n"
|
|
"If set to 'Stretched', the bitmap will be stretched both verticall and horizontally to fit inside "
|
|
"the control's extents.\n\n"
|
|
"If set to 'Centered', the bitmap will stay at its original resolution centered in the control's "
|
|
"rectangle (getting clipped if the control is smaller than the texture)." );
|
|
addProtectedField( "autoFitExtents", TypeBool, Offset( mAutoFitExtents, GuiBitmapButtonCtrl ),
|
|
&_setAutoFitExtents, &defaultProtectedGetFn,
|
|
"If true, the control's extents will be set to match the bitmap's extents when setting the bitmap.\n"
|
|
"The bitmap extents will always be taken from the default/normal bitmap (in case the extents of the various "
|
|
"bitmaps do not match up.)" );
|
|
addField( "useModifiers", TypeBool, Offset( mUseModifiers, GuiBitmapButtonCtrl ),
|
|
"If true, per-modifier button functionality is enabled.\n"
|
|
"@ref guibitmapbutton_modifiers" );
|
|
addField( "useStates", TypeBool, Offset( mUseStates, GuiBitmapButtonCtrl ),
|
|
"If true, per-mouse state button functionality is enabled.\n"
|
|
"Defaults to true.\n\n"
|
|
"If you do not use per-state images on this button set this to false to speed up the loading process "
|
|
"by inhibiting searches for the individual images." );
|
|
addField("masked", TypeBool, Offset(mMasked, GuiBitmapButtonCtrl),"Use alpha masking for interaction.");
|
|
|
|
endGroup( "Bitmap" );
|
|
|
|
Parent::initPersistFields();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool GuiBitmapButtonCtrl::onWake()
|
|
{
|
|
if (! Parent::onWake())
|
|
return false;
|
|
|
|
setActive( true );
|
|
setBitmap( getBitmap() );
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::onSleep()
|
|
{
|
|
if( dStricmp(mBitmapName, "texhandle") != 0 )
|
|
for( U32 i = 0; i < NumModifiers; ++ i )
|
|
{
|
|
mTextures[ i ].mTextureNormal = NULL;
|
|
mTextures[ i ].mTextureHilight = NULL;
|
|
mTextures[ i ].mTextureDepressed = NULL;
|
|
mTextures[ i ].mTextureInactive = NULL;
|
|
}
|
|
|
|
if (mBitmapAsset.notNull())
|
|
mBitmap = NULL;
|
|
|
|
Parent::onSleep();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool GuiBitmapButtonCtrl::_setAutoFitExtents( void *object, const char *index, const char *data )
|
|
{
|
|
GuiBitmapButtonCtrl* ctrl = reinterpret_cast< GuiBitmapButtonCtrl* >( object );
|
|
ctrl->setAutoFitExtents( dAtob( data ) );
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/*bool GuiBitmapButtonCtrl::_setBitmap(void* object, const char* index, const char* data)
|
|
{
|
|
GuiBitmapButtonCtrl* ctrl = reinterpret_cast< GuiBitmapButtonCtrl* >( object );
|
|
ctrl->setBitmap( StringTable->insert(data) );
|
|
return false;
|
|
}*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Legacy method. Can just assign to bitmap field.
|
|
/*DefineEngineMethod(GuiBitmapButtonCtrl, setBitmap, void, (const char* path), ,
|
|
"Set the bitmap to show on the button.\n"
|
|
"@param path Path to the texture file in any of the supported formats.\n" )
|
|
{
|
|
object->setBitmap( StringTable->insert(path) );
|
|
}*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::inspectPostApply()
|
|
{
|
|
Parent::inspectPostApply();
|
|
|
|
setBitmap(getBitmap());
|
|
|
|
// if the extent is set to (0,0) in the gui editor and appy hit, this control will
|
|
// set it's extent to be exactly the size of the normal bitmap (if present)
|
|
|
|
if ((getWidth() == 0) && (getHeight() == 0) && mTextures[ 0 ].mTextureNormal)
|
|
{
|
|
setExtent( mTextures[ 0 ].mTextureNormal->getWidth(), mTextures[ 0 ].mTextureNormal->getHeight());
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::setAutoFitExtents( bool state )
|
|
{
|
|
mAutoFitExtents = state;
|
|
if( mAutoFitExtents )
|
|
setBitmap( mBitmapName );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::setBitmap( StringTableEntry name )
|
|
{
|
|
PROFILE_SCOPE( GuiBitmapButtonCtrl_setBitmap );
|
|
|
|
_setBitmap(name);
|
|
if( !isAwake() )
|
|
return;
|
|
|
|
if( mBitmapAsset.notNull())
|
|
{
|
|
if( dStricmp( getBitmap(), "texhandle" ) != 0 )
|
|
{
|
|
const U32 count = mUseModifiers ? NumModifiers : 1;
|
|
for( U32 i = 0; i < count; ++ i )
|
|
{
|
|
static String modifiers[] =
|
|
{
|
|
"",
|
|
"_ctrl",
|
|
"_alt",
|
|
"_shift"
|
|
};
|
|
|
|
static String s_n[2] = { "_n", "_n_image" };
|
|
static String s_d[2] = { "_d", "_d_image" };
|
|
static String s_h[2] = { "_h", "_h_image" };
|
|
static String s_i[2] = { "_i", "_i_image" };
|
|
|
|
String baseName = mBitmapAssetId;
|
|
|
|
//strip any pre-assigned suffix, just in case
|
|
baseName = baseName.replace("_n_image", "");
|
|
baseName = baseName.replace("_n", "");
|
|
|
|
if( mUseModifiers )
|
|
baseName += modifiers[ i ];
|
|
|
|
mTextures[ i ].mTextureNormal = GFXTexHandle( mBitmapAsset->getImageFile(), &GFXDefaultGUIProfile, avar("%s() - mTextureNormal (line %d)", __FUNCTION__, __LINE__));
|
|
|
|
if( mUseStates )
|
|
{
|
|
//normal lookup
|
|
StringTableEntry lookupName;
|
|
for (U32 s = 0; s < 2; s++)
|
|
{
|
|
if (!mTextures[i].mTextureNormal)
|
|
{
|
|
lookupName = StringTable->insert(String(baseName + s_n[s]).c_str());
|
|
if (AssetDatabase.isDeclaredAsset(lookupName))
|
|
{
|
|
mTextures[i].mTextureNormalAssetId = lookupName;
|
|
mTextures[i].mTextureNormalAsset = mTextures[i].mTextureNormalAssetId;
|
|
}
|
|
|
|
if (mTextures[i].mTextureNormalAsset.notNull())
|
|
{
|
|
mTextures[i].mTextureNormalAsset->load();
|
|
if (mTextures[i].mTextureNormalAsset->getStatus() == AssetBase::Ok)
|
|
{
|
|
mTextures[i].mTextureNormal = GFXTexHandle(mTextures[i].mTextureNormalAsset->getImageFile(), &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Hilight lookup
|
|
for (U32 s = 0; s < 2; s++)
|
|
{
|
|
lookupName = StringTable->insert(String(baseName + s_h[s]).c_str());
|
|
if (AssetDatabase.isDeclaredAsset(lookupName))
|
|
{
|
|
mTextures[i].mTextureHilightAssetId = lookupName;
|
|
mTextures[i].mTextureHilightAsset = mTextures[i].mTextureHilightAssetId;
|
|
}
|
|
|
|
if (mTextures[i].mTextureHilightAsset.notNull())
|
|
{
|
|
mTextures[i].mTextureHilightAsset->load();
|
|
if (mTextures[i].mTextureHilightAsset->getStatus() == AssetBase::Ok)
|
|
{
|
|
mTextures[i].mTextureHilight = GFXTexHandle(mTextures[i].mTextureHilightAsset->getImageFile(), &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !mTextures[ i ].mTextureHilight )
|
|
mTextures[ i ].mTextureHilight = mTextures[ i ].mTextureNormal;
|
|
|
|
//Depressed lookup
|
|
for (U32 s = 0; s < 2; s++)
|
|
{
|
|
lookupName = StringTable->insert(String(baseName + s_d[s]).c_str());
|
|
if (AssetDatabase.isDeclaredAsset(lookupName))
|
|
{
|
|
mTextures[i].mTextureDepressedAssetId = lookupName;
|
|
mTextures[i].mTextureDepressedAsset = mTextures[i].mTextureDepressedAssetId;
|
|
}
|
|
|
|
if (mTextures[i].mTextureDepressedAsset.notNull())
|
|
{
|
|
mTextures[i].mTextureDepressedAsset->load();
|
|
if (mTextures[i].mTextureDepressedAsset->getStatus() == AssetBase::Ok)
|
|
{
|
|
mTextures[i].mTextureDepressed = GFXTexHandle(mTextures[i].mTextureDepressedAsset->getImageFile(), &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !mTextures[ i ].mTextureDepressed )
|
|
mTextures[ i ].mTextureDepressed = mTextures[ i ].mTextureHilight;
|
|
|
|
//Depressed lookup
|
|
for (U32 s = 0; s < 2; s++)
|
|
{
|
|
lookupName = StringTable->insert(String(baseName + s_i[s]).c_str());
|
|
if (AssetDatabase.isDeclaredAsset(lookupName))
|
|
{
|
|
mTextures[i].mTextureInactiveAssetId = lookupName;
|
|
mTextures[i].mTextureInactiveAsset = mTextures[i].mTextureInactiveAssetId;
|
|
}
|
|
|
|
if (mTextures[i].mTextureInactiveAsset.notNull())
|
|
{
|
|
mTextures[i].mTextureInactiveAsset->load();
|
|
if (mTextures[i].mTextureInactiveAsset->getStatus() == AssetBase::Ok)
|
|
{
|
|
mTextures[i].mTextureInactive = GFXTexHandle(mTextures[i].mTextureInactiveAsset->getImageFile(), &GFXDefaultGUIProfile, avar("%s() - mTextureDepressed (line %d)", __FUNCTION__, __LINE__));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !mTextures[ i ].mTextureInactive )
|
|
mTextures[ i ].mTextureInactive = mTextures[ i ].mTextureNormal;
|
|
}
|
|
|
|
if( i == 0 && mTextures[ i ].mTextureNormal.isNull() && mTextures[ i ].mTextureHilight.isNull() && mTextures[ i ].mTextureDepressed.isNull() && mTextures[ i ].mTextureInactive.isNull() )
|
|
{
|
|
Con::warnf( "GuiBitmapButtonCtrl::setBitmap - Unable to load texture: %s", mBitmapName );
|
|
this->setBitmap( StringTable->insert(GFXTextureManager::getUnavailableTexturePath().c_str()) );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( mAutoFitExtents && !mTextures[ 0 ].mTextureNormal.isNull() )
|
|
setExtent( mTextures[ 0 ].mTextureNormal.getWidth(), mTextures[ 0 ].mTextureNormal.getHeight() );
|
|
}
|
|
else
|
|
{
|
|
for( U32 i = 0; i < NumModifiers; ++ i )
|
|
{
|
|
mTextures[ i ].mTextureNormal = NULL;
|
|
mTextures[ i ].mTextureHilight = NULL;
|
|
mTextures[ i ].mTextureDepressed = NULL;
|
|
mTextures[ i ].mTextureInactive = NULL;
|
|
}
|
|
}
|
|
|
|
setUpdate();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::setBitmapHandles(GFXTexHandle normal, GFXTexHandle highlighted, GFXTexHandle depressed, GFXTexHandle inactive)
|
|
{
|
|
const U32 count = mUseModifiers ? NumModifiers : 1;
|
|
for( U32 i = 0; i < count; ++ i )
|
|
{
|
|
mTextures[ i ].mTextureNormal = normal;
|
|
mTextures[ i ].mTextureHilight = highlighted;
|
|
mTextures[ i ].mTextureDepressed = depressed;
|
|
mTextures[ i ].mTextureInactive = inactive;
|
|
|
|
if (!mTextures[ i ].mTextureHilight)
|
|
mTextures[ i ].mTextureHilight = mTextures[ i ].mTextureNormal;
|
|
if (!mTextures[ i ].mTextureDepressed)
|
|
mTextures[ i ].mTextureDepressed = mTextures[ i ].mTextureHilight;
|
|
if (!mTextures[ i ].mTextureInactive)
|
|
mTextures[ i ].mTextureInactive = mTextures[ i ].mTextureNormal;
|
|
|
|
if (mTextures[ i ].mTextureNormal.isNull() && mTextures[ i ].mTextureHilight.isNull() && mTextures[ i ].mTextureDepressed.isNull() && mTextures[ i ].mTextureInactive.isNull())
|
|
{
|
|
Con::warnf("GuiBitmapButtonCtrl::setBitmapHandles() - Invalid texture handles");
|
|
setBitmap( StringTable->insert(GFXTextureManager::getUnavailableTexturePath().c_str()) );
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
mBitmapName = "texhandle";
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
GuiBitmapButtonCtrl::Modifier GuiBitmapButtonCtrl::getCurrentModifier()
|
|
{
|
|
U8 modifierKeys = Input::getModifierKeys();
|
|
|
|
if( modifierKeys & SI_PRIMARY_CTRL )
|
|
return ModifierCtrl;
|
|
else if( modifierKeys & SI_PRIMARY_ALT )
|
|
return ModifierAlt;
|
|
else if( modifierKeys & SI_SHIFT )
|
|
return ModifierShift;
|
|
|
|
return ModifierNone;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
GFXTexHandle& GuiBitmapButtonCtrl::getTextureForCurrentState()
|
|
{
|
|
U32 index = ModifierNone;
|
|
if( mUseModifiers )
|
|
index = getCurrentModifier();
|
|
|
|
if( !mUseStates )
|
|
{
|
|
if( mTextures[ index ].mTextureNormal )
|
|
return mTextures[ 0 ].mTextureNormal;
|
|
else
|
|
return mTextures[ index ].mTextureNormal;
|
|
}
|
|
|
|
switch( getState() )
|
|
{
|
|
case NORMAL:
|
|
if( !mTextures[ index ].mTextureNormal )
|
|
return mTextures[ 0 ].mTextureNormal;
|
|
else
|
|
return mTextures[ index ].mTextureNormal;
|
|
|
|
case HILIGHT:
|
|
if( !mTextures[ index ].mTextureHilight )
|
|
return mTextures[ 0 ].mTextureHilight;
|
|
else
|
|
return mTextures[ index ].mTextureHilight;
|
|
|
|
case DEPRESSED:
|
|
if( !mTextures[ index ].mTextureDepressed )
|
|
return mTextures[ 0 ].mTextureDepressed;
|
|
else
|
|
return mTextures[ index ].mTextureDepressed;
|
|
|
|
default:
|
|
if( !mTextures[ index ].mTextureInactive )
|
|
return mTextures[ 0 ].mTextureInactive;
|
|
else
|
|
return mTextures[ index ].mTextureInactive;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::onAction()
|
|
{
|
|
Parent::onAction();
|
|
|
|
if( mUseModifiers )
|
|
{
|
|
switch( getCurrentModifier() )
|
|
{
|
|
case ModifierNone:
|
|
onDefaultClick_callback();
|
|
break;
|
|
|
|
case ModifierCtrl:
|
|
onCtrlClick_callback();
|
|
break;
|
|
|
|
case ModifierAlt:
|
|
onAltClick_callback();
|
|
break;
|
|
|
|
case ModifierShift:
|
|
onShiftClick_callback();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
|
|
{
|
|
GFXTexHandle& texture = getTextureForCurrentState();
|
|
if( texture )
|
|
{
|
|
renderButton( texture, offset, updateRect );
|
|
renderChildControls( offset, updateRect );
|
|
}
|
|
else
|
|
Parent::onRender(offset, updateRect);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonCtrl::renderButton( GFXTexHandle &texture, const Point2I &offset, const RectI& updateRect )
|
|
{
|
|
GFX->getDrawUtil()->clearBitmapModulation();
|
|
GFX->getDrawUtil()->setBitmapModulation(mColor);
|
|
|
|
switch( mBitmapMode )
|
|
{
|
|
case BitmapStretched:
|
|
{
|
|
RectI rect( offset, getExtent() );
|
|
GFX->getDrawUtil()->drawBitmapStretch( texture, rect );
|
|
break;
|
|
}
|
|
|
|
case BitmapCentered:
|
|
{
|
|
Point2I p = offset;
|
|
|
|
p.x += getExtent().x / 2 - texture.getWidth() / 2;
|
|
p.y += getExtent().y / 2 - texture.getHeight() / 2;
|
|
|
|
GFX->getDrawUtil()->drawBitmap( texture, p );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// GuiBitmapButtonTextCtrl.
|
|
//=============================================================================
|
|
|
|
IMPLEMENT_CONOBJECT( GuiBitmapButtonTextCtrl);
|
|
|
|
ConsoleDocClass( GuiBitmapButtonTextCtrl,
|
|
"@brief An extension of GuiBitmapButtonCtrl that additionally renders a text label on the bitmapped button.\n\n"
|
|
|
|
"The text for the label is taken from the GuiButtonBaseCtrl::text property.\n\n"
|
|
|
|
"For rendering, the label is placed, relative to the control's upper left corner, at the text offset specified in the "
|
|
"control's profile (GuiControlProfile::textOffset) and justified according to the profile's setting (GuiControlProfile::justify).\n\n"
|
|
|
|
"@see GuiControlProfile::textOffset\n"
|
|
"@see GuiControlProfile::justify\n"
|
|
"@ingroup GuiButtons"
|
|
);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GuiBitmapButtonTextCtrl::renderButton( GFXTexHandle &texture, const Point2I &offset, const RectI& updateRect )
|
|
{
|
|
Parent::renderButton( texture, offset, updateRect );
|
|
|
|
Point2I textPos = offset;
|
|
if(mDepressed)
|
|
textPos += Point2I(1,1);
|
|
|
|
// Make sure we take the profile's textOffset into account.
|
|
textPos += mProfile->mTextOffset;
|
|
|
|
GFX->getDrawUtil()->setBitmapModulation( mProfile->mFontColor );
|
|
renderJustifiedText(textPos, getExtent(), mButtonText);
|
|
}
|
|
|
|
bool GuiBitmapButtonCtrl::pointInControl(const Point2I& parentCoordPoint)
|
|
{
|
|
if (mMasked && getTextureForCurrentState())
|
|
{
|
|
ColorI rColor(0, 0, 0, 0);
|
|
GBitmap* bmp;
|
|
|
|
const RectI &bounds = getBounds();
|
|
S32 xt = parentCoordPoint.x - bounds.point.x;
|
|
S32 yt = parentCoordPoint.y - bounds.point.y;
|
|
|
|
bmp = getTextureForCurrentState().getBitmap();
|
|
if (!bmp)
|
|
{
|
|
setBitmap(mBitmapName);
|
|
bmp = getTextureForCurrentState().getBitmap();
|
|
}
|
|
|
|
S32 relativeXRange = this->getExtent().x;
|
|
S32 relativeYRange = this->getExtent().y;
|
|
S32 fileXRange = bmp->getHeight(0);
|
|
S32 fileYRange = bmp->getWidth(0);
|
|
//Con::errorf("xRange:[%i -- %i], Range:[%i -- %i] pos:(%i,%i)",relativeXRange,fileXRange,relativeYRange,fileYRange,xt,yt);
|
|
|
|
S32 fileX = (xt*fileXRange) / relativeXRange;
|
|
S32 fileY = (yt*fileYRange) / relativeYRange;
|
|
//Con::errorf("Checking %s @ (%i,%i)",this->getName(),fileX,fileY);
|
|
|
|
bmp->getColor(fileX, fileY, rColor);
|
|
|
|
if (rColor.alpha)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
return Parent::pointInControl(parentCoordPoint);
|
|
}
|
|
|
|
DEF_ASSET_BINDS(GuiBitmapButtonCtrl, Bitmap);
|