mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 07:04:36 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
201
Engine/source/gui/game/guiChunkedBitmapCtrl.cpp
Normal file
201
Engine/source/gui/game/guiChunkedBitmapCtrl.cpp
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/bitmap/gBitmap.h"
|
||||
#include "gui/core/guiControl.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxTextureHandle.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
|
||||
class GuiChunkedBitmapCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
void renderRegion(const Point2I &offset, const Point2I &extent);
|
||||
|
||||
protected:
|
||||
StringTableEntry mBitmapName;
|
||||
GFXTexHandle mTexHandle;
|
||||
bool mUseVariable;
|
||||
bool mTile;
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiChunkedBitmapCtrl);
|
||||
DECLARE_CATEGORY( "Gui Images" );
|
||||
|
||||
GuiChunkedBitmapCtrl();
|
||||
static void initPersistFields();
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setBitmap(const char *name);
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
};
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiChunkedBitmapCtrl);
|
||||
|
||||
ConsoleDocClass( GuiChunkedBitmapCtrl,
|
||||
"@brief This is a control that will render a specified bitmap or a bitmap specified in a referenced variable.\n\n"
|
||||
|
||||
"This control allows you to either set a bitmap with the \"bitmap\" field or with the setBitmap method. You can also choose "
|
||||
"to reference a variable in the \"variable\" field such as \"$image\" and then set \"useVariable\" to true. This will cause it to "
|
||||
"synchronize the variable with the bitmap displayed (if the variable holds a valid image). You can then change the variable and "
|
||||
"effectively changed the displayed image.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"$image = \"anotherbackground.png\";\n"
|
||||
"new GuiChunkedBitmapCtrl(ChunkedBitmap)\n"
|
||||
"{\n"
|
||||
" bitmap = \"background.png\";\n"
|
||||
" variable = \"$image\";\n"
|
||||
" useVariable = false;\n"
|
||||
"}\n\n"
|
||||
"// This will result in the control rendering \"background.png\"\n"
|
||||
"// If we now set the useVariable to true it will now render \"anotherbackground.png\"\n"
|
||||
"ChunkedBitmap.useVariable = true;\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see GuiControl::variable\n\n"
|
||||
|
||||
"@ingroup GuiImages\n"
|
||||
);
|
||||
|
||||
|
||||
void GuiChunkedBitmapCtrl::initPersistFields()
|
||||
{
|
||||
addGroup("GuiChunkedBitmapCtrl");
|
||||
addField( "bitmap", TypeFilename, Offset( mBitmapName, GuiChunkedBitmapCtrl ), "This is the bitmap to render to the control." );
|
||||
addField( "useVariable", TypeBool, Offset( mUseVariable, GuiChunkedBitmapCtrl ), "This decides whether to use the \"bitmap\" file "
|
||||
"or a bitmap stored in \"variable\"");
|
||||
addField( "tile", TypeBool, Offset( mTile, GuiChunkedBitmapCtrl ), "This is no longer in use");
|
||||
endGroup("GuiChunkedBitmapCtrl");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GuiChunkedBitmapCtrl, setBitmap, void, (const char* filename),,
|
||||
"@brief Set the image rendered in this control.\n\n"
|
||||
"@param filename The image name you want to set\n"
|
||||
"@tsexample\n"
|
||||
"ChunkedBitmap.setBitmap(\"images/background.png\");"
|
||||
"@endtsexample\n\n")
|
||||
{
|
||||
object->setBitmap( filename );
|
||||
}
|
||||
|
||||
GuiChunkedBitmapCtrl::GuiChunkedBitmapCtrl()
|
||||
{
|
||||
mBitmapName = StringTable->insert("");
|
||||
mUseVariable = false;
|
||||
mTile = false;
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::setBitmap(const char *name)
|
||||
{
|
||||
bool awake = mAwake;
|
||||
if(awake)
|
||||
onSleep();
|
||||
|
||||
mBitmapName = StringTable->insert(name);
|
||||
if(awake)
|
||||
onWake();
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
bool GuiChunkedBitmapCtrl::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return false;
|
||||
|
||||
if( !mTexHandle
|
||||
&& ( ( mBitmapName && mBitmapName[ 0 ] )
|
||||
|| ( mUseVariable && mConsoleVariable && mConsoleVariable[ 0 ] ) ) )
|
||||
{
|
||||
if ( mUseVariable )
|
||||
mTexHandle.set( Con::getVariable( mConsoleVariable ), &GFXDefaultGUIProfile, avar("%s() - mTexHandle (line %d)", __FUNCTION__, __LINE__) );
|
||||
else
|
||||
mTexHandle.set( mBitmapName, &GFXDefaultGUIProfile, avar("%s() - mTexHandle (line %d)", __FUNCTION__, __LINE__) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::onSleep()
|
||||
{
|
||||
mTexHandle = NULL;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::renderRegion(const Point2I &offset, const Point2I &extent)
|
||||
{
|
||||
/*
|
||||
U32 widthCount = mTexHandle.getTextureCountWidth();
|
||||
U32 heightCount = mTexHandle.getTextureCountHeight();
|
||||
if(!widthCount || !heightCount)
|
||||
return;
|
||||
|
||||
F32 widthScale = F32(extent.x) / F32(mTexHandle.getWidth());
|
||||
F32 heightScale = F32(extent.y) / F32(mTexHandle.getHeight());
|
||||
GFX->setBitmapModulation(ColorF(1,1,1));
|
||||
for(U32 i = 0; i < widthCount; i++)
|
||||
{
|
||||
for(U32 j = 0; j < heightCount; j++)
|
||||
{
|
||||
GFXTexHandle t = mTexHandle.getSubTexture(i, j);
|
||||
RectI stretchRegion;
|
||||
stretchRegion.point.x = (S32)(i * 256 * widthScale + offset.x);
|
||||
stretchRegion.point.y = (S32)(j * 256 * heightScale + offset.y);
|
||||
if(i == widthCount - 1)
|
||||
stretchRegion.extent.x = extent.x + offset.x - stretchRegion.point.x;
|
||||
else
|
||||
stretchRegion.extent.x = (S32)((i * 256 + t.getWidth() ) * widthScale + offset.x - stretchRegion.point.x);
|
||||
if(j == heightCount - 1)
|
||||
stretchRegion.extent.y = extent.y + offset.y - stretchRegion.point.y;
|
||||
else
|
||||
stretchRegion.extent.y = (S32)((j * 256 + t.getHeight()) * heightScale + offset.y - stretchRegion.point.y);
|
||||
GFX->drawBitmapStretch(t, stretchRegion);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void GuiChunkedBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
|
||||
if( mTexHandle )
|
||||
{
|
||||
RectI boundsRect( offset, getExtent());
|
||||
GFX->getDrawUtil()->drawBitmapStretch( mTexHandle, boundsRect, GFXBitmapFlip_None, GFXTextureFilterLinear );
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect);
|
||||
}
|
||||
201
Engine/source/gui/game/guiFadeinBitmapCtrl.cpp
Normal file
201
Engine/source/gui/game/guiFadeinBitmapCtrl.cpp
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/game/guiFadeinBitmapCtrl.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "math/mathTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT( GuiFadeinBitmapCtrl );
|
||||
|
||||
ConsoleDocClass( GuiFadeinBitmapCtrl,
|
||||
"@brief A GUI control which renders a black square over a bitmap image. The black square will fade out, then fade back in after a determined time.\n"
|
||||
"This control is especially useful for transitions and splash screens.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"new GuiFadeinBitmapCtrl()\n"
|
||||
" {\n"
|
||||
" fadeinTime = \"1000\";\n"
|
||||
" waitTime = \"2000\";\n"
|
||||
" fadeoutTime = \"1000\";\n"
|
||||
" done = \"1\";\n"
|
||||
" // Additional GUI properties that are not specific to GuiFadeinBitmapCtrl have been omitted from this example.\n"
|
||||
" };\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see GuiBitmapCtrl\n\n"
|
||||
"@ingroup GuiCore\n"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( GuiFadeinBitmapCtrl, click, void, (),(),
|
||||
"@brief Informs the script level that this object received a Click event from the cursor or keyboard.\n\n"
|
||||
"@tsexample\n"
|
||||
"GuiFadeInBitmapCtrl::click(%this)\n"
|
||||
" {\n"
|
||||
" // Code to run when click occurs\n"
|
||||
" }\n"
|
||||
"@endtsexample\n\n"
|
||||
"@see GuiCore\n\n"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( GuiFadeinBitmapCtrl, onDone, void, (),(),
|
||||
"@brief Informs the script level that this object has completed is fade cycle.\n\n"
|
||||
"@tsexample\n"
|
||||
"GuiFadeInBitmapCtrl::onDone(%this)\n"
|
||||
" {\n"
|
||||
" // Code to run when the fade cycle completes\n"
|
||||
" }\n"
|
||||
"@endtsexample\n\n"
|
||||
"@see GuiCore\n\n"
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiFadeinBitmapCtrl::GuiFadeinBitmapCtrl()
|
||||
: mFadeColor( 0.f, 0.f, 0.f ),
|
||||
mStartTime( 0 ),
|
||||
mFadeInTime( 1000 ),
|
||||
mWaitTime( 2000 ),
|
||||
mFadeOutTime( 1000 ),
|
||||
mDone( false )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiFadeinBitmapCtrl::initPersistFields()
|
||||
{
|
||||
addGroup( "Fading" );
|
||||
|
||||
addField( "fadeColor", TypeColorF, Offset( mFadeColor, GuiFadeinBitmapCtrl ),
|
||||
"Color to fade in from and fade out to." );
|
||||
addField( "fadeInTime", TypeS32, Offset( mFadeInTime, GuiFadeinBitmapCtrl ),
|
||||
"Milliseconds for the bitmap to fade in." );
|
||||
addField( "waitTime", TypeS32, Offset( mWaitTime, GuiFadeinBitmapCtrl ),
|
||||
"Milliseconds to wait after fading in before fading out the bitmap." );
|
||||
addField( "fadeOutTime", TypeS32, Offset( mFadeOutTime, GuiFadeinBitmapCtrl ),
|
||||
"Milliseconds for the bitmap to fade out." );
|
||||
addField( "fadeInEase", TypeEaseF, Offset( mFadeInEase, GuiFadeinBitmapCtrl ),
|
||||
"Easing curve for fade-in." );
|
||||
addField( "fadeOutEase", TypeEaseF, Offset( mFadeOutEase, GuiFadeinBitmapCtrl ),
|
||||
"Easing curve for fade-out." );
|
||||
addField( "done", TypeBool, Offset( mDone, GuiFadeinBitmapCtrl ),
|
||||
"Whether the fade cycle has finished running." );
|
||||
|
||||
endGroup( "Fading" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiFadeinBitmapCtrl::onPreRender()
|
||||
{
|
||||
Parent::onPreRender();
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiFadeinBitmapCtrl::onMouseDown(const GuiEvent &)
|
||||
{
|
||||
click_callback();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiFadeinBitmapCtrl::onKeyDown(const GuiEvent &)
|
||||
{
|
||||
click_callback();
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiFadeinBitmapCtrl::onWake()
|
||||
{
|
||||
if( !Parent::onWake() )
|
||||
return false;
|
||||
|
||||
// Reset reference time.
|
||||
mStartTime = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiFadeinBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
Parent::onRender(offset, updateRect);
|
||||
|
||||
// Set reference time if we haven't already. This is done here when rendering
|
||||
// starts so that we begin counting from the time the control is actually
|
||||
// visible rather than from its onWake() (which may be a considerable time
|
||||
// before the control actually gets to render).
|
||||
|
||||
if( !mStartTime )
|
||||
mStartTime = Platform::getRealMilliseconds();
|
||||
|
||||
// Compute overlay alpha.
|
||||
|
||||
U32 elapsed = Platform::getRealMilliseconds() - mStartTime;
|
||||
|
||||
U32 alpha;
|
||||
if( elapsed < mFadeInTime )
|
||||
{
|
||||
// fade-in
|
||||
alpha = 255.f * ( 1.0f - mFadeInEase.getValue( elapsed, 0.f, 1.f, mFadeInTime ) );
|
||||
}
|
||||
else if( elapsed < ( mFadeInTime + mWaitTime ) )
|
||||
{
|
||||
// wait
|
||||
alpha = 0;
|
||||
}
|
||||
else if( elapsed < ( mFadeInTime + mWaitTime + mFadeOutTime ) )
|
||||
{
|
||||
// fade out
|
||||
elapsed -= ( mFadeInTime + mWaitTime );
|
||||
alpha = mFadeOutEase.getValue( elapsed, 0.f, 255.f, mFadeOutTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
// done state
|
||||
alpha = mFadeOutTime ? 255 : 0;
|
||||
mDone = true;
|
||||
|
||||
// Trigger onDone callback except when in Gui Editor.
|
||||
|
||||
if( !smDesignTime )
|
||||
onDone_callback();
|
||||
}
|
||||
|
||||
// Render overlay on top of bitmap.
|
||||
|
||||
ColorI color = mFadeColor;
|
||||
color.alpha = alpha;
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill( offset, getExtent() + offset, color );
|
||||
}
|
||||
89
Engine/source/gui/game/guiFadeinBitmapCtrl.h
Normal file
89
Engine/source/gui/game/guiFadeinBitmapCtrl.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIFADEINBITMAPCTRL_H_
|
||||
#define _GUIFADEINBITMAPCTRL_H_
|
||||
|
||||
#ifndef _GUIBITMAPCTRL_H_
|
||||
#include "gui/controls/guiBitmapCtrl.h"
|
||||
#endif
|
||||
#ifndef _MEASE_H_
|
||||
#include "math/mEase.h"
|
||||
#endif
|
||||
|
||||
|
||||
/// A control that fades a bitmap in and out.
|
||||
class GuiFadeinBitmapCtrl : public GuiBitmapCtrl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiBitmapCtrl Parent;
|
||||
|
||||
protected:
|
||||
|
||||
/// Color we fade in from and fade out to.
|
||||
ColorF mFadeColor;
|
||||
|
||||
/// Reference time on which to base all fade timings.
|
||||
U32 mStartTime;
|
||||
|
||||
/// Milliseconds for bitmap to fade in.
|
||||
U32 mFadeInTime;
|
||||
|
||||
/// Milliseconds to wait before fade-out.
|
||||
U32 mWaitTime;
|
||||
|
||||
/// Milliseconds for bitmap to fade out.
|
||||
U32 mFadeOutTime;
|
||||
|
||||
/// Easing curve for fade-in.
|
||||
EaseF mFadeInEase;
|
||||
|
||||
/// Easing curve for fade-out.
|
||||
EaseF mFadeOutEase;
|
||||
|
||||
/// Whether the fade cycle has run completely.
|
||||
bool mDone;
|
||||
|
||||
public:
|
||||
|
||||
GuiFadeinBitmapCtrl();
|
||||
|
||||
// GuiControl.
|
||||
virtual void onPreRender();
|
||||
virtual void onMouseDown(const GuiEvent &);
|
||||
virtual bool onKeyDown(const GuiEvent &);
|
||||
virtual bool onWake();
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect);
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT( GuiFadeinBitmapCtrl );
|
||||
DECLARE_DESCRIPTION( "A control that shows a bitmap. It fades the bitmap in a set amount of time,\n"
|
||||
"then waits a set amount of time, and finally fades the bitmap back out in\n"
|
||||
"another set amount of time." );
|
||||
|
||||
DECLARE_CALLBACK( void, click, ());
|
||||
DECLARE_CALLBACK( void, onDone, ());
|
||||
};
|
||||
|
||||
#endif // !_GUIFADEINBITMAPCTRL_H_
|
||||
189
Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp
Normal file
189
Engine/source/gui/game/guiIdleCamFadeBitmapCtrl.cpp
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "gfx/gfxDrawUtil.h"
|
||||
|
||||
|
||||
class GuiIdleCamFadeBitmapCtrl : public GuiBitmapCtrl
|
||||
{
|
||||
typedef GuiBitmapCtrl Parent;
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiIdleCamFadeBitmapCtrl);
|
||||
DECLARE_CATEGORY( "Gui Images" );
|
||||
|
||||
U32 wakeTime;
|
||||
bool done;
|
||||
U32 fadeinTime;
|
||||
U32 fadeoutTime;
|
||||
bool doFadeIn;
|
||||
bool doFadeOut;
|
||||
|
||||
GuiIdleCamFadeBitmapCtrl()
|
||||
{
|
||||
wakeTime = 0;
|
||||
fadeinTime = 1000;
|
||||
fadeoutTime = 1000;
|
||||
done = false;
|
||||
|
||||
doFadeIn = false;
|
||||
doFadeOut = false;
|
||||
}
|
||||
void onPreRender()
|
||||
{
|
||||
Parent::onPreRender();
|
||||
setUpdate();
|
||||
}
|
||||
void onMouseDown(const GuiEvent &)
|
||||
{
|
||||
Con::executef(this, "click");
|
||||
}
|
||||
bool onKeyDown(const GuiEvent &)
|
||||
{
|
||||
Con::executef(this, "click");
|
||||
return true;
|
||||
}
|
||||
bool onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return false;
|
||||
wakeTime = Platform::getRealMilliseconds();
|
||||
return true;
|
||||
}
|
||||
|
||||
void fadeIn()
|
||||
{
|
||||
wakeTime = Platform::getRealMilliseconds();
|
||||
doFadeIn = true;
|
||||
doFadeOut = false;
|
||||
done = false;
|
||||
}
|
||||
|
||||
void fadeOut()
|
||||
{
|
||||
wakeTime = Platform::getRealMilliseconds();
|
||||
doFadeIn = false;
|
||||
doFadeOut = true;
|
||||
done = false;
|
||||
}
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
U32 elapsed = Platform::getRealMilliseconds() - wakeTime;
|
||||
|
||||
U32 alpha;
|
||||
if (doFadeOut && elapsed < fadeoutTime)
|
||||
{
|
||||
// fade out
|
||||
alpha = 255 - (255 * (F32(elapsed) / F32(fadeoutTime)));
|
||||
}
|
||||
else if (doFadeIn && elapsed < fadeinTime)
|
||||
{
|
||||
// fade in
|
||||
alpha = 255 * F32(elapsed) / F32(fadeinTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// done state
|
||||
alpha = doFadeIn ? 255 : 0;
|
||||
done = true;
|
||||
}
|
||||
|
||||
ColorI color(255,255,255,alpha);
|
||||
if (mTextureObject)
|
||||
{
|
||||
GFX->getDrawUtil()->setBitmapModulation(color);
|
||||
|
||||
if(mWrap)
|
||||
{
|
||||
|
||||
GFXTextureObject* texture = mTextureObject;
|
||||
RectI srcRegion;
|
||||
RectI dstRegion;
|
||||
float xdone = ((float)getExtent().x/(float)texture->mBitmapSize.x)+1;
|
||||
float ydone = ((float)getExtent().y/(float)texture->mBitmapSize.y)+1;
|
||||
|
||||
int xshift = mStartPoint.x%texture->mBitmapSize.x;
|
||||
int yshift = mStartPoint.y%texture->mBitmapSize.y;
|
||||
for(int y = 0; y < ydone; ++y)
|
||||
for(int 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);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
RectI rect(offset, getExtent());
|
||||
GFX->getDrawUtil()->drawBitmapStretch(mTextureObject, rect);
|
||||
}
|
||||
}
|
||||
|
||||
if (mProfile->mBorder || !mTextureObject)
|
||||
{
|
||||
RectI rect(offset.x, offset.y, getExtent().x, getExtent().y);
|
||||
ColorI borderCol(mProfile->mBorderColor);
|
||||
borderCol.alpha = alpha;
|
||||
GFX->getDrawUtil()->drawRect(rect, borderCol);
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect);
|
||||
}
|
||||
|
||||
static void initPersistFields()
|
||||
{
|
||||
addField("fadeinTime", TypeS32, Offset(fadeinTime, GuiIdleCamFadeBitmapCtrl));
|
||||
addField("fadeoutTime", TypeS32, Offset(fadeoutTime, GuiIdleCamFadeBitmapCtrl));
|
||||
addField("done", TypeBool, Offset(done, GuiIdleCamFadeBitmapCtrl));
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiIdleCamFadeBitmapCtrl);
|
||||
|
||||
ConsoleDocClass( GuiIdleCamFadeBitmapCtrl,
|
||||
"@brief GUI that will fade the current view in and out.\n\n"
|
||||
"Main difference between this and FadeinBitmap is this appears to "
|
||||
"fade based on the source texture.\n\n"
|
||||
"This is going to be deprecated, and any useful code ported to FadeinBitmap\n\n"
|
||||
"@internal");
|
||||
|
||||
ConsoleMethod(GuiIdleCamFadeBitmapCtrl, fadeIn, void, 2, 2, "()"
|
||||
"@internal")
|
||||
{
|
||||
object->fadeIn();
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiIdleCamFadeBitmapCtrl, fadeOut, void, 2, 2, "()"
|
||||
"@internal")
|
||||
{
|
||||
object->fadeOut();
|
||||
}
|
||||
918
Engine/source/gui/game/guiMessageVectorCtrl.cpp
Normal file
918
Engine/source/gui/game/guiMessageVectorCtrl.cpp
Normal file
|
|
@ -0,0 +1,918 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/game/guiMessageVectorCtrl.h"
|
||||
|
||||
#include "gui/utility/messageVector.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gui/containers/guiScrollCtrl.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiMessageVectorCtrl);
|
||||
|
||||
ConsoleDocClass( GuiMessageVectorCtrl,
|
||||
"@brief A chat HUD control that displays messages from a MessageVector.\n\n"
|
||||
|
||||
"This renders messages from a MessageVector; the important thing "
|
||||
"here is that the MessageVector holds all the messages we care "
|
||||
"about, while we can destroy and create these GUI controls as "
|
||||
"needed.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// Declare ChatHud, which is what will display the actual chat from a MessageVector\n"
|
||||
"new GuiMessageVectorCtrl(ChatHud) {\n"
|
||||
" profile = \"ChatHudMessageProfile\";\n"
|
||||
" horizSizing = \"width\";\n"
|
||||
" vertSizing = \"height\";\n"
|
||||
" position = \"1 1\";\n"
|
||||
" extent = \"252 16\";\n"
|
||||
" minExtent = \"8 8\";\n"
|
||||
" visible = \"1\";\n"
|
||||
" helpTag = \"0\";\n"
|
||||
" lineSpacing = \"0\";\n"
|
||||
" lineContinuedIndex = \"10\";\n"
|
||||
" matchColor = \"0 0 255 255\";\n"
|
||||
" maxColorIndex = \"5\";\n"
|
||||
"};\n\n"
|
||||
"// All messages are stored in this HudMessageVector, the actual\n"
|
||||
"// MainChatHud only displays the contents of this vector.\n"
|
||||
"new MessageVector(HudMessageVector);\n\n"
|
||||
"// Attach the MessageVector to the chat control\n"
|
||||
"chatHud.attach(HudMessageVector);\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see MessageVector for more details on how this is used\n"
|
||||
|
||||
"@ingroup GuiUtil\n");
|
||||
|
||||
|
||||
//-------------------------------------- Console functions
|
||||
DefineEngineMethod( GuiMessageVectorCtrl, attach, bool, ( MessageVector* item),,
|
||||
"@brief Push a line onto the back of the list.\n\n"
|
||||
|
||||
"@param item The GUI element being pushed into the control\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// All messages are stored in this HudMessageVector, the actual\n"
|
||||
"// MainChatHud only displays the contents of this vector.\n"
|
||||
"new MessageVector(HudMessageVector);\n\n"
|
||||
"// Attach the MessageVector to the chat control\n"
|
||||
"chatHud.attach(HudMessageVector);\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@return Value")
|
||||
{
|
||||
if (item == NULL)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "Could not find MessageVector: %s", item);
|
||||
return false;
|
||||
}
|
||||
|
||||
return object->attach(item);
|
||||
}
|
||||
|
||||
//ConsoleMethod(GuiMessageVectorCtrl, attach, bool, 3, 3, "(MessageVector item)"
|
||||
// "Make this gui control display messages from the specified MessageVector")
|
||||
//{
|
||||
// MessageVector* pMV = NULL;
|
||||
// Sim::findObject(argv[2], pMV);
|
||||
// if (pMV == NULL) {
|
||||
// Con::errorf(ConsoleLogEntry::General, "Could not find MessageVector: %s", argv[2]);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return object->attach(pMV);
|
||||
//}
|
||||
|
||||
DefineEngineMethod( GuiMessageVectorCtrl, detach, void, (),,
|
||||
"@brief Stop listing messages from the MessageVector previously attached to, if any.\n\n"
|
||||
|
||||
"Detailed description\n\n"
|
||||
|
||||
"@param param Description\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// Deatch the MessageVector from HudMessageVector\n"
|
||||
"// HudMessageVector will no longer render the text\n"
|
||||
"chatHud.detach();\n"
|
||||
"@endtsexample\n\n")
|
||||
{
|
||||
if (object->isAttached() == false)
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl: double detach");
|
||||
return;
|
||||
}
|
||||
|
||||
object->detach();
|
||||
}
|
||||
|
||||
//ConsoleMethod(GuiMessageVectorCtrl, detach, void, 2, 2, "()"
|
||||
// "Stop listing messages from the MessageVector previously attached to, if any.")
|
||||
//{
|
||||
// if (object->isAttached() == false) {
|
||||
// Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl: double detach");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// object->detach();
|
||||
//}
|
||||
|
||||
struct TempLineBreak
|
||||
{
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Callback for messageVector
|
||||
void sMVCtrlCallback(void * spectatorKey,
|
||||
const MessageVector::MessageCode code,
|
||||
const U32 argument)
|
||||
{
|
||||
GuiMessageVectorCtrl* pMVC = reinterpret_cast<GuiMessageVectorCtrl*>(spectatorKey);
|
||||
pMVC->callbackRouter(code, argument);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiMessageVectorCtrl::GuiMessageVectorCtrl()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mLineWrappings);
|
||||
VECTOR_SET_ASSOCIATION(mSpecialMarkers);
|
||||
VECTOR_SET_ASSOCIATION(mLineElements);
|
||||
|
||||
mMessageVector = NULL;
|
||||
mLineSpacingPixels = 0;
|
||||
mLineContinuationIndent = 10;
|
||||
|
||||
mMouseDown = false;
|
||||
mMouseSpecialLine = -1;
|
||||
mMouseSpecialRef = -1;
|
||||
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
mAllowedMatches[i] = "";
|
||||
mSpecialColor.set(0, 0, 255);
|
||||
|
||||
mMaxColorIndex = 9;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiMessageVectorCtrl::~GuiMessageVectorCtrl()
|
||||
{
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
AssertFatal(mSpecialMarkers.size() == 0, "Error, special markers not properly cleared!");
|
||||
AssertFatal(mLineElements.size() == 0, "Error, line elements not properly cleared!");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::initPersistFields()
|
||||
{
|
||||
addField("lineSpacing", TypeS32, Offset(mLineSpacingPixels, GuiMessageVectorCtrl));
|
||||
addField("lineContinuedIndex", TypeS32, Offset(mLineContinuationIndent, GuiMessageVectorCtrl));
|
||||
addField("allowedMatches", TypeString, Offset(mAllowedMatches, GuiMessageVectorCtrl), 16);
|
||||
addField("matchColor", TypeColorI, Offset(mSpecialColor, GuiMessageVectorCtrl));
|
||||
addField("maxColorIndex", TypeS32, Offset(mMaxColorIndex, GuiMessageVectorCtrl));
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
||||
bool GuiMessageVectorCtrl::onAdd()
|
||||
{
|
||||
return Parent::onAdd();
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiMessageVectorCtrl::isAttached() const
|
||||
{
|
||||
return (mMessageVector != NULL);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiMessageVectorCtrl::attach(MessageVector* newAttachment)
|
||||
{
|
||||
AssertFatal(newAttachment, "No attachment!");
|
||||
if (newAttachment == NULL || !isAwake())
|
||||
return false;
|
||||
|
||||
if (isAttached()) {
|
||||
Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl::attach: overriding attachment");
|
||||
detach();
|
||||
}
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
|
||||
mMessageVector = newAttachment;
|
||||
mMessageVector->registerSpectator(sMVCtrlCallback, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::detach()
|
||||
{
|
||||
if (isAttached() == false) {
|
||||
Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl::detach: not attached!");
|
||||
return;
|
||||
}
|
||||
|
||||
mMessageVector->unregisterSpectator(this);
|
||||
mMessageVector = NULL;
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::lineInserted(const U32 arg)
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
|
||||
GuiScrollCtrl* pScroll = dynamic_cast<GuiScrollCtrl*>(getParent());
|
||||
bool fullyScrolled = pScroll->isScrolledToBottom();
|
||||
|
||||
mSpecialMarkers.insert(arg);
|
||||
createSpecialMarkers(mSpecialMarkers[arg], mMessageVector->getLine(arg).message);
|
||||
|
||||
mLineWrappings.insert(arg);
|
||||
createLineWrapping(mLineWrappings[arg], mMessageVector->getLine(arg).message);
|
||||
|
||||
mLineElements.insert(arg);
|
||||
createLineElement(mLineElements[arg], mLineWrappings[arg], mSpecialMarkers[arg]);
|
||||
|
||||
U32 numLines = 0;
|
||||
for (U32 i = 0; i < mLineWrappings.size(); i++) {
|
||||
// We need to rebuild the physicalLineStart markers at the same time as
|
||||
// we find out how many of them are left...
|
||||
mLineElements[i].physicalLineStart = numLines;
|
||||
|
||||
numLines += mLineWrappings[i].numLines;
|
||||
}
|
||||
|
||||
Point2I newExtent = getExtent();
|
||||
newExtent.y = (mProfile->mFont->getHeight() + mLineSpacingPixels) * getMax(numLines, U32(1));
|
||||
setExtent(newExtent);
|
||||
if(fullyScrolled)
|
||||
pScroll->scrollTo(0, 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::lineDeleted(const U32 arg)
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
AssertFatal(arg < mLineWrappings.size(), "Error, out of bounds line deleted!");
|
||||
|
||||
// It's a somewhat involved process to delete the lineelements...
|
||||
LineElement& rElement = mLineElements[arg];
|
||||
|
||||
TextElement* walk = rElement.headLineElements;
|
||||
while (walk != NULL) {
|
||||
TextElement* lineWalk = walk->nextInLine;
|
||||
while (lineWalk != NULL) {
|
||||
TextElement* temp = lineWalk;
|
||||
lineWalk = lineWalk->nextPhysicalLine;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
TextElement* temp = walk;
|
||||
walk = walk->nextPhysicalLine;
|
||||
delete temp;
|
||||
}
|
||||
rElement.headLineElements = NULL;
|
||||
mLineElements.erase(arg);
|
||||
|
||||
delete [] mLineWrappings[arg].startEndPairs;
|
||||
mLineWrappings.erase(arg);
|
||||
|
||||
delete [] mSpecialMarkers[arg].specials;
|
||||
mSpecialMarkers.erase(arg);
|
||||
|
||||
U32 numLines = 0;
|
||||
for (U32 i = 0; i < mLineWrappings.size(); i++) {
|
||||
// We need to rebuild the physicalLineStart markers at the same time as
|
||||
// we find out how many of them are left...
|
||||
mLineElements[i].physicalLineStart = numLines;
|
||||
|
||||
numLines += mLineWrappings[i].numLines;
|
||||
}
|
||||
|
||||
U32 newHeight = (mProfile->mFont->getHeight() + mLineSpacingPixels) * getMax(numLines, U32(1));
|
||||
resize(getPosition(), Point2I(getWidth(), newHeight));
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::vectorDeleted()
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared out!");
|
||||
|
||||
mMessageVector = NULL;
|
||||
U32 newHeight = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
resize(getPosition(), Point2I(getWidth(), newHeight));
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::callbackRouter(const MessageVector::MessageCode code,
|
||||
const U32 arg)
|
||||
{
|
||||
switch (code) {
|
||||
case MessageVector::LineInserted:
|
||||
lineInserted(arg);
|
||||
break;
|
||||
case MessageVector::LineDeleted:
|
||||
lineDeleted(arg);
|
||||
break;
|
||||
case MessageVector::VectorDeletion:
|
||||
vectorDeleted();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::createSpecialMarkers(SpecialMarkers& rSpecial, const char* string)
|
||||
{
|
||||
// The first thing we need to do is create a version of the string with no uppercase
|
||||
// chars for matching...
|
||||
|
||||
String pLCCopyStr = String::ToLower( string );
|
||||
const char* pLCCopy = pLCCopyStr.c_str();
|
||||
|
||||
Vector<TempLineBreak> tempSpecials(__FILE__, __LINE__);
|
||||
Vector<S32> tempTypes(__FILE__, __LINE__);
|
||||
|
||||
const char* pCurr = pLCCopy;
|
||||
while (pCurr[0] != '\0') {
|
||||
const char* pMinMatch = &pLCCopy[dStrlen(string)];
|
||||
U32 minMatchType = 0xFFFFFFFF;
|
||||
AssertFatal(pMinMatch[0] == '\0', "Error, bad positioning of sentry...");
|
||||
|
||||
// Find the earliest match
|
||||
for (U32 i = 0; i < 16; i++) {
|
||||
if (mAllowedMatches[i][0] == '\0')
|
||||
continue;
|
||||
|
||||
const char* pMatch = dStrstr(pCurr, mAllowedMatches[i]);
|
||||
if (pMatch != NULL && pMatch < pMinMatch) {
|
||||
pMinMatch = pMatch;
|
||||
minMatchType = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (pMinMatch[0] != '\0') {
|
||||
AssertFatal(minMatchType != 0xFFFFFFFF, "Hm, that's bad");
|
||||
// Found a match => now find the end
|
||||
U32 start = pMinMatch - pLCCopy;
|
||||
U32 j;
|
||||
for (j = 1; pLCCopy[start + j] != '\0'; j++) {
|
||||
if (pLCCopy[start + j] == '\n' ||
|
||||
pLCCopy[start + j] == ' ' ||
|
||||
pLCCopy[start + j] == '\t')
|
||||
break;
|
||||
}
|
||||
AssertFatal(j > 0, "Error, j must be > 0 at this point!");
|
||||
U32 end = start + j - 1;
|
||||
|
||||
tempSpecials.increment();
|
||||
tempSpecials.last().start = start;
|
||||
tempSpecials.last().end = end;
|
||||
tempTypes.push_back(minMatchType);
|
||||
|
||||
pCurr = &pLCCopy[end + 1];
|
||||
} else {
|
||||
// No match. This will cause the while loop to terminate...
|
||||
pCurr = pMinMatch;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rSpecial.numSpecials = tempSpecials.size()) != 0) {
|
||||
rSpecial.specials = new SpecialMarkers::Special[tempSpecials.size()];
|
||||
for (U32 i = 0; i < tempSpecials.size(); i++) {
|
||||
rSpecial.specials[i].start = tempSpecials[i].start;
|
||||
rSpecial.specials[i].end = tempSpecials[i].end;
|
||||
rSpecial.specials[i].specialType = tempTypes[i];
|
||||
}
|
||||
} else {
|
||||
rSpecial.specials = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::createLineWrapping(LineWrapping& rWrapping, const char* string)
|
||||
{
|
||||
Vector<TempLineBreak> tempBreaks(__FILE__, __LINE__);
|
||||
|
||||
U32 i;
|
||||
U32 currStart = 0;
|
||||
U32 length = dStrlen(string);
|
||||
if (length != 0) {
|
||||
for (i = 0; i < length; i++) {
|
||||
if (string[i] == '\n') {
|
||||
tempBreaks.increment();
|
||||
tempBreaks.last().start = currStart;
|
||||
tempBreaks.last().end = i-1;
|
||||
currStart = i+1;
|
||||
} else if (i == length - 1) {
|
||||
tempBreaks.increment();
|
||||
tempBreaks.last().start = currStart;
|
||||
tempBreaks.last().end = i;
|
||||
currStart = i+1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tempBreaks.increment();
|
||||
tempBreaks.last().start = 0;
|
||||
tempBreaks.last().end = -1;
|
||||
}
|
||||
|
||||
U32 splitWidth = getWidth();
|
||||
U32 currLine = 0;
|
||||
while (currLine < tempBreaks.size()) {
|
||||
TempLineBreak& rLine = tempBreaks[currLine];
|
||||
if (rLine.start >= rLine.end) {
|
||||
if (currLine == 0)
|
||||
splitWidth -= mLineContinuationIndent;
|
||||
currLine++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, there's some actual text in this line. How long is it?
|
||||
U32 baseLength = mProfile->mFont->getStrNWidthPrecise((const UTF8 *)&string[rLine.start], rLine.end-rLine.start+1);
|
||||
if (baseLength > splitWidth) {
|
||||
// DMMNOTE: Replace with bin search eventually
|
||||
U32 currPos = 0;
|
||||
U32 breakPos = 0;
|
||||
for (currPos = 0; currPos < rLine.end-rLine.start+1; currPos++) {
|
||||
U32 currLength = mProfile->mFont->getStrNWidthPrecise((const UTF8 *)&string[rLine.start], currPos+1);
|
||||
if (currLength > splitWidth)
|
||||
{
|
||||
// Make sure that the currPos has advanced, then set the breakPoint.
|
||||
breakPos = currPos != 0 ? currPos - 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currPos == rLine.end-rLine.start+1) {
|
||||
AssertFatal(false, "Error, if the line must be broken, the position must be before this point!");
|
||||
currLine++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, the character at breakPos is the last valid char we can render. We
|
||||
// want to scan back to the first whitespace character (which, in the bounds
|
||||
// of the line, is guaranteed to be a space or a tab).
|
||||
U32 originalBreak = breakPos;
|
||||
while (true) {
|
||||
if (string[rLine.start + breakPos] == ' ' || string[rLine.start + breakPos] == '\t') {
|
||||
break;
|
||||
} else {
|
||||
AssertFatal(string[rLine.start + breakPos] != '\n',
|
||||
"Bad characters in line range...");
|
||||
if (breakPos == 0) {
|
||||
breakPos = originalBreak;
|
||||
break;
|
||||
}
|
||||
breakPos--;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, everything up to and including breakPos is in the currentLine. Insert
|
||||
// a new line at this point, and put everything after in that line.
|
||||
S32 oldStart = rLine.start;
|
||||
S32 oldEnd = rLine.end;
|
||||
rLine.end = rLine.start + breakPos;
|
||||
|
||||
// Note that rLine is NOTNOTNOTNOT valid after this point!
|
||||
tempBreaks.insert(currLine+1);
|
||||
tempBreaks[currLine+1].start = oldStart + breakPos + 1;
|
||||
tempBreaks[currLine+1].end = oldEnd;
|
||||
}
|
||||
|
||||
if (currLine == 0)
|
||||
splitWidth -= mLineContinuationIndent;
|
||||
currLine++;
|
||||
}
|
||||
|
||||
rWrapping.numLines = tempBreaks.size();
|
||||
rWrapping.startEndPairs = new LineWrapping::SEPair[tempBreaks.size()];
|
||||
for (i = 0; i < tempBreaks.size(); i++) {
|
||||
rWrapping.startEndPairs[i].start = tempBreaks[i].start;
|
||||
rWrapping.startEndPairs[i].end = tempBreaks[i].end;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::createLineElement(LineElement& rElement,
|
||||
LineWrapping& rWrapping,
|
||||
SpecialMarkers& rSpecial)
|
||||
{
|
||||
// First, do a straighforward translation of the wrapping...
|
||||
TextElement** ppWalk = &rElement.headLineElements;
|
||||
for (U32 i = 0; i < rWrapping.numLines; i++) {
|
||||
*ppWalk = new TextElement;
|
||||
|
||||
(*ppWalk)->nextInLine = NULL;
|
||||
(*ppWalk)->nextPhysicalLine = NULL;
|
||||
(*ppWalk)->specialReference = -1;
|
||||
|
||||
(*ppWalk)->start = rWrapping.startEndPairs[i].start;
|
||||
(*ppWalk)->end = rWrapping.startEndPairs[i].end;
|
||||
|
||||
ppWalk = &((*ppWalk)->nextPhysicalLine);
|
||||
}
|
||||
|
||||
if (rSpecial.numSpecials != 0) {
|
||||
// Ok. Now, walk down the lines, and split the elements into their constituent parts...
|
||||
//
|
||||
TextElement* walk = rElement.headLineElements;
|
||||
while (walk) {
|
||||
TextElement* walkAcross = walk;
|
||||
while (walkAcross) {
|
||||
S32 specialMatch = -1;
|
||||
for (U32 i = 0; i < rSpecial.numSpecials; i++) {
|
||||
if (walkAcross->start <= rSpecial.specials[i].end &&
|
||||
walkAcross->end >= rSpecial.specials[i].start) {
|
||||
specialMatch = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialMatch != -1) {
|
||||
// We have a match here. Break it into the appropriate number of segments.
|
||||
// this will vary depending on how the overlap is occuring...
|
||||
if (walkAcross->start >= rSpecial.specials[specialMatch].start) {
|
||||
if (walkAcross->end <= rSpecial.specials[specialMatch].end) {
|
||||
// The whole thing is part of the special
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->specialReference = specialMatch;
|
||||
} else {
|
||||
// The first part is in the special, the tail is out
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->specialReference = -1;
|
||||
|
||||
walkAcross->specialReference = specialMatch;
|
||||
walkAcross->nextInLine->end = walkAcross->end;
|
||||
walkAcross->end = rSpecial.specials[specialMatch].end;
|
||||
walkAcross->nextInLine->start = rSpecial.specials[specialMatch].end + 1;
|
||||
|
||||
AssertFatal(walkAcross->end >= walkAcross->start && walkAcross->nextInLine->end >= walkAcross->nextInLine->start, "Bad textelements generated!");
|
||||
}
|
||||
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
} else {
|
||||
if (walkAcross->end <= rSpecial.specials[specialMatch].end) {
|
||||
// The first part is out of the special, the second part in.
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->specialReference = specialMatch;
|
||||
|
||||
walkAcross->specialReference = -1;
|
||||
walkAcross->nextInLine->end = walkAcross->end;
|
||||
walkAcross->end = rSpecial.specials[specialMatch].start - 1;
|
||||
walkAcross->nextInLine->start = rSpecial.specials[specialMatch].start;
|
||||
|
||||
AssertFatal(walkAcross->end >= walkAcross->start && walkAcross->nextInLine->end >= walkAcross->nextInLine->start, "Bad textelements generated!");
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
} else {
|
||||
// First out, middle in, last out. Oy.
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->specialReference = specialMatch;
|
||||
|
||||
walkAcross->nextInLine->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->nextInLine->specialReference = -1;
|
||||
|
||||
walkAcross->nextInLine->start = rSpecial.specials[specialMatch].start;
|
||||
walkAcross->nextInLine->end = rSpecial.specials[specialMatch].end;
|
||||
walkAcross->nextInLine->nextInLine->start = rSpecial.specials[specialMatch].end+1;
|
||||
walkAcross->nextInLine->nextInLine->end = walkAcross->end;
|
||||
walkAcross->end = walkAcross->nextInLine->start - 1;
|
||||
AssertFatal((walkAcross->end >= walkAcross->start &&
|
||||
walkAcross->nextInLine->end >= walkAcross->nextInLine->start &&
|
||||
walkAcross->nextInLine->nextInLine->end >= walkAcross->nextInLine->nextInLine->start),
|
||||
"Bad textelements generated!");
|
||||
walkAcross = walkAcross->nextInLine->nextInLine;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
}
|
||||
}
|
||||
|
||||
walk = walk->nextPhysicalLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiMessageVectorCtrl::onWake()
|
||||
{
|
||||
if (Parent::onWake() == false)
|
||||
return false;
|
||||
|
||||
if (bool(mProfile->mFont) == false)
|
||||
return false;
|
||||
|
||||
mMinSensibleWidth = 1;
|
||||
|
||||
for (U32 i = 0; i < 256; i++) {
|
||||
if (mProfile->mFont->isValidChar(U8(i))) {
|
||||
if (mProfile->mFont->getCharWidth(U8(i)) > mMinSensibleWidth)
|
||||
mMinSensibleWidth = mProfile->mFont->getCharWidth(U8(i));
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::onSleep()
|
||||
{
|
||||
if (isAttached())
|
||||
detach();
|
||||
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::onRender(Point2I offset,
|
||||
const RectI& updateRect)
|
||||
{
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
Parent::onRender(offset, updateRect);
|
||||
if (isAttached()) {
|
||||
U32 linePixels = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
U32 currLine = 0;
|
||||
ColorI lastColor = mProfile->mFontColor;
|
||||
for (U32 i = 0; i < mMessageVector->getNumLines(); i++) {
|
||||
|
||||
TextElement* pElement = mLineElements[i].headLineElements;
|
||||
while (pElement != NULL) {
|
||||
Point2I localStart(pElement == mLineElements[i].headLineElements ? 0 : mLineContinuationIndent, currLine * linePixels);
|
||||
|
||||
Point2I globalCheck = localToGlobalCoord(localStart);
|
||||
U32 globalRangeStart = globalCheck.y;
|
||||
U32 globalRangeEnd = globalCheck.y + mProfile->mFont->getHeight();
|
||||
if (globalRangeStart > updateRect.point.y + updateRect.extent.y ||
|
||||
globalRangeEnd < updateRect.point.y) {
|
||||
currLine++;
|
||||
pElement = pElement->nextPhysicalLine;
|
||||
continue;
|
||||
}
|
||||
|
||||
TextElement* walkAcross = pElement;
|
||||
while (walkAcross) {
|
||||
if (walkAcross->start > walkAcross->end)
|
||||
break;
|
||||
|
||||
Point2I globalStart = localToGlobalCoord(localStart);
|
||||
|
||||
U32 strWidth;
|
||||
if (walkAcross->specialReference == -1) {
|
||||
drawer->setBitmapModulation(lastColor);
|
||||
drawer->setTextAnchorColor(mProfile->mFontColor);
|
||||
strWidth = drawer->drawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
||||
walkAcross->end - walkAcross->start + 1, mProfile->mFontColors, mMaxColorIndex);
|
||||
drawer->getBitmapModulation(&lastColor); // in case an embedded color tag changed it
|
||||
} else {
|
||||
drawer->getBitmapModulation( &lastColor );
|
||||
drawer->setBitmapModulation(mSpecialColor);
|
||||
drawer->setTextAnchorColor(mProfile->mFontColor);
|
||||
strWidth = drawer->drawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
||||
walkAcross->end - walkAcross->start + 1);
|
||||
|
||||
// in case we have 2 in a row...
|
||||
drawer->setBitmapModulation(lastColor);
|
||||
}
|
||||
|
||||
// drawTextN returns the rightmost X coord, so subtract leftmost coord to get the width
|
||||
strWidth -= globalStart.x;
|
||||
|
||||
if (walkAcross->specialReference != -1) {
|
||||
Point2I lineStart = localStart;
|
||||
Point2I lineEnd = localStart;
|
||||
lineStart.y += mProfile->mFont->getBaseline() + 1;
|
||||
lineEnd.x += strWidth;
|
||||
lineEnd.y += mProfile->mFont->getBaseline() + 1;
|
||||
|
||||
drawer->drawLine(localToGlobalCoord(lineStart),
|
||||
localToGlobalCoord(lineEnd),
|
||||
mSpecialColor);
|
||||
}
|
||||
|
||||
localStart.x += strWidth;
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
}
|
||||
|
||||
currLine++;
|
||||
pElement = pElement->nextPhysicalLine;
|
||||
}
|
||||
}
|
||||
drawer->clearBitmapModulation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::parentResized(const RectI& oldParentRect, const RectI& newParentRect)
|
||||
{
|
||||
Parent::parentResized(oldParentRect, newParentRect);
|
||||
|
||||
// If we have a MesssageVector, detach/reattach so we can reflow the text.
|
||||
if (mMessageVector)
|
||||
{
|
||||
MessageVector *reflowme = mMessageVector;
|
||||
|
||||
detach();
|
||||
attach(reflowme);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::findSpecialFromCoord(const Point2I& point, S32* specialLine, S32* specialRef)
|
||||
{
|
||||
if (mLineElements.size() == 0) {
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
U32 linePixels = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
|
||||
if ((point.x < 0 || point.x >= getWidth()) ||
|
||||
(point.y < 0 || point.y >= getHeight())) {
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ok, we have real work to do here. Let's determine the physical line that it's on...
|
||||
U32 physLine = point.y / linePixels;
|
||||
AssertFatal(physLine >= 0, "Bad physical line!");
|
||||
|
||||
// And now we find the LineElement that contains that physicalLine...
|
||||
U32 elemIndex;
|
||||
for (elemIndex = 0; elemIndex < mLineElements.size(); elemIndex++) {
|
||||
if (mLineElements[elemIndex].physicalLineStart > physLine) {
|
||||
// We've passed it.
|
||||
AssertFatal(elemIndex != 0, "Error, bad elemIndex, check assumptions.");
|
||||
elemIndex--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (elemIndex == mLineElements.size()) {
|
||||
// On the last line...
|
||||
elemIndex = mLineElements.size() - 1;
|
||||
}
|
||||
|
||||
TextElement* line = mLineElements[elemIndex].headLineElements;
|
||||
for (U32 i = 0; i < physLine - mLineElements[elemIndex].physicalLineStart; i++)
|
||||
{
|
||||
if (line->nextPhysicalLine == NULL)
|
||||
{
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
line = line->nextPhysicalLine;
|
||||
AssertFatal(line != NULL, "Error, moved too far!");
|
||||
}
|
||||
|
||||
// Ok, line represents the current line. We now need to find out which textelement
|
||||
// the points x coord falls in.
|
||||
U32 currX = 0;
|
||||
if ((physLine - mLineElements[elemIndex].physicalLineStart) != 0) {
|
||||
currX = mLineContinuationIndent;
|
||||
// First, if this isn't the first line in this wrapping, we have to make sure
|
||||
// that the coord isn't in the margin...
|
||||
if (point.x < mLineContinuationIndent) {
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (line->start > line->end) {
|
||||
// Empty line special case...
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
while (line) {
|
||||
U32 newX = currX + mProfile->mFont->getStrNWidth((const UTF8 *)mMessageVector->getLine(elemIndex).message,
|
||||
line->end - line->start + 1);
|
||||
if (point.x < newX) {
|
||||
// That's the one!
|
||||
*specialLine = elemIndex;
|
||||
*specialRef = line->specialReference;
|
||||
return;
|
||||
}
|
||||
|
||||
currX = newX;
|
||||
line = line->nextInLine;
|
||||
}
|
||||
|
||||
// Off to the right. Aw...
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::onMouseDown(const GuiEvent& event)
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
mouseUnlock();
|
||||
|
||||
mMouseDown = true;
|
||||
|
||||
// Find the special we are in, if any...
|
||||
findSpecialFromCoord(globalToLocalCoord(event.mousePoint),
|
||||
&mMouseSpecialLine, &mMouseSpecialRef);
|
||||
}
|
||||
|
||||
void GuiMessageVectorCtrl::onMouseUp(const GuiEvent& event)
|
||||
{
|
||||
Parent::onMouseUp(event);
|
||||
mouseUnlock();
|
||||
|
||||
// Is this an up from a dragged click?
|
||||
if (mMouseDown == false)
|
||||
return;
|
||||
|
||||
// Find the special we are in, if any...
|
||||
|
||||
S32 currSpecialLine;
|
||||
S32 currSpecialRef;
|
||||
findSpecialFromCoord(globalToLocalCoord(event.mousePoint), &currSpecialLine, &currSpecialRef);
|
||||
|
||||
if (currSpecialRef != -1 &&
|
||||
(currSpecialLine == mMouseSpecialLine &&
|
||||
currSpecialRef == mMouseSpecialRef)) {
|
||||
// Execute the callback
|
||||
SpecialMarkers& rSpecial = mSpecialMarkers[currSpecialLine];
|
||||
S32 specialStart = rSpecial.specials[currSpecialRef].start;
|
||||
S32 specialEnd = rSpecial.specials[currSpecialRef].end;
|
||||
|
||||
char* copyURL = new char[specialEnd - specialStart + 2];
|
||||
dStrncpy(copyURL, &mMessageVector->getLine(currSpecialLine).message[specialStart], specialEnd - specialStart + 1);
|
||||
copyURL[specialEnd - specialStart + 1] = '\0';
|
||||
|
||||
Con::executef(this, "urlClickCallback", copyURL);
|
||||
delete [] copyURL;
|
||||
}
|
||||
|
||||
mMouseDown = false;
|
||||
mMouseSpecialLine = -1;
|
||||
mMouseSpecialRef = -1;
|
||||
}
|
||||
|
||||
156
Engine/source/gui/game/guiMessageVectorCtrl.h
Normal file
156
Engine/source/gui/game/guiMessageVectorCtrl.h
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIMESSAGEVECTORCTRL_H_
|
||||
#define _GUIMESSAGEVECTORCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
#ifndef _MESSAGEVECTOR_H_
|
||||
#include "gui/utility/messageVector.h"
|
||||
#endif
|
||||
|
||||
/// Render a MessageVector (chat HUD)
|
||||
///
|
||||
/// This renders messages from a MessageVector; the important thing
|
||||
/// here is that the MessageVector holds all the messages we care
|
||||
/// about, while we can destroy and create these GUI controls as
|
||||
/// needed. (For instance, Tribes 2 used seperate GuiMessageVectorCtrl
|
||||
/// controls in the different HUD modes.)
|
||||
class GuiMessageVectorCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
//-------------------------------------- Public interfaces...
|
||||
public:
|
||||
struct SpecialMarkers {
|
||||
struct Special {
|
||||
S32 specialType;
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
|
||||
U32 numSpecials;
|
||||
Special* specials;
|
||||
};
|
||||
|
||||
GuiMessageVectorCtrl();
|
||||
~GuiMessageVectorCtrl();
|
||||
|
||||
bool isAttached() const;
|
||||
bool attach(MessageVector*);
|
||||
void detach();
|
||||
|
||||
// Gui control overrides
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
void inspectPostApply();
|
||||
void parentResized(const RectI& oldParentRect, const RectI& newParentRect);
|
||||
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
// void onMouseMove(const GuiEvent &event);
|
||||
|
||||
// Overrideables
|
||||
protected:
|
||||
virtual void lineInserted(const U32);
|
||||
virtual void lineDeleted(const U32);
|
||||
virtual void vectorDeleted();
|
||||
|
||||
MessageVector* mMessageVector;
|
||||
|
||||
// Font resource
|
||||
protected:
|
||||
U32 mMinSensibleWidth;
|
||||
|
||||
U32 mLineSpacingPixels;
|
||||
U32 mLineContinuationIndent;
|
||||
|
||||
StringTableEntry mAllowedMatches[16];
|
||||
ColorI mSpecialColor;
|
||||
|
||||
U32 mMaxColorIndex;
|
||||
|
||||
bool mMouseDown;
|
||||
S32 mMouseSpecialLine;
|
||||
S32 mMouseSpecialRef;
|
||||
|
||||
/// Derived classes must keep this set of variables consistent if they
|
||||
/// use this classes onRender. Note that this has the fairly large
|
||||
/// disadvantage of requiring lots of ugly, tiny mem allocs. A rewrite
|
||||
/// to a more memory friendly version might be a good idea...
|
||||
struct LineWrapping {
|
||||
struct SEPair {
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
|
||||
U32 numLines;
|
||||
SEPair* startEndPairs; /// start[linex] = startEndPairs[linex*2+0]
|
||||
/// end[linex] = startEndPairs[linex*2+1]
|
||||
/// if end < start, line is empty...
|
||||
};
|
||||
|
||||
struct TextElement {
|
||||
TextElement* nextInLine;
|
||||
TextElement* nextPhysicalLine;
|
||||
|
||||
S32 specialReference; /// if (!= -1), indicates a special reference
|
||||
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
struct LineElement {
|
||||
U32 physicalLineStart;
|
||||
|
||||
TextElement* headLineElements;
|
||||
};
|
||||
|
||||
Vector<LineWrapping> mLineWrappings;
|
||||
Vector<SpecialMarkers> mSpecialMarkers;
|
||||
Vector<LineElement> mLineElements;
|
||||
|
||||
void createLineWrapping(LineWrapping&, const char*);
|
||||
void createSpecialMarkers(SpecialMarkers&, const char*);
|
||||
void createLineElement(LineElement&, LineWrapping&, SpecialMarkers&);
|
||||
|
||||
void findSpecialFromCoord(const Point2I&, S32*, S32*);
|
||||
|
||||
public:
|
||||
void callbackRouter(const MessageVector::MessageCode, const U32);
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CONOBJECT(GuiMessageVectorCtrl);
|
||||
DECLARE_CATEGORY( "Gui Game" );
|
||||
DECLARE_DESCRIPTION( "A chat HUD control that displays messages from a MessageVector." );
|
||||
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
#endif // _H_GUIMESSAGEVECTORCTRL_
|
||||
286
Engine/source/gui/game/guiProgressBitmapCtrl.cpp
Normal file
286
Engine/source/gui/game/guiProgressBitmapCtrl.cpp
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/game/guiProgressBitmapCtrl.h"
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT( GuiProgressBitmapCtrl );
|
||||
|
||||
ConsoleDocClass( GuiProgressBitmapCtrl,
|
||||
"@brief A horizontal progress bar rendered from a repeating image.\n\n"
|
||||
|
||||
"This class is used give progress feedback to the user. Unlike GuiProgressCtrl which simply "
|
||||
"renders a filled rectangle, GuiProgressBitmapCtrl renders the bar using a bitmap.\n\n"
|
||||
|
||||
"This bitmap can either be simple, plain image which is then stretched into the current extents of the bar "
|
||||
"as it fills up or it can be a bitmap array with three entries. In the case of a bitmap array, the "
|
||||
"first entry in the array is used to render the left cap of the bar and the third entry in the array "
|
||||
"is used to render the right cap of the bar. The second entry is streched in-between the two caps.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// This example shows one way to break down a long-running computation into phases\n"
|
||||
"// and incrementally update a progress bar between the phases.\n"
|
||||
"\n"
|
||||
"new GuiProgressBitmapCtrl( Progress )\n"
|
||||
"{\n"
|
||||
" bitmap = \"core/art/gui/images/loading\";\n"
|
||||
" extent = \"300 50\";\n"
|
||||
" position = \"100 100\";\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"// Put the control on the canvas.\n"
|
||||
"%wrapper = new GuiControl();\n"
|
||||
"%wrapper.addObject( Progress );\n"
|
||||
"Canvas.pushDialog( %wrapper );\n"
|
||||
"\n"
|
||||
"// Start the computation.\n"
|
||||
"schedule( 1, 0, \"phase1\" );\n"
|
||||
"\n"
|
||||
"function phase1()\n"
|
||||
"{\n"
|
||||
" Progress.setValue( 0 );\n"
|
||||
"\n"
|
||||
" // Perform some computation.\n"
|
||||
" //...\n"
|
||||
"\n"
|
||||
" // Update progress.\n"
|
||||
" Progress.setValue( 0.25 );\n"
|
||||
"\n"
|
||||
" // Schedule next phase. Don't call directly so engine gets a change to run refresh.\n"
|
||||
" schedule( 1, 0, \"phase2\" );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function phase2()\n"
|
||||
"{\n"
|
||||
" // Perform some computation.\n"
|
||||
" //...\n"
|
||||
"\n"
|
||||
" // Update progress.\n"
|
||||
" Progress.setValue( 0.7 );\n"
|
||||
"\n"
|
||||
" // Schedule next phase. Don't call directly so engine gets a change to run refresh.\n"
|
||||
" schedule( 1, 0, \"phase3\" );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function phase3()\n"
|
||||
"{\n"
|
||||
" // Perform some computation.\n"
|
||||
" //...\n"
|
||||
"\n"
|
||||
" // Update progress.\n"
|
||||
" Progress.setValue( 0.9 );\n"
|
||||
"\n"
|
||||
" // Schedule next phase. Don't call directly so engine gets a change to run refresh.\n"
|
||||
" schedule( 1, 0, \"phase4\" );\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function phase4()\n"
|
||||
"{\n"
|
||||
" // Perform some computation.\n"
|
||||
" //...\n"
|
||||
"\n"
|
||||
" // Final update of progress.\n"
|
||||
" Progress.setValue( 1.0 );\n"
|
||||
"}\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see GuiProgressCtrl\n\n"
|
||||
|
||||
"@ingroup GuiValues"
|
||||
);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiProgressBitmapCtrl::GuiProgressBitmapCtrl()
|
||||
: mProgress( 0.f ),
|
||||
mBitmapName( StringTable->EmptyString() ),
|
||||
mUseVariable( false ),
|
||||
mTile( false )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiProgressBitmapCtrl::initPersistFields()
|
||||
{
|
||||
addProtectedField( "bitmap", TypeFilename, Offset( mBitmapName, GuiProgressBitmapCtrl ),
|
||||
_setBitmap, defaultProtectedGetFn,
|
||||
"~Path to the bitmap file to use for rendering the progress bar.\n\n"
|
||||
"If the profile assigned to the control already has a bitmap assigned, this property need not be "
|
||||
"set in which case the bitmap from the profile is used."
|
||||
);
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiProgressBitmapCtrl::setBitmap( const char* name )
|
||||
{
|
||||
bool awake = mAwake;
|
||||
if( awake )
|
||||
onSleep();
|
||||
|
||||
mBitmapName = StringTable->insert( name );
|
||||
if( awake )
|
||||
onWake();
|
||||
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char* GuiProgressBitmapCtrl::getScriptValue()
|
||||
{
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%g", mProgress);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiProgressBitmapCtrl::setScriptValue(const char *value)
|
||||
{
|
||||
//set the value
|
||||
if (! value)
|
||||
mProgress = 0.0f;
|
||||
else
|
||||
mProgress = dAtof(value);
|
||||
|
||||
//validate the value
|
||||
mProgress = mClampF(mProgress, 0.f, 1.f);
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiProgressBitmapCtrl::onPreRender()
|
||||
{
|
||||
const char * var = getVariable();
|
||||
if(var)
|
||||
{
|
||||
F32 value = mClampF(dAtof(var), 0.f, 1.f);
|
||||
if(value != mProgress)
|
||||
{
|
||||
mProgress = value;
|
||||
setUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiProgressBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
RectI ctrlRect(offset, getExtent());
|
||||
|
||||
//grab lowest dimension
|
||||
if(getHeight() <= getWidth())
|
||||
mDim = getHeight();
|
||||
else
|
||||
mDim = getWidth();
|
||||
|
||||
GFX->getDrawUtil()->clearBitmapModulation();
|
||||
|
||||
if(mNumberOfBitmaps == 1)
|
||||
{
|
||||
//draw the progress with image
|
||||
S32 width = (S32)((F32)(getWidth()) * mProgress);
|
||||
if (width > 0)
|
||||
{
|
||||
//drawing stretch bitmap
|
||||
RectI progressRect = ctrlRect;
|
||||
progressRect.extent.x = width;
|
||||
GFX->getDrawUtil()->drawBitmapStretchSR(mProfile->mTextureObject, progressRect, mProfile->mBitmapArrayRects[0]);
|
||||
}
|
||||
}
|
||||
else if(mNumberOfBitmaps >= 3)
|
||||
{
|
||||
//drawing left-end bitmap
|
||||
RectI progressRectLeft(ctrlRect.point.x, ctrlRect.point.y, mDim, mDim);
|
||||
GFX->getDrawUtil()->drawBitmapStretchSR(mProfile->mTextureObject, progressRectLeft, mProfile->mBitmapArrayRects[0]);
|
||||
|
||||
//draw the progress with image
|
||||
S32 width = (S32)((F32)(getWidth()) * mProgress);
|
||||
if (width > mDim)
|
||||
{
|
||||
//drawing stretch bitmap
|
||||
RectI progressRect = ctrlRect;
|
||||
progressRect.point.x += mDim;
|
||||
progressRect.extent.x = (width - mDim - mDim);
|
||||
if (progressRect.extent.x < 0)
|
||||
progressRect.extent.x = 0;
|
||||
GFX->getDrawUtil()->drawBitmapStretchSR(mProfile->mTextureObject, progressRect, mProfile->mBitmapArrayRects[1]);
|
||||
|
||||
//drawing right-end bitmap
|
||||
RectI progressRectRight(progressRect.point.x + progressRect.extent.x, ctrlRect.point.y, mDim, mDim );
|
||||
GFX->getDrawUtil()->drawBitmapStretchSR(mProfile->mTextureObject, progressRectRight, mProfile->mBitmapArrayRects[2]);
|
||||
}
|
||||
}
|
||||
else
|
||||
Con::warnf("guiProgressBitmapCtrl only processes an array of bitmaps == 1 or >= 3");
|
||||
|
||||
//if there's a border, draw it
|
||||
if (mProfile->mBorder)
|
||||
GFX->getDrawUtil()->drawRect(ctrlRect, mProfile->mBorderColor);
|
||||
|
||||
Parent::onRender( offset, updateRect );
|
||||
|
||||
//render the children
|
||||
renderChildControls(offset, updateRect);
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiProgressBitmapCtrl::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return false;
|
||||
|
||||
mNumberOfBitmaps = mProfile->constructBitmapArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Methods.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Methods ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( GuiProgressBitmapCtrl, setBitmap, void, ( const char* filename ),,
|
||||
"Set the bitmap to use for rendering the progress bar.\n\n"
|
||||
"@param filename ~Path to the bitmap file.\n\n"
|
||||
"@note Directly assign to #bitmap rather than using this method.\n\n"
|
||||
"@see GuiProgressBitmapCtrl::setBitmap" )
|
||||
{
|
||||
object->setBitmap( filename );
|
||||
}
|
||||
83
Engine/source/gui/game/guiProgressBitmapCtrl.h
Normal file
83
Engine/source/gui/game/guiProgressBitmapCtrl.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GuiProgressBitmapCtrl_H_
|
||||
#define _GuiProgressBitmapCtrl_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "gui/controls/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
|
||||
//FIXME: WTH is this derived from GuiTextCtrl?? should be a GuiControl
|
||||
|
||||
|
||||
/// A control that renders a horizontal progress bar from a repeating bitmap image.
|
||||
class GuiProgressBitmapCtrl : public GuiTextCtrl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
protected:
|
||||
|
||||
F32 mProgress;
|
||||
StringTableEntry mBitmapName;
|
||||
bool mUseVariable;
|
||||
bool mTile;
|
||||
S32 mNumberOfBitmaps;
|
||||
S32 mDim;
|
||||
|
||||
static bool _setBitmap( void* object, const char* index, const char* data )
|
||||
{
|
||||
static_cast< GuiProgressBitmapCtrl* >( object )->setBitmap( data );
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
GuiProgressBitmapCtrl();
|
||||
|
||||
void setBitmap( const char* name );
|
||||
|
||||
//console related methods
|
||||
virtual const char *getScriptValue();
|
||||
virtual void setScriptValue(const char *value);
|
||||
|
||||
// GuiTextCtrl.
|
||||
virtual void onPreRender();
|
||||
virtual void onRender( Point2I offset, const RectI &updateRect );
|
||||
virtual bool onWake();
|
||||
|
||||
DECLARE_CONOBJECT( GuiProgressBitmapCtrl );
|
||||
DECLARE_CATEGORY( "Gui Values" );
|
||||
DECLARE_DESCRIPTION( "A control that shows a horizontal progress bar that is rendered\n"
|
||||
"by repeating a bitmap." );
|
||||
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
#endif
|
||||
116
Engine/source/gui/game/guiProgressCtrl.cpp
Normal file
116
Engine/source/gui/game/guiProgressCtrl.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/game/guiProgressCtrl.h"
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiProgressCtrl);
|
||||
|
||||
ConsoleDocClass( GuiProgressCtrl,
|
||||
"@brief GUI Control which displays a horizontal bar which increases as the progress value of 0.0 - 1.0 increases.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
" new GuiProgressCtrl(JS_statusBar)\n"
|
||||
" {\n"
|
||||
" //Properties not specific to this control have been omitted from this example.\n"
|
||||
" };\n\n"
|
||||
"// Define the value to set the progress bar"
|
||||
"%value = \"0.5f\"\n\n"
|
||||
"// Set the value of the progress bar, from 0.0 - 1.0\n"
|
||||
"%thisGuiProgressCtrl.setValue(%value);\n"
|
||||
"// Get the value of the progress bar.\n"
|
||||
"%progress = %thisGuiProgressCtrl.getValue();\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see GuiTextCtrl\n"
|
||||
"@see GuiControl\n\n"
|
||||
|
||||
"@ingroup GuiValues\n"
|
||||
);
|
||||
|
||||
GuiProgressCtrl::GuiProgressCtrl()
|
||||
{
|
||||
mProgress = 0.0f;
|
||||
}
|
||||
|
||||
const char* GuiProgressCtrl::getScriptValue()
|
||||
{
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%g", mProgress);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GuiProgressCtrl::setScriptValue(const char *value)
|
||||
{
|
||||
//set the value
|
||||
if (! value)
|
||||
mProgress = 0.0f;
|
||||
else
|
||||
mProgress = dAtof(value);
|
||||
|
||||
//validate the value
|
||||
mProgress = mClampF(mProgress, 0.f, 1.f);
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiProgressCtrl::onPreRender()
|
||||
{
|
||||
const char * var = getVariable();
|
||||
if(var)
|
||||
{
|
||||
F32 value = mClampF(dAtof(var), 0.f, 1.f);
|
||||
if(value != mProgress)
|
||||
{
|
||||
mProgress = value;
|
||||
setUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiProgressCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
RectI ctrlRect(offset, getExtent());
|
||||
|
||||
//draw the progress
|
||||
S32 width = (S32)((F32)(getWidth()) * mProgress);
|
||||
if (width > 0)
|
||||
{
|
||||
RectI progressRect = ctrlRect;
|
||||
progressRect.extent.x = width;
|
||||
GFX->getDrawUtil()->drawRectFill(progressRect, mProfile->mFillColor);
|
||||
}
|
||||
|
||||
//now draw the border
|
||||
if (mProfile->mBorder)
|
||||
GFX->getDrawUtil()->drawRect(ctrlRect, mProfile->mBorderColor);
|
||||
|
||||
Parent::onRender( offset, updateRect );
|
||||
|
||||
//render the children
|
||||
renderChildControls(offset, updateRect);
|
||||
}
|
||||
|
||||
58
Engine/source/gui/game/guiProgressCtrl.h
Normal file
58
Engine/source/gui/game/guiProgressCtrl.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIPROGRESSCTRL_H_
|
||||
#define _GUIPROGRESSCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "gui/controls/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
|
||||
class GuiProgressCtrl : public GuiTextCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
F32 mProgress;
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiProgressCtrl);
|
||||
DECLARE_CATEGORY( "Gui Values" );
|
||||
DECLARE_DESCRIPTION( "A control that display a horizontal progress bar. The bar is\n"
|
||||
"rendered using as a filled rectangle (properties determined by profile)." );
|
||||
GuiProgressCtrl();
|
||||
|
||||
//console related methods
|
||||
virtual const char *getScriptValue();
|
||||
virtual void setScriptValue(const char *value);
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue