Initial commit

This commit is contained in:
Eagle517
2025-02-17 23:17:30 -06:00
commit 7cad314c94
4726 changed files with 1145203 additions and 0 deletions

View File

@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "gui/controls/guiBackgroundCtrl.h"
IMPLEMENT_CONOBJECT(GuiBackgroundCtrl);
//--------------------------------------------------------------------------
GuiBackgroundCtrl::GuiBackgroundCtrl() : GuiControl()
{
mDraw = false;
}
//--------------------------------------------------------------------------
void GuiBackgroundCtrl::onRender(Point2I offset, const RectI &updateRect)
{
if ( mDraw )
Parent::onRender( offset, updateRect );
renderChildControls(offset, updateRect);
}

View File

@ -0,0 +1,29 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIBACKGROUNDCTRL_H_
#define _GUIBACKGROUNDCTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
/// Renders a background, so you can have a backdrop for your GUI.
class GuiBackgroundCtrl : public GuiControl
{
private:
typedef GuiControl Parent;
public:
bool mDraw;
//creation methods
DECLARE_CONOBJECT(GuiBackgroundCtrl);
GuiBackgroundCtrl();
void onRender(Point2I offset, const RectI &updateRect);
};
#endif

View File

@ -0,0 +1,120 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (c) 2002 GarageGames.Com
//-----------------------------------------------------------------------------
#include "gui/core/guiControl.h"
#include "dgl/dgl.h"
/// Renders a skinned border.
class GuiBitmapBorderCtrl : public GuiControl
{
typedef GuiControl Parent;
enum {
BorderTopLeft,
BorderTopRight,
BorderTop,
BorderLeft,
BorderRight,
BorderBottomLeft,
BorderBottom,
BorderBottomRight,
NumBitmaps
};
RectI *mBitmapBounds; ///< bmp is [3*n], bmpHL is [3*n + 1], bmpNA is [3*n + 2]
TextureHandle mTextureHandle;
public:
bool onWake();
void onSleep();
void onRender(Point2I offset, const RectI &updateRect);
DECLARE_CONOBJECT(GuiBitmapBorderCtrl);
};
IMPLEMENT_CONOBJECT(GuiBitmapBorderCtrl);
bool GuiBitmapBorderCtrl::onWake()
{
if (! Parent::onWake())
return false;
//get the texture for the close, minimize, and maximize buttons
mTextureHandle = mProfile->mTextureHandle;
bool result = mProfile->constructBitmapArray() >= NumBitmaps;
AssertFatal(result, "Failed to create the bitmap array");
if(!result)
return false;
mBitmapBounds = mProfile->mBitmapArrayRects.address();
return true;
}
void GuiBitmapBorderCtrl::onSleep()
{
mTextureHandle = NULL;
Parent::onSleep();
}
void GuiBitmapBorderCtrl::onRender(Point2I offset, const RectI &updateRect)
{
renderChildControls( offset, updateRect );
dglSetClipRect(updateRect);
//draw the outline
RectI winRect;
winRect.point = offset;
winRect.extent = mBounds.extent;
winRect.point.x += mBitmapBounds[BorderLeft].extent.x;
winRect.point.y += mBitmapBounds[BorderTop].extent.y;
winRect.extent.x -= mBitmapBounds[BorderLeft].extent.x + mBitmapBounds[BorderRight].extent.x;
winRect.extent.y -= mBitmapBounds[BorderTop].extent.y + mBitmapBounds[BorderBottom].extent.y;
if(mProfile->mOpaque)
dglDrawRectFill(winRect, mProfile->mFillColor);
dglClearBitmapModulation();
dglDrawBitmapSR(mTextureHandle, offset, mBitmapBounds[BorderTopLeft]);
dglDrawBitmapSR(mTextureHandle, Point2I(offset.x + mBounds.extent.x - mBitmapBounds[BorderTopRight].extent.x, offset.y),
mBitmapBounds[BorderTopRight]);
RectI destRect;
destRect.point.x = offset.x + mBitmapBounds[BorderTopLeft].extent.x;
destRect.point.y = offset.y;
destRect.extent.x = mBounds.extent.x - mBitmapBounds[BorderTopLeft].extent.x - mBitmapBounds[BorderTopRight].extent.x;
destRect.extent.y = mBitmapBounds[BorderTop].extent.y;
RectI stretchRect = mBitmapBounds[BorderTop];
stretchRect.inset(1,0);
dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
destRect.point.x = offset.x;
destRect.point.y = offset.y + mBitmapBounds[BorderTopLeft].extent.y;
destRect.extent.x = mBitmapBounds[BorderLeft].extent.x;
destRect.extent.y = mBounds.extent.y - mBitmapBounds[BorderTopLeft].extent.y - mBitmapBounds[BorderBottomLeft].extent.y;
stretchRect = mBitmapBounds[BorderLeft];
stretchRect.inset(0,1);
dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
destRect.point.x = offset.x + mBounds.extent.x - mBitmapBounds[BorderRight].extent.x;
destRect.extent.x = mBitmapBounds[BorderRight].extent.x;
destRect.point.y = offset.y + mBitmapBounds[BorderTopRight].extent.y;
destRect.extent.y = mBounds.extent.y - mBitmapBounds[BorderTopRight].extent.y - mBitmapBounds[BorderBottomRight].extent.y;
stretchRect = mBitmapBounds[BorderRight];
stretchRect.inset(0,1);
dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
dglDrawBitmapSR(mTextureHandle, offset + Point2I(0, mBounds.extent.y - mBitmapBounds[BorderBottomLeft].extent.y), mBitmapBounds[BorderBottomLeft]);
dglDrawBitmapSR(mTextureHandle, offset + mBounds.extent - mBitmapBounds[BorderBottomRight].extent, mBitmapBounds[BorderBottomRight]);
destRect.point.x = offset.x + mBitmapBounds[BorderBottomLeft].extent.x;
destRect.extent.x = mBounds.extent.x - mBitmapBounds[BorderBottomLeft].extent.x - mBitmapBounds[BorderBottomRight].extent.x;
destRect.point.y = offset.y + mBounds.extent.y - mBitmapBounds[BorderBottom].extent.y;
destRect.extent.y = mBitmapBounds[BorderBottom].extent.y;
stretchRect = mBitmapBounds[BorderBottom];
stretchRect.inset(1,0);
dglDrawBitmapStretchSR(mTextureHandle, destRect, stretchRect);
}

View File

@ -0,0 +1,234 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
//
// Copyright (c) 2001 GarageGames.Com
//-----------------------------------------------------------------------------
//-------------------------------------
//
// Bitmap Button Contrl
// Set 'bitmap' comsole field to base name of bitmaps to use. This control will
// append '_n' for normal
// append '_h' for hilighted
// append '_d' for depressed
//
// if bitmap cannot be found it will use the default bitmap to render.
//
// if the extent is set to (0,0) in the gui editor and appy hit, this control will
// set it's extent to be exactly the size of the normal bitmap (if present)
//
#include "console/console.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "platform/platformAudio.h"
#include "gui/core/guiCanvas.h"
#include "gui/core/guiDefaultControlRender.h"
#include "gui/controls/guiBitmapButtonCtrl.h"
IMPLEMENT_CONOBJECT(GuiBitmapButtonCtrl);
//-------------------------------------
GuiBitmapButtonCtrl::GuiBitmapButtonCtrl()
{
mBitmapName = StringTable->insert("");
mBounds.extent.set(140, 30);
}
//-------------------------------------
void GuiBitmapButtonCtrl::initPersistFields()
{
Parent::initPersistFields();
addField("bitmap", TypeFilename, Offset(mBitmapName, GuiBitmapButtonCtrl));
}
//-------------------------------------
bool GuiBitmapButtonCtrl::onWake()
{
if (! Parent::onWake())
return false;
setActive(true);
setBitmap(mBitmapName);
return true;
}
//-------------------------------------
void GuiBitmapButtonCtrl::onSleep()
{
mTextureNormal = NULL;
mTextureHilight = NULL;
mTextureDepressed = NULL;
Parent::onSleep();
}
//-------------------------------------
ConsoleMethod( GuiBitmapButtonCtrl, setBitmap, void, 3, 3, "(filepath name)")
{
object->setBitmap(argv[2]);
}
//-------------------------------------
void GuiBitmapButtonCtrl::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 normal bitmap (if present)
Parent::inspectPostApply();
if ((mBounds.extent.x == 0) && (mBounds.extent.y == 0) && mTextureNormal)
{
TextureObject *texture = (TextureObject *) mTextureNormal;
mBounds.extent.x = texture->bitmapWidth;
mBounds.extent.y = texture->bitmapHeight;
}
}
//-------------------------------------
void GuiBitmapButtonCtrl::setBitmap(const char *name)
{
mBitmapName = StringTable->insert(name);
if(!isAwake())
return;
if (*mBitmapName)
{
char buffer[1024];
char *p;
dStrcpy(buffer, name);
p = buffer + dStrlen(buffer);
dStrcpy(p, "_n");
mTextureNormal = TextureHandle(buffer, BitmapTexture, true);
dStrcpy(p, "_h");
mTextureHilight = TextureHandle(buffer, BitmapTexture, true);
if (!mTextureHilight)
mTextureHilight = mTextureNormal;
dStrcpy(p, "_d");
mTextureDepressed = TextureHandle(buffer, BitmapTexture, true);
if (!mTextureDepressed)
mTextureDepressed = mTextureHilight;
dStrcpy(p, "_i");
mTextureInactive = TextureHandle(buffer, BitmapTexture, true);
if (!mTextureInactive)
mTextureInactive = mTextureNormal;
}
else
{
mTextureNormal = NULL;
mTextureHilight = NULL;
mTextureDepressed = NULL;
mTextureInactive = NULL;
}
setUpdate();
}
//-------------------------------------
void GuiBitmapButtonCtrl::onRender(Point2I offset, const RectI& updateRect)
{
enum {
NORMAL,
HILIGHT,
DEPRESSED,
INACTIVE
} state = NORMAL;
if (mActive)
{
if (mMouseOver) state = HILIGHT;
if (mDepressed || mStateOn) state = DEPRESSED;
}
else
state = INACTIVE;
switch (state)
{
case NORMAL: renderButton(mTextureNormal, offset, updateRect); break;
case HILIGHT: renderButton(mTextureHilight ? mTextureHilight : mTextureNormal, offset, updateRect); break;
case DEPRESSED: renderButton(mTextureDepressed, offset, updateRect); break;
case INACTIVE: renderButton(mTextureInactive ? mTextureInactive : mTextureNormal, offset, updateRect); break;
}
}
//------------------------------------------------------------------------------
void GuiBitmapButtonCtrl::renderButton(TextureHandle &texture, Point2I &offset, const RectI& updateRect)
{
if (texture)
{
RectI rect(offset, mBounds.extent);
dglClearBitmapModulation();
dglDrawBitmapStretch(texture, rect);
renderChildControls( offset, updateRect);
}
else
Parent::onRender(offset, updateRect);
}
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiBitmapButtonTextCtrl);
void GuiBitmapButtonTextCtrl::onRender(Point2I offset, const RectI& updateRect)
{
enum {
NORMAL,
HILIGHT,
DEPRESSED,
INACTIVE
} state = NORMAL;
if (mActive)
{
if (mMouseOver) state = HILIGHT;
if (mDepressed || mStateOn) state = DEPRESSED;
}
else
state = INACTIVE;
TextureHandle texture;
switch (state)
{
case NORMAL:
texture = mTextureNormal;
break;
case HILIGHT:
texture = mTextureHilight;
break;
case DEPRESSED:
texture = mTextureDepressed;
break;
case INACTIVE:
texture = mTextureInactive;
if(!texture)
texture = mTextureNormal;
break;
}
if (texture)
{
RectI rect(offset, mBounds.extent);
dglClearBitmapModulation();
dglDrawBitmapStretch(texture, rect);
Point2I textPos = offset;
if(mDepressed)
textPos += Point2I(1,1);
// Make sure we take the profile's textOffset into account.
textPos += mProfile->mTextOffset;
dglSetBitmapModulation( mProfile->mFontColor );
renderJustifiedText(textPos, mBounds.extent, mButtonText);
renderChildControls( offset, updateRect);
}
else
Parent::onRender(offset, updateRect);
}

View File

@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIBITMAPBUTTON_H_
#define _GUIBITMAPBUTTON_H_
#ifndef _GUIBUTTONCTRL_H_
#include "gui/controls/guiButtonCtrl.h"
#endif
#ifndef _GTEXMANAGER_H_
#include "dgl/gTexManager.h"
#endif
///-------------------------------------
/// Bitmap Button Contrl
/// Set 'bitmap' comsole field to base name of bitmaps to use. This control will
/// append '_n' for normal
/// append '_h' for hilighted
/// append '_d' for depressed
///
/// if bitmap cannot be found it will use the default bitmap to render.
///
/// if the extent is set to (0,0) in the gui editor and apply hit, this control will
/// set it's extent to be exactly the size of the normal bitmap (if present)
///
class GuiBitmapButtonCtrl : public GuiButtonCtrl
{
private:
typedef GuiButtonCtrl Parent;
protected:
StringTableEntry mBitmapName;
TextureHandle mTextureNormal;
TextureHandle mTextureHilight;
TextureHandle mTextureDepressed;
TextureHandle mTextureInactive;
void renderButton(TextureHandle &texture, Point2I &offset, const RectI& updateRect);
public:
DECLARE_CONOBJECT(GuiBitmapButtonCtrl);
GuiBitmapButtonCtrl();
static void initPersistFields();
//Parent methods
bool onWake();
void onSleep();
void inspectPostApply();
void setBitmap(const char *name);
void onRender(Point2I offset, const RectI &updateRect);
};
class GuiBitmapButtonTextCtrl : public GuiBitmapButtonCtrl
{
typedef GuiBitmapButtonCtrl Parent;
public:
DECLARE_CONOBJECT(GuiBitmapButtonTextCtrl);
void onRender(Point2I offset, const RectI &updateRect);
};
#endif //_GUI_BITMAP_BUTTON_CTRL_H

View File

@ -0,0 +1,166 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/consoleTypes.h"
#include "dgl/dgl.h"
#include "gui/controls/guiBitmapCtrl.h"
IMPLEMENT_CONOBJECT(GuiBitmapCtrl);
GuiBitmapCtrl::GuiBitmapCtrl(void)
{
mBitmapName = StringTable->insert("");
startPoint.set(0, 0);
mWrap = false;
}
void GuiBitmapCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup("Misc");
addField("bitmap", TypeFilename, Offset(mBitmapName, GuiBitmapCtrl));
addField("wrap", TypeBool, Offset(mWrap, GuiBitmapCtrl));
endGroup("Misc");
}
ConsoleMethod( GuiBitmapCtrl, setValue, void, 4, 4, "(int xAxis, int yAxis)"
"Set the offset of the bitmap.")
{
object->setValue(dAtoi(argv[2]), dAtoi(argv[3]));
}
ConsoleMethod( GuiBitmapCtrl, setBitmap, void, 3, 3, "(string filename)"
"Set the bitmap displayed in the control. Note that it is limited in size, to 256x256.")
{
object->setBitmap(argv[2]);
}
bool GuiBitmapCtrl::onWake()
{
if (! Parent::onWake())
return false;
setActive(true);
setBitmap(mBitmapName);
return true;
}
void GuiBitmapCtrl::onSleep()
{
mTextureHandle = NULL;
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();
if (!mWrap && (mBounds.extent.x == 0) && (mBounds.extent.y == 0) && mTextureHandle)
{
TextureObject *texture = (TextureObject *) mTextureHandle;
mBounds.extent.x = texture->bitmapWidth;
mBounds.extent.y = texture->bitmapHeight;
}
}
void GuiBitmapCtrl::setBitmap(const char *name, bool resize)
{
mBitmapName = StringTable->insert(name);
if (*mBitmapName) {
mTextureHandle = TextureHandle(mBitmapName, BitmapTexture, true);
// Resize the control to fit the bitmap
if (resize) {
TextureObject* texture = (TextureObject *) mTextureHandle;
mBounds.extent.x = texture->bitmapWidth;
mBounds.extent.y = texture->bitmapHeight;
Point2I extent = getParent()->getExtent();
parentResized(extent,extent);
}
}
else
mTextureHandle = NULL;
setUpdate();
}
void GuiBitmapCtrl::setBitmap(const TextureHandle &handle, bool resize)
{
mTextureHandle = handle;
// Resize the control to fit the bitmap
if (resize) {
TextureObject* texture = (TextureObject *) mTextureHandle;
mBounds.extent.x = texture->bitmapWidth;
mBounds.extent.y = texture->bitmapHeight;
Point2I extent = getParent()->getExtent();
parentResized(extent,extent);
}
}
void GuiBitmapCtrl::onRender(Point2I offset, const RectI &updateRect)
{
if (mTextureHandle)
{
dglClearBitmapModulation();
if(mWrap)
{
TextureObject* texture = (TextureObject *) mTextureHandle;
RectI srcRegion;
RectI dstRegion;
float xdone = ((float)mBounds.extent.x/(float)texture->bitmapWidth)+1;
float ydone = ((float)mBounds.extent.y/(float)texture->bitmapHeight)+1;
int xshift = startPoint.x%texture->bitmapWidth;
int yshift = startPoint.y%texture->bitmapHeight;
for(int y = 0; y < ydone; ++y)
for(int x = 0; x < xdone; ++x)
{
srcRegion.set(0,0,texture->bitmapWidth,texture->bitmapHeight);
dstRegion.set( ((texture->bitmapWidth*x)+offset.x)-xshift,
((texture->bitmapHeight*y)+offset.y)-yshift,
texture->bitmapWidth,
texture->bitmapHeight);
dglDrawBitmapStretchSR(texture,dstRegion, srcRegion, false);
}
}
else
{
RectI rect(offset, mBounds.extent);
dglDrawBitmapStretch(mTextureHandle, rect);
}
}
if (mProfile->mBorder || !mTextureHandle)
{
RectI rect(offset.x, offset.y, mBounds.extent.x, mBounds.extent.y);
dglDrawRect(rect, mProfile->mBorderColor);
}
renderChildControls(offset, updateRect);
}
void GuiBitmapCtrl::setValue(S32 x, S32 y)
{
if (mTextureHandle)
{
TextureObject* texture = (TextureObject *) mTextureHandle;
x+=texture->bitmapWidth/2;
y+=texture->bitmapHeight/2;
}
while (x < 0)
x += 256;
startPoint.x = x % 256;
while (y < 0)
y += 256;
startPoint.y = y % 256;
}

View File

@ -0,0 +1,49 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIBITMAPCTRL_H_
#define _GUIBITMAPCTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
#ifndef _GTEXMANAGER_H_
#include "dgl/gTexManager.h"
#endif
/// Renders a bitmap.
class GuiBitmapCtrl : public GuiControl
{
private:
typedef GuiControl Parent;
protected:
StringTableEntry mBitmapName;
TextureHandle mTextureHandle;
Point2I startPoint;
bool mWrap;
public:
//creation methods
DECLARE_CONOBJECT(GuiBitmapCtrl);
GuiBitmapCtrl();
static void initPersistFields();
//Parental methods
bool onWake();
void onSleep();
void inspectPostApply();
void setBitmap(const char *name,bool resize = false);
void setBitmap(const TextureHandle &handle,bool resize = false);
S32 getWidth() const { return(mTextureHandle.getWidth()); }
S32 getHeight() const { return(mTextureHandle.getHeight()); }
void onRender(Point2I offset, const RectI &updateRect);
void setValue(S32 x, S32 y);
};
#endif

View File

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiButtonBaseCtrl.h"
class GuiBorderButtonCtrl : public GuiButtonBaseCtrl
{
typedef GuiButtonBaseCtrl Parent;
protected:
public:
DECLARE_CONOBJECT(GuiBorderButtonCtrl);
void onRender(Point2I offset, const RectI &updateRect);
};
IMPLEMENT_CONOBJECT(GuiBorderButtonCtrl);
void GuiBorderButtonCtrl::onRender(Point2I offset, const RectI &updateRect)
{
RectI bounds(offset, mBounds.extent);
if(mActive && mMouseOver)
{
bounds.inset(2,2);
dglDrawRect(bounds, mProfile->mFontColorHL);
bounds.inset(-2,-2);
}
if(mActive && (mStateOn || mDepressed))
{
dglDrawRect(bounds, mProfile->mFontColorHL);
bounds.inset(1,1);
dglDrawRect(bounds, mProfile->mFontColorHL);
}
renderChildControls(offset, updateRect);
}

View File

