Torque3D/Engine/source/gui/controls/guiBitmapCtrl.cpp

294 lines
9.4 KiB
C++
Raw Normal View History

2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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/controls/guiBitmapCtrl.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "console/engineAPI.h"
#include "gfx/gfxDevice.h"
#include "gfx/gfxDrawUtil.h"
#include "materials/matTextureTarget.h"
2012-09-19 15:15:01 +00:00
IMPLEMENT_CONOBJECT(GuiBitmapCtrl);
2024-12-21 23:02:23 +00:00
ConsoleDocClass(GuiBitmapCtrl,
2012-09-19 15:15:01 +00:00
"@brief A gui control that is used to display an image.\n\n"
2024-12-21 23:02:23 +00:00
2012-09-19 15:15:01 +00:00
"The image is stretched to the constraints of the control by default. However, the control can also\n"
"tile the image as well.\n\n"
"The image itself is stored inside the GuiBitmapCtrl::bitmap field. The boolean value that decides\n"
"whether the image is stretched or tiled is stored inside the GuiBitmapCtrl::wrap field.\n"
2024-12-21 23:02:23 +00:00
2012-09-19 15:15:01 +00:00
"@tsexample\n"
"// Create a tiling GuiBitmapCtrl that displays \"myImage.png\"\n"
"%bitmapCtrl = new GuiBitmapCtrl()\n"
"{\n"
" bitmap = \"myImage.png\";\n"
" wrap = \"true\";\n"
"};\n"
"@endtsexample\n\n"
2024-12-21 23:02:23 +00:00
2012-09-19 15:15:01 +00:00
"@ingroup GuiControls"
);
GuiBitmapCtrl::GuiBitmapCtrl(void)
2024-12-21 23:02:23 +00:00
: mStartPoint(0, 0),
mColor(ColorI::WHITE),
mAngle(0),
2024-12-21 23:02:23 +00:00
mWrap(false),
mBitmap(NULL),
mBitmapName(StringTable->EmptyString())
2012-09-19 15:15:01 +00:00
{
}
void GuiBitmapCtrl::initPersistFields()
{
docsURL;
2024-12-21 23:02:23 +00:00
addGroup("Bitmap");
INITPERSISTFIELD_IMAGEASSET(Bitmap, GuiBitmapCtrl, "The bitmap to render in this BitmapCtrl.")
2024-12-21 23:02:23 +00:00
addField("color", TypeColorI, Offset(mColor, GuiBitmapCtrl), "color mul");
addField("wrap", TypeBool, Offset(mWrap, GuiBitmapCtrl), "If true, the bitmap is tiled inside the control rather than stretched to fit.");
addFieldV("angle", TypeRangedF32, Offset(mAngle, GuiBitmapCtrl), &CommonValidators::DegreeRange, "rotation");
2012-09-19 15:15:01 +00:00
endGroup( "Bitmap" );
Parent::initPersistFields();
}
bool GuiBitmapCtrl::onWake()
{
2024-12-21 23:02:23 +00:00
if (!Parent::onWake())
2012-09-19 15:15:01 +00:00
return false;
setActive(true);
2012-09-19 15:15:01 +00:00
return true;
}
void GuiBitmapCtrl::onSleep()
{
Parent::onSleep();
}
//-------------------------------------
void GuiBitmapCtrl::inspectPostApply()
{
// 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 bitmap (if present)
Parent::inspectPostApply();
2024-12-21 23:02:23 +00:00
if (!mWrap && (getExtent().x == 0) && (getExtent().y == 0) && mBitmapAsset.notNull())
2012-09-19 15:15:01 +00:00
{
2024-12-21 23:02:23 +00:00
setExtent(mBitmap->getWidth(), mBitmap->getHeight());
2012-09-19 15:15:01 +00:00
}
}
2024-12-21 23:02:23 +00:00
void GuiBitmapCtrl::setBitmap(const char* name, bool resize)
2012-09-19 15:15:01 +00:00
{
2024-12-21 23:02:23 +00:00
// coming in here we are probably getting a filename.
if (AssetDatabase.isDeclaredAsset(name))
{
_setBitmap(StringTable->insert(name));
}
else
{
StringTableEntry assetId = ImageAsset::getAssetIdByFilename(StringTable->insert(name));
if (assetId != StringTable->EmptyString())
_setBitmap(assetId);
else
_setBitmap(name);
2024-12-21 23:02:23 +00:00
}
2012-09-19 15:15:01 +00:00
2024-12-21 23:02:23 +00:00
mBitmap = mBitmapAsset->getTexture(&GFXDefaultGUIProfile);
if (mBitmapAsset.notNull() && resize)
{
2024-12-21 23:02:23 +00:00
setExtent(mBitmap->getWidth(), mBitmap->getHeight());
updateSizing();
2012-09-19 15:15:01 +00:00
}
setUpdate();
}
void GuiBitmapCtrl::setBitmapHandle(GFXTexHandle handle, bool resize)
{
mBitmap = handle;
2012-09-19 15:15:01 +00:00
mBitmapName = StringTable->insert("texhandle");
2012-09-19 15:15:01 +00:00
// Resize the control to fit the bitmap
2024-12-21 23:02:23 +00:00
if (resize)
2012-09-19 15:15:01 +00:00
{
setExtent(mBitmap->getWidth(), mBitmap->getHeight());
2012-09-19 15:15:01 +00:00
updateSizing();
}
}
2024-12-21 23:02:23 +00:00
void GuiBitmapCtrl::updateSizing()
2012-09-19 15:15:01 +00:00
{
2024-12-21 23:02:23 +00:00
if (!getParent())
return;
// updates our bounds according to our horizSizing and verSizing rules
RectI fakeBounds(getPosition(), getParent()->getExtent());
parentResized(fakeBounds, fakeBounds);
}
void GuiBitmapCtrl::onRender(Point2I offset, const RectI& updateRect)
{
if (mBitmap.isNull() && mBitmapAsset.notNull())
mBitmap = getBitmap();
if (mBitmap)
2012-09-19 15:15:01 +00:00
{
GFX->getDrawUtil()->clearBitmapModulation();
GFX->getDrawUtil()->setBitmapModulation(mColor);
2024-12-21 23:02:23 +00:00
if (mWrap)
{
2012-09-19 15:15:01 +00:00
// We manually draw each repeat because non power of two textures will
// not tile correctly when rendered with GFX->drawBitmapTile(). The non POT
// bitmap will be padded by the hardware, and we'll see lots of slack
// in the texture. So... lets do what we must: draw each repeat by itself:
2024-12-21 23:02:23 +00:00
GFXTextureObject* texture = mBitmap;
RectI srcRegion;
RectI dstRegion;
F32 xdone = ((F32)getExtent().x / (F32)texture->mBitmapSize.x) + 1;
F32 ydone = ((F32)getExtent().y / (F32)texture->mBitmapSize.y) + 1;
S32 xshift = mStartPoint.x % texture->mBitmapSize.x;
S32 yshift = mStartPoint.y % texture->mBitmapSize.y;
for (S32 y = 0; y < ydone; ++y)
for (S32 x = 0; x < xdone; ++x)
{
srcRegion.set(0, 0, texture->mBitmapSize.x, texture->mBitmapSize.y);
dstRegion.set(((texture->mBitmapSize.x * x) + offset.x) - xshift,
((texture->mBitmapSize.y * y) + offset.y) - yshift,
texture->mBitmapSize.x,
texture->mBitmapSize.y);
GFX->getDrawUtil()->drawBitmapStretchSR(texture, dstRegion, srcRegion, GFXBitmapFlip_None, GFXTextureFilterLinear, mAngle);
2024-12-21 23:02:23 +00:00
}
2012-09-19 15:15:01 +00:00
2024-12-21 23:02:23 +00:00
}
else
2012-09-19 15:15:01 +00:00
{
RectI rect(offset, getExtent());
GFX->getDrawUtil()->drawBitmapStretch(mBitmap, rect, GFXBitmapFlip_None, GFXTextureFilterLinear, false, mAngle);
2012-09-19 15:15:01 +00:00
}
}
if (mProfile->mBorder || !mBitmap)
2012-09-19 15:15:01 +00:00
{
RectI rect(offset.x, offset.y, getExtent().x, getExtent().y);
GFX->getDrawUtil()->drawRect(rect, mProfile->mBorderColor);
}
renderChildControls(offset, updateRect);
}
void GuiBitmapCtrl::setValue(S32 x, S32 y)
{
2024-12-21 23:02:23 +00:00
if (mBitmapAsset.notNull())
2012-09-19 15:15:01 +00:00
{
2024-12-21 23:02:23 +00:00
x += mBitmapAsset->getTextureBitmapWidth() / 2;
y += mBitmapAsset->getTextureBitmapHeight() / 2;
}
while (x < 0)
x += 256;
mStartPoint.x = x % 256;
while (y < 0)
y += 256;
mStartPoint.y = y % 256;
2012-09-19 15:15:01 +00:00
}
2024-12-21 23:02:23 +00:00
DefineEngineMethod(GuiBitmapCtrl, setValue, void, (S32 x, S32 y), ,
2012-09-19 15:15:01 +00:00
"Set the offset of the bitmap within the control.\n"
"@param x The x-axis offset of the image.\n"
"@param y The y-axis offset of the image.\n")
{
object->setValue(x, y);
}
//
static ConsoleDocFragment _sGuiBitmapCtrlSetBitmap1(
"@brief Assign an image to the control.\n\n"
"Child controls with resize according to their layout settings.\n"
"@param filename The filename of the image.\n"
"@param resize Optional parameter. If true, the GUI will resize to fit the image.",
"GuiBitmapCtrl", // The class to place the method in; use NULL for functions.
2024-12-21 23:02:23 +00:00
"void setBitmap( String filename, bool resize );"); // The definition string.
2012-09-19 15:15:01 +00:00
static ConsoleDocFragment _sGuiBitmapCtrlSetBitmap2(
"@brief Assign an image to the control.\n\n"
"Child controls will resize according to their layout settings.\n"
"@param filename The filename of the image.\n"
"@param resize A boolean value that decides whether the ctrl refreshes or not.",
"GuiBitmapCtrl", // The class to place the method in; use NULL for functions.
2024-12-21 23:02:23 +00:00
"void setBitmap( String filename );"); // The definition string.
2012-09-19 15:15:01 +00:00
//"Set the bitmap displayed in the control. Note that it is limited in size, to 256x256."
2024-12-21 23:02:23 +00:00
DefineEngineMethod(GuiBitmapCtrl, setBitmap, void, (const char* fileRoot, bool resize), (false),
2012-09-19 15:15:01 +00:00
"( String filename | String filename, bool resize ) Assign an image to the control.\n\n"
2024-12-21 23:02:23 +00:00
"@hide")
2012-09-19 15:15:01 +00:00
{
char filename[1024];
Con::expandScriptFilename(filename, sizeof(filename), fileRoot);
2024-12-21 23:02:23 +00:00
object->setBitmap(filename, resize);
2012-09-19 15:15:01 +00:00
}
2024-12-21 23:02:23 +00:00
DefineEngineMethod(GuiBitmapCtrl, getBitmap, const char*, (), ,
"Gets the current bitmap set for this control.\n\n"
"@hide")
{
2024-12-21 23:02:23 +00:00
return object->_getBitmap();
}
2024-12-21 23:02:23 +00:00
DefineEngineMethod(GuiBitmapCtrl, setNamedTexture, bool, (String namedtexture), ,
"@brief Set a texture as the image.\n\n"
"@param namedtexture The name of the texture (NamedTexTarget).\n"
2024-12-21 23:02:23 +00:00
"@return true if the texture exists.")
{
GFXTexHandle theTex;
2024-12-21 23:02:23 +00:00
NamedTexTarget* namedTarget = NULL;
namedTarget = NamedTexTarget::find(namedtexture.c_str());
2024-12-21 23:02:23 +00:00
if (namedTarget)
{
2024-12-21 23:02:23 +00:00
theTex = namedTarget->getTexture(0);
}
2024-12-21 23:02:23 +00:00
if (theTex.isValid())
{
2024-12-21 23:02:23 +00:00
object->setBitmapHandle(theTex, false);
return true; //a new texture was set correctly
}
return false; //we couldn't change the texture
}