@ -0,0 +1,311 @@
//-----------------------------------------------------------------------------
// Torque Engine
//
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "platform/platformAudio.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiButtonBaseCtrl.h"
#include "i18n/lang.h"
IMPLEMENT_CONOBJECT(GuiButtonBaseCtrl);
GuiButtonBaseCtrl::GuiButtonBaseCtrl()
{
mDepressed = false;
mMouseOver = false;
mActive = true;
mButtonText = StringTable->insert("Button");
mButtonTextID = StringTable->insert("");
mStateOn = false;
mRadioGroup = -1;
mButtonType = ButtonTypePush;
}
bool GuiButtonBaseCtrl::onWake()
{
if(!Parent::onWake())
return false;
// is we have a script variable, make sure we're in sync
if ( mConsoleVariable[0] )
mStateOn = Con::getBoolVariable( mConsoleVariable );
if(mButtonTextID && *mButtonTextID != 0)
setTextID(mButtonTextID);
return true;
}
ConsoleMethod( GuiButtonBaseCtrl, performClick, void, 2, 2, "() - simulates a button click from script." )
{
argc; argv;
object->onAction();
}
ConsoleMethod( GuiButtonBaseCtrl, setText, void, 3, 3, "(string text) - sets the text of the button to the string." )
{
argc;
object->setText( argv[2] );
}
ConsoleMethod( GuiButtonBaseCtrl, setTextID, void, 3, 3, "(string id) - sets the text of the button to the localized string." )
{
argc;
object->setTextID(argv[2]);
}
ConsoleMethod( GuiButtonBaseCtrl, getText, const char *, 2, 2, "() - returns the text of the button." )
{
argc; argv;
return object->getText( );
}
static EnumTable::Enums buttonTypeEnums[] =
{
{ GuiButtonBaseCtrl::ButtonTypePush, "PushButton" },
{ GuiButtonBaseCtrl::ButtonTypeCheck, "ToggleButton" },
{ GuiButtonBaseCtrl::ButtonTypeRadio, "RadioButton" },
};
static EnumTable gButtonTypeTable(3, &buttonTypeEnums[0]);
void GuiButtonBaseCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup("Misc");
addField("text", TypeCaseString, Offset(mButtonText, GuiButtonBaseCtrl));
addField("textID", TypeString, Offset(mButtonTextID, GuiButtonBaseCtrl));
addField("groupNum", TypeS32, Offset(mRadioGroup, GuiButtonBaseCtrl));
addField("buttonType", TypeEnum, Offset(mButtonType, GuiButtonBaseCtrl), 1, &gButtonTypeTable);
endGroup("Misc");
}
void GuiButtonBaseCtrl::setText(const char *text)
{
mButtonText = StringTable->insert(text);
}
void GuiButtonBaseCtrl::setTextID(const char *id)
{
S32 n = Con::getIntVariable(id, -1);
if(n != -1)
{
mButtonTextID = StringTable->insert(id);
setTextID(n);
}
}
void GuiButtonBaseCtrl::setTextID(S32 id)
{
const UTF8 *str = getGUIString(id);
if(str)
setText((const char*)str);
//mButtonTextID = id;
}
const char *GuiButtonBaseCtrl::getText()
{
return mButtonText;
}
//---------------------------------------------------------------------------
void GuiButtonBaseCtrl::acceleratorKeyPress(U32)
{
if (! mActive)
return;
//set the bool
mDepressed = true;
if (mProfile->mTabable)
setFirstResponder();
}
//---------------------------------------------------------------------------
void GuiButtonBaseCtrl::acceleratorKeyRelease(U32)
{
if (! mActive)
return;
if (mDepressed)
{
//set the bool
mDepressed = false;
//perform the action
onAction();
}
//update
setUpdate();
}
void GuiButtonBaseCtrl::onMouseDown(const GuiEvent &event)
{
if (! mActive)
return;
if (mProfile->mCanKeyFocus)
setFirstResponder();
if (mProfile->mSoundButtonDown)
{
F32 pan = (F32(event.mousePoint.x)/F32(Canvas->mBounds.extent.x)*2.0f-1.0f)*0.8f;
AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
alxPlay(handle);
}
//lock the mouse
mouseLock();
mDepressed = true;
//update
setUpdate();
}
void GuiButtonBaseCtrl::onMouseEnter(const GuiEvent &event)
{
setUpdate();
if(isMouseLocked())
{
mDepressed = true;
mMouseOver = true;
}
else
{
if ( mActive && mProfile->mSoundButtonOver )
{
F32 pan = (F32(event.mousePoint.x)/F32(Canvas->mBounds.extent.x)*2.0f-1.0f)*0.8f;
AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
alxPlay(handle);
}
mMouseOver = true;
}
}
void GuiButtonBaseCtrl::onMouseLeave(const GuiEvent &)
{
setUpdate();
if(isMouseLocked())
mDepressed = false;
mMouseOver = false;
}
void GuiButtonBaseCtrl::onMouseUp(const GuiEvent &)
{
if (! mActive)
return;
mouseUnlock();
setUpdate();
//if we released the mouse within this control, perform the action
if (mDepressed)
onAction();
mDepressed = false;
}
//--------------------------------------------------------------------------
bool GuiButtonBaseCtrl::onKeyDown(const GuiEvent &event)
{
//if the control is a dead end, kill the event
if (!mActive)
return true;
//see if the key down is a return or space or not
if ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
&& event.modifier == 0)
{
if ( mProfile->mSoundButtonDown )
{
F32 pan = ( F32( event.mousePoint.x ) / F32( Canvas->mBounds.extent.x ) * 2.0f - 1.0f ) * 0.8f;
AUDIOHANDLE handle = alxCreateSource( mProfile->mSoundButtonDown );
alxPlay( handle );
}
return true;
}
//otherwise, pass the event to it's parent
return Parent::onKeyDown(event);
}
//--------------------------------------------------------------------------
bool GuiButtonBaseCtrl::onKeyUp(const GuiEvent &event)
{
//if the control is a dead end, kill the event
if (!mActive)
return true;
//see if the key down is a return or space or not
if (mDepressed &&
(event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
event.modifier == 0)
{
onAction();
return true;
}
//otherwise, pass the event to it's parent
return Parent::onKeyUp(event);
}
//---------------------------------------------------------------------------
void GuiButtonBaseCtrl::setScriptValue(const char *value)
{
mStateOn = dAtob(value);
// Update the console variable:
if ( mConsoleVariable[0] )
Con::setBoolVariable( mConsoleVariable, mStateOn );
setUpdate();
}
//---------------------------------------------------------------------------
const char *GuiButtonBaseCtrl::getScriptValue()
{
return mStateOn ? "1" : "0";
}
//---------------------------------------------------------------------------
void GuiButtonBaseCtrl::onAction()
{
if(!mActive)
return;
if(mButtonType == ButtonTypeCheck)
{
mStateOn = mStateOn ? false : true;
// Update the console variable:
if ( mConsoleVariable[0] )
Con::setBoolVariable( mConsoleVariable, mStateOn );
// Execute the console command (if any)
if( mConsoleCommand[0] )
Con::evaluate( mConsoleCommand, false );
}
else if(mButtonType == ButtonTypeRadio)
{
mStateOn = true;
messageSiblings(mRadioGroup);
}
setUpdate();
Parent::onAction();
}
//---------------------------------------------------------------------------
void GuiButtonBaseCtrl::onMessage( GuiControl *sender, S32 msg )
{
Parent::onMessage(sender, msg);
if( mRadioGroup == msg && mButtonType == ButtonTypeRadio )
{
setUpdate();
mStateOn = ( sender == this );
}
}

View File

@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
// Torque Engine
//
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIBUTTONBASECTRL_H_
#define _GUIBUTTONBASECTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
// all the button functionality is moving into buttonBase
// thus, all subclasses will just be rendering classes,
// and radios and check boxes can be done using pushbuttons
// or bitmap buttons.
class GuiButtonBaseCtrl : public GuiControl
{
typedef GuiControl Parent;
protected:
StringTableEntry mButtonText;
StringTableEntry mButtonTextID;
bool mDepressed;
bool mMouseOver;
bool mStateOn;
S32 mButtonType;
S32 mRadioGroup;
public:
enum {
ButtonTypePush,
ButtonTypeCheck,
ButtonTypeRadio,
};
GuiButtonBaseCtrl();
bool onWake();
DECLARE_CONOBJECT(GuiButtonBaseCtrl);
static void initPersistFields();
void setText(const char *text);
void setTextID(S32 id);
void setTextID(const char *id);
const char *getText();
void acceleratorKeyPress(U32 index);
void acceleratorKeyRelease(U32 index);
void onMouseDown(const GuiEvent &);
void onMouseUp(const GuiEvent &);
void onMouseEnter(const GuiEvent &);
void onMouseLeave(const GuiEvent &);
bool onKeyDown(const GuiEvent &event);
bool onKeyUp(const GuiEvent &event);
void setScriptValue(const char *value);
const char *getScriptValue();
void onMessage(GuiControl *,S32 msg);
void onAction();
};
#endif

View File

@ -0,0 +1,54 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "platform/platformAudio.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiButtonCtrl.h"
#include "gui/core/guiDefaultControlRender.h"
IMPLEMENT_CONOBJECT(GuiButtonCtrl);
GuiButtonCtrl::GuiButtonCtrl()
{
mBounds.extent.set(140, 30);
mButtonText = StringTable->insert("Button");
}
//--------------------------------------------------------------------------
void GuiButtonCtrl::onRender(Point2I offset,
const RectI& updateRect)
{
bool highlight = mMouseOver;
bool depressed = mDepressed;
ColorI fontColor = mActive ? (highlight ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA;
ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA;
ColorI borderColor = mActive ? mProfile->mBorderColor : mProfile->mBorderColorNA;
RectI boundsRect(offset, mBounds.extent);
if( mProfile->mBorder != 0 )
{
if (mDepressed || mStateOn)
renderFilledBorder( boundsRect, mProfile->mBorderColorHL, mProfile->mFillColorHL );
else
renderFilledBorder( boundsRect, mProfile->mBorderColor, mProfile->mFillColor );
}
Point2I textPos = offset;
if(depressed)
textPos += Point2I(1,1);
dglSetBitmapModulation( fontColor );
renderJustifiedText(textPos, mBounds.extent, mButtonText);
//render the children
renderChildControls( offset, updateRect);
}

View File

@ -0,0 +1,24 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIBUTTONCTRL_H_
#define _GUIBUTTONCTRL_H_
#ifndef _GUIBUTTONBASECTRL_H_
#include "gui/controls/guiButtonBaseCtrl.h"
#endif
class GuiButtonCtrl : public GuiButtonBaseCtrl
{
typedef GuiButtonBaseCtrl Parent;
public:
DECLARE_CONOBJECT(GuiButtonCtrl);
GuiButtonCtrl();
void onRender(Point2I offset, const RectI &updateRect);
};
#endif //_GUI_BUTTON_CTRL_H

View File

@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiCheckBoxCtrl.h"
#include "console/consoleTypes.h"
IMPLEMENT_CONOBJECT(GuiCheckBoxCtrl);
//---------------------------------------------------------------------------
GuiCheckBoxCtrl::GuiCheckBoxCtrl()
{
mBounds.extent.set(140, 30);
mStateOn = false;
mIndent = 0;
mButtonType = ButtonTypeCheck;
}
//---------------------------------------------------------------------------
bool GuiCheckBoxCtrl::onWake()
{
if(!Parent::onWake())
return false;
// make sure there is a bitmap array for this control type
// if it is declared as such in the control
mProfile->constructBitmapArray();
return true;
}
//---------------------------------------------------------------------------
void GuiCheckBoxCtrl::onRender(Point2I offset, const RectI &updateRect)
{
ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA;
ColorI fontColor = mMouseOver ? mProfile->mFontColorHL : mProfile->mFontColor;
ColorI insideBorderColor = isFirstResponder() ? mProfile->mBorderColorHL : mProfile->mBorderColor;
// just draw the check box and the text:
S32 xOffset = 0;
dglClearBitmapModulation();
if(mProfile->mBitmapArrayRects.size() >= 4)
{
S32 index = mStateOn;
if(!mActive)
index = 2;
else if(mDepressed)
index += 2;
xOffset = mProfile->mBitmapArrayRects[0].extent.x + 2 + mIndent;
S32 y = (mBounds.extent.y - mProfile->mBitmapArrayRects[0].extent.y) / 2;
dglDrawBitmapSR(mProfile->mTextureHandle, offset + Point2I(mIndent, y), mProfile->mBitmapArrayRects[index]);
}
if(mButtonText[0] != NULL)
{
dglSetBitmapModulation( fontColor );
renderJustifiedText(Point2I(offset.x + xOffset, offset.y),
Point2I(mBounds.extent.x - mBounds.extent.y, mBounds.extent.y),
mButtonText);
}
//render the children
renderChildControls(offset, updateRect);
}
//---------------------------------------------------------------------------
// EOF //

View File

@ -0,0 +1,27 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUICHECKBOXCTRL_H_
#define _GUICHECKBOXCTRL_H_
#ifndef _GUIBUTTONBASECTRL_H_
#include "gui/controls/guiButtonBaseCtrl.h"
#endif
class GuiCheckBoxCtrl : public GuiButtonBaseCtrl
{
typedef GuiButtonBaseCtrl Parent;
protected:
public:
S32 mIndent;
DECLARE_CONOBJECT(GuiCheckBoxCtrl);
GuiCheckBoxCtrl();
void onRender(Point2I offset, const RectI &updateRect);
bool onWake();
};
#endif //_GUI_CHECKBOX_CTRL_H

View File

@ -0,0 +1,390 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "platform/platformAudio.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiButtonCtrl.h"
#include "gui/core/guiDefaultControlRender.h"
#include "gui/controls/guiColorPicker.h"
/// @name Common colors we use
/// @{
ColorF colorWhite(1.,1.,1.);
ColorF colorWhiteBlend(1.,1.,1.,.75);
ColorF colorBlack(.0,.0,.0);
ColorI GuiColorPickerCtrl::mColorRange[7] = {
ColorI(255,0,0), // Red
ColorI(255,0,255), // Pink
ColorI(0,0,255), // Blue
ColorI(0,255,255), // Light blue
ColorI(0,255,0), // Green
ColorI(255,255,0), // Yellow
ColorI(255,0,0), // Red
};
/// @}
IMPLEMENT_CONOBJECT(GuiColorPickerCtrl);
//--------------------------------------------------------------------------
GuiColorPickerCtrl::GuiColorPickerCtrl()
{
mBounds.extent.set(140, 30);
mDisplayMode = pPallet;
mBaseColor = ColorF(1.,.0,1.);
mPickColor = ColorF(.0,.0,.0);
mSelectorPos = Point2I(0,0);
mMouseDown = mMouseOver = false;
mActive = true;
mPositionChanged = false;
mSelectorGap = 1;
mActionOnMove = false;
}
//--------------------------------------------------------------------------
static EnumTable::Enums gColorPickerModeEnums[] =
{
{ GuiColorPickerCtrl::pPallet, "Pallet" },
{ GuiColorPickerCtrl::pHorizColorRange, "HorizColor"},
{ GuiColorPickerCtrl::pVertColorRange, "VertColor" },
{ GuiColorPickerCtrl::pBlendColorRange, "BlendColor"},
{ GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha"},
{ GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" },
{ GuiColorPickerCtrl::pDropperBackground, "Dropper" },
};
static EnumTable gColorPickerModeTable( 7, gColorPickerModeEnums );
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup("ColorPicker");
addField("BaseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl));
addField("PickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl));
addField("SelectorGap", TypeS32, Offset(mSelectorGap, GuiColorPickerCtrl));
addField("DisplayMode", TypeEnum, Offset(mDisplayMode, GuiColorPickerCtrl), 1, &gColorPickerModeTable );
addField("ActionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl));
endGroup("ColorPicker");
}
//--------------------------------------------------------------------------
// Function to draw a box which can have 4 different colors in each corner blended together
void dglDrawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, ColorF &c3, ColorF &c4)
{
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x - 1;
S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y - 1;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glColor4f(c1.red, c1.green, c1.blue, c1.alpha);
glVertex2f(l, t);
glColor4f(c2.red, c2.green, c2.blue, c2.alpha);
glVertex2f(r, t);
glColor4f(c3.red, c3.green, c3.blue, c3.alpha);
glVertex2f(r, b);
glColor4f(c4.red, c4.green, c4.blue, c4.alpha);
glVertex2f(l, b);
glEnd();
}
//--------------------------------------------------------------------------
/// Function to draw a set of boxes blending throughout an array of colors
void dglDrawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors)
{
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x - 1;
S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y - 1;
// Calculate increment value
S32 x_inc = int(mFloor((r - l) / (numColors-1)));
S32 y_inc = int(mFloor((b - t) / (numColors-1)));
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
for (U16 i=0;i<numColors-1;i++)
{
// If we are at the end, x_inc and y_inc need to go to the end (otherwise there is a rendering bug)
if (i == numColors-2)
{
x_inc += r-l-1;
y_inc += b-t-1;
}
if (!vertical) // Horizontal (+x)
{
// First color
glColor4ub(colors[i].red, colors[i].green, colors[i].blue, colors[i].alpha);
glVertex2f(l, t);
glVertex2f(l, b);
// Second color
glColor4ub(colors[i+1].red, colors[i+1].green, colors[i+1].blue, colors[i+1].alpha);
glVertex2f(l+x_inc, b);
glVertex2f(l+x_inc, t);
l += x_inc;
}
else // Vertical (+y)
{
// First color
glColor4ub(colors[i].red, colors[i].green, colors[i].blue, colors[i].alpha);
glVertex2f(l, t);
glVertex2f(r, t);
// Second color
glColor4ub(colors[i+1].red, colors[i+1].green, colors[i+1].blue, colors[i+1].alpha);
glVertex2f(r, t+y_inc);
glVertex2f(l, t+y_inc);
t += y_inc;
}
}
glEnd();
}
void GuiColorPickerCtrl::drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode)
{
U16 sMax = mSelectorGap*2;
switch (mode)
{
case sVertical:
// Now draw the vertical selector
// Up -> Pos
if (selectorPos.y != bounds.point.y+1)
dglDrawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, colorWhiteBlend);
// Down -> Pos
if (selectorPos.y != bounds.point.y+bounds.extent.y)
dglDrawLine(selectorPos.x, selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, colorWhiteBlend);
break;
case sHorizontal:
// Now draw the horizontal selector
// Left -> Pos
if (selectorPos.x != bounds.point.x)
dglDrawLine(bounds.point.x, selectorPos.y-1, selectorPos.x-sMax, selectorPos.y-1, colorWhiteBlend);
// Right -> Pos
if (selectorPos.x != bounds.point.x)
dglDrawLine(bounds.point.x+mSelectorPos.x+sMax, selectorPos.y-1, bounds.point.x + bounds.extent.x, selectorPos.y-1, colorWhiteBlend);
break;
}
}
//--------------------------------------------------------------------------
/// Function to invoke calls to draw the picker box and selector
void GuiColorPickerCtrl::renderColorBox(RectI &bounds)
{
RectI pickerBounds;
pickerBounds.point.x = bounds.point.x+1;
pickerBounds.point.y = bounds.point.y+1;
pickerBounds.extent.x = bounds.extent.x-1;
pickerBounds.extent.y = bounds.extent.y-1;
if (mProfile->mBorder)
dglDrawRect(bounds, mProfile->mBorderColor);
Point2I selectorPos = Point2I(bounds.point.x+mSelectorPos.x+1, bounds.point.y+mSelectorPos.y+1);
// Draw color box differently depending on mode
switch (mDisplayMode)
{
case pHorizColorRange:
dglDrawBlendRangeBox( pickerBounds, false, 7, mColorRange);
drawSelector( pickerBounds, selectorPos, sVertical );
break;
case pVertColorRange:
dglDrawBlendRangeBox( pickerBounds, true, 7, mColorRange);
drawSelector( pickerBounds, selectorPos, sHorizontal );
break;
case pHorizAlphaRange:
dglDrawBlendBox( pickerBounds, colorBlack, colorWhite, colorWhite, colorBlack );
drawSelector( pickerBounds, selectorPos, sVertical );
break;
case pVertAlphaRange:
dglDrawBlendBox( pickerBounds, colorBlack, colorBlack, colorWhite, colorWhite );
drawSelector( pickerBounds, selectorPos, sHorizontal );
break;
case pBlendColorRange:
dglDrawBlendBox( pickerBounds, colorWhite, mBaseColor, colorBlack, colorBlack );
drawSelector( pickerBounds, selectorPos, sHorizontal );
drawSelector( pickerBounds, selectorPos, sVertical );
break;
case pDropperBackground:
break;
case pPallet:
default:
dglDrawRectFill( pickerBounds, mBaseColor );
break;
}
}
void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
{
RectI boundsRect(offset, mBounds.extent);
renderColorBox(boundsRect);
if (mPositionChanged)
{
mPositionChanged = false;
Point2I extent = Canvas->getExtent();
// If we are anything but a pallete, change the pick color
if (mDisplayMode != pPallet)
{
// To simplify things a bit, just read the color via glReadPixels()
GLfloat rBuffer[4];
glReadBuffer(GL_BACK);
U32 buf_x = offset.x+mSelectorPos.x+1;
U32 buf_y = extent.y-(offset.y+mSelectorPos.y+1);
glReadPixels(buf_x, buf_y, 1, 1, GL_RGBA, GL_FLOAT, rBuffer);
mPickColor.red = rBuffer[0];
mPickColor.green = rBuffer[1];
mPickColor.blue = rBuffer[2];
mPickColor.alpha = rBuffer[3];
// Now do onAction() if we are allowed
if (mActionOnMove)
onAction();
}
}
//render the children
renderChildControls( offset, updateRect);
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos)
{
Point2I extent = mBounds.extent;
RectI rect;
if (mDisplayMode != pDropperBackground)
{
extent.x -= 3;
extent.y -= 2;
rect = RectI(Point2I(1,1), extent);
}
else
{
rect = RectI(Point2I(0,0), extent);
}
if (rect.pointInRect(pos))
{
mSelectorPos = pos;
mPositionChanged = true;
// We now need to update
setUpdate();
}
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
{
if (!mActive)
return;
if (mDisplayMode == pDropperBackground)
return;
if (mProfile->mCanKeyFocus)
setFirstResponder();
// Update the picker cross position
if (mDisplayMode != pPallet)
setSelectorPos(globalToLocalCoord(event.mousePoint));
mMouseDown = true;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
{
if ((mActive && mMouseDown) || (mActive && (mDisplayMode == pDropperBackground)))
{
// Update the picker cross position
if (mDisplayMode != pPallet)
setSelectorPos(globalToLocalCoord(event.mousePoint));
}
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
{
// Only for dropper mode
if (mActive && (mDisplayMode == pDropperBackground))
setSelectorPos(globalToLocalCoord(event.mousePoint));
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseEnter(const GuiEvent &event)
{
mMouseOver = true;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseLeave(const GuiEvent &)
{
// Reset state
mMouseOver = false;
mMouseDown = false;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseUp(const GuiEvent &)
{
//if we released the mouse within this control, perform the action
if (mActive && mMouseDown && (mDisplayMode != pDropperBackground))
{
onAction();
mMouseDown = false;
}
else if (mActive && (mDisplayMode == pDropperBackground))
{
// In a dropper, the alt command executes the mouse up action (to signal stopping)
if ( mAltConsoleCommand[0] )
Con::evaluate( mAltConsoleCommand, false );
}
}
//--------------------------------------------------------------------------
const char *GuiColorPickerCtrl::getScriptValue()
{
static char temp[256];
ColorF color = getValue();
dSprintf(temp,256,"%f %f %f %f",color.red, color.green, color.blue, color.alpha);
return temp;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::setScriptValue(const char *value)
{
ColorF newValue;
dSscanf(value, "%f %f %f %f", &newValue.red, &newValue.green, &newValue.blue, &newValue.alpha);
setValue(newValue);
}
ConsoleMethod(GuiColorPickerCtrl, getSelectorPos, const char*, 2, 2, "Gets the current position of the selector")
{
char *temp = Con::getReturnBuffer(256);
Point2I pos;
pos = object->getSelectorPos();
dSprintf(temp,256,"%d %d",pos.x, pos.y);
return temp;
}
ConsoleMethod(GuiColorPickerCtrl, setSelectorPos, void, 3, 3, "Sets the current position of the selector")
{
Point2I newPos;
dSscanf(argv[2], "%d %d", &newPos.x, &newPos.y);
object->setSelectorPos(newPos);
}
ConsoleMethod(GuiColorPickerCtrl, updateColor, void, 2, 2, "Forces update of pick color")
{
object->updateColor();
}

View File

@ -0,0 +1,121 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUICOLORPICKER_H_
#define _GUICOLORPICKER_H_
#ifndef _GUICONTROL_H_
#include "gui/guiControl.h"
#endif
//----------------------------
/// GuiColorPickerCtrl
///
/// This control draws a box containing a color specified by mPickColor,
/// in a way according to one of the PickMode enum's, stored as mDisplayMode.
///
/// The color the box represents is stored as mBaseColour (for pPallete, pBlendColorRange),
/// whilst the color chosen by the box is stored as mPickColor.
///
/// Whenever the control is clicked, it will do one of many things :
///
/// -# If its in pPallete mode, execute the regular "command"
/// -# If its in pBlendColorRange mode, update the selector position. The position will be re-read upon the next render. In addition, a cross will be drawn where the color has been selected from. As with 1, "command" will be executed.
/// -# If its in pHorizColorRange or pVertColorRange mode, it will function in a similar manner to 2, but the selector will resemble a horizontal or vertical bar.
/// -# If its in pHorizAlphaRange or pVertAlphaRange mode, it will also function the same way as 3
/// -# If its in pDropperBackground mode, nothing will happen
///
/// Colours are drawn in different ways according to mDisplayMode:
///
/// -# With pPallete, a box with a blank color, mBaseColor is drawn.
/// -# With pHorizColorRange, a horizontal box with colors blending in the range, mColorRange.
/// -# With pVertColorRange, a vertical box with colors blending in the range, mColorRange.
/// -# With pBlendColorRange, a box, the bottom colors being black, but the top left being white, and the top right being mBaseColor.
/// -# With pHorizAlphaRange, a horizontal box with black blending with an alpha from 0 to 255
/// -# With pVertAlphaRange, a vertical box with black blending with an apha from 0 to 255
/// -# With pDropperBackground, nothing is drawn
class GuiColorPickerCtrl : public GuiControl
{
typedef GuiControl Parent;
public:
enum PickMode
{
pPallet = 0, ///< We just have a solid color; We just act like a pallet
pHorizColorRange, ///< We have a range of base colors going horizontally
pVertColorRange, ///< We have a range of base colors going vertically
pBlendColorRange, ///< We have a box which shows a range in brightness of the color
pHorizAlphaRange, ///< We have a box which shows a range in alpha going horizontally
pVertAlphaRange, ///< We have a box which shows a range in alpha going vertically
pDropperBackground ///< The control does not draw anything; Only does something when you click, or move the mouse (when active)
};
enum SelectorMode
{
sHorizontal = 0, ///< Horizontal selector with small gap
sVertical, ///< Vertical selector with small gap
};
protected:
/// @name Core Rendering functions
/// @{
void renderColorBox(RectI &bounds); ///< Function that draws the actual color box
void drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode); ///< Function that draws the selection indicator
/// @}
/// @name Core Variables
/// @{
ColorF mPickColor; ///< Color that has been picked from control
ColorF mBaseColor; ///< Colour we display (in case of pallet and blend mode)
PickMode mDisplayMode; ///< Current color display mode of the selector
Point2I mSelectorPos; ///< Current position of the selector
bool mPositionChanged; ///< Current position has changed since last render?
bool mMouseOver; ///< Mouse is over?
bool mMouseDown; ///< Mouse button down?
bool mActionOnMove; ///< Perform onAction() when position has changed?
S32 mSelectorGap; ///< The half-way "gap" between the selector pos and where the selector is allowed to draw.
static ColorI mColorRange[7]; ///< Color range for pHorizColorRange and pVertColorRange
/// @}
public:
DECLARE_CONOBJECT(GuiColorPickerCtrl);
GuiColorPickerCtrl();
static void initPersistFields();
void onRender(Point2I offset, const RectI &updateRect);
/// @name Color Value Functions
/// @{
/// NOTE: setValue only sets baseColor, since setting pickColor wouldn't be useful
void setValue(ColorF &value) {mBaseColor = value;}
/// NOTE: getValue() returns baseColor if pallet (since pallet controls can't "pick" colours themselves)
ColorF getValue() {return mDisplayMode == pPallet ? mBaseColor : mPickColor;}
const char *getScriptValue();
void setScriptValue(const char *value);
void updateColor() {mPositionChanged = true;}
/// @}
/// @name Selector Functions
/// @{
void setSelectorPos(const Point2I &pos); ///< Set new pos (in local coords)
Point2I getSelectorPos() {return mSelectorPos;}
/// @}
/// @name Input Events
/// @{
void onMouseDown(const GuiEvent &);
void onMouseUp(const GuiEvent &);
void onMouseMove(const GuiEvent &event);
void onMouseDragged(const GuiEvent &event);
void onMouseEnter(const GuiEvent &);
void onMouseLeave(const GuiEvent &);
/// @}
};
#endif

106
engine/gui/controls/guiConsole.cc Executable file
View File

@ -0,0 +1,106 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiTypes.h"
#include "gui/core/guiControl.h"
#include "gui/controls/guiConsole.h"
#include "gui/containers/guiScrollCtrl.h"
IMPLEMENT_CONOBJECT(GuiConsole);
GuiConsole::GuiConsole()
{
mBounds.extent.set(1, 1);
mCellSize.set(1, 1);
mSize.set(1, 0);
}
bool GuiConsole::onWake()
{
if (! Parent::onWake())
return false;
//get the font
mFont = mProfile->mFont;
return true;
}
S32 GuiConsole::getMaxWidth(S32 startIndex, S32 endIndex)
{
//sanity check
U32 size;
ConsoleLogEntry *log;
Con::getLockLog(log, size);
if(startIndex < 0 || (U32)endIndex >= size || startIndex > endIndex)
return 0;
S32 result = 0;
for(S32 i = startIndex; i <= endIndex; i++)
result = getMax(result, (S32)(mFont->getStrWidth((const UTF8 *)log[i].mString)));
Con::unlockLog();
return(result + 6);
}
void GuiConsole::onPreRender()
{
//see if the size has changed
U32 prevSize = mBounds.extent.y / mCellSize.y;
U32 size;
ConsoleLogEntry *log;
Con::getLockLog(log, size);
Con::unlockLog(); // we unlock immediately because we only use size here, not log.
if(size != prevSize)
{
//first, find out if the console was scrolled up
bool scrolled = false;
GuiScrollCtrl *parent = dynamic_cast<GuiScrollCtrl*>(getParent());
if(parent)
scrolled = parent->isScrolledToBottom();
//find the max cell width for the new entries
S32 newMax = getMaxWidth(prevSize, size - 1);
if(newMax > mCellSize.x)
mCellSize.set(newMax, mFont->getHeight());
//set the array size
mSize.set(1, size);
//resize the control
resize(mBounds.point, Point2I(mCellSize.x, mCellSize.y * size));
//if the console was not scrolled, make the last entry visible
if (scrolled)
scrollCellVisible(Point2I(0,mSize.y - 1));
}
}
void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, bool /*mouseOver*/)
{
U32 size;
ConsoleLogEntry *log;
Con::getLockLog(log, size);
ConsoleLogEntry &entry = log[cell.y];
switch (entry.mLevel)
{
case ConsoleLogEntry::Normal: dglSetBitmapModulation(mProfile->mFontColor); break;
case ConsoleLogEntry::Warning: dglSetBitmapModulation(mProfile->mFontColorHL); break;
case ConsoleLogEntry::Error: dglSetBitmapModulation(mProfile->mFontColorNA); break;
}
dglDrawText(mFont, Point2I(offset.x + 3, offset.y), entry.mString, mProfile->mFontColors);
Con::unlockLog();
}

View File

@ -0,0 +1,32 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUICONSOLE_H_
#define _GUICONSOLE_H_
#ifndef _GUIARRAYCTRL_H_
#include "gui/core/guiArrayCtrl.h"
#endif
class GuiConsole : public GuiArrayCtrl
{
private:
typedef GuiArrayCtrl Parent;
Resource<GFont> mFont;
S32 getMaxWidth(S32 startIndex, S32 endIndex);
public:
GuiConsole();
DECLARE_CONOBJECT(GuiConsole);
bool onWake();
void onPreRender();
void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
};
#endif

View File

@ -0,0 +1,89 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiConsoleEditCtrl.h"
#include "core/frameAllocator.h"
IMPLEMENT_CONOBJECT(GuiConsoleEditCtrl);
GuiConsoleEditCtrl::GuiConsoleEditCtrl()
{
mSinkAllKeyEvents = true;
mSiblingScroller = NULL;
mUseSiblingScroller = true;
}
void GuiConsoleEditCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup("Misc");
addField("useSiblingScroller", TypeBool, Offset(mUseSiblingScroller, GuiConsoleEditCtrl));
endGroup("Misc");
}
bool GuiConsoleEditCtrl::onKeyDown(const GuiEvent &event)
{
S32 stringLen = dStrlen(mText);
setUpdate();
if (event.keyCode == KEY_TAB)
{
if (event.modifier & SI_SHIFT)
{
// Do some skullduggery so that we're working against the mTextBuffer.
FrameTemp<UTF8> tmpBuff(mTextBuffer.length() * 3 + 1);
mTextBuffer.get(tmpBuff, mTextBuffer.length() * 3 + 1);
mCursorPos = Con::tabComplete(tmpBuff, mCursorPos, GuiTextCtrl::MAX_STRING_LENGTH, false);
mTextBuffer.set(tmpBuff);
return true;
}
else
{
FrameTemp<UTF8> tmpBuff(GuiTextCtrl::MAX_STRING_LENGTH + 1);
mTextBuffer.get(tmpBuff, GuiTextCtrl::MAX_STRING_LENGTH + 1);
mCursorPos = Con::tabComplete(tmpBuff, mCursorPos, GuiTextCtrl::MAX_STRING_LENGTH, true);
mTextBuffer.set(tmpBuff);
return true;
}
}
else if ((event.keyCode == KEY_PAGE_UP) || (event.keyCode == KEY_PAGE_DOWN))
{
// See if there's some other widget that can scroll the console history.
if (mUseSiblingScroller)
{
if (mSiblingScroller)
{
return mSiblingScroller->onKeyDown(event);
}
else
{
// Let's see if we can find it...
SimGroup* pGroup = getGroup();
if (pGroup)
{
// Find the first scroll control in the same group as us.
for (SimSetIterator itr(pGroup); *itr; ++itr)
{
if (mSiblingScroller = dynamic_cast<GuiScrollCtrl*>(*itr))
{
return mSiblingScroller->onKeyDown(event);
}
}
}
// No luck... so don't try, next time.
mUseSiblingScroller = false;
}
}
}
return Parent::onKeyDown(event);
}

View File

@ -0,0 +1,37 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUICONSOLEEDITCTRL_H_
#define _GUICONSOLEEDITCTRL_H_
#ifndef _GUITYPES_H_
#include "gui/core/guiTypes.h"
#endif
#ifndef _GUITEXTEDITCTRL_H_
#include "gui/controls/guiTextEditCtrl.h"
#endif
#ifndef _GUISCROLLCTRL_H_
#include "gui/containers/guiScrollCtrl.h"
#endif
class GuiConsoleEditCtrl : public GuiTextEditCtrl
{
private:
typedef GuiTextEditCtrl Parent;
protected:
bool mUseSiblingScroller;
GuiScrollCtrl* mSiblingScroller;
public:
GuiConsoleEditCtrl();
DECLARE_CONOBJECT(GuiConsoleEditCtrl);
static void initPersistFields();
bool onKeyDown(const GuiEvent &event);
};
#endif //_GUI_TEXTEDIT_CTRL_H

View File

@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/consoleTypes.h"
#include "console/console.h"
#include "core/color.h"
#include "gui/controls/guiConsoleTextCtrl.h"
#include "dgl/dgl.h"
IMPLEMENT_CONOBJECT(GuiConsoleTextCtrl);
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
GuiConsoleTextCtrl::GuiConsoleTextCtrl()
{
//default fonts
mConsoleExpression = NULL;
mResult = NULL;
}
void GuiConsoleTextCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup("Misc");
addField("expression", TypeCaseString, Offset(mConsoleExpression, GuiConsoleTextCtrl));
endGroup("Misc");
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
bool GuiConsoleTextCtrl::onWake()
{
if (! Parent::onWake())
return false;
mFont = mProfile->mFont;
return true;
}
void GuiConsoleTextCtrl::onSleep()
{
Parent::onSleep();
mFont = NULL;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
void GuiConsoleTextCtrl::setText(const char *txt)
{
//make sure we don't call this before onAdd();
AssertFatal(mProfile, "Can't call setText() until setProfile() has been called.");
if (txt)
mConsoleExpression = StringTable->insert(txt);
else
mConsoleExpression = NULL;
//Make sure we have a font
mProfile->incRefCount();
mFont = mProfile->mFont;
setUpdate();
//decrement the profile referrence
mProfile->decRefCount();
}
void GuiConsoleTextCtrl::calcResize()
{
if (!mResult)
return;
//resize
if (mProfile->mAutoSizeWidth)
{
if (mProfile->mAutoSizeHeight)
resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mResult) + 4, mFont->getHeight() + 4));
else
resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mResult) + 4, mBounds.extent.y));
}
else if (mProfile->mAutoSizeHeight)
{
resize(mBounds.point, Point2I(mBounds.extent.x, mFont->getHeight() + 4));
}
}
void GuiConsoleTextCtrl::onPreRender()
{
if (mConsoleExpression)
mResult = Con::evaluatef("$temp = %s;", mConsoleExpression);
calcResize();
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
void GuiConsoleTextCtrl::onRender(Point2I offset, const RectI &updateRect)
{
// draw the background rectangle
RectI r(offset, mBounds.extent);
dglDrawRectFill(r, ColorI(255,255,255));
// draw the border
r.extent += r.point;
glColor4ub(0, 0, 0, 0);
glBegin(GL_LINE_LOOP);
glVertex2i(r.point.x, r.point.y);
glVertex2i(r.extent.x-1, r.point.y);
glVertex2i(r.extent.x-1, r.extent.y-1);
glVertex2i(r.point.x, r.extent.y-1);
glEnd();
if (mResult)
{
S32 txt_w = mFont->getStrWidth((const UTF8 *)mResult);
Point2I localStart;
switch (mProfile->mAlignment)
{
case GuiControlProfile::RightJustify:
localStart.set(mBounds.extent.x - txt_w-2, 0);
break;
case GuiControlProfile::CenterJustify:
localStart.set((mBounds.extent.x - txt_w) / 2, 0);
break;
default:
// GuiControlProfile::LeftJustify
localStart.set(2,0);
break;
}
Point2I globalStart = localToGlobalCoord(localStart);
//draw the text
dglSetBitmapModulation(mProfile->mFontColor);
dglDrawText(mFont, globalStart, mResult, mProfile->mFontColors);
}
//render the child controls
renderChildControls(offset, updateRect);
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
const char *GuiConsoleTextCtrl::getScriptValue()
{
return getText();
}
void GuiConsoleTextCtrl::setScriptValue(const char *val)
{
setText(val);
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
// EOF //

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUICONSOLETEXTCTRL_H_
#define _GUICONSOLETEXTCTRL_H_
#ifndef _GFONT_H_
#include "dgl/gFont.h"
#endif
#ifndef _GUITYPES_H_
#include "gui/core/guiTypes.h"
#endif
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
class GuiConsoleTextCtrl : public GuiControl
{
private:
typedef GuiControl Parent;
public:
enum Constants { MAX_STRING_LENGTH = 255 };
protected:
const char *mConsoleExpression;
const char *mResult;
Resource<GFont> mFont;
public:
//creation methods
DECLARE_CONOBJECT(GuiConsoleTextCtrl);
GuiConsoleTextCtrl();
static void initPersistFields();
//Parental methods
bool onWake();
void onSleep();
//text methods
virtual void setText(const char *txt = NULL);
const char *getText() { return mConsoleExpression; }
//rendering methods
void calcResize();
void onPreRender(); // do special pre render processing
void onRender(Point2I offset, const RectI &updateRect);
//Console methods
const char *getScriptValue();
void setScriptValue(const char *value);
};
#endif //_GUI_TEXT_CONTROL_H_

View File

@ -0,0 +1,108 @@
#include "core/findMatch.h"
#include "gui/controls/guiDirectoryFileListCtrl.h"
IMPLEMENT_CONOBJECT( GuiDirectoryFileListCtrl );
GuiDirectoryFileListCtrl::GuiDirectoryFileListCtrl()
{
}
bool GuiDirectoryFileListCtrl::onWake()
{
if( !Parent::onWake() )
return false;
setCurrentPath( "/", "*.*" );
return true;
}
void GuiDirectoryFileListCtrl::onMouseDown(const GuiEvent &event)
{
Parent::onMouseDown( event );
if( event.mouseClickCount == 2 && getNamespace() )
Con::executef(this, 1, "onDoubleClick");
}
void GuiDirectoryFileListCtrl::openDirectory()
{
Vector<Platform::FileInfo> fileVector;
Platform::dumpPath( mFilePath, fileVector, 0 );
// Clear the current file listing
clear();
// Does this dir have any files?
if( fileVector.empty() )
return;
// If so, iterate through and list them
Vector<Platform::FileInfo>::iterator i = fileVector.begin();
for( S32 j=0 ; i != fileVector.end(); i++, j++ )
{
if( FindMatch::isMatchMultipleExprs( mFilter, (*i).pFileName,false ) )
addEntry( j++, (*i).pFileName );
}
//Done!
}
bool GuiDirectoryFileListCtrl::setCurrentPath( StringTableEntry path, StringTableEntry filter )
{
// Oops, gotta give us a path to work with
if( !path )
return false;
char ExpandedPath[512];
char FullPath[512];
dMemset( ExpandedPath, 0, 512 );
dMemset( FullPath, 0, 512 );
Con::expandScriptFilename( ExpandedPath, 512, path );
if( ExpandedPath[0] != '/' )
dSprintf( FullPath, 512, "%s/%s", Platform::getWorkingDirectory(), ExpandedPath );
else
dSprintf( FullPath, 512, "%s%s", Platform::getWorkingDirectory(), ExpandedPath );
// Platform::isDirectory expects no trailing / so make sure we conform
if( FullPath[ dStrlen( FullPath ) - 1 ] == '/' )
FullPath[ dStrlen( FullPath ) - 1 ] = 0x00;
if( ! filter )
filter = StringTable->insert("*.*");
// A bad path!? For shame...
if( !Platform::isDirectory( FullPath ) && !Platform::hasSubDirectory( FullPath ) )
return false;
// Store our new info
mFilePath = StringTable->insert( FullPath );
mFilter = StringTable->insert( filter );
// Update our view
openDirectory();
// Peace out!
return true;
}
StringTableEntry GuiDirectoryFileListCtrl::getSelectedFileName()
{
return StringTable->insert( getSelectedText() );
}
ConsoleMethod( GuiDirectoryFileListCtrl, setPath, bool, 3, 4, "setPath(path,filter) - directory to enumerate files from (without trailing slash)" )
{
return object->setCurrentPath( argv[2], argv[3] );
}
ConsoleMethod( GuiDirectoryFileListCtrl, getSelectedFile, const char*, 2, 2, "getSelectedFile () - returns the currently selected file name" )
{
return object->getSelectedFileName();
}

View File

@ -0,0 +1,40 @@
#ifndef _GUI_DIRECTORYFILELISTCTRL_H_
#define _GUI_DIRECTORYFILELISTCTRL_H_
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#ifndef _GUITEXTLISTCTRL_H_
#include "gui/controls/guiTextListCtrl.h"
#endif
class GuiDirectoryFileListCtrl : public GuiTextListCtrl
{
private:
typedef GuiTextListCtrl Parent;
protected:
StringTableEntry mFilePath;
StringTableEntry mFilter;
void openDirectory();
public:
GuiDirectoryFileListCtrl();
DECLARE_CONOBJECT(GuiDirectoryFileListCtrl);
/// Set the current path to grab files from
bool setCurrentPath( StringTableEntry path, StringTableEntry filter );
bool setCurrentFilter( StringTableEntry filter );
/// Get the currently selected file's name
StringTableEntry getSelectedFileName();
virtual void onMouseDown(const GuiEvent &event);
bool onWake();
};
#endif

View File

@ -0,0 +1,382 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "gui/controls/guiDirectoryTreeCtrl.h"
IMPLEMENT_CONOBJECT(GuiDirectoryTreeCtrl);
GuiDirectoryTreeCtrl::GuiDirectoryTreeCtrl(): GuiTreeViewCtrl()
{
// Parent configuration
mBounds.set( 0,0,200,100 );
mDestroyOnSleep = false;
mSupportMouseDragging = false;
mMultipleSelections = false;
mSelPath = StringTable->insert("");
}
bool GuiDirectoryTreeCtrl::onAdd()
{
if( !Parent::onAdd() )
return false;
// Kill off any existing items
destroyTree();
// Specify our icons
buildIconTable( NULL );
// Here we're going to grab our system volumes from the platform layer and create them as roots
//
// Note : that we're passing a 1 as the last parameter to Platform::dumpDirectories, which tells it
// how deep to dump in recursion. This is an optimization to keep from dumping the whole file system
// to the tree. The tree will dump more paths as necessary when the virtual parents are expanded,
// much as windows does.
ResourceManager->initExcludedDirectories();
StringTableEntry RootPath = ResourceManager->getModPaths();
//getUnit(argv[1], dAtoi(argv[2]), " \t\n");
S32 modCount = getUnitCount( RootPath, ";" );
for( S32 i = 0; i < modCount; i++ )
{
// Compose full mod path location, and dump the path to our vector
StringTableEntry currentMod = getUnit( RootPath, i, ";" );
char fullModPath [512];
dMemset( fullModPath, 0, 512 );
dSprintf( fullModPath, 512, "%s/%s/", Platform::getWorkingDirectory(), currentMod );
Vector<StringTableEntry> pathVec;
Platform::dumpDirectories( fullModPath, pathVec, 1, true);
if( ! pathVec.empty() )
{
// Iterate through the returned paths and add them to the tree
Vector<StringTableEntry>::iterator j = pathVec.begin();
for( ; j != pathVec.end(); j++ )
{
char fullModPathSub [512];
dMemset( fullModPathSub, 0, 512 );
dSprintf( fullModPathSub, 512, "%s/%s", currentMod, (*j) );
addPathToTree( fullModPathSub );
}
}
else
addPathToTree( fullModPath );
}
return true;
}
bool GuiDirectoryTreeCtrl::onWake()
{
if( !Parent::onWake() )
return false;
// Success!
return true;
}
bool GuiDirectoryTreeCtrl::onVirtualParentExpand(Item *item)
{
if( !item || !item->isExpanded() )
return true;
StringTableEntry pathToExpand = item->getValue();
if( !pathToExpand )
{
Con::errorf("GuiDirectoryTreeCtrl::onVirtualParentExpand - Unable to retrieve item value!");
return false;
}
Vector<StringTableEntry> pathVec;
Platform::dumpDirectories( pathToExpand, pathVec, 1, true );
if( ! pathVec.empty() )
{
// Iterate through the returned paths and add them to the tree
Vector<StringTableEntry>::iterator i = pathVec.begin();
for( ; i != pathVec.end(); i++ )
recurseInsert(item, (*i) );
item->setExpanded( true );
}
item->setVirtualParent( false );
// Update our tree view
buildVisibleTree();
return true;
}
bool GuiDirectoryTreeCtrl::buildIconTable(const char * icons)
{
// Icons should be designated by the bitmap/png file names (minus the file extensions)
// and separated by colons (:).
if (!icons)
icons = StringTable->insert("common/ui/bs:common/ui/folder:common/ui/folder_closed");
return Parent::buildIconTable( icons );
}
void GuiDirectoryTreeCtrl::addPathToTree( StringTableEntry path )
{
if( !path )
{
Con::errorf("GuiDirectoryTreeCtrl::addPathToTree - Invalid Path!");
return;
}
// Identify which root (volume) this path belongs to (if any)
S32 root = getFirstRootItem();
StringTableEntry ourPath = &path[ dStrcspn( path, "//" ) + 1];
StringTableEntry ourRoot = getUnit( path, 0, "//" );
// There are no current roots, we can safely create one
if( root == 0 )
{
recurseInsert( NULL, path );
}
else
{
while( root != 0 )
{
if( dStrcmp( getItemValue( root ), ourRoot ) == 0 )
{
recurseInsert( getItem( root ), ourPath );
break;
}
root = this->getNextSiblingItem( root );
}
// We found none so we'll create one
if ( root == 0 )
{
recurseInsert( NULL, path );
}
}
}
void GuiDirectoryTreeCtrl::onItemSelected( Item *item )
{
Con::executef( this, 2, "onSelectPath", avar("%s",item->getValue()) );
mSelPath = StringTable->insert( item->getValue() );
if( Platform::hasSubDirectory( item->getValue() ) )
item->setVirtualParent( true );
}
void GuiDirectoryTreeCtrl::recurseInsert( Item* parent, StringTableEntry path )
{
if( !path )
return;
char szPathCopy [ 1024 ];
dMemset( szPathCopy, 0, 1024 );
dStrcpy( szPathCopy, path );
// Jump over the first character if it's a root /
char *curPos = szPathCopy;
if( *curPos == '/' )
curPos++;
char *delim = dStrchr( curPos, '/' );
if ( delim )
{
// terminate our / and then move our pointer to the next character (rest of the path)
*delim = 0x00;
delim++;
}
S32 itemIndex = 0;
// only insert blindly if we have no root
if( !parent )
{
itemIndex = insertItem( 0, curPos, curPos );
getItem( itemIndex )->setNormalImage( Icon_FolderClosed );
getItem( itemIndex )->setExpandedImage( Icon_Folder );
}
else
{
Item *item = parent;
char *szValue = new char[ 1024 ];
dMemset( szValue, 0, 1024 );
dSprintf( szValue, 1024, "%s/%s", parent->getValue(), curPos );
Item *exists = item->findChildByValue( szValue );
if( !exists && dStrcmp( curPos, "" ) != 0 )
{
// Since we're adding a child this parent can't be a virtual parent, so clear that flag
item->setVirtualParent( false );
itemIndex = insertItem( item->getID(), curPos);
getItem( itemIndex )->setValue( szValue );
getItem( itemIndex )->setNormalImage( Icon_FolderClosed );
getItem( itemIndex )->setExpandedImage( Icon_Folder );
}
else
{
delete []szValue;
itemIndex = ( item != NULL ) ? ( ( exists != NULL ) ? exists->getID() : -1 ) : -1;
}
}
// since we're only dealing with volumes and directories, all end nodes will be virtual parents
// so if we are at the bottom of the rabbit hole, set the item to be a virtual parent
Item* item = getItem( itemIndex );
if( delim )
{
if( ( dStrcmp( delim, "" ) == 0 ) && item )
{
item->setExpanded( false );
if( parent && Platform::hasSubDirectory( item->getValue() ) )
item->setVirtualParent( true );
}
}
else
{
if( item )
{
item->setExpanded( false );
if( parent && Platform::hasSubDirectory( item->getValue() ) )
item->setVirtualParent( true );
}
}
// Down the rabbit hole we go
recurseInsert( getItem( itemIndex ), delim );
}
StringTableEntry GuiDirectoryTreeCtrl::getUnit(const char *string, U32 index, const char *set)
{
U32 sz;
while(index--)
{
if(!*string)
return "";
sz = dStrcspn(string, set);
if (string[sz] == 0)
return "";
string += (sz + 1);
}
sz = dStrcspn(string, set);
if (sz == 0)
return "";
char *ret = Con::getReturnBuffer(sz+1);
dStrncpy(ret, string, sz);
ret[sz] = '\0';
return ret;
}
StringTableEntry GuiDirectoryTreeCtrl::getUnits(const char *string, S32 startIndex, S32 endIndex, const char *set)
{
S32 sz;
S32 index = startIndex;
while(index--)
{
if(!*string)
return "";
sz = dStrcspn(string, set);
if (string[sz] == 0)
return "";
string += (sz + 1);
}
const char *startString = string;
while(startIndex <= endIndex--)
{
sz = dStrcspn(string, set);
string += sz;
if (*string == 0)
break;
string++;
}
if(!*string)
string++;
U32 totalSize = (U32(string - startString));
char *ret = Con::getReturnBuffer(totalSize);
dStrncpy(ret, startString, totalSize - 1);
ret[totalSize-1] = '\0';
return ret;
}
U32 GuiDirectoryTreeCtrl::getUnitCount(const char *string, const char *set)
{
U32 count = 0;
U8 last = 0;
while(*string)
{
last = *string++;
for(U32 i =0; set[i]; i++)
{
if(last == set[i])
{
count++;
last = 0;
break;
}
}
}
if(last)
count++;
return count;
}
ConsoleMethod( GuiDirectoryTreeCtrl, getSelectedPath, const char*, 2,2, "getSelectedPath() - returns the currently selected path in the tree")
{
return object->getSelectedPath();
}
StringTableEntry GuiDirectoryTreeCtrl::getSelectedPath()
{
return mSelPath;
}
ConsoleMethod( GuiDirectoryTreeCtrl, setSelectedPath, bool, 3, 3, "setSelectedPath(path) - expands the tree to the specified path")
{
return object->setSelectedPath( argv[2] );
}
bool GuiDirectoryTreeCtrl::setSelectedPath( StringTableEntry path )
{
if( !path )
return false;
// Since we only list one deep on paths, we need to add the path to the tree just incase it isn't already indexed in the tree
// or else we wouldn't be able to select a path we hadn't previously browsed to. :)
if( Platform::isDirectory( path ) )
addPathToTree( path );
// see if we have a child that matches what we want
for(U32 i = 0; i < mItems.size(); i++)
{
if( dStricmp( mItems[i]->getValue(), path ) == 0 )
{
Item* item = mItems[i];
AssertFatal(item,"GuiDirectoryTreeCtrl::setSelectedPath - Item Index Bad, Fatal Mistake!!!");
item->setExpanded( true );
clearSelection();
setItemSelected( item->getID(), true );
// make sure all of it's parents are expanded
S32 parent = getParentItem( item->getID() );
while( parent != 0 )
{
setItemExpanded( parent, true );
parent = getParentItem( parent );
}
// Rebuild our tree just incase we've oops'd
buildVisibleTree();
scrollVisible( item );
}
}
return false;
}

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUI_DIRECTORYTREECTRL_H_
#define _GUI_DIRECTORYTREECTRL_H_
#ifndef _PLATFORM_H_
#include "platform/platform.h"
#endif
#ifndef _RESMANAGER_H_
#include "core/resManager.h"
#endif
#ifndef _GUI_TREEVIEWCTRL_H
#include "gui/controls/guiTreeViewCtrl.h"
#endif
class GuiDirectoryTreeCtrl : public GuiTreeViewCtrl
{
private:
typedef GuiTreeViewCtrl Parent;
// Utility functions
void recurseInsert( Item* parent, StringTableEntry path );
void addPathToTree( StringTableEntry path );
protected:
StringTableEntry mSelPath;
public:
enum
{
Icon_Folder = 1,
Icon_FolderClosed
};
GuiDirectoryTreeCtrl();
bool onWake();
bool onAdd();
bool onVirtualParentExpand(Item *item);
void onItemSelected( Item *item );
StringTableEntry getSelectedPath();
bool setSelectedPath( StringTableEntry path );
bool buildIconTable(const char * icons);
// Mod Path Parsing
StringTableEntry getUnit(const char *string, U32 index, const char *set);
StringTableEntry getUnits(const char *string, S32 startIndex, S32 endIndex, const char *set);
U32 getUnitCount(const char *string, const char *set);
DECLARE_CONOBJECT(GuiDirectoryTreeCtrl);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,275 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIMLTEXTCTRL_H_
#define _GUIMLTEXTCTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
#ifndef _STRINGBUFFER_H_
#include "core/stringBuffer.h"
#endif
class GFont;
class GuiMLTextCtrl : public GuiControl
{
typedef GuiControl Parent;
//-------------------------------------- Public interfaces...
public:
enum Justification
{
LeftJustify,
RightJustify,
CenterJustify,
};
struct Font {
char *faceName;
U32 faceNameLen;
U32 size;
Resource<GFont> fontRes;
Font *next;
};
struct Bitmap {
const char *bitmapName;
U32 bitmapNameLen;
TextureHandle bitmapHandle;
Bitmap *next;
};
struct URL
{
bool mouseDown;
U32 textStart;
U32 len;
bool noUnderline;
};
struct Style
{
ColorI color;
ColorI shadowColor;
ColorI linkColor;
ColorI linkColorHL;
Point2I shadowOffset;
Font *font;
bool used;
Style *next;
};
struct Atom
{
U32 textStart;
U32 len;
U32 xStart;
U32 yStart;
U32 width;
U32 baseLine;
U32 descent;
Style *style;
bool isClipped;
URL *url;
Atom *next;
};
struct Line {
U32 y;
U32 height;
U32 divStyle;
U32 textStart;
U32 len;
Atom *atomList;
Line *next;
};
struct BitmapRef : public RectI
{
BitmapRef *nextBlocker;
U32 textStart;
U32 len;
Bitmap *bitmap;
BitmapRef *next;
};
struct LineTag {
U32 id;
S32 y;
LineTag *next;
};
GuiMLTextCtrl();
~GuiMLTextCtrl();
// Text retrieval functions
U32 getNumChars() const;
U32 getText(char* pBuffer, const U32 bufferSize) const;
U32 getWrappedText(char* pBuffer, const U32 bufferSize) const;
const char* getTextContent();
void insertChars(const char* inputChars,
const U32 numInputChars,
const U32 position);
// Text substitution functions
void setText(const char* textBuffer, const U32 numChars);
void addText(const char* textBuffer, const U32 numChars, bool reformat);
void setAlpha(F32 alpha) { mAlpha = alpha;}
bool setCursorPosition(const S32);
void ensureCursorOnScreen();
// Scroll functions
void scrollToTag( U32 id );
void scrollToTop();
void scrollToBottom();
virtual void reflow();
DECLARE_CONOBJECT(GuiMLTextCtrl);
static void initPersistFields();
void setScriptValue(const char *value);
const char *getScriptValue();
static char *stripControlChars(const char *inString);
//-------------------------------------- Protected Structures and constants
protected:
bool mIsEditCtrl;
U32 *mTabStops;
U32 mTabStopCount;
U32 mCurTabStop;
F32 mAlpha;
DataChunker mViewChunker;
DataChunker mResourceChunker;
Line *mLineList;
Bitmap *mBitmapList;
BitmapRef *mBitmapRefList;
Font *mFontList;
LineTag *mTagList;
bool mDirty;
Style *mCurStyle;
U32 mCurLMargin;
U32 mCurRMargin;
U32 mCurJustify;
U32 mCurDiv;
U32 mCurY;
U32 mCurClipX;
Atom *mLineAtoms;
Atom **mLineAtomPtr;
Atom *mEmitAtoms;
Atom **mEmitAtomPtr;
BitmapRef mSentinel;
Line **mLineInsert;
BitmapRef *mBlockList;
U32 mScanPos;
U32 mCurX;
U32 mMaxY;
URL *mCurURL;
URL *mHitURL;
void freeLineBuffers();
void freeResources();
Bitmap *allocBitmap(char *bitmapName, U32 bitmapNameLen);
Font *allocFont(char *faceName, U32 faceNameLen, U32 size);
LineTag *allocLineTag(U32 id);
void emitNewLine(U32 textStart);
Atom *buildTextAtom(U32 start, U32 len, U32 left, U32 right, URL *url);
void emitTextToken(U32 textStart, U32 len);
void emitBitmapToken(Bitmap *bmp, U32 textStart, bool bitmapBreak);
void processEmitAtoms();
Atom *splitAtomListEmit(Atom *list, U32 width);
void drawAtomText(bool sel, U32 start, U32 end, Atom *atom, Line *line, Point2I offset);
Atom *findHitAtom(const Point2I localCoords);
Style *allocStyle(Style *style);
static const U32 csmTextBufferGrowthSize;
//-------------------------------------- Data...
protected:
// Cursor position should always be <= mCurrTextSize
U32 mCursorPosition;
// Actual text data. The line buffer is rebuilt from the linear text
// given a specific width. TextBuffer is /not/ \0 terminated
StringBuffer mTextBuffer;
U32 mLineStart;
S32 mMaxBufferSize;
StringTableEntry mInitialText;
// Selection information
bool mSelectionActive;
U32 mSelectionStart;
U32 mSelectionEnd;
U32 mVertMoveAnchor;
bool mVertMoveAnchorValid;
S32 mSelectionAnchor;
Point2I mSelectionAnchorDropped;
// Font resource
Resource<GFont> mFont;
U32 mMinSensibleWidth;
// Console settable parameters
U32 mLineSpacingPixels;
bool mAllowColorChars;
// Too many chars sound:
AudioProfile* mDeniedSound;
//-------------------------------------- Protected interface
protected:
// Inserting and deleting character blocks...
void deleteChars(const U32 rangeStart,
const U32 rangeEnd);
void copyToClipboard(const U32 rangeStart,
const U32 rangeEnd);
// Selection maintainance
bool isSelectionActive() const;
void clearSelection();
// Pixel -> textposition mappings
S32 getTextPosition(const Point2I& localPosition);
// Gui control overrides
bool onAdd();
bool onWake();
void onSleep();
void onPreRender();
void onRender(Point2I offset, const RectI &updateRect);
void getCursorPositionAndColor(Point2I &cursorTop, Point2I &cursorBottom, ColorI &color);
void inspectPostApply();
void resize(const Point2I &newPosition, const Point2I &newExtent);
void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
bool onKeyDown(const GuiEvent& event);
void onMouseDown(const GuiEvent&);
void onMouseDragged(const GuiEvent&);
void onMouseUp(const GuiEvent&);
public:
void setSelectionStart( U32 start ) { clearSelection(); mSelectionStart = start; };
void setSelectionEnd( U32 end ) { mSelectionEnd = end;};
void setSelectionActive(bool active) { mSelectionActive = active; };
S32 getCursorPosition() { return( mCursorPosition ); }
};
#endif // _H_GUIMLTEXTCTRL_

View File

@ -0,0 +1,376 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "gui/controls/guiMLTextEditCtrl.h"
#include "gui/containers/guiScrollCtrl.h"
#include "dgl/dgl.h"
#include "console/consoleTypes.h"
#include "platform/event.h"
#include "core/frameAllocator.h"
#include "core/stringBuffer.h"
IMPLEMENT_CONOBJECT(GuiMLTextEditCtrl);
//--------------------------------------------------------------------------
GuiMLTextEditCtrl::GuiMLTextEditCtrl()
{
mEscapeCommand = StringTable->insert( "" );
mIsEditCtrl = true;
mActive = true;
mVertMoveAnchorValid = false;
}
//--------------------------------------------------------------------------
GuiMLTextEditCtrl::~GuiMLTextEditCtrl()
{
}
//--------------------------------------------------------------------------
void GuiMLTextEditCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
{
// We don't want to get any smaller than our parent:
Point2I newExt = newExtent;
GuiControl* parent = getParent();
if ( parent )
newExt.y = getMax( parent->mBounds.extent.y, newExt.y );
Parent::resize( newPosition, newExt );
}
//--------------------------------------------------------------------------
void GuiMLTextEditCtrl::initPersistFields()
{
Parent::initPersistFields();
addField( "escapeCommand", TypeString, Offset( mEscapeCommand, GuiMLTextEditCtrl ) );
}
//--------------------------------------------------------------------------
// Key events...
bool GuiMLTextEditCtrl::onKeyDown(const GuiEvent& event)
{
setUpdate();
//handle modifiers first...
if (event.modifier & SI_CTRL)
{
switch(event.keyCode)
{
//copy/cut
case KEY_C:
case KEY_X:
{
//make sure we actually have something selected
if (mSelectionActive)
{
copyToClipboard(mSelectionStart, mSelectionEnd);
//if we're cutting, also delete the selection
if (event.keyCode == KEY_X)
{
mSelectionActive = false;
deleteChars(mSelectionStart, mSelectionEnd);
mCursorPosition = mSelectionStart;
}
else
mCursorPosition = mSelectionEnd + 1;
}
return true;
}
//paste
case KEY_V:
{
const char *clipBuf = Platform::getClipboard();
if (dStrlen(clipBuf) > 0)
{
// Normal ascii keypress. Go ahead and add the chars...
if (mSelectionActive == true)
{
mSelectionActive = false;
deleteChars(mSelectionStart, mSelectionEnd);
mCursorPosition = mSelectionStart;
}
insertChars(clipBuf, dStrlen(clipBuf), mCursorPosition);
}
return true;
}
}
}
else if ( event.modifier & SI_SHIFT )
{
switch ( event.keyCode )
{
case KEY_TAB:
return( Parent::onKeyDown( event ) );
}
}
else if ( event.modifier == 0 )
{
switch (event.keyCode)
{
// Escape:
case KEY_ESCAPE:
if ( mEscapeCommand[0] )
{
Con::evaluate( mEscapeCommand );
return( true );
}
return( Parent::onKeyDown( event ) );
// Deletion
case KEY_BACKSPACE:
case KEY_DELETE:
handleDeleteKeys(event);
return true;
// Cursor movement
case KEY_LEFT:
case KEY_RIGHT:
case KEY_UP:
case KEY_DOWN:
case KEY_HOME:
case KEY_END:
handleMoveKeys(event);
return true;
// Special chars...
case KEY_TAB:
// insert 3 spaces
if (mSelectionActive == true)
{
mSelectionActive = false;
deleteChars(mSelectionStart, mSelectionEnd);
mCursorPosition = mSelectionStart;
}
insertChars( "\t", 1, mCursorPosition );
return true;
case KEY_RETURN:
// insert carriage return
if (mSelectionActive == true)
{
mSelectionActive = false;
deleteChars(mSelectionStart, mSelectionEnd);
mCursorPosition = mSelectionStart;
}
insertChars( "\n", 1, mCursorPosition );
return true;
}
}
if (event.ascii != 0)
{
// Normal ascii keypress. Go ahead and add the chars...
if (mSelectionActive == true)
{
mSelectionActive = false;
deleteChars(mSelectionStart, mSelectionEnd);
mCursorPosition = mSelectionStart;
}
UTF8 *outString = NULL;
U32 outStringLen = 0;
#ifdef TORQUE_UNICODE
UTF16 inData[2] = { event.ascii, 0 };
StringBuffer inBuff(inData);
FrameTemp<UTF8> outBuff(4);
inBuff.get(outBuff, 4);
outString = outBuff;
outStringLen = dStrlen(outBuff);
#else
char ascii = char(event.ascii);
outString = &ascii;
outStringLen = 1;
#endif
insertChars(outString, outStringLen, mCursorPosition);
mVertMoveAnchorValid = false;
return true;
}
// Otherwise, let the parent have the event...
return Parent::onKeyDown(event);
}
//--------------------------------------
void GuiMLTextEditCtrl::handleDeleteKeys(const GuiEvent& event)
{
if ( isSelectionActive() )
{
mSelectionActive = false;
deleteChars(mSelectionStart, mSelectionEnd);
mCursorPosition = mSelectionStart;
}
else
{
switch ( event.keyCode )
{
case KEY_BACKSPACE:
if (mCursorPosition != 0)
{
// delete one character left
deleteChars(mCursorPosition-1, mCursorPosition-1);
setUpdate();
}
break;
case KEY_DELETE:
if (mCursorPosition != mTextBuffer.length())
{
// delete one character right
deleteChars(mCursorPosition, mCursorPosition);
setUpdate();
}
break;
default:
AssertFatal(false, "Unknown key code received!");
}
}
}
//--------------------------------------
void GuiMLTextEditCtrl::handleMoveKeys(const GuiEvent& event)
{
if ( event.modifier & SI_SHIFT )
return;
mSelectionActive = false;
switch ( event.keyCode )
{
case KEY_LEFT:
mVertMoveAnchorValid = false;
// move one left
if ( mCursorPosition != 0 )
{
mCursorPosition--;
setUpdate();
}
break;
case KEY_RIGHT:
mVertMoveAnchorValid = false;
// move one right
if ( mCursorPosition != mTextBuffer.length() )
{
mCursorPosition++;
setUpdate();
}
break;
case KEY_UP:
case KEY_DOWN:
{
Line* walk;
for ( walk = mLineList; walk->next; walk = walk->next )
{
if ( mCursorPosition <= ( walk->textStart + walk->len ) )
break;
}
if ( !walk )
return;
if ( event.keyCode == KEY_UP )
{
if ( walk == mLineList )
return;
}
else if ( walk->next == NULL )
return;
Point2I newPos;
newPos.set( 0, walk->y );
// Find the x-position:
if ( !mVertMoveAnchorValid )
{
Point2I cursorTopP, cursorBottomP;
ColorI color;
getCursorPositionAndColor(cursorTopP, cursorBottomP, color);
mVertMoveAnchor = cursorTopP.x;
mVertMoveAnchorValid = true;
}
newPos.x = mVertMoveAnchor;
// Set the new y-position:
if (event.keyCode == KEY_UP)
newPos.y--;
else
newPos.y += (walk->height + 1);
if (setCursorPosition(getTextPosition(newPos)))
mVertMoveAnchorValid = false;
break;
}
case KEY_HOME:
case KEY_END:
{
mVertMoveAnchorValid = false;
Line* walk;
for (walk = mLineList; walk->next; walk = walk->next)
{
if (mCursorPosition <= (walk->textStart + walk->len))
break;
}
if (walk)
{
if (event.keyCode == KEY_HOME)
{
//place the cursor at the beginning of the first atom if there is one
if (walk->atomList)
mCursorPosition = walk->atomList->textStart;
else
mCursorPosition = walk->textStart;
}
else
{
mCursorPosition = walk->textStart;
mCursorPosition += walk->len;
}
setUpdate();
}
break;
}
default:
AssertFatal(false, "Unknown move key code was received!");
}
ensureCursorOnScreen();
}
//--------------------------------------------------------------------------
void GuiMLTextEditCtrl::onRender(Point2I offset, const RectI& updateRect)
{
Parent::onRender(offset, updateRect);
// We are the first responder, draw our cursor in the appropriate position...
if (isFirstResponder())
{
Point2I top, bottom;
ColorI color;
getCursorPositionAndColor(top, bottom, color);
dglDrawLine(top + offset, bottom + offset, mProfile->mCursorColor);
}
}

View File

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIMLTEXTEDITCTRL_H_
#define _GUIMLTEXTEDITCTRL_H_
#ifndef _GUIMLTEXTCTRL_H_
#include "gui/controls/guiMLTextCtrl.h"
#endif
class GuiMLTextEditCtrl : public GuiMLTextCtrl
{
typedef GuiMLTextCtrl Parent;
//-------------------------------------- Overrides
protected:
StringTableEntry mEscapeCommand;
// Events
bool onKeyDown(const GuiEvent&event);
// Event forwards
void handleMoveKeys(const GuiEvent&);
void handleDeleteKeys(const GuiEvent&);
// rendering
void onRender(Point2I offset, const RectI &updateRect);
public:
GuiMLTextEditCtrl();
~GuiMLTextEditCtrl();
void resize(const Point2I &newPosition, const Point2I &newExtent);
DECLARE_CONOBJECT(GuiMLTextEditCtrl);
static void initPersistFields();
};
#endif // _H_GUIMLTEXTEDITCTRL_

View File

@ -0,0 +1,811 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiPopUpCtrl.h"
#include "console/consoleTypes.h"
#include "gui/core/guiDefaultControlRender.h"
IMPLEMENT_CONOBJECT(GuiPopUpMenuCtrl);
GuiPopUpBackgroundCtrl::GuiPopUpBackgroundCtrl(GuiPopUpMenuCtrl *ctrl, GuiPopUpTextListCtrl *textList)
{
mPopUpCtrl = ctrl;
mTextList = textList;
}
void GuiPopUpBackgroundCtrl::onMouseDown(const GuiEvent &event)
{
mTextList->setSelectedCell(Point2I(-1,-1));
mPopUpCtrl->closePopUp();
}
//------------------------------------------------------------------------------
GuiPopUpTextListCtrl::GuiPopUpTextListCtrl()
{
mPopUpCtrl = NULL;
}
//------------------------------------------------------------------------------
GuiPopUpTextListCtrl::GuiPopUpTextListCtrl(GuiPopUpMenuCtrl *ctrl)
{
mPopUpCtrl = ctrl;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void GuiPopUpTextListCtrl::onCellSelected( Point2I /*cell*/ )
{
// Do nothing, the parent control will take care of everything...
}
//------------------------------------------------------------------------------
bool GuiPopUpTextListCtrl::onKeyDown(const GuiEvent &event)
{
//if the control is a dead end, don't process the input:
if ( !mVisible || !mActive || !mAwake )
return false;
//see if the key down is a <return> or not
if ( event.modifier == 0 )
{
if ( event.keyCode == KEY_RETURN )
{
mPopUpCtrl->closePopUp();
return true;
}
else if ( event.keyCode == KEY_ESCAPE )
{
mSelectedCell.set( -1, -1 );
mPopUpCtrl->closePopUp();
return true;
}
}
//otherwise, pass the event to it's parent
return Parent::onKeyDown(event);
}
void GuiPopUpTextListCtrl::onMouseDown(const GuiEvent &event)
{
Parent::onMouseDown(event);
mPopUpCtrl->closePopUp();
}
//------------------------------------------------------------------------------
void GuiPopUpTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
{
ColorI fontColor;
mPopUpCtrl->getFontColor( fontColor, mList[cell.y].id, selected, mouseOver );
dglSetBitmapModulation( fontColor );
dglDrawText( mFont, Point2I( offset.x + 4, offset.y ), mList[cell.y].text );
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
GuiPopUpMenuCtrl::GuiPopUpMenuCtrl(void)
{
VECTOR_SET_ASSOCIATION(mEntries);
VECTOR_SET_ASSOCIATION(mSchemes);
mSelIndex = -1;
mActive = true;
mMaxPopupHeight = 200;
mScrollDir = GuiScrollCtrl::None;
mScrollCount = 0;
mLastYvalue = 0;
mIncValue = 0;
mRevNum = 0;
mInAction = false;
}
//------------------------------------------------------------------------------
GuiPopUpMenuCtrl::~GuiPopUpMenuCtrl()
{
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::initPersistFields(void)
{
Parent::initPersistFields();
addField("maxPopupHeight", TypeS32, Offset(mMaxPopupHeight, GuiPopUpMenuCtrl));
}
//------------------------------------------------------------------------------
ConsoleMethod( GuiPopUpMenuCtrl, add, void, 4, 5, "(string name, int idNum, int scheme=0)")
{
if ( argc > 4 )
object->addEntry(argv[2],dAtoi(argv[3]),dAtoi(argv[4]));
else
object->addEntry(argv[2],dAtoi(argv[3]),0);
}
ConsoleMethod( GuiPopUpMenuCtrl, addScheme, void, 6, 6, "(int id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL)")
{
ColorI fontColor, fontColorHL, fontColorSEL;
U32 r, g, b;
char buf[64];
dStrcpy( buf, argv[3] );
char* temp = dStrtok( buf, " \0" );
r = temp ? dAtoi( temp ) : 0;
temp = dStrtok( NULL, " \0" );
g = temp ? dAtoi( temp ) : 0;
temp = dStrtok( NULL, " \0" );
b = temp ? dAtoi( temp ) : 0;
fontColor.set( r, g, b );
dStrcpy( buf, argv[4] );
temp = dStrtok( buf, " \0" );
r = temp ? dAtoi( temp ) : 0;
temp = dStrtok( NULL, " \0" );
g = temp ? dAtoi( temp ) : 0;
temp = dStrtok( NULL, " \0" );
b = temp ? dAtoi( temp ) : 0;
fontColorHL.set( r, g, b );
dStrcpy( buf, argv[5] );
temp = dStrtok( buf, " \0" );
r = temp ? dAtoi( temp ) : 0;
temp = dStrtok( NULL, " \0" );
g = temp ? dAtoi( temp ) : 0;
temp = dStrtok( NULL, " \0" );
b = temp ? dAtoi( temp ) : 0;
fontColorSEL.set( r, g, b );
object->addScheme( dAtoi( argv[2] ), fontColor, fontColorHL, fontColorSEL );
}
ConsoleMethod( GuiPopUpMenuCtrl, setText, void, 3, 3, "(string text)")
{
object->setText(argv[2]);
}
ConsoleMethod( GuiPopUpMenuCtrl, getText, const char*, 2, 2, "")
{
return object->getText();
}
ConsoleMethod( GuiPopUpMenuCtrl, clear, void, 2, 2, "Clear the popup list.")
{
object->clear();
}
ConsoleMethod(GuiPopUpMenuCtrl, sort, void, 2, 2, "Sort the list alphabetically.")
{
object->sort();
}
ConsoleMethod( GuiPopUpMenuCtrl, forceOnAction, void, 2, 2, "")
{
object->onAction();
}
ConsoleMethod( GuiPopUpMenuCtrl, forceClose, void, 2, 2, "")
{
object->closePopUp();
}
ConsoleMethod( GuiPopUpMenuCtrl, getSelected, S32, 2, 2, "")
{
return object->getSelected();
}
ConsoleMethod( GuiPopUpMenuCtrl, setSelected, void, 3, 3, "(int id)")
{
object->setSelected(dAtoi(argv[2]));
}
ConsoleMethod( GuiPopUpMenuCtrl, getTextById, const char*, 3, 3, "(int id)")
{
return(object->getTextById(dAtoi(argv[2])));
}
ConsoleMethod( GuiPopUpMenuCtrl, setEnumContent, void, 4, 4, "(string class, string enum)"
"This fills the popup with a classrep's field enumeration type info.\n\n"
"More of a helper function than anything. If console access to the field list is added, "
"at least for the enumerated types, then this should go away..")
{
AbstractClassRep * classRep = AbstractClassRep::getClassList();
// walk the class list to get our class
while(classRep)
{
if(!dStricmp(classRep->getClassName(), argv[2]))
break;
classRep = classRep->getNextClass();
}
// get it?
if(!classRep)
{
Con::warnf(ConsoleLogEntry::General, "failed to locate class rep for '%s'", argv[2]);
return;
}
// walk the fields to check for this one (findField checks StringTableEntry ptrs...)
U32 i;
for(i = 0; i < classRep->mFieldList.size(); i++)
if(!dStricmp(classRep->mFieldList[i].pFieldname, argv[3]))
break;
// found it?
if(i == classRep->mFieldList.size())
{
Con::warnf(ConsoleLogEntry::General, "failed to locate field '%s' for class '%s'", argv[3], argv[2]);
return;
}
const AbstractClassRep::Field & field = classRep->mFieldList[i];
// check the type
if(field.type != TypeEnum)
{
Con::warnf(ConsoleLogEntry::General, "field '%s' is not an enumeration for class '%s'", argv[3], argv[2]);
return;
}
AssertFatal(field.table, avar("enumeration '%s' for class '%s' with NULL ", argv[3], argv[2]));
// fill it
for(i = 0; i < field.table->size; i++)
object->addEntry(field.table->table[i].label, field.table->table[i].index);
}
//------------------------------------------------------------------------------
ConsoleMethod( GuiPopUpMenuCtrl, findText, S32, 3, 3, "(string text)"
"Returns the position of the first entry containing the specified text.")
{
return( object->findText( argv[2] ) );
}
//------------------------------------------------------------------------------
ConsoleMethod( GuiPopUpMenuCtrl, size, S32, 2, 2, "Get the size of the menu - the number of entries in it.")
{
return( object->getNumEntries() );
}
//------------------------------------------------------------------------------
ConsoleMethod( GuiPopUpMenuCtrl, replaceText, void, 3, 3, "(bool doReplaceText)")
{
object->replaceText(dAtoi(argv[2]));
}
//------------------------------------------------------------------------------
bool GuiPopUpMenuCtrl::onAdd()
{
if (!Parent::onAdd())
return false;
mSelIndex = -1;
mReplaceText = true;
return true;
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::onSleep()
{
Parent::onSleep();
closePopUp(); // Tests in function.
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::clear()
{
mEntries.setSize(0);
setText("");
mSelIndex = -1;
mRevNum = 0;
}
//------------------------------------------------------------------------------
static S32 QSORT_CALLBACK textCompare(const void *a,const void *b)
{
GuiPopUpMenuCtrl::Entry *ea = (GuiPopUpMenuCtrl::Entry *) (a);
GuiPopUpMenuCtrl::Entry *eb = (GuiPopUpMenuCtrl::Entry *) (b);
return (dStricmp(ea->buf, eb->buf));
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::sort()
{
dQsort((void *)&(mEntries[0]), mEntries.size(), sizeof(Entry), textCompare);
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::addEntry(const char *buf, S32 id, U32 scheme)
{
Entry e;
dStrcpy(e.buf, buf);
e.id = id;
e.scheme = scheme;
// see if there is a shortcut key
char * cp = dStrchr(e.buf, '~');
e.ascii = cp ? cp[1] : 0;
mEntries.push_back(e);
if ( mInAction && mTl )
{
// Add the new entry:
mTl->addEntry( e.id, e.buf );
repositionPopup();
}
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::addScheme( U32 id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL )
{
if ( !id )
return;
Scheme newScheme;
newScheme.id = id;
newScheme.fontColor = fontColor;
newScheme.fontColorHL = fontColorHL;
newScheme.fontColorSEL = fontColorSEL;
mSchemes.push_back( newScheme );
}
//------------------------------------------------------------------------------
S32 GuiPopUpMenuCtrl::getSelected()
{
if (mSelIndex == -1)
return 0;
return mEntries[mSelIndex].id;
}
//------------------------------------------------------------------------------
const char* GuiPopUpMenuCtrl::getTextById(S32 id)
{
for ( U32 i = 0; i < mEntries.size(); i++ )
{
if ( mEntries[i].id == id )
return( mEntries[i].buf );
}
return( "" );
}
//------------------------------------------------------------------------------
S32 GuiPopUpMenuCtrl::findText( const char* text )
{
for ( U32 i = 0; i < mEntries.size(); i++ )
{
if ( dStrcmp( text, mEntries[i].buf ) == 0 )
return( mEntries[i].id );
}
return( -1 );
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::setSelected(S32 id)
{
S32 i;
for (i = 0; U32(i) < mEntries.size(); i++)
if (id == mEntries[i].id)
{
i = (mRevNum > i) ? mRevNum - i : i;
mSelIndex = i;
setText(mEntries[i].buf);
// Now perform the popup action:
char idval[24];
dSprintf( idval, sizeof(idval), "%d", mEntries[mSelIndex].id );
Con::executef( this, 3, "onSelect", idval, mEntries[mSelIndex].buf );
return;
}
setText("");
mSelIndex = -1;
Con::executef( this, 1, "onCancel" );
// Execute the popup console command:
if ( mConsoleCommand[0] )
Con::evaluate( mConsoleCommand, false );
}
//------------------------------------------------------------------------------
const char *GuiPopUpMenuCtrl::getScriptValue()
{
return getText();
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
{
updateRect;
Point2I localStart;
if(mScrollDir != GuiScrollCtrl::None)
autoScroll();
RectI r(offset, mBounds.extent);
RectI buttonRect( ( r.point.x + r.extent.x ) - 18, r.point.y + 2, 16, r.extent.y - 4);
if( mProfile->mBorder && mProfile->mOpaque)
{
if(mInAction)
{
renderFilledBorder(r, mProfile->mBorderColorHL, mProfile->mFillColor);
renderFilledBorder( buttonRect, mProfile->mBorderColorHL, mProfile->mFillColorNA);
}
else
{
renderFilledBorder(r, mProfile->mBorderColorHL, mProfile->mFillColor);
renderFilledBorder( buttonRect, mProfile->mBorderColorHL, mProfile->mFillColorNA);
}
}
S32 txt_w = mFont->getStrWidth((const UTF8 *)mText);
localStart.x = 0;
localStart.y = (mBounds.extent.y - (mFont->getHeight())) / 2;
// align the horizontal
switch (mProfile->mAlignment)
{
case GuiControlProfile::RightJustify:
localStart.x = mBounds.extent.x - txt_w;
break;
case GuiControlProfile::CenterJustify:
localStart.x = (mBounds.extent.x - txt_w) / 2;
break;
default: // GuiControlProfile::LeftJustify
localStart.x = 4;
break;
}
Point2I globalStart = localToGlobalCoord(localStart);
dglSetBitmapModulation(mProfile->mFontColor);
dglDrawText(mFont, globalStart, mText, mProfile->mFontColors);
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::closePopUp()
{
if ( !mInAction )
return;
// Get the selection from the text list:
mSelIndex = mTl->getSelectedCell().y;
mSelIndex = (mRevNum >= mSelIndex && mSelIndex != -1) ? mRevNum - mSelIndex : mSelIndex;
if ( mSelIndex != -1 )
{
if(mReplaceText)
setText( mEntries[mSelIndex].buf );
setIntVariable( mEntries[mSelIndex].id );
}
// Release the mouse:
mInAction = false;
mTl->mouseUnlock();
// Pop the background:
getRoot()->popDialogControl(mBackground);
// Kill the popup:
mBackground->removeObject( mSc );
mTl->deleteObject();
mSc->deleteObject();
mBackground->deleteObject();
// Set this as the first responder:
setFirstResponder();
// Now perform the popup action:
if ( mSelIndex != -1 )
{
char idval[24];
dSprintf( idval, sizeof(idval), "%d", mEntries[mSelIndex].id );
Con::executef( this, 3, "onSelect", idval, mEntries[mSelIndex].buf );
}
else
Con::executef( this, 1, "onCancel" );
// Execute the popup console command:
if ( mConsoleCommand[0] )
Con::evaluate( mConsoleCommand, false );
}
//------------------------------------------------------------------------------
bool GuiPopUpMenuCtrl::onKeyDown(const GuiEvent &event)
{
//if the control is a dead end, don't process the input:
if ( !mVisible || !mActive || !mAwake )
return false;
//see if the key down is a <return> or not
if ( event.keyCode == KEY_RETURN && event.modifier == 0 )
{
onAction();
return true;
}
S32 selected = mSelIndex;
switch( event.keyCode )
{
case KEY_RIGHT:
case KEY_DOWN:
if( ( selected + 1 ) < mEntries.size() )
setSelected( mEntries[selected + 1].id );
break;
case KEY_UP:
case KEY_LEFT:
if( ( selected - 1 ) > 0 )
setSelected( mEntries[selected - 1].id );
break;
}
//otherwise, pass the event to its parent
return Parent::onKeyDown( event );
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::onAction()
{
GuiControl *canCtrl = getParent();
addChildren();
GuiCanvas *root = getRoot();
Point2I windowExt = root->mBounds.extent;
mBackground->mBounds.point.set(0,0);
mBackground->mBounds.extent = root->mBounds.extent;
S32 textWidth = 0, width = mBounds.extent.x;
const S32 menuSpace = 5;
const S32 textSpace = 2;
bool setScroll = false;
for(U32 i=0; i<mEntries.size(); ++i)
if(S32(mFont->getStrWidth((const UTF8 *)mEntries[i].buf)) > textWidth)
textWidth = mFont->getStrWidth((const UTF8 *)mEntries[i].buf);
if(textWidth > mBounds.extent.x)
{
textWidth +=10;
width = textWidth;
}
mTl->setCellSize(Point2I(width, mFont->getHeight()+3));
for(U32 j=0; j<mEntries.size(); ++j)
mTl->addEntry(mEntries[j].id, mEntries[j].buf);
Point2I pointInGC = canCtrl->localToGlobalCoord(mBounds.point);
Point2I scrollPoint(pointInGC.x, pointInGC.y + mBounds.extent.y);
//Calc max Y distance, so Scroll Ctrl will fit on window
S32 maxYdis = windowExt.y - pointInGC.y - mBounds.extent.y - menuSpace;
//If scroll bars need to be added
if(maxYdis < mTl->mBounds.extent.y + textSpace)
{
//Should we pop menu list above the button
if(maxYdis < pointInGC.y - menuSpace)
{
reverseTextList();
maxYdis = pointInGC.y - menuSpace;
//Does the menu need a scroll bar
if(maxYdis < mTl->mBounds.extent.y + textSpace)
{
//Calc for the width of the scroll bar
if(textWidth >= width)
width += 20;
mTl->setCellSize(Point2I(width,mFont->getHeight() + textSpace));
//Pop menu list above the button
scrollPoint.set(pointInGC.x, menuSpace - 1);
setScroll = true;
}
//No scroll bar needed
else
{
maxYdis = mTl->mBounds.extent.y + textSpace;
scrollPoint.set(pointInGC.x, pointInGC.y - maxYdis -1);
}
}
//Scroll bar needed but Don't pop above button
else
{
mRevNum = 0;
//Calc for the width of the scroll bar
if(textWidth >= width)
width += 20;
mTl->setCellSize(Point2I(width,mFont->getHeight() + textSpace));
setScroll = true;
}
}
//No scroll bar needed
else
maxYdis = mTl->mBounds.extent.y + textSpace;
//offset it from the background so it lines up properly
mSc->mBounds.point = mBackground->globalToLocalCoord(scrollPoint);
if(mSc->mBounds.point.x + width > mBackground->mBounds.extent.x)
if(width - mBounds.extent.x > 0)
mSc->mBounds.point.x -= width - mBounds.extent.x;
mSc->mBounds.extent.set(width-1, maxYdis);
mSc->registerObject();
mTl->registerObject();
mBackground->registerObject();
mSc->addObject( mTl );
mBackground->addObject( mSc );
// JDD - push the popup dialog to the topmost layer, so it's never under anything
root->pushDialogControl(mBackground,99);
if ( setScroll )
{
if ( mSelIndex )
mTl->scrollCellVisible( Point2I(0, mSelIndex));
else
mTl->scrollCellVisible( Point2I( 0, 0 ) );
}
mTl->setFirstResponder();
mInAction = true;
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::addChildren()
{
mTl = new GuiPopUpTextListCtrl(this);
AssertFatal(mTl, "Failed to create the GuiPopUpTextListCtrl for the PopUpMenu");
mTl->mProfile = mProfile;
mTl->setField("noDuplicates", "false");
mSc = new GuiScrollCtrl;
AssertFatal(mSc, "Failed to create the GuiScrollCtrl for the PopUpMenu");
mSc->mProfile = mProfile;
mSc->setField("hScrollBar","AlwaysOff");
mSc->setField("vScrollBar","dynamic");
mBackground = new GuiPopUpBackgroundCtrl(this, mTl);
AssertFatal(mBackground, "Failed to create the GuiBackgroundCtrl for the PopUpMenu");
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::repositionPopup()
{
if ( !mInAction || !mSc || !mTl )
return;
// I'm not concerned with this right now...
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::reverseTextList()
{
mTl->clear();
for(S32 i=mEntries.size()-1; i >= 0; --i)
mTl->addEntry(mEntries[i].id, mEntries[i].buf);
// Don't lose the selected cell:
if ( mSelIndex >= 0 )
mTl->setSelectedCell( Point2I( 0, mEntries.size() - mSelIndex - 1 ) );
mRevNum = mEntries.size() - 1;
}
//------------------------------------------------------------------------------
bool GuiPopUpMenuCtrl::getFontColor( ColorI &fontColor, S32 id, bool selected, bool mouseOver )
{
U32 i;
Entry* entry = NULL;
for ( i = 0; i < mEntries.size(); i++ )
{
if ( mEntries[i].id == id )
{
entry = &mEntries[i];
break;
}
}
if ( !entry )
return( false );
if ( entry->scheme != 0 )
{
// Find the entry's color scheme:
for ( i = 0; i < mSchemes.size(); i++ )
{
if ( mSchemes[i].id == entry->scheme )
{
fontColor = selected ? mSchemes[i].fontColorSEL : mouseOver ? mSchemes[i].fontColorHL : mSchemes[i].fontColor;
return( true );
}
}
}
// Default color scheme...
fontColor = selected ? mProfile->mFontColorSEL : mouseOver ? mProfile->mFontColorHL : mProfile->mFontColor;
return( true );
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::onMouseDown(const GuiEvent &event)
{
event;
onAction();
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::onMouseUp(const GuiEvent &event)
{
event;
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::setupAutoScroll(const GuiEvent &event)
{
GuiControl *parent = getParent();
if (! parent) return;
Point2I mousePt = mSc->globalToLocalCoord(event.mousePoint);
mEventSave = event;
if(mLastYvalue != mousePt.y)
{
mScrollDir = GuiScrollCtrl::None;
if(mousePt.y > mSc->mBounds.extent.y || mousePt.y < 0)
{
S32 topOrBottom = (mousePt.y > mSc->mBounds.extent.y) ? 1 : 0;
mSc->scrollTo(0, topOrBottom);
return;
}
F32 percent = (F32)mousePt.y / (F32)mSc->mBounds.extent.y;
if(percent > 0.7f && mousePt.y > mLastYvalue)
{
mIncValue = percent - 0.5f;
mScrollDir = GuiScrollCtrl::DownArrow;
}
else if(percent < 0.3f && mousePt.y < mLastYvalue)
{
mIncValue = 0.5f - percent;
mScrollDir = GuiScrollCtrl::UpArrow;
}
mLastYvalue = mousePt.y;
}
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::autoScroll()
{
mScrollCount += mIncValue;
while(mScrollCount > 1)
{
mSc->autoScroll(mScrollDir);
mScrollCount -= 1;
}
mTl->onMouseMove(mEventSave);
}
//------------------------------------------------------------------------------
void GuiPopUpMenuCtrl::replaceText(S32 boolVal)
{
mReplaceText = boolVal;
}
// EOF //

View File

@ -0,0 +1,131 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIPOPUPCTRL_H_
#define _GUIPOPUPCTRL_H_
#ifndef _GUITEXTCTRL_H_
#include "gui/controls/guiTextCtrl.h"
#endif
#ifndef _GUITEXTLISTCTRL_H_
#include "gui/controls/guiTextListCtrl.h"
#endif
#ifndef _GUIBUTTONCTRL_H_
#include "gui/controls/guiButtonCtrl.h"
#endif
#ifndef _GUIBACKGROUNDCTRL_H_
#include "gui/controls/guiBackgroundCtrl.h"
#endif
#ifndef _GUISCROLLCTRL_H_
#include "gui/containers/guiScrollCtrl.h"
#endif
class GuiPopUpMenuCtrl;
class GuiPopUpTextListCtrl;
class GuiPopUpBackgroundCtrl : public GuiControl
{
protected:
GuiPopUpMenuCtrl *mPopUpCtrl;
GuiPopUpTextListCtrl *mTextList;
public:
GuiPopUpBackgroundCtrl(GuiPopUpMenuCtrl *ctrl, GuiPopUpTextListCtrl* textList);
void onMouseDown(const GuiEvent &event);
};
class GuiPopUpTextListCtrl : public GuiTextListCtrl
{
private:
typedef GuiTextListCtrl Parent;
protected:
GuiPopUpMenuCtrl *mPopUpCtrl;
public:
GuiPopUpTextListCtrl(); // for inheritance
GuiPopUpTextListCtrl(GuiPopUpMenuCtrl *ctrl);
// GuiArrayCtrl overload:
void onCellSelected(Point2I cell);
// GuiControl overloads:
bool onKeyDown(const GuiEvent &event);
void onMouseDown(const GuiEvent &event);
void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
};
class GuiPopUpMenuCtrl : public GuiTextCtrl
{
typedef GuiTextCtrl Parent;
public:
struct Entry
{
char buf[256];
S32 id;
U16 ascii;
U16 scheme;
};
struct Scheme
{
U32 id;
ColorI fontColor;
ColorI fontColorHL;
ColorI fontColorSEL;
};
protected:
GuiPopUpTextListCtrl *mTl;
GuiScrollCtrl *mSc;
GuiPopUpBackgroundCtrl *mBackground;
Vector<Entry> mEntries;
Vector<Scheme> mSchemes;
S32 mSelIndex;
S32 mMaxPopupHeight;
F32 mIncValue;
F32 mScrollCount;
S32 mLastYvalue;
GuiEvent mEventSave;
S32 mRevNum;
bool mInAction;
bool mReplaceText;
virtual void addChildren();
virtual void repositionPopup();
public:
GuiPopUpMenuCtrl(void);
~GuiPopUpMenuCtrl();
GuiScrollCtrl::Region mScrollDir;
bool onAdd();
void onSleep();
void sort();
void addEntry(const char *buf, S32 id, U32 scheme = 0);
void addScheme(U32 id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL);
void onRender(Point2I offset, const RectI &updateRect);
void onAction();
virtual void closePopUp();
void clear();
void onMouseDown(const GuiEvent &event);
void onMouseUp(const GuiEvent &event);
void setupAutoScroll(const GuiEvent &event);
void autoScroll();
bool onKeyDown(const GuiEvent &event);
void reverseTextList();
bool getFontColor(ColorI &fontColor, S32 id, bool selected, bool mouseOver);
S32 getSelected();
void setSelected(S32 id);
const char *getScriptValue();
const char *getTextById(S32 id);
S32 findText( const char* text );
S32 getNumEntries() { return( mEntries.size() ); }
void replaceText(S32);
DECLARE_CONOBJECT(GuiPopUpMenuCtrl);
static void initPersistFields(void);
};
#endif //_GUI_POPUPMENU_CTRL_H

View File

@ -0,0 +1,18 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiRadioCtrl.h"
#include "console/consoleTypes.h"
//---------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiRadioCtrl);
GuiRadioCtrl::GuiRadioCtrl()
{
mButtonType = ButtonTypeRadio;
}

View File

@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIRADIOCTRL_H_
#define _GUIRADIOCTRL_H_
#ifndef _GUICHECKBOXCTRLL_H_
#include "gui/controls/guiCheckBoxCtrl.h"
#endif
// the radio button renders exactly the same as the check box
// the only difference is it sends messages to its siblings to
// turn themselves off.
class GuiRadioCtrl : public GuiCheckBoxCtrl
{
typedef GuiCheckBoxCtrl Parent;
public:
DECLARE_CONOBJECT(GuiRadioCtrl);
GuiRadioCtrl();
};
#endif //_GUI_RADIO_CTRL_H

View File

@ -0,0 +1,250 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/consoleTypes.h"
#include "dgl/dgl.h"
#include "dgl/gTexManager.h"
#include "gui/controls/guiSliderCtrl.h"
#include "gui/core/guiDefaultControlRender.h"
#include "platform/event.h"
IMPLEMENT_CONOBJECT(GuiSliderCtrl);
//----------------------------------------------------------------------------
GuiSliderCtrl::GuiSliderCtrl(void)
{
mActive = true;
mRange.set( 0.0f, 1.0f );
mTicks = 10;
mValue = 0.5f;
mThumbSize.set(8,20);
mShiftPoint = 5;
mShiftExtent = 10;
mDisplayValue = false;
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::initPersistFields()
{
Parent::initPersistFields();
addGroup( "Slider" );
addField("range", TypePoint2F, Offset(mRange, GuiSliderCtrl));
addField("ticks", TypeS32, Offset(mTicks, GuiSliderCtrl));
addField("value", TypeF32, Offset(mValue, GuiSliderCtrl));
endGroup( "Slider" );
}
//----------------------------------------------------------------------------
ConsoleMethod( GuiSliderCtrl, getValue, F32, 2, 2, "Get the position of the slider.")
{
return object->getValue();
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::setScriptValue(const char *val)
{
mValue = dAtof(val);
updateThumb(mValue);
}
//----------------------------------------------------------------------------
bool GuiSliderCtrl::onWake()
{
if (! Parent::onWake())
return false;
if(mThumbSize.y + mProfile->mFont->getHeight()-4 <= mBounds.extent.y)
mDisplayValue = true;
else
mDisplayValue = false;
updateThumb( mValue, true );
return true;
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onMouseDown(const GuiEvent &event)
{
if ( !mActive || !mAwake || !mVisible )
return;
mouseLock();
setFirstResponder();
Point2I curMousePos = globalToLocalCoord(event.mousePoint);
F32 value;
if (mBounds.extent.x >= mBounds.extent.y)
value = F32(curMousePos.x-mShiftPoint) / F32(mBounds.extent.x-mShiftExtent)*(mRange.y-mRange.x) + mRange.x;
else
value = F32(curMousePos.y) / F32(mBounds.extent.y)*(mRange.y-mRange.x) + mRange.x;
updateThumb(value);
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onMouseDragged(const GuiEvent &event)
{
if ( !mActive || !mAwake || !mVisible )
return;
Point2I curMousePos = globalToLocalCoord(event.mousePoint);
F32 value;
if (mBounds.extent.x >= mBounds.extent.y)
value = F32(curMousePos.x-mShiftPoint) / F32(mBounds.extent.x-mShiftExtent)*(mRange.y-mRange.x) + mRange.x;
else
value = F32(curMousePos.y) / F32(mBounds.extent.y)*(mRange.y-mRange.x) + mRange.x;
if (value > mRange.y)
value = mRange.y;
else if (value < mRange.x)
value = mRange.x;
if ((event.modifier & SI_SHIFT) && mTicks > 2) {
// If the shift key is held, snap to the nearest tick, if any are being drawn
F32 tickStep = (mRange.y - mRange.x) / F32(mTicks + 1);
F32 tickSteps = (value - mRange.x) / tickStep;
S32 actualTick = S32(tickSteps + 0.5);
value = actualTick * tickStep + mRange.x;
AssertFatal(value <= mRange.y && value >= mRange.x, "Error, out of bounds value generated from shift-snap of slider");
}
updateThumb(value);
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onMouseUp(const GuiEvent &)
{
if ( !mActive || !mAwake || !mVisible )
return;
mouseUnlock();
if (mConsoleCommand[0])
{
char buf[16];
dSprintf(buf, sizeof(buf), "%d", getId());
Con::setVariable("$ThisControl", buf);
Con::evaluate(mConsoleCommand, false);
}
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::updateThumb( F32 value, bool onWake )
{
mValue = value;
// clamp the thumb to legal values
if (mValue < mRange.x) mValue = mRange.x;
if (mValue > mRange.y) mValue = mRange.y;
Point2I ext = mBounds.extent;
ext.x -= ( mShiftExtent + mThumbSize.x ) / 2;
// update the bounding thumb rect
if (mBounds.extent.x >= mBounds.extent.y)
{ // HORZ thumb
S32 mx = (S32)((F32(ext.x) * (mValue-mRange.x) / (mRange.y-mRange.x)));
S32 my = ext.y/2;
if(mDisplayValue)
my = mThumbSize.y/2;
mThumb.point.x = mx - (mThumbSize.x/2);
mThumb.point.y = my - (mThumbSize.y/2);
mThumb.extent = mThumbSize;
}
else
{ // VERT thumb
S32 mx = ext.x/2;
S32 my = (S32)((F32(ext.y) * (mValue-mRange.x) / (mRange.y-mRange.x)));
mThumb.point.x = mx - (mThumbSize.y/2);
mThumb.point.y = my - (mThumbSize.x/2);
mThumb.extent.x = mThumbSize.y;
mThumb.extent.y = mThumbSize.x;
}
setFloatVariable(mValue);
setUpdate();
// Use the alt console command if you want to continually update:
if ( !onWake && mAltConsoleCommand[0] )
Con::evaluate( mAltConsoleCommand, false );
}
//----------------------------------------------------------------------------
void GuiSliderCtrl::onRender(Point2I offset, const RectI &updateRect)
{
Point2I pos(offset.x+mShiftPoint, offset.y);
Point2I ext(mBounds.extent.x - mShiftExtent, mBounds.extent.y);
if (mBounds.extent.x >= mBounds.extent.y)
{
Point2I mid(ext.x, ext.y/2);
if(mDisplayValue)
mid.set(ext.x, mThumbSize.y/2);
glColor4f(0, 0, 0, 1);
glBegin(GL_LINES);
// horz rule
glVertex2i(pos.x, pos.y+mid.y);
glVertex2i(pos.x+mid.x, pos.y+mid.y);
// tick marks
for (U32 t = 0; t <= (mTicks+1); t++)
{
S32 x = (S32)(F32(mid.x-1)/F32(mTicks+1)*F32(t));
glVertex2i(pos.x+x, pos.y+mid.y-mShiftPoint);
glVertex2i(pos.x+x, pos.y+mid.y+mShiftPoint);
}
glEnd();
}
else
{
Point2I mid(ext.x/2, ext.y);
glColor4f(0, 0, 0, 1);
glBegin(GL_LINES);
// horz rule
glVertex2i(pos.x+mid.x, pos.y);
glVertex2i(pos.x+mid.x, pos.y+mid.y);
// tick marks
for (U32 t = 0; t <= (mTicks+1); t++)
{
S32 y = (S32)(F32(mid.y-1)/F32(mTicks+1)*F32(t));
glVertex2i(pos.x+mid.x-mShiftPoint, pos.y+y);
glVertex2i(pos.x+mid.x+mShiftPoint, pos.y+y);
}
glEnd();
mDisplayValue = false;
}
// draw the thumb
RectI thumb = mThumb;
thumb.point += pos;
renderRaisedBox(thumb, mProfile);
if(mDisplayValue)
{
char buf[20];
dSprintf(buf,sizeof(buf),"%0.3f",mValue);
Point2I textStart = thumb.point;
S32 txt_w = mProfile->mFont->getStrWidth((const UTF8 *)buf);
textStart.x += (S32)((thumb.extent.x/2.0f));
textStart.y += thumb.extent.y - 2; //19
textStart.x -= (txt_w/2);
if(textStart.x < offset.x)
textStart.x = offset.x;
else if(textStart.x + txt_w > offset.x+mBounds.extent.x)
textStart.x -=((textStart.x + txt_w) - (offset.x+mBounds.extent.x));
dglSetBitmapModulation(mProfile->mFontColor);
dglDrawText(mProfile->mFont, textStart, buf, mProfile->mFontColors);
}
renderChildControls(offset, updateRect);
}

View File

@ -0,0 +1,48 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUISLIDERCTRL_H_
#define _GUISLIDERCTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
class GuiSliderCtrl : public GuiControl
{
private:
typedef GuiControl Parent;
protected:
Point2F mRange;
U32 mTicks;
F32 mValue;
RectI mThumb;
Point2I mThumbSize;
void updateThumb( F32 value, bool onWake = false );
S32 mShiftPoint;
S32 mShiftExtent;
bool mDisplayValue;
public:
//creation methods
DECLARE_CONOBJECT(GuiSliderCtrl);
GuiSliderCtrl();
static void initPersistFields();
//Parental methods
bool onWake();
void onMouseDown(const GuiEvent &event);
void onMouseDragged(const GuiEvent &event);
void onMouseUp(const GuiEvent &);
F32 getValue() { return mValue; }
void setScriptValue(const char *val);
void onRender(Point2I offset, const RectI &updateRect);
};
#endif

View File

@ -0,0 +1,227 @@
//-----------------------------------------------------------------------------
// Justin DuJardin
// Gui Tab Page Control Class
//-----------------------------------------------------------------------------
#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiTabPageCtrl.h"
#include "gui/core/guiDefaultControlRender.h"
#include "gui/editor/guiEditCtrl.h"
IMPLEMENT_CONOBJECT(GuiTabPageCtrl);
GuiTabPageCtrl::GuiTabPageCtrl(void)
{
mBounds.extent.set(100, 200);
mMinSize.set(50, 50);
dStrcpy(mText,(UTF8*)"TabPage");
mActive = true;
}
void GuiTabPageCtrl::initPersistFields()
{
Parent::initPersistFields();
}
bool GuiTabPageCtrl::onWake()
{
if (! Parent::onWake())
return false;
return true;
}
void GuiTabPageCtrl::onSleep()
{
Parent::onSleep();
}
GuiControl* GuiTabPageCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
{
return Parent::findHitControl(pt, initialLayer);
}
void GuiTabPageCtrl::onMouseDown(const GuiEvent &event)
{
setUpdate();
Point2I localPoint = globalToLocalCoord( event.mousePoint );
GuiControl *ctrl = findHitControl(localPoint);
if (ctrl && ctrl != this)
{
ctrl->onMouseDown(event);
}
}
void GuiTabPageCtrl::onMouseDownEditor(const GuiEvent &event, Point2I offset )
{
// This shouldn't be called if it's not design time, but check just incase
if ( GuiControl::smDesignTime )
{
GuiEditCtrl* edit = GuiControl::smEditorHandle;
if( edit )
edit->select( this );
}
}
GuiControl *GuiTabPageCtrl::findNextTabable(GuiControl *curResponder, bool firstCall)
{
//set the global if this is the first call (directly from the canvas)
if (firstCall)
{
GuiControl::smCurResponder = NULL;
}
//if the window does not already contain the first responder, return false
//ie. Can't tab into or out of a window
if (! ControlIsChild(curResponder))
{
return NULL;
}
//loop through, checking each child to see if it is the one that follows the firstResponder
GuiControl *tabCtrl = NULL;
iterator i;
for (i = begin(); i != end(); i++)
{
GuiControl *ctrl = static_cast<GuiControl *>(*i);
tabCtrl = ctrl->findNextTabable(curResponder, false);
if (tabCtrl) break;
}
//to ensure the tab cycles within the current window...
if (! tabCtrl)
{
tabCtrl = findFirstTabable();
}
mFirstResponder = tabCtrl;
return tabCtrl;
}
GuiControl *GuiTabPageCtrl::findPrevTabable(GuiControl *curResponder, bool firstCall)
{
if (firstCall)
{
GuiControl::smPrevResponder = NULL;
}
//if the window does not already contain the first responder, return false
//ie. Can't tab into or out of a window
if (! ControlIsChild(curResponder))
{
return NULL;
}
//loop through, checking each child to see if it is the one that follows the firstResponder
GuiControl *tabCtrl = NULL;
iterator i;
for (i = begin(); i != end(); i++)
{
GuiControl *ctrl = static_cast<GuiControl *>(*i);
tabCtrl = ctrl->findPrevTabable(curResponder, false);
if (tabCtrl) break;
}
//to ensure the tab cycles within the current window...
if (! tabCtrl)
{
tabCtrl = findLastTabable();
}
mFirstResponder = tabCtrl;
return tabCtrl;
}
bool GuiTabPageCtrl::onKeyDown(const GuiEvent &event)
{
if ((event.keyCode == KEY_TAB) && (event.modifier & SI_CTRL))
{
//find the next sibling window, and select it
GuiControl *parent = getParent();
if (parent)
{
GuiTabPageCtrl *firstWindow = NULL;
iterator i;
for (i = parent->begin(); i != parent->end(); i++)
{
GuiTabPageCtrl *ctrl = dynamic_cast<GuiTabPageCtrl *>(*i);
if (ctrl && ctrl->getTabIndex() == mTabIndex + 1)
{
ctrl->selectWindow();
return true;
}
else if (ctrl && ctrl->getTabIndex() == 0)
{
firstWindow = ctrl;
}
}
//recycle from the beginning
if (firstWindow != this)
{
firstWindow->selectWindow();
return true;
}
}
}
return Parent::onKeyDown(event);
}
void GuiTabPageCtrl::selectWindow(void)
{
//first make sure this window is the front most of its siblings
GuiControl *parent = getParent();
if (parent)
{
parent->pushObjectToBack(this);
}
//also set the first responder to be the one within this window
setFirstResponder(mFirstResponder);
}
void GuiTabPageCtrl::onRender(Point2I offset,const RectI &updateRect)
{
RectI winRect;
winRect.point = offset;
winRect.extent = mBounds.extent;
dglSetClipRect( winRect );
if( mProfile->mTextureHandle && ( mProfile->mBitmapArrayRects.size() == 0 ) )
{
TextureObject* texture = (TextureObject *) mProfile->mTextureHandle;
RectI srcRegion;
RectI dstRegion;
float xdone = ((float)mBounds.extent.x/(float)texture->bitmapWidth)+1;
float ydone = ((float)mBounds.extent.y/(float)texture->bitmapHeight)+1;
int xshift = texture->bitmapWidth;
int yshift = texture->bitmapHeight;
for(int y = 0; y < ydone; ++y)
{
for(int x = 0; x < xdone; ++x)
{
srcRegion.set(0,0,texture->bitmapWidth,texture->bitmapHeight);
dstRegion.set( ((texture->bitmapWidth*x)+offset.x)-xshift,
((texture->bitmapHeight*y)+offset.y)-yshift,
texture->bitmapWidth,
texture->bitmapHeight);
dglDrawBitmapStretchSR(texture,dstRegion, srcRegion, false);
}
}
}
else
dglDrawRectFill(winRect, mProfile->mFillColor);
//render the children
renderChildControls( offset, updateRect );
}

View File

@ -0,0 +1,47 @@
//-----------------------------------------------------------------------------
// Justin DuJardin
// Gui Tab Page Control Class
//-----------------------------------------------------------------------------
#ifndef _GUITABPAGECTRL_H_
#define _GUITABPAGECTRL_H_
#ifndef _GUITEXTCTRL_H_
#include "gui/controls/guiTextCtrl.h"
#endif
class GuiTabPageCtrl : public GuiTextCtrl
{
private:
typedef GuiTextCtrl Parent;
Point2I mMinSize;
S32 mTabIndex;
public:
GuiTabPageCtrl();
DECLARE_CONOBJECT(GuiTabPageCtrl);
static void initPersistFields();
bool onWake(); ///< The page awakens (becomes active)!
void onSleep(); ///< The page sleeps (zzzzZZ - becomes inactive)
GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1); ///< Find which control is hit by the mouse starting at a specified layer
void onMouseDown(const GuiEvent &event); ///< Called when a mouseDown event occurs
void onMouseDownEditor(const GuiEvent &event, Point2I offset ); ///< Called when a mouseDown event occurs and the GUI editor is active
S32 getTabIndex(void) { return mTabIndex; } ///< Get the tab index of this control
//only cycle tabs through the current window, so overwrite the method
GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);
GuiControl* findPrevTabable(GuiControl *curResponder, bool firstCall = true);
bool onKeyDown(const GuiEvent &event); ///< Called when a keyDown event occurs
void selectWindow(void); ///< Select this window
void onRender(Point2I offset, const RectI &updateRect); ///< Called when it's time to render this page to the scene
};
#endif //_GUI_WINDOW_CTRL_H

View File

@ -0,0 +1,197 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/consoleTypes.h"
#include "console/console.h"
#include "core/color.h"
#include "gui/controls/guiTextCtrl.h"
#include "dgl/dgl.h"
#include "i18n/lang.h"
// -----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(GuiTextCtrl);
GuiTextCtrl::GuiTextCtrl()
{
//default fonts
mInitialText = StringTable->insert("");
mInitialTextID = StringTable->insert("");
mText[0] = '\0';
mMaxStrLen = GuiTextCtrl::MAX_STRING_LENGTH;
}
ConsoleMethod( GuiTextCtrl, setText, void, 3, 3, "obj.setText( newText )" )
{
argc;
object->setText( argv[2] );
}
ConsoleMethod( GuiTextCtrl, setTextID, void, 3, 3, "obj.setTextID( newText )" )
{
argc;
object->setTextID( argv[2] );
}
void GuiTextCtrl::initPersistFields()
{
Parent::initPersistFields();
addField( "text", TypeCaseString, Offset( mInitialText, GuiTextCtrl ) );
addField( "textID", TypeString, Offset( mInitialTextID, GuiTextCtrl ) );
addField( "maxLength", TypeS32, Offset( mMaxStrLen, GuiTextCtrl ) );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
bool GuiTextCtrl::onAdd()
{
if(!Parent::onAdd())
return false;
dStrncpy(mText, (UTF8*)mInitialText, MAX_STRING_LENGTH);
mText[MAX_STRING_LENGTH] = '\0';
return true;
}
void GuiTextCtrl::inspectPostApply()
{
Parent::inspectPostApply();
if(mInitialTextID && *mInitialTextID != 0)
setTextID(mInitialTextID);
else
setText(mInitialText);
}
bool GuiTextCtrl::onWake()
{
if ( !Parent::onWake() )
return false;
mFont = mProfile->mFont;
AssertFatal(mFont, "GuiTextCtrl::onWake: invalid font in profile" );
if(mInitialTextID && *mInitialTextID != 0)
setTextID(mInitialTextID);
if ( mConsoleVariable[0] )
{
const char *txt = Con::getVariable( mConsoleVariable );
if ( txt )
{
if ( dStrlen( txt ) > mMaxStrLen )
{
char* buf = new char[mMaxStrLen + 1];
dStrncpy( buf, txt, mMaxStrLen );
buf[mMaxStrLen] = 0;
setScriptValue( buf );
delete [] buf;
}
else
setScriptValue( txt );
}
}
//resize
if ( mProfile->mAutoSizeWidth )
{
if ( mProfile->mAutoSizeHeight )
resize( mBounds.point, Point2I( mFont->getStrWidth((const UTF8 *) mText ), mFont->getHeight() + 4 ) );
else
resize( mBounds.point, Point2I( mFont->getStrWidth((const UTF8 *) mText ), mBounds.extent.y ) );
}
else if ( mProfile->mAutoSizeHeight )
resize( mBounds.point, Point2I( mBounds.extent.x, mFont->getHeight() + 4 ) );
return true;
}
void GuiTextCtrl::onSleep()
{
Parent::onSleep();
mFont = NULL;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
void GuiTextCtrl::setText(const char *txt)
{
//make sure we don't call this before onAdd();
if( !mProfile )
return;
if (txt)
dStrncpy(mText, (UTF8*)txt, MAX_STRING_LENGTH);
mText[MAX_STRING_LENGTH] = '\0';
//Make sure we have a font
mProfile->incRefCount();
mFont = mProfile->mFont;
//resize
if (mProfile->mAutoSizeWidth)
{
if (mProfile->mAutoSizeHeight)
resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mText), mFont->getHeight() + 4));
else
resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mText), mBounds.extent.y));
}
else if (mProfile->mAutoSizeHeight)
{
resize(mBounds.point, Point2I(mBounds.extent.x, mFont->getHeight() + 4));
}
setVariable((char*)mText);
setUpdate();
//decrement the profile referrence
mProfile->decRefCount();
}
void GuiTextCtrl::setTextID(const char *id)
{
S32 n = Con::getIntVariable(id, -1);
if(n != -1)
{
mInitialTextID = StringTable->insert(id);
setTextID(n);
}
}
void GuiTextCtrl::setTextID(S32 id)
{
const UTF8 *str = getGUIString(id);
if(str)
setText((const char*)str);
//mInitialTextID = id;
}
//------------------------------------------------------------------------------
void GuiTextCtrl::onPreRender()
{
const char * var = getVariable();
if(var && var[0] && dStricmp((char*)mText, var))
setText(var);
}
//------------------------------------------------------------------------------
void GuiTextCtrl::onRender(Point2I offset, const RectI &updateRect)
{
dglSetBitmapModulation( mProfile->mFontColor );
renderJustifiedText(offset, mBounds.extent, (char*)mText);
//render the child controls
renderChildControls(offset, updateRect);
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
const char *GuiTextCtrl::getScriptValue()
{
return getText();
}
void GuiTextCtrl::setScriptValue(const char *val)
{
setText(val);
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
// EOF //

View File

@ -0,0 +1,64 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUITEXTCTRL_H_
#define _GUITEXTCTRL_H_
#ifndef _GFONT_H_
#include "dgl/gNewFont.h"
#endif
#ifndef _GUITYPES_H_
#include "gui/core/guiTypes.h"
#endif
#ifndef _GUICONTROL_H_
#include "gui/core/guiControl.h"
#endif
class GuiTextCtrl : public GuiControl
{
private:
typedef GuiControl Parent;
public:
enum Constants { MAX_STRING_LENGTH = 255 };
protected:
StringTableEntry mInitialText;
StringTableEntry mInitialTextID;
UTF8 mText[MAX_STRING_LENGTH + 1];
S32 mMaxStrLen; // max string len, must be less then or equal to 255
Resource<GFont> mFont;
public:
//creation methods
DECLARE_CONOBJECT(GuiTextCtrl);
GuiTextCtrl();
static void initPersistFields();
//Parental methods
bool onAdd();
virtual bool onWake();
virtual void onSleep();
//text methods
virtual void setText(const char *txt = NULL);
virtual void setTextID(S32 id);
virtual void setTextID(const char *id);
const char *getText() { return (const char*)mText; }
void inspectPostApply();
//rendering methods
void onPreRender();
void onRender(Point2I offset, const RectI &updateRect);
void displayText( S32 xOffset, S32 yOffset );
//Console methods
const char *getScriptValue();
void setScriptValue(const char *value);
};
#endif //_GUI_TEXT_CONTROL_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUITEXTEDITCTRL_H_
#define _GUITEXTEDITCTRL_H_
#ifndef _GUITYPES_H_
#include "gui/core/guiTypes.h"
#endif
#ifndef _GUITEXTCTRL_H_
#include "gui/controls/guiTextCtrl.h"
#endif
#ifndef _STRINGBUFFER_H_
#include "core/stringBuffer.h"
#endif
class GuiTextEditCtrl : public GuiTextCtrl
{
private:
typedef GuiTextCtrl Parent;
static U32 smNumAwake;
protected:
StringBuffer mTextBuffer;
StringTableEntry mValidateCommand;
StringTableEntry mEscapeCommand;
AudioProfile* mDeniedSound;
// for animating the cursor
S32 mNumFramesElapsed;
U32 mTimeLastCursorFlipped;
ColorI mCursorColor;
bool mCursorOn;
//Edit Cursor
GuiCursor* mEditCursor;
bool mInsertOn;
S32 mMouseDragStart;
Point2I mTextOffset;
bool mTextOffsetReset;
bool mDragHit;
bool mTabComplete;
S32 mScrollDir;
//undo members
StringBuffer mUndoText;
S32 mUndoBlockStart;
S32 mUndoBlockEnd;
S32 mUndoCursorPos;
void saveUndoState();
S32 mBlockStart;
S32 mBlockEnd;
S32 mCursorPos;
S32 setCursorPos(const Point2I &offset);
bool mHistoryDirty;
S32 mHistoryLast;
S32 mHistoryIndex;
S32 mHistorySize;
bool mPasswordText;
StringTableEntry mPasswordMask;
bool mSinkAllKeyEvents; // any non-ESC key is handled here or not at all
UTF8 **mHistoryBuf;
void updateHistory(StringBuffer *txt, bool moveIndex);
void playDeniedSound();
void execConsoleCallback();
public:
GuiTextEditCtrl();
~GuiTextEditCtrl();
DECLARE_CONOBJECT(GuiTextEditCtrl);
static void initPersistFields();
bool onAdd();
bool onWake();
void onSleep();
void getText(char *dest); // dest must be of size
// StructDes::MAX_STRING_LEN + 1
bool initCursors();
void getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent);
void setText(S32 tag);
virtual void setText(const char *txt);
S32 getCursorPos() { return( mCursorPos ); }
void reallySetCursorPos( const S32 newPos );
const char *getScriptValue();
void setScriptValue(const char *value);
bool onKeyDown(const GuiEvent &event);
void onMouseDown(const GuiEvent &event);
void onMouseDragged(const GuiEvent &event);
void onMouseUp(const GuiEvent &event);
virtual void setFirstResponder();
virtual void onLoseFirstResponder();
void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
bool hasText();
void onStaticModified(const char* slotName);
void onPreRender();
void onRender(Point2I offset, const RectI &updateRect);
virtual void drawText( const RectI &drawRect, bool isFocused );
};
#endif //_GUI_TEXTEDIT_CTRL_H

View File

@ -0,0 +1,271 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiTextEditSliderCtrl.h"
IMPLEMENT_CONOBJECT(GuiTextEditSliderCtrl);
GuiTextEditSliderCtrl::GuiTextEditSliderCtrl()
{
mRange.set(0.0f, 1.0f);
mIncAmount = 1.0f;
mValue = 0.0f;
mMulInc = 0;
mIncCounter = 0.0f;
mFormat = StringTable->insert("%3.2f");
mTextAreaHit = None;
}
GuiTextEditSliderCtrl::~GuiTextEditSliderCtrl()
{
}
void GuiTextEditSliderCtrl::initPersistFields()
{
Parent::initPersistFields();
addField("format", TypeString, Offset(mFormat, GuiTextEditSliderCtrl));
addField("range", TypePoint2F, Offset(mRange, GuiTextEditSliderCtrl));
addField("increment", TypeF32, Offset(mIncAmount, GuiTextEditSliderCtrl));
}
void GuiTextEditSliderCtrl::getText(char *dest)
{
Parent::getText(dest);
}
void GuiTextEditSliderCtrl::setText(const char *txt)
{
mValue = dAtof(txt);
checkRange();
setValue();
}
bool GuiTextEditSliderCtrl::onKeyDown(const GuiEvent &event)
{
return Parent::onKeyDown(event);
}
void GuiTextEditSliderCtrl::checkRange()
{
if(mValue < mRange.x)
mValue = mRange.x;
else if(mValue > mRange.y)
mValue = mRange.y;
}
void GuiTextEditSliderCtrl::setValue()
{
char buf[20];
dSprintf(buf,sizeof(buf),mFormat, mValue);
Parent::setText(buf);
}
void GuiTextEditSliderCtrl::onMouseDown(const GuiEvent &event)
{
char txt[20];
Parent::getText(txt);
mValue = dAtof(txt);
mMouseDownTime = Sim::getCurrentTime();
GuiControl *parent = getParent();
if(!parent)
return;
Point2I camPos = event.mousePoint;
Point2I point = parent->localToGlobalCoord(mBounds.point);
if(camPos.x > point.x + mBounds.extent.x - 14)
{
if(camPos.y > point.y + (mBounds.extent.y/2))
{
mValue -=mIncAmount;
mTextAreaHit = ArrowDown;
mMulInc = -0.15f;
}
else
{
mValue +=mIncAmount;
mTextAreaHit = ArrowUp;
mMulInc = 0.15f;
}
checkRange();
setValue();
mouseLock();
return;
}
Parent::onMouseDown(event);
}
void GuiTextEditSliderCtrl::onMouseDragged(const GuiEvent &event)
{
if(mTextAreaHit == None || mTextAreaHit == Slider)
{
mTextAreaHit = Slider;
GuiControl *parent = getParent();
if(!parent)
return;
Point2I camPos = event.mousePoint;
Point2I point = parent->localToGlobalCoord(mBounds.point);
F32 maxDis = 100;
F32 val;
if(camPos.y < point.y)
{
if(point.y < maxDis)
maxDis = point.y;
val = point.y - maxDis;
if(point.y > 0)
mMulInc= 1.0f-(((float)camPos.y - val) / maxDis);
else
mMulInc = 1.0f;
checkIncValue();
return;
}
else if(camPos.y > point.y + mBounds.extent.y)
{
GuiCanvas *root = getRoot();
val = root->mBounds.extent.y - (point.y + mBounds.extent.y);
if(val < maxDis)
maxDis = val;
if( val > 0)
mMulInc= -(float)(camPos.y - (point.y + mBounds.extent.y))/maxDis;
else
mMulInc = -1.0f;
checkIncValue();
return;
}
mTextAreaHit = None;
Parent::onMouseDragged(event);
}
}
void GuiTextEditSliderCtrl::onMouseUp(const GuiEvent &event)
{
mMulInc = 0.0f;
mouseUnlock();
//if we released the mouse within this control, then the parent will call
//the mConsoleCommand other wise we have to call it.
Parent::onMouseUp(event);
//if we didn't release the mouse within this control, then perform the action
if (!cursorInControl())
Con::evaluate(mConsoleCommand, false);
mTextAreaHit = None;
}
void GuiTextEditSliderCtrl::checkIncValue()
{
if(mMulInc > 1.0f)
mMulInc = 1.0f;
else if(mMulInc < -1.0f)
mMulInc = -1.0f;
}
void GuiTextEditSliderCtrl::timeInc(U32 elapseTime)
{
S32 numTimes = elapseTime / 750;
if(mTextAreaHit != Slider && numTimes > 0)
{
if(mTextAreaHit == ArrowUp)
mMulInc = 0.15f * numTimes;
else
mMulInc = -0.15f * numTimes;
checkIncValue();
}
}
void GuiTextEditSliderCtrl::onRender(Point2I offset, const RectI &updateRect)
{
if(mTextAreaHit != None)
{
U32 elapseTime = Sim::getCurrentTime() - mMouseDownTime;
if(elapseTime > 750 || mTextAreaHit == Slider)
{
timeInc(elapseTime);
mIncCounter += mMulInc;
if(mIncCounter >= 1.0f || mIncCounter <= -1.0f)
{
mValue = (mMulInc > 0.0f) ? mValue+mIncAmount : mValue-mIncAmount;
mIncCounter = (mIncCounter > 0.0f) ? mIncCounter-1 : mIncCounter+1;
checkRange();
setValue();
}
}
}
Parent::onRender(offset, updateRect);
Point2I start(offset.x + mBounds.extent.x - 14, offset.y);
Point2I midPoint(start.x + 7, start.y + (mBounds.extent.y/2));
dglDrawRectFill(Point2I(start.x+1,start.y+1), Point2I(start.x+13,start.y+mBounds.extent.y-1) , mProfile->mFillColor);
dglDrawLine(start, Point2I(start.x, start.y+mBounds.extent.y),mProfile->mFontColor);
dglDrawLine(Point2I(start.x,midPoint.y),
Point2I(start.x+14,midPoint.y),
mProfile->mFontColor);
glColor3i(0,0,0);
glBegin(GL_TRIANGLES);
if(mTextAreaHit == ArrowUp)
{
glVertex2i(midPoint.x, start.y+1);
glVertex2i(start.x+11,midPoint.y-2);
glVertex2i(start.x+3,midPoint.y-2);
}
else
{
glVertex2i(midPoint.x, start.y+2);
glVertex2i(start.x+11,midPoint.y-1);
glVertex2i(start.x+3,midPoint.y-1);
}
if(mTextAreaHit == ArrowDown)
{
glVertex2i(midPoint.x, start.y+mBounds.extent.y-1);
glVertex2i(start.x+11,midPoint.y+3);
glVertex2i(start.x+3,midPoint.y+3);
}
else
{
glVertex2i(midPoint.x, start.y+mBounds.extent.y-2);
glVertex2i(start.x+11,midPoint.y+2);
glVertex2i(start.x+3,midPoint.y+2);
}
glEnd();
}
void GuiTextEditSliderCtrl::onPreRender()
{
if (isFirstResponder())
{
U32 timeElapsed = Platform::getVirtualMilliseconds() - mTimeLastCursorFlipped;
mNumFramesElapsed++;
if ((timeElapsed > 500) && (mNumFramesElapsed > 3))
{
mCursorOn = !mCursorOn;
mTimeLastCursorFlipped = Sim::getCurrentTime();
mNumFramesElapsed = 0;
setUpdate();
}
//update the cursor if the text is scrolling
if (mDragHit)
{
if ((mScrollDir < 0) && (mCursorPos > 0))
{
mCursorPos--;
}
else if ((mScrollDir > 0) && (mCursorPos < (S32)dStrlen(mText)))
{
mCursorPos++;
}
}
}
}

View File

@ -0,0 +1,67 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUITEXTEDITSLIDERCTRL_H_
#define _GUITEXTEDITSLIDERCTRL_H_
#ifndef _GUITYPES_H_
#include "gui/core/guiTypes.h"
#endif
#ifndef _GUITEXTEDITCTRL_H_
#include "gui/controls/guiTextEditCtrl.h"
#endif
class GuiTextEditSliderCtrl : public GuiTextEditCtrl
{
private:
typedef GuiTextEditCtrl Parent;
Point2F mRange;
F32 mIncAmount;
F32 mValue;
F32 mIncCounter;
F32 mMulInc;
StringTableEntry mFormat;
U32 mMouseDownTime;
// max string len, must be less then or equal to 255
public:
enum CtrlArea
{
None,
Slider,
ArrowUp,
ArrowDown
};
private:
CtrlArea mTextAreaHit;
public:
GuiTextEditSliderCtrl();
~GuiTextEditSliderCtrl();
DECLARE_CONOBJECT(GuiTextEditSliderCtrl);
static void initPersistFields();
void getText(char *dest); // dest must be of size
// StructDes::MAX_STRING_LEN + 1
void setText(S32 tag);
void setText(const char *txt);
void setValue();
void checkRange();
void checkIncValue();
void timeInc(U32 elapseTime);
bool onKeyDown(const GuiEvent &event);
void onMouseDown(const GuiEvent &event);
void onMouseDragged(const GuiEvent &event);
void onMouseUp(const GuiEvent &event);
void onPreRender();
void onRender(Point2I offset, const RectI &updateRect);
};
#endif //_GUI_TEXTEDIT_CTRL_H

View File

@ -0,0 +1,580 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/controls/guiTextListCtrl.h"
#include "gui/containers/guiScrollCtrl.h"
IMPLEMENT_CONOBJECT(GuiTextListCtrl);
static int sortColumn;
static bool sIncreasing;
static const char *getColumn(const char *text)
{
int ct = sortColumn;
while(ct--)
{
text = dStrchr(text, '\t');
if(!text)
return "";
text++;
}
return text;
}
static S32 QSORT_CALLBACK textCompare( const void* a, const void* b )
{
GuiTextListCtrl::Entry *ea = (GuiTextListCtrl::Entry *) (a);
GuiTextListCtrl::Entry *eb = (GuiTextListCtrl::Entry *) (b);
S32 result = dStricmp( getColumn( ea->text ), getColumn( eb->text ) );
return ( sIncreasing ? result : -result );
}
static S32 QSORT_CALLBACK numCompare(const void *a,const void *b)
{
GuiTextListCtrl::Entry *ea = (GuiTextListCtrl::Entry *) (a);
GuiTextListCtrl::Entry *eb = (GuiTextListCtrl::Entry *) (b);
const char* aCol = getColumn( ea->text );
const char* bCol = getColumn( eb->text );
F32 result = dAtof(aCol) - dAtof(bCol);
S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0);
return ( sIncreasing ? res : -res );
}
GuiTextListCtrl::GuiTextListCtrl()
{
VECTOR_SET_ASSOCIATION(mList);
VECTOR_SET_ASSOCIATION(mColumnOffsets);
mActive = true;
mEnumerate = false;
mResizeCell = true;
mSize.set(1, 0);
mColumnOffsets.push_back(0);
mFitParentWidth = true;
mClipColumnText = false;
}
void GuiTextListCtrl::initPersistFields()
{
Parent::initPersistFields();
addField("enumerate", TypeBool, Offset(mEnumerate, GuiTextListCtrl));
addField("resizeCell", TypeBool, Offset(mResizeCell, GuiTextListCtrl));
addField("columns", TypeS32Vector, Offset(mColumnOffsets, GuiTextListCtrl));
addField("fitParentWidth", TypeBool, Offset(mFitParentWidth, GuiTextListCtrl));
addField("clipColumnText", TypeBool, Offset(mClipColumnText, GuiTextListCtrl));
}
ConsoleMethod(GuiTextListCtrl, getSelectedId, S32, 2, 2, "Get the ID of the currently selected item.")
{
return object->getSelectedId();
}
ConsoleMethod( GuiTextListCtrl, setSelectedById, void, 3, 3, "(int id)"
"Finds the specified entry by id, then marks its row as selected.")
{
S32 index = object->findEntryById(dAtoi(argv[2]));
if(index < 0)
return ;
object->setSelectedCell(Point2I(0, index));
}
ConsoleMethod( GuiTextListCtrl, setSelectedRow, void, 3, 3, "(int rowNum)"
"Selects the specified row.")
{
object->setSelectedCell( Point2I( 0, dAtoi( argv[2] ) ) );
}
ConsoleMethod( GuiTextListCtrl, clearSelection, void, 2, 2, "Set the selection to nothing.")
{
object->setSelectedCell(Point2I(-1, -1));
}
ConsoleMethod(GuiTextListCtrl, addRow, S32, 4, 5, "(int id, string text, int index=0)"
"Returns row number of the new item.")
{
S32 ret = object->mList.size();
if(argc < 5)
object->addEntry(dAtoi(argv[2]), argv[3]);
else
object->insertEntry(dAtoi(argv[2]), argv[3], dAtoi(argv[4]));
return ret;
}
ConsoleMethod( GuiTextListCtrl, setRowById, void, 4, 4, "(int id, string text)")
{
object->setEntry(dAtoi(argv[2]), argv[3]);
}
ConsoleMethod( GuiTextListCtrl, sort, void, 3, 4, "(int columnID, bool increasing=false)"
"Performs a standard (alphabetical) sort on the values in the specified column.")
{
if ( argc == 3 )
object->sort(dAtoi(argv[2]));
else
object->sort( dAtoi( argv[2] ), dAtob( argv[3] ) );
}
ConsoleMethod(GuiTextListCtrl, sortNumerical, void, 3, 4, "(int columnID, bool increasing=false)"
"Perform a numerical sort on the values in the specified column.")
{
if ( argc == 3 )
object->sortNumerical( dAtoi( argv[2] ) );
else
object->sortNumerical( dAtoi( argv[2] ), dAtob( argv[3] ) );
}
ConsoleMethod( GuiTextListCtrl, clear, void, 2, 2, "Clear the list.")
{
object->clear();
}
ConsoleMethod( GuiTextListCtrl, rowCount, S32, 2, 2, "Get the number of rows.")
{
return object->getNumEntries();
}
ConsoleMethod( GuiTextListCtrl, getRowId, S32, 3, 3, "(int index)"
"Get the row ID for an index.")
{
U32 index = dAtoi(argv[2]);
if(index >= object->getNumEntries())
return -1;
return object->mList[index].id;
}
ConsoleMethod( GuiTextListCtrl, getRowTextById, const char*, 3, 3, "(int id)"
"Get the text of a row with the specified id.")
{
S32 index = object->findEntryById(dAtoi(argv[2]));
if(index < 0)
return "";
return object->mList[index].text;
}
ConsoleMethod( GuiTextListCtrl, getRowNumById, S32, 3, 3, "(int id)"
"Get the row number for a specified id.")
{
S32 index = object->findEntryById(dAtoi(argv[2]));
if(index < 0)
return -1;
return index;
}
ConsoleMethod( GuiTextListCtrl, getRowText, const char*, 3, 3, "(int index)"
"Get the text of the row with the specified index.")
{
U32 index = dAtoi(argv[2]);
if(index < 0 || index >= object->mList.size())
return "";
return object->mList[index].text;
}
ConsoleMethod( GuiTextListCtrl, removeRowById, void, 3, 3,"(int id)"
"Remove row with the specified id.")
{
object->removeEntry(dAtoi(argv[2]));
}
ConsoleMethod( GuiTextListCtrl, removeRow, void, 3, 3, "(int index)"
"Remove a row from the table, based on its index.")
{
U32 index = dAtoi(argv[2]);
object->removeEntryByIndex(index);
}
ConsoleMethod( GuiTextListCtrl, scrollVisible, void, 3, 3, "(int rowNum)"
"Scroll so the specified row is visible.")
{
object->scrollCellVisible(Point2I(0, dAtoi(argv[2])));
}
ConsoleMethod( GuiTextListCtrl, findTextIndex, S32, 3, 3, "(string needle)"
"Find needle in the list, and return the row number it was found in.")
{
return( object->findEntryByText( argv[2] ) );
}
ConsoleMethod( GuiTextListCtrl, setRowActive, void, 4, 4, "(int rowNum, bool active)"
"Mark a specified row as active/not.")
{
object->setEntryActive( U32( dAtoi( argv[2] ) ), dAtob( argv[3] ) );
}
ConsoleMethod( GuiTextListCtrl, isRowActive, bool, 3, 3, "(int rowNum)"
"Is the specified row currently active?")
{
return( object->isEntryActive( U32( dAtoi( argv[2] ) ) ) );
}
bool GuiTextListCtrl::onWake()
{
if(!Parent::onWake())
return false;
setSize(mSize);
return true;
}
U32 GuiTextListCtrl::getSelectedId()
{
if (mSelectedCell.y == -1)
return InvalidId;
return mList[mSelectedCell.y].id;
}
void GuiTextListCtrl::onCellSelected(Point2I cell)
{
Con::executef(this, 3, "onSelect", Con::getIntArg(mList[cell.y].id), mList[cell.y].text);
if (mConsoleCommand[0])
Con::evaluate(mConsoleCommand, false);
}
void GuiTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
{
if ( mList[cell.y].active )
{
if (selected || (mProfile->mMouseOverSelected && mouseOver))
{
dglDrawRectFill(RectI(offset.x, offset.y, mCellSize.x, mCellSize.y), mProfile->mFillColorHL);
dglSetBitmapModulation(mProfile->mFontColorHL);
}
else
dglSetBitmapModulation(mouseOver ? mProfile->mFontColorHL : mProfile->mFontColor);
}
else
dglSetBitmapModulation( mProfile->mFontColorNA );
const char *text = mList[cell.y].text;
for(U32 index = 0; index < mColumnOffsets.size(); index++)
{
const char *nextCol = dStrchr(text, '\t');
if(mColumnOffsets[index] >= 0)
{
dsize_t slen;
if(nextCol)
slen = nextCol - text;
else
slen = dStrlen(text);
Point2I pos(offset.x + 4 + mColumnOffsets[index], offset.y);
RectI saveClipRect;
bool clipped = false;
if(mClipColumnText && (index != (mColumnOffsets.size() - 1)))
{
saveClipRect = dglGetClipRect();
RectI clipRect(pos, Point2I(mColumnOffsets[index+1] - mColumnOffsets[index] - 4, mCellSize.y));
if(clipRect.intersect(saveClipRect))
{
clipped = true;
dglSetClipRect(clipRect);
}
}
dglDrawTextN(mFont, pos, text, slen, mProfile->mFontColors);
if(clipped)
dglSetClipRect(saveClipRect);
}
if(!nextCol)
break;
text = nextCol+1;
}
}
U32 GuiTextListCtrl::getRowWidth(Entry *row)
{
U32 width = 1;
const char *text = row->text;
for(U32 index = 0; index < mColumnOffsets.size(); index++)
{
const char *nextCol = dStrchr(text, '\t');
U32 textWidth;
if(nextCol)
textWidth = mFont->getStrNWidth((const UTF8*)text, nextCol - text);
else
textWidth = mFont->getStrWidth((const UTF8*)text);
if(mColumnOffsets[index] >= 0)
width = getMax(width, mColumnOffsets[index] + textWidth);
if(!nextCol)
break;
text = nextCol+1;
}
return width;
}
void GuiTextListCtrl::insertEntry(U32 id, const char *text, S32 index)
{
Entry e;
e.text = dStrdup(text);
e.id = id;
e.active = true;
if(!mList.size())
mList.push_back(e);
else
{
if(index > mList.size())
index = mList.size();
mList.insert(&mList[index],e);
}
setSize(Point2I(1, mList.size()));
}
void GuiTextListCtrl::addEntry(U32 id, const char *text)
{
Entry e;
e.text = dStrdup(text);
e.id = id;
e.active = true;
mList.push_back(e);
setSize(Point2I(1, mList.size()));
}
void GuiTextListCtrl::setEntry(U32 id, const char *text)
{
S32 e = findEntryById(id);
if(e == -1)
addEntry(id, text);
else
{
dFree(mList[e].text);
mList[e].text = dStrdup(text);
// Still have to call this to make sure cells are wide enough for new values:
setSize( Point2I( 1, mList.size() ) );
}
setUpdate();
}
void GuiTextListCtrl::setEntryActive(U32 id, bool active)
{
S32 index = findEntryById( id );
if ( index == -1 )
return;
if ( mList[index].active != active )
{
mList[index].active = active;
// You can't have an inactive entry selected...
if ( !active && mSelectedCell.y >= 0 && mSelectedCell.y < mList.size()
&& mList[mSelectedCell.y].id == id )
setSelectedCell( Point2I( -1, -1 ) );
setUpdate();
}
}
S32 GuiTextListCtrl::findEntryById(U32 id)
{
for(U32 i = 0; i < mList.size(); i++)
if(mList[i].id == id)
return i;
return -1;
}
S32 GuiTextListCtrl::findEntryByText(const char *text)
{
for(U32 i = 0; i < mList.size(); i++)
if(!dStricmp(mList[i].text, text))
return i;
return -1;
}
bool GuiTextListCtrl::isEntryActive(U32 id)
{
S32 index = findEntryById( id );
if ( index == -1 )
return( false );
return( mList[index].active );
}
void GuiTextListCtrl::setSize(Point2I newSize)
{
mSize = newSize;
if ( bool( mFont ) )
{
if ( mSize.x == 1 && mFitParentWidth )
{
GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl *>(getParent());
if ( parent )
mCellSize.x = parent->getContentExtent().x;
}
else
{
// Find the maximum width cell:
S32 maxWidth = 1;
for ( U32 i = 0; i < mList.size(); i++ )
{
U32 rWidth = getRowWidth( &mList[i] );
if ( rWidth > maxWidth )
maxWidth = rWidth;
}
mCellSize.x = maxWidth + 8;
}
mCellSize.y = mFont->getHeight() + 2;
}
Point2I newExtent( newSize.x * mCellSize.x + mHeaderDim.x, newSize.y * mCellSize.y + mHeaderDim.y );
resize( mBounds.point, newExtent );
}
void GuiTextListCtrl::clear()
{
while (mList.size())
removeEntry(mList[0].id);
mMouseOverCell.set( -1, -1 );
setSelectedCell(Point2I(-1, -1));
}
void GuiTextListCtrl::sort(U32 column, bool increasing)
{
if (getNumEntries() < 2)
return;
sortColumn = column;
sIncreasing = increasing;
dQsort((void *)&(mList[0]), mList.size(), sizeof(Entry), textCompare);
}
void GuiTextListCtrl::sortNumerical( U32 column, bool increasing )
{
if ( getNumEntries() < 2 )
return;
sortColumn = column;
sIncreasing = increasing;
dQsort( (void*) &( mList[0] ), mList.size(), sizeof( Entry ), numCompare );
}
void GuiTextListCtrl::onRemove()
{
clear();
Parent::onRemove();
}
U32 GuiTextListCtrl::getNumEntries()
{
return mList.size();
}
void GuiTextListCtrl::removeEntryByIndex(S32 index)
{
if(index < 0 || index >= mList.size())
return;
dFree(mList[index].text);
mList.erase(index);
setSize(Point2I( 1, mList.size()));
setSelectedCell(Point2I(-1, -1));
}
void GuiTextListCtrl::removeEntry(U32 id)
{
S32 index = findEntryById(id);
removeEntryByIndex(index);
}
const char *GuiTextListCtrl::getSelectedText()
{
if (mSelectedCell.y == -1)
return NULL;
return mList[mSelectedCell.y].text;
}
const char *GuiTextListCtrl::getScriptValue()
{
return getSelectedText();
}
void GuiTextListCtrl::setScriptValue(const char *val)
{
S32 e = findEntryByText(val);
if(e == -1)
setSelectedCell(Point2I(-1, -1));
else
setSelectedCell(Point2I(0, e));
}
bool GuiTextListCtrl::onKeyDown( const GuiEvent &event )
{
//if this control is a dead end, make sure the event stops here
if ( !mVisible || !mActive || !mAwake )
return true;
S32 yDelta = 0;
switch( event.keyCode )
{
case KEY_RETURN:
if ( mAltConsoleCommand[0] )
Con::evaluate( mAltConsoleCommand, false );
break;
case KEY_LEFT:
case KEY_UP:
if ( mSelectedCell.y > 0 )
{
mSelectedCell.y--;
yDelta = -mCellSize.y;
}
break;
case KEY_DOWN:
case KEY_RIGHT:
if ( mSelectedCell.y < ( mList.size() - 1 ) )
{
mSelectedCell.y++;
yDelta = mCellSize.y;
}
break;
case KEY_HOME:
if ( mList.size() )
{
mSelectedCell.y = 0;
yDelta = -(mCellSize.y * mList.size() + 1 );
}
break;
case KEY_END:
if ( mList.size() )
{
mSelectedCell.y = mList.size() - 1;
yDelta = (mCellSize.y * mList.size() + 1 );
}
break;
case KEY_DELETE:
if ( mSelectedCell.y >= 0 && mSelectedCell.y < mList.size() )
Con::executef( this, 2, "onDeleteKey", Con::getIntArg( mList[mSelectedCell.y].id ) );
break;
default:
return( Parent::onKeyDown( event ) );
break;
};
GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl *>(getParent());
if ( parent )
parent->scrollDelta( 0, yDelta );
return ( true );
}

View File

@ -0,0 +1,92 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUITEXTLISTCTRL_H_
#define _GUITEXTLISTCTRL_H_
#ifndef _GUIARRAYCTRL_H_
#include "gui/core/guiArrayCtrl.h"
#endif
class GuiTextListCtrl : public GuiArrayCtrl
{
private:
typedef GuiArrayCtrl Parent;
public:
struct Entry
{
char *text;
U32 id;
bool active;
};
Vector<Entry> mList;
bool mEnumerate;
bool mResizeCell;
protected:
enum ScrollConst
{
UP = 0,
DOWN = 1
};
enum {
InvalidId = 0xFFFFFFFF
};
Vector<S32> mColumnOffsets;
bool mFitParentWidth;
bool mClipColumnText;
U32 getRowWidth(Entry *row);
void onCellSelected(Point2I cell);
public:
GuiTextListCtrl();
DECLARE_CONOBJECT(GuiTextListCtrl);
static void initPersistFields();
virtual void setCellSize( const Point2I &size ){ mCellSize = size; }
virtual void getCellSize( Point2I &size ){ size = mCellSize; }
const char *getScriptValue();
void setScriptValue(const char *value);
U32 getNumEntries();
void clear();
virtual void addEntry(U32 id, const char *text);
virtual void insertEntry(U32 id, const char *text, S32 index);
void setEntry(U32 id, const char *text);
void setEntryActive(U32 id, bool active);
S32 findEntryById(U32 id);
S32 findEntryByText(const char *text);
bool isEntryActive(U32 id);
U32 getEntryId(U32 index);
bool onWake();
void removeEntry(U32 id);
virtual void removeEntryByIndex(S32 id);
virtual void sort(U32 column, bool increasing = true);
virtual void sortNumerical(U32 column, bool increasing = true);
U32 getSelectedId();
const char *getSelectedText();
bool onKeyDown(const GuiEvent &event);
virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
void setSize(Point2I newSize);
void onRemove();
void addColumnOffset(S32 offset) { mColumnOffsets.push_back(offset); }
void clearColumnOffsets() { mColumnOffsets.clear(); }
};
#endif //_GUI_TEXTLIST_CTRL_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,389 @@
#ifndef _GUI_TREEVIEWCTRL_H
#define _GUI_TREEVIEWCTRL_H
#include "core/bitSet.h"
#include "math/mRect.h"
#include "dgl/gFont.h"
#include "gui/core/guiControl.h"
#include "gui/core/guiArrayCtrl.h"
//------------------------------------------------------------------------------
class GuiTreeViewCtrl : public GuiArrayCtrl
{
private:
typedef GuiArrayCtrl Parent;
protected:
/// @section GuiControl_Intro Introduction
/// @nosubgrouping
///
struct Item
{
enum ItemState
{
Selected = BIT(0),
Expanded = BIT(1),
Focus = BIT(2),
MouseOverBmp = BIT(3),
MouseOverText = BIT(4),
InspectorData = BIT(5), ///< Set if we're representing some inspector
/// info (ie, use mInspectorInfo, not mScriptInfo)
VirtualParent = BIT(6), ///< This indicates that we should be rendered as
/// a parent even though we don't have any children.
/// This is useful for preventing scenarios where
/// we might want to create thousands of
/// Items that might never be shown (for instance
/// if we're browsing the object hierarchy in
/// Torque, which might have thousands of objects).
};
BitSet32 mState;
S16 mId;
U16 mTabLevel;
Item * mParent;
Item * mChild;
Item * mNext;
Item * mPrevious;
S32 mIcon; //stores the icon that will represent the item in the tree
Item();
~Item();
struct ScriptTag
{
S8 mNormalImage;
S8 mExpandedImage;
char* mText;
char* mValue;
} mScriptInfo;
struct InspectorTag
{
SimObjectPtr<SimObject> mObject;
} mInspectorInfo;
/// @name Get Methods
/// @{
///
const S8 getNormalImage() const;
const S8 getExpandedImage() const;
char *getText();
char *getValue();
inline const S16 getID() const { return mId; };
SimObject *getObject();
const U32 getDisplayTextLength();
const S32 getDisplayTextWidth(GFont *font);
void getDisplayText(U32 bufLen, char *buf);
/// @}
/// @name Set Methods
/// @{
/// Set whether an item is expanded or not (showing children or having them hidden)
void setExpanded(const bool f);
/// Set the image to display when an item IS expanded
void setExpandedImage(const S8 id);
/// Set the image to display when an item is NOT expanded
void setNormalImage(const S8 id);
/// Assign a SimObject pointer to an inspector data item
void setObject(SimObject *obj);
/// Set the items displayable text (caption)
void setText(char *txt);
/// Set the items script value (data)
void setValue(const char *val);
/// Set the items virtual parent flag
void setVirtualParent( bool value );
/// @}
/// @name State Retrieval
/// @{
/// Returns true if this item is expanded. For
/// inspector objects, the expansion is stored
/// on the SimObject, for other things we use our
/// bit vector.
const bool isExpanded() const;
/// Returns true if an item is inspector data
/// or false if it's just an item.
inline const bool isInspectorData() const { return mState.test(InspectorData); };
/// Returns true if we should show the expand art
/// and make the item interact with the mouse as if
/// it were a parent.
const bool isParent() const;
/// @}
/// @name Searching Methods
/// @{
/// Find an inspector data item by it's SimObject pointer
Item *findChildByValue(const SimObject *obj);
/// Find a regular data item by it's script value
Item *findChildByValue(StringTableEntry Value);
/// @}
};
/// @name Enums
/// @{
///
enum TreeState
{
RebuildVisible = BIT(0), ///< Temporary flag, we have to rebuild the tree.
IsInspector = BIT(1), ///< We are mapping a SimObject hierarchy.
IsEditable = BIT(2), ///< We allow items to be moved around.
IsDeletable = BIT(3), ///< We allow items to be deleted.
ShowTreeLines = BIT(4), ///< Should we render tree lines or just icons?
};
protected:
enum
{
MaxIcons = 32,
};
enum Icons
{
Default1 = 0,
SimGroup1,
SimGroup2,
SimGroup3,
SimGroup4,
Audio,
Camera,
fxFoliageReplicator,
fxLight,
fxShapeReplicator,
fxSunLight,
Hidden,
Interior,
Lightning,
Lock1,
Lock2,
MissionArea,
Particle,
Path,
Pathmarker,
PhysicalArea,
Precipitation,
Shape,
Sky,
StaticShape,
Sun,
Terrain,
Trigger,
Water,
Default,
Icon31,
Icon32
};
enum mDragMidPointFlags
{
NomDragMidPoint,
AbovemDragMidPoint,
BelowmDragMidPoint
};
///
enum HitFlags
{
OnIndent = BIT(0),
OnImage = BIT(1),
OnText = BIT(2),
OnRow = BIT(3),
};
///
enum BmpIndices
{
BmpDunno,
BmpLastChild,
BmpChild,
BmpExp,
BmpExpN,
BmpExpP,
BmpExpPN,
BmpCon,
BmpConN,
BmpConP,
BmpConPN,
BmpLine,
BmpGlow,
};
/// @}
public:
///
Vector<Item*> mItems;
Vector<Item*> mVisibleItems;
Vector<Item*> mSelectedItems;
Vector<S32> mSelected; ///< Used for tracking stuff that was
/// selected, but may not have been
/// created at time of selection
S32 mItemCount;
Item * mItemFreeList; ///< We do our own free list, as we
/// we want to be able to recycle
/// item ids and do some other clever
/// things.
Item * mRoot;
S32 mInstantGroup;
S32 mMaxWidth;
S32 mSelectedItem;
S32 mDraggedToItem;
S32 mTempItem;
S32 mStart;
BitSet32 mFlags;
protected:
TextureHandle mIconTable[MaxIcons];
// for debugging
bool mDebug;
S32 mTabSize;
S32 mTextOffset;
bool mFullRowSelect;
S32 mItemHeight;
bool mDestroyOnSleep;
bool mSupportMouseDragging;
bool mMultipleSelections;
S32 mOldDragY;
S32 mCurrentDragCell;
S32 mPreviousDragCell;
S32 mDragMidPoint;
bool mMouseDragged;
StringTableEntry mBitmapBase;
TextureHandle mTexRollover;
TextureHandle mTexSelected;
ColorI mAltFontColor;
ColorI mAltFontColorHL;
ColorI mAltFontColorSE;
SimObjectPtr<SimObject> mRootObject;
void destroyChildren(Item * item, Item * parent);
void destroyItem(Item * item);
void destroyTree();
void deleteItem(Item *item);
void buildItem(Item * item, U32 tabLevel);
void buildVisibleTree();
bool hitTest(const Point2I & pnt, Item* & item, BitSet32 & flags);
virtual bool onVirtualParentBuild(Item *item);
virtual bool onVirtualParentExpand(Item *item);
virtual bool onVirtualParentCollapse(Item *item);
virtual void onItemSelected( Item *item );
void addInspectorDataItem(Item *parent, SimObject *obj);
public:
GuiTreeViewCtrl();
virtual ~GuiTreeViewCtrl();
/// Used for syncing the mSelected and mSelectedItems lists.
void syncSelection();
void lockSelection(bool lock);
void hideSelection(bool hide);
void addSelection(S32 itemId);
/// Should use addSelection and removeSelection when calling from script
/// instead of setItemSelected. Use setItemSelected when you want to select
/// something in the treeview as it has script call backs.
void removeSelection(S32 itemId);
/// Sets the flag of the item with the matching itemId.
bool setItemSelected(S32 itemId, bool select);
bool setItemExpanded(S32 itemId, bool expand);
bool setItemValue(S32 itemId, StringTableEntry Value);
const char * getItemText(S32 itemId);
const char * getItemValue(S32 itemId);
StringTableEntry getTextToRoot(S32 itemId, const char *delimiter = "");
Item * getItem(S32 itemId);
Item * createItem(S32 icon);
bool editItem( S32 itemId, const char* newText, const char* newValue );
// insertion/removal
void unlinkItem(Item * item);
S32 insertItem(S32 parentId, const char * text, const char * value = "", const char * iconString = "", S16 normalImage = 0, S16 expandedImage = 1);
bool removeItem(S32 itemId);
bool buildIconTable(const char * icons);
void setInstantGroup(SimObject * obj);
S32 getIcon(const char * iconString);
// tree items
const S32 getFirstRootItem() const;
S32 getChildItem(S32 itemId);
S32 getParentItem(S32 itemId);
S32 getNextSiblingItem(S32 itemId);
S32 getPrevSiblingItem(S32 itemId);
S32 getItemCount();
S32 getSelectedItem();
void moveItemUp( S32 itemId );
// misc.
bool scrollVisible( Item *item );
void deleteSelection();
void clearSelection();
S32 findItemByName(const char *name);
// GuiControl
bool onWake();
void onSleep();
void onPreRender();
bool onKeyDown( const GuiEvent &event );
void onMouseDown(const GuiEvent &event);
void onMiddleMouseDown(const GuiEvent &event);
void onMouseMove(const GuiEvent &event);
void onMouseEnter(const GuiEvent &event);
void onMouseLeave(const GuiEvent &event);
void onRightMouseDown(const GuiEvent &event);
void onMouseDragged(const GuiEvent &event);
void onMouseUp(const GuiEvent &event);
/// Returns false if the object is a child of one of the inner items.
bool childSearch(Item * item, SimObject *obj, bool yourBaby);
/// Find immediately available inspector items (eg ones that aren't children of other inspector items)
/// and then update their sets
void inspectorSearch(Item * item, Item * parent, SimSet * parentSet, SimSet * newParentSet);
// GuiArrayCtrl
void onRenderCell(Point2I offset, Point2I cell, bool, bool);
void onRender(Point2I offset, const RectI &updateRect);
static void initPersistFields();
void inspectObject(SimObject * obj, bool okToEdit);
DECLARE_CONOBJECT(GuiTreeViewCtrl);
};
#endif