mirror of
https://github.com/tribes2/engine.git
synced 2026-03-06 22:10:28 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
283
gui/channelVector.cc
Normal file
283
gui/channelVector.cc
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/channelVector.h"
|
||||
|
||||
struct TempLineBreak
|
||||
{
|
||||
S32 start;
|
||||
S32 end;
|
||||
char *content;
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(ChannelVector);
|
||||
|
||||
//-------------------------------------- Console methods
|
||||
ConsoleMethod(ChannelVector,AddMember,bool,4,5,"obj.addMember(id,nick,flags)")
|
||||
{
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
if (argc == 4)
|
||||
return pCV->addMember(dAtoi(argv[2]),argv[3]);
|
||||
else
|
||||
return pCV->addMember(dAtoi(argv[2]),argv[3],dAtoi(argv[4]));
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,RemoveMember,bool,3,3,"obj.removeMember(id)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->removeMember(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,Sort,void,2,2,"obj.sort()")
|
||||
{
|
||||
argc; argv;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
pCV->sort();
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,FindMember,S32,3,3,"obj.findMember(id)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->findMember(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,NumMembers,S32,2,2,"obj.numMembers()")
|
||||
{
|
||||
argc; argv;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->numMembers();
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,GetMemberId,S32,3,3,"obj.getMemberId(i)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->getMemberId(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,GetMemberNick,const char *,3,3,"obj.getMemberNick(i)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->getMemberNick(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,SetMemberNick,bool,4,4,"obj.setMemberNick(i,nick)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->setMemberNick(dAtoi(argv[2]),argv[3]);
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,SetFlags,void,5,5,"obj.setFlags(i,flags,set)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
pCV->setFlags(dAtoi(argv[2]),dAtoi(argv[3]),dAtob(argv[4]));
|
||||
}
|
||||
|
||||
ConsoleMethod(ChannelVector,GetFlags,S32,3,3,"obj.getFlags(i)")
|
||||
{
|
||||
argc;
|
||||
ChannelVector* pCV = static_cast<ChannelVector*>(object);
|
||||
|
||||
return pCV->getFlags(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ChannelVector::ChannelVector()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mLineTags);
|
||||
VECTOR_SET_ASSOCIATION(mMembers);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ChannelVector::~ChannelVector()
|
||||
{
|
||||
for (U32 i = 0; i < mLineTags.size(); ++i)
|
||||
delete [] mLineTags[i].specials;
|
||||
mLineTags.clear();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
S32 QSORT_CALLBACK ChannelVector::compareMembers(const void *a, const void *b)
|
||||
{
|
||||
Member *memberA = (Member*) a;
|
||||
Member *memberB = (Member*) b;
|
||||
|
||||
S32 ao = memberA->flags & (PERSON_SPEAKER|PERSON_OPERATOR);
|
||||
S32 bo = memberB->flags & (PERSON_SPEAKER|PERSON_OPERATOR);
|
||||
|
||||
if (ao != bo)
|
||||
return (bo-ao);
|
||||
|
||||
char atag[64];
|
||||
const char *anick;
|
||||
char btag[64];
|
||||
const char *bnick;
|
||||
|
||||
dStrcpy(atag,memberA->nick);
|
||||
atag[7] = '\0';
|
||||
if (dStrcmp(atag,"<tribe:") == 0)
|
||||
anick = &memberA->nick[9];
|
||||
else
|
||||
anick = memberA->nick;
|
||||
dStrcpy(btag,memberB->nick);
|
||||
btag[7] = '\0';
|
||||
if (dStrcmp(btag,"<tribe:") == 0)
|
||||
bnick = &memberB->nick[9];
|
||||
else
|
||||
bnick = memberB->nick;
|
||||
|
||||
|
||||
return (dStricmp(anick, bnick));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void ChannelVector::sort()
|
||||
{
|
||||
dQsort((void*) &mMembers[0], mMembers.size(), sizeof(Member), compareMembers);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ChannelVector::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ChannelVector::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool ChannelVector::onAdd()
|
||||
{
|
||||
return Parent::onAdd();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ChannelVector::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ChannelVector::insertLine(const U32 position, const char *newMessage, const S32 newMessageTag)
|
||||
{
|
||||
Vector<TempLineBreak> tempSpecials(__FILE__, __LINE__);
|
||||
Vector<S32> tempTypes(__FILE__, __LINE__);
|
||||
|
||||
char *copy = new char[dStrlen(newMessage) + 1];
|
||||
const char* cur = copy;
|
||||
|
||||
dStrcpy(copy,newMessage);
|
||||
while(cur[0] != '\0')
|
||||
{
|
||||
const char *open;
|
||||
|
||||
if ((open = dStrstr(cur,"<tribe:")) != NULL)
|
||||
{
|
||||
const char *close;
|
||||
|
||||
tempTypes.push_back((open[7] == '0') ? NickTag : TribeTag);
|
||||
tempSpecials.increment();
|
||||
|
||||
TempLineBreak &tag = tempSpecials.last();
|
||||
|
||||
tag.start = open - copy;
|
||||
tag.content = NULL;
|
||||
open += 9;
|
||||
close = dStrstr(open,"</tribe>");
|
||||
tag.end = tag.start + (close-open) - 1;
|
||||
|
||||
dMemcpy(©[tag.start],open,tag.end-tag.start+1);
|
||||
dStrcpy(©[tag.end+1],close+8);
|
||||
|
||||
cur = ©[tempSpecials.last().end+1];
|
||||
}
|
||||
else
|
||||
if ((open = dStrstr(cur,"<t2server:")) != NULL)
|
||||
{
|
||||
const char *close;
|
||||
|
||||
tempTypes.push_back(ServerTag);
|
||||
tempSpecials.increment();
|
||||
|
||||
TempLineBreak &tag = tempSpecials.last();
|
||||
|
||||
tag.start = open - copy;
|
||||
|
||||
const char *content = open+10;
|
||||
|
||||
open = dStrstr(open,">");
|
||||
tag.content = new char[open-content+1];
|
||||
dMemcpy(tag.content,content,open-content);
|
||||
tag.content[open-content] = '\0';
|
||||
++open;
|
||||
close = dStrstr(open,"</t2server>");
|
||||
tag.end = tag.start + (close-open) - 1;
|
||||
|
||||
dMemcpy(©[tag.start],open,tag.end-tag.start+1);
|
||||
dStrcpy(©[tag.end+1],close+11);
|
||||
|
||||
cur = ©[tag.end+1];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
SpecialMarkers tags;
|
||||
|
||||
if ((tags.numSpecials = tempSpecials.size()) != 0) {
|
||||
tags.specials = new SpecialMarkers::Special[tempSpecials.size()];
|
||||
for (U32 i = 0; i < tempSpecials.size(); i++) {
|
||||
tags.specials[i].specialType = tempTypes[i];
|
||||
tags.specials[i].start = tempSpecials[i].start;
|
||||
tags.specials[i].end = tempSpecials[i].end;
|
||||
tags.specials[i].content = tempSpecials[i].content;
|
||||
}
|
||||
} else
|
||||
tags.specials = NULL;
|
||||
mLineTags.insert(position);
|
||||
mLineTags[position] = tags;
|
||||
|
||||
Parent::insertLine(position,copy,newMessageTag);
|
||||
|
||||
delete [] copy;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void ChannelVector::deleteLine(const U32 position)
|
||||
{
|
||||
delete [] mLineTags[position].specials;
|
||||
mLineTags.erase(position);
|
||||
|
||||
Parent::deleteLine(position);
|
||||
}
|
||||
202
gui/channelVector.h
Normal file
202
gui/channelVector.h
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _CHANNELVECTOR_H_
|
||||
#define _CHANNELVECTOR_H_
|
||||
|
||||
#ifndef _GUIMESSAGEVECTORCTRL_H_
|
||||
#include "GUI/guiMessageVectorCtrl.h"
|
||||
#endif
|
||||
|
||||
class ChannelVector : public MessageVector
|
||||
{
|
||||
private:
|
||||
typedef MessageVector Parent;
|
||||
|
||||
enum Constants {
|
||||
// Person flags
|
||||
PERSON_SPEAKER = BIT(0),
|
||||
PERSON_OPERATOR = BIT(1),
|
||||
PERSON_IGNORE = BIT(2),
|
||||
PERSON_AWAY = BIT(3),
|
||||
};
|
||||
|
||||
public:
|
||||
enum {
|
||||
NickTag = -3,
|
||||
TribeTag = -2,
|
||||
ServerTag = -1,
|
||||
};
|
||||
|
||||
struct SpecialMarkers {
|
||||
struct Special {
|
||||
S32 specialType;
|
||||
S32 start;
|
||||
S32 end;
|
||||
char *content;
|
||||
|
||||
Special() { content = NULL; };
|
||||
~Special() { delete [] content; };
|
||||
};
|
||||
|
||||
U32 numSpecials;
|
||||
Special* specials;
|
||||
};
|
||||
|
||||
ChannelVector();
|
||||
~ChannelVector();
|
||||
|
||||
DECLARE_CONOBJECT(ChannelVector);
|
||||
|
||||
virtual void insertLine(const U32 position, const char*, const S32);
|
||||
virtual void deleteLine(const U32);
|
||||
|
||||
const SpecialMarkers & getLineTags(U32 position)
|
||||
{
|
||||
return mLineTags[position];
|
||||
}
|
||||
|
||||
bool addMember(S32 id, const char *nick, S32 flags = 0);
|
||||
bool removeMember(S32 id);
|
||||
static S32 QSORT_CALLBACK compareMembers(const void *a, const void *b);
|
||||
void sort();
|
||||
S32 findMember(S32 id);
|
||||
S32 numMembers();
|
||||
S32 getMemberId(S32 i);
|
||||
const char *getMemberNick(S32 i);
|
||||
bool setMemberNick(S32 i, const char *nick);
|
||||
void setFlags(S32 i, S32 flags, bool set);
|
||||
S32 getFlags(S32 i);
|
||||
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
protected:
|
||||
struct Member
|
||||
{
|
||||
S32 id;
|
||||
StringTableEntry nick;
|
||||
S32 flags;
|
||||
};
|
||||
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
Vector<SpecialMarkers> mLineTags;
|
||||
Vector<Member> mMembers;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool ChannelVector::addMember(S32 id, const char *nick, S32 flags)
|
||||
{
|
||||
Vector<Member>::iterator itr = mMembers.begin();
|
||||
|
||||
for (; itr != mMembers.end(); itr++)
|
||||
if (id == itr->id)
|
||||
break;
|
||||
|
||||
if (itr == mMembers.end())
|
||||
{
|
||||
mMembers.increment();
|
||||
|
||||
Member *pm = mMembers.end()-1;
|
||||
|
||||
pm->id = id;
|
||||
pm->nick = StringTable->insert(nick);
|
||||
pm->flags = flags;
|
||||
sort();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool ChannelVector::removeMember(S32 id)
|
||||
{
|
||||
Vector<Member>::iterator itr = mMembers.begin();
|
||||
|
||||
for (; itr != mMembers.end(); itr++)
|
||||
if (id == itr->id)
|
||||
{
|
||||
mMembers.erase(itr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline S32 ChannelVector::findMember(S32 id)
|
||||
{
|
||||
for (S32 i = 0; i < mMembers.size(); ++i)
|
||||
if (id == mMembers[i].id)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline S32 ChannelVector::numMembers()
|
||||
{
|
||||
return mMembers.size();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline S32 ChannelVector::getMemberId(S32 i)
|
||||
{
|
||||
if (i >= 0 && i < mMembers.size())
|
||||
return mMembers[i].id;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline const char * ChannelVector::getMemberNick(S32 i)
|
||||
{
|
||||
if (i >= 0 && i < mMembers.size())
|
||||
return mMembers[i].nick;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool ChannelVector::setMemberNick(S32 i, const char *nick)
|
||||
{
|
||||
if (i >= 0 && i < mMembers.size())
|
||||
{
|
||||
mMembers[i].nick = StringTable->insert(nick);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void ChannelVector::setFlags(S32 i, S32 flags, bool set)
|
||||
{
|
||||
if (i >= 0 && i < mMembers.size())
|
||||
if (set)
|
||||
mMembers[i].flags |= flags;
|
||||
else
|
||||
mMembers[i].flags &= ~flags;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline S32 ChannelVector::getFlags(S32 i)
|
||||
{
|
||||
if (i >= 0 && i < mMembers.size())
|
||||
return mMembers[i].flags;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // _H_CHANNELVECTOR_
|
||||
488
gui/guiArrayCtrl.cc
Normal file
488
gui/guiArrayCtrl.cc
Normal file
|
|
@ -0,0 +1,488 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "Platform/event.h"
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
#include "GUI/guiArrayCtrl.h"
|
||||
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
GuiArrayCtrl::GuiArrayCtrl()
|
||||
{
|
||||
mActive = true;
|
||||
|
||||
mCellSize.set(80, 30);
|
||||
mSize = Point2I(5, 30);
|
||||
mSelectedCell.set(-1, -1);
|
||||
mMouseOverCell.set(-1, -1);
|
||||
mHeaderDim.set(0, 0);
|
||||
}
|
||||
|
||||
bool GuiArrayCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
//get the font
|
||||
mFont = mProfile->mFont;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onSleep()
|
||||
{
|
||||
Parent::onSleep();
|
||||
mFont = NULL;
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
void GuiArrayCtrl::setSize(Point2I newSize)
|
||||
{
|
||||
mSize = newSize;
|
||||
Point2I newExtent(newSize.x * mCellSize.x + mHeaderDim.x, newSize.y * mCellSize.y + mHeaderDim.y);
|
||||
|
||||
resize(mBounds.point, newExtent);
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::getScrollDimensions(S32 &cell_size, S32 &num_cells)
|
||||
{
|
||||
cell_size = mCellSize.y;
|
||||
num_cells = mSize.y;
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
bool GuiArrayCtrl::cellSelected(Point2I cell)
|
||||
{
|
||||
if (cell.x < 0 || cell.x >= mSize.x || cell.y < 0 || cell.y >= mSize.y)
|
||||
{
|
||||
mSelectedCell = Point2I(-1,-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
mSelectedCell = cell;
|
||||
scrollSelectionVisible();
|
||||
onCellSelected(cell);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onCellSelected(Point2I cell)
|
||||
{
|
||||
Con::executef(this, 3, "onSelect", Con::getFloatArg(cell.x), Con::getFloatArg(cell.y));
|
||||
|
||||
//call the console function
|
||||
if (mConsoleCommand[0])
|
||||
Con::evaluate(mConsoleCommand, false);
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::setSelectedCell(Point2I cell)
|
||||
{
|
||||
cellSelected(cell);
|
||||
}
|
||||
|
||||
Point2I GuiArrayCtrl::getSelectedCell()
|
||||
{
|
||||
return mSelectedCell;
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::scrollSelectionVisible()
|
||||
{
|
||||
scrollCellVisible(mSelectedCell);
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::scrollCellVisible(Point2I cell)
|
||||
{
|
||||
//make sure we have a parent
|
||||
GuiControl *parent = getParent();
|
||||
if (! parent) return;
|
||||
|
||||
//make sure we have a valid cell selected
|
||||
if ((cell.x < 0) || (cell.y < 0)) return;
|
||||
|
||||
//get the parent extent, and the offset of the selected cell
|
||||
Point2I parentExtent = parent->getExtent();
|
||||
Point2I cellPos(mBounds.point.x + cell.x * mCellSize.x,
|
||||
mBounds.point.y + cell.y * mCellSize.y);
|
||||
|
||||
Point2I delta(0,0);
|
||||
|
||||
//find out how far the selected cell is outside the parent extent horizontally
|
||||
if (cellPos.x <= 0)
|
||||
{
|
||||
delta.x = -cellPos.x;
|
||||
}
|
||||
else if (cellPos.x + mCellSize.x > parentExtent.x)
|
||||
{
|
||||
delta.x = parentExtent.x - (cellPos.x + mCellSize.x);
|
||||
}
|
||||
|
||||
//find out how far the selected cell is outside the parent extent vertically
|
||||
if (cellPos.y <= 0)
|
||||
{
|
||||
delta.y = -cellPos.y;
|
||||
}
|
||||
else if (cellPos.y + mCellSize.y > parentExtent.y)
|
||||
{
|
||||
delta.y = parentExtent.y - (cellPos.y + mCellSize.y);
|
||||
}
|
||||
|
||||
//if we need to scroll, set the new position
|
||||
if (delta.x || delta.y)
|
||||
{
|
||||
Point2I newPosition = mBounds.point;
|
||||
newPosition.x += delta.x;
|
||||
newPosition.y += delta.y;
|
||||
resize(newPosition, mBounds.extent);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::scrollSelectionTop()
|
||||
{
|
||||
scrollCellTop( mSelectedCell );
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::scrollSelectionBottom()
|
||||
{
|
||||
scrollCellBottom( mSelectedCell );
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::scrollCellTop( Point2I cell )
|
||||
{
|
||||
// Make sure we have a parent:
|
||||
GuiControl* parent = getParent();
|
||||
if ( !parent )
|
||||
return;
|
||||
|
||||
// Make sure the cell is valid:
|
||||
if ( ( cell.x < 0 ) || ( cell.y < 0 ) )
|
||||
return;
|
||||
|
||||
// This is the >desired< new position--let the scroll control decide
|
||||
// whether it is a reasonable position or not...
|
||||
Point2I newPos( -( cell.x * mCellSize.x ), -( cell.y * mCellSize.y ) );
|
||||
resize( newPos, mBounds.extent );
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::scrollCellBottom( Point2I cell )
|
||||
{
|
||||
// Make sure we have a parent:
|
||||
GuiControl* parent = getParent();
|
||||
if ( !parent )
|
||||
return;
|
||||
|
||||
// Make sure the cell is valid:
|
||||
if ( ( cell.x < 0 ) || ( cell.y < 0 ) )
|
||||
return;
|
||||
|
||||
// This is the >desired< new position--let the scroll control decide
|
||||
// whether it is a reasonable position or not...
|
||||
Point2I newPos( parent->mBounds.extent.x - ( ( cell.x + 1 ) * mCellSize.x ),
|
||||
parent->mBounds.extent.y - ( ( cell.y + 1 ) * mCellSize.y ) );
|
||||
resize( newPos, mBounds.extent );
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
void GuiArrayCtrl::onRenderColumnHeaders(Point2I offset, Point2I parentOffset, Point2I headerDim)
|
||||
{
|
||||
if (mProfile->mBorder)
|
||||
{
|
||||
RectI cellR(offset.x + headerDim.x, parentOffset.y, mBounds.extent.x - headerDim.x, headerDim.y);
|
||||
dglDrawRectFill(cellR, mProfile->mBorderColor);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onRenderRowHeader(Point2I offset, Point2I parentOffset, Point2I headerDim, Point2I cell)
|
||||
{
|
||||
ColorI color;
|
||||
RectI cellR;
|
||||
if (cell.x % 2)
|
||||
color.set(255, 0, 0, 255);
|
||||
else
|
||||
color.set(0, 255, 0, 255);
|
||||
|
||||
cellR.point.set(parentOffset.x, offset.y);
|
||||
cellR.extent.set(headerDim.x, mCellSize.y);
|
||||
dglDrawRectFill(cellR, color);
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
|
||||
{
|
||||
ColorI color(255 * (cell.x % 2), 255 * (cell.y % 2), 255 * ((cell.x + cell.y) % 2), 255);
|
||||
if (selected)
|
||||
{
|
||||
color.set(255, 0, 0, 255);
|
||||
}
|
||||
else if (mouseOver)
|
||||
{
|
||||
color.set(0, 0, 255, 255);
|
||||
}
|
||||
|
||||
//draw the cell
|
||||
RectI cellR(offset.x, offset.y, mCellSize.x, mCellSize.y);
|
||||
dglDrawRectFill(cellR, color);
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
firstResponder;
|
||||
|
||||
//make sure we have a parent
|
||||
GuiControl *parent = getParent();
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
S32 i, j;
|
||||
RectI headerClip;
|
||||
RectI clipRect(updateRect.point, updateRect.extent);
|
||||
|
||||
Point2I parentOffset = parent->localToGlobalCoord(Point2I(0, 0));
|
||||
|
||||
//if we have column headings
|
||||
if (mHeaderDim.y > 0)
|
||||
{
|
||||
headerClip.point.x = parentOffset.x + mHeaderDim.x;
|
||||
headerClip.point.y = parentOffset.y;
|
||||
headerClip.extent.x = clipRect.extent.x - headerClip.point.x;
|
||||
headerClip.extent.y = mHeaderDim.y;
|
||||
|
||||
if (headerClip.intersect(clipRect))
|
||||
{
|
||||
dglSetClipRect(headerClip);
|
||||
|
||||
//now render the header
|
||||
onRenderColumnHeaders(offset, parentOffset, mHeaderDim);
|
||||
|
||||
clipRect.point.y = headerClip.point.y + headerClip.extent.y - 1;
|
||||
}
|
||||
offset.y += mHeaderDim.y;
|
||||
}
|
||||
|
||||
//if we have row headings
|
||||
if (mHeaderDim.x > 0)
|
||||
{
|
||||
clipRect.point.x = getMax(clipRect.point.x, parentOffset.x + mHeaderDim.x);
|
||||
offset.x += mHeaderDim.x;
|
||||
}
|
||||
|
||||
//save the original for clipping the row headers
|
||||
RectI origClipRect = clipRect;
|
||||
|
||||
for (j = 0; j < mSize.y; j++)
|
||||
{
|
||||
//skip until we get to a visible row
|
||||
if ((j + 1) * mCellSize.y + offset.y < updateRect.point.y)
|
||||
continue;
|
||||
|
||||
//break once we've reached the last visible row
|
||||
if(j * mCellSize.y + offset.y >= updateRect.point.y + updateRect.extent.y)
|
||||
break;
|
||||
|
||||
//render the header
|
||||
if (mHeaderDim.x > 0)
|
||||
{
|
||||
headerClip.point.x = parentOffset.x;
|
||||
headerClip.extent.x = mHeaderDim.x;
|
||||
headerClip.point.y = offset.y + j * mCellSize.y;
|
||||
headerClip.extent.y = mCellSize.y;
|
||||
if (headerClip.intersect(origClipRect))
|
||||
{
|
||||
dglSetClipRect(headerClip);
|
||||
|
||||
//render the row header
|
||||
onRenderRowHeader(Point2I(0, offset.y + j * mCellSize.y),
|
||||
Point2I(parentOffset.x, offset.y + j * mCellSize.y),
|
||||
mHeaderDim, Point2I(0, j));
|
||||
}
|
||||
}
|
||||
|
||||
//render the cells for the row
|
||||
for (i = 0; i < mSize.x; i++)
|
||||
{
|
||||
//skip past columns off the left edge
|
||||
if ((i + 1) * mCellSize.x + offset.x < updateRect.point.x)
|
||||
continue;
|
||||
|
||||
//break once past the last visible column
|
||||
if (i * mCellSize.x + offset.x >= updateRect.point.x + updateRect.extent.x)
|
||||
break;
|
||||
|
||||
S32 cellx = offset.x + i * mCellSize.x;
|
||||
S32 celly = offset.y + j * mCellSize.y;
|
||||
|
||||
RectI cellClip(cellx, celly, mCellSize.x, mCellSize.y);
|
||||
|
||||
//make sure the cell is within the update region
|
||||
if (cellClip.intersect(clipRect))
|
||||
{
|
||||
//set the clip rect
|
||||
dglSetClipRect(cellClip);
|
||||
|
||||
//render the cell
|
||||
onRenderCell(Point2I(cellx, celly), Point2I(i, j),
|
||||
i == mSelectedCell.x && j == mSelectedCell.y,
|
||||
i == mMouseOverCell.x && j == mMouseOverCell.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if ( !mActive || !mAwake || !mVisible ) return;
|
||||
|
||||
//let the guiControl method take care of the rest
|
||||
Parent::onMouseDown(event);
|
||||
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
|
||||
//store the previously selected cell
|
||||
Point2I prevSelected = mSelectedCell;
|
||||
|
||||
//select the new cell
|
||||
cellSelected(Point2I(cell.x, cell.y));
|
||||
|
||||
//if we double clicked on the *same* cell, evaluate the altConsole Command
|
||||
if ( ( event.mouseClickCount > 1 ) && ( prevSelected == mSelectedCell ) && mAltConsoleCommand[0] )
|
||||
Con::evaluate( mAltConsoleCommand, false );
|
||||
}
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onMouseEnter(const GuiEvent &event)
|
||||
{
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
|
||||
//get the cell
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
mMouseOverCell = cell;
|
||||
setUpdateRegion(Point2I(cell.x * mCellSize.x + mHeaderDim.x,
|
||||
cell.y * mCellSize.y + mHeaderDim.y), mCellSize );
|
||||
}
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onMouseLeave(const GuiEvent & /*event*/)
|
||||
{
|
||||
setUpdateRegion(Point2I(mMouseOverCell.x * mCellSize.x + mHeaderDim.x,
|
||||
mMouseOverCell.y * mCellSize.y + mHeaderDim.y), mCellSize);
|
||||
mMouseOverCell.set(-1,-1);
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onMouseMove(const GuiEvent &event)
|
||||
{
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if (cell.x != mMouseOverCell.x || cell.y != mMouseOverCell.y)
|
||||
{
|
||||
if (mMouseOverCell.x != -1)
|
||||
{
|
||||
setUpdateRegion(Point2I(mMouseOverCell.x * mCellSize.x + mHeaderDim.x,
|
||||
mMouseOverCell.y * mCellSize.y + mHeaderDim.y), mCellSize);
|
||||
}
|
||||
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
setUpdateRegion(Point2I(cell.x * mCellSize.x + mHeaderDim.x,
|
||||
cell.y * mCellSize.y + mHeaderDim.y), mCellSize);
|
||||
mMouseOverCell = cell;
|
||||
}
|
||||
else
|
||||
mMouseOverCell.set(-1,-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiArrayCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if this control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake)) return true;
|
||||
|
||||
//get the parent
|
||||
S32 pageSize = 1;
|
||||
GuiControl *parent = getParent();
|
||||
if (parent && mCellSize.y > 0)
|
||||
{
|
||||
pageSize = getMax(1, (parent->mBounds.extent.y / mCellSize.y) - 1);
|
||||
}
|
||||
|
||||
Point2I delta(0,0);
|
||||
switch (event.keyCode)
|
||||
{
|
||||
case KEY_LEFT:
|
||||
delta.set(-1, 0);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
delta.set(1, 0);
|
||||
break;
|
||||
case KEY_UP:
|
||||
delta.set(0, -1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
delta.set(0, 1);
|
||||
break;
|
||||
case KEY_PAGE_UP:
|
||||
delta.set(0, -pageSize);
|
||||
break;
|
||||
case KEY_PAGE_DOWN:
|
||||
delta.set(0, pageSize);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
cellSelected( Point2I( 0, 0 ) );
|
||||
return( true );
|
||||
case KEY_END:
|
||||
cellSelected( Point2I( 0, mSize.y - 1 ) );
|
||||
return( true );
|
||||
default:
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
if (mSize.x < 1 || mSize.y < 1)
|
||||
return true;
|
||||
|
||||
//select the first cell if no previous cell was selected
|
||||
if (mSelectedCell.x == -1 || mSelectedCell.y == -1)
|
||||
{
|
||||
cellSelected(Point2I(0,0));
|
||||
return true;
|
||||
}
|
||||
|
||||
//select the cell
|
||||
Point2I cell = mSelectedCell;
|
||||
cell.x = getMax(0, getMin(mSize.x - 1, cell.x + delta.x));
|
||||
cell.y = getMax(0, getMin(mSize.y - 1, cell.y + delta.y));
|
||||
cellSelected(cell);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiArrayCtrl::onRightMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if ( !mActive || !mAwake || !mVisible )
|
||||
return;
|
||||
|
||||
Parent::onRightMouseDown( event );
|
||||
|
||||
Point2I pt = globalToLocalCoord( event.mousePoint );
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
char buf[32];
|
||||
dSprintf( buf, sizeof( buf ), "%d %d", event.mousePoint.x, event.mousePoint.y );
|
||||
// Pass it to the console:
|
||||
Con::executef(this, 4, "onRightMouseDown", Con::getIntArg(cell.x), Con::getIntArg(cell.y), buf);
|
||||
}
|
||||
}
|
||||
76
gui/guiArrayCtrl.h
Normal file
76
gui/guiArrayCtrl.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#define _GUIARRAYCTRL_H_
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "GUI/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiArrayCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
|
||||
Point2I mHeaderDim;
|
||||
Point2I mSize;
|
||||
Point2I mCellSize;
|
||||
Point2I mSelectedCell;
|
||||
Point2I mMouseOverCell;
|
||||
|
||||
Resource<GFont> mFont;
|
||||
|
||||
bool cellSelected(Point2I cell);
|
||||
virtual void onCellSelected(Point2I cell);
|
||||
public:
|
||||
|
||||
GuiArrayCtrl();
|
||||
DECLARE_CONOBJECT(GuiArrayCtrl);
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
//array attribute methods
|
||||
Point2I getSize() { return mSize; }
|
||||
virtual void setSize(Point2I size);
|
||||
void setHeaderDim(const Point2I &dim) { mHeaderDim = dim; }
|
||||
void getScrollDimensions(S32 &cell_size, S32 &num_cells);
|
||||
|
||||
//selected cell methods
|
||||
void setSelectedCell(Point2I cell);
|
||||
void deselectCells() { mSelectedCell.set(-1,-1); }
|
||||
Point2I getSelectedCell();
|
||||
void scrollSelectionVisible();
|
||||
void scrollCellVisible(Point2I cell);
|
||||
void scrollSelectionTop();
|
||||
void scrollSelectionBottom();
|
||||
void scrollCellTop(Point2I cell);
|
||||
void scrollCellBottom(Point2I cell);
|
||||
|
||||
//rendering methods
|
||||
virtual void onRenderColumnHeaders(Point2I offset, Point2I parentOffset, Point2I headerDim);
|
||||
virtual void onRenderRowHeader(Point2I offset, Point2I parentOffset, Point2I headerDim, Point2I cell);
|
||||
virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
|
||||
//void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
|
||||
//mouse input methods
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseEnter(const GuiEvent &event);
|
||||
void onMouseLeave(const GuiEvent &event);
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onRightMouseDown(const GuiEvent &event);
|
||||
|
||||
};
|
||||
|
||||
#endif //_GUI_ARRAY_CTRL_H
|
||||
1387
gui/guiAviBitmapCtrl.cc
Normal file
1387
gui/guiAviBitmapCtrl.cc
Normal file
File diff suppressed because it is too large
Load diff
190
gui/guiAviBitmapCtrl.h
Normal file
190
gui/guiAviBitmapCtrl.h
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIAVIBITMAPCTRL_H_
|
||||
#define _GUIAVIBITMAPCTRL_H_
|
||||
|
||||
#if !ENABLE_AVI_GUI && !ENABLE_MPG_GUI
|
||||
|
||||
class GuiAviBitmapCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
bool mDone;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiAviBitmapCtrl);
|
||||
GuiAviBitmapCtrl();
|
||||
~GuiAviBitmapCtrl();
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
#endif /* No movie control */
|
||||
|
||||
|
||||
#if ENABLE_AVI_GUI
|
||||
|
||||
class GuiAviBitmapCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mAviFilename;
|
||||
StringTableEntry mWavFilename;
|
||||
U32 mNumTextures;
|
||||
TextureHandle *mTextureHandles;
|
||||
U32 mWidthCount;
|
||||
U32 mHeightCount;
|
||||
U32 mBitmapWidth;
|
||||
U32 mBitmapAlignedWidth;
|
||||
U32 mBitmapHeight;
|
||||
|
||||
PAVIFILE mPFile;
|
||||
PAVISTREAM mPAviVideo; // video stream to play
|
||||
|
||||
AUDIOHANDLE mWavHandle; // music to play along with it
|
||||
|
||||
bool mBPlaying;
|
||||
bool mDone;
|
||||
bool mLetterBox;
|
||||
F32 mFrate;
|
||||
F32 mSpeed;
|
||||
S32 mTimePlayStart;
|
||||
S32 mTimePlayStartPos;
|
||||
S16 mPlayFPrev;
|
||||
S16 mPlayFSkipped;
|
||||
S32 mVidsCurrent; // attempted frame to draw
|
||||
S32 mVidsPrevious; // last successfully decoded frame
|
||||
S32 mVidsPrevKey, mVidsNextKey;
|
||||
S32 mVidsFirst, mVidsLast;
|
||||
S32 mCBVBuf;
|
||||
U8 *mPVBuf;
|
||||
|
||||
HIC mHic;
|
||||
FOURCC mFccHandler;
|
||||
BITMAPINFOHEADER *mPBiSrc;
|
||||
BITMAPINFOHEADER *mPBiDst;
|
||||
S32 mCBuf;
|
||||
U8 *mPBuf;
|
||||
bool mSwapRB;
|
||||
ALint mAudioLatency;
|
||||
|
||||
S32 fileOpen();
|
||||
S32 fileClose();
|
||||
S32 movieOpen();
|
||||
S32 movieClose();
|
||||
S32 vidsVideoOpen();
|
||||
S32 vidsVideoClose();
|
||||
S32 vidsVideoStart();
|
||||
S32 vidsVideoStop();
|
||||
S32 vidsVideoDraw();
|
||||
S32 vidsTimeToSample(S32 lTime);
|
||||
bool vidsIsKey(S32 frame = -1);
|
||||
void vidsResetDraw() { mVidsPrevious = -1; }
|
||||
bool vidsSync();
|
||||
void vidsCatchup();
|
||||
S32 vcmOpen(FOURCC fccHandler, BITMAPINFOHEADER *pbiSrc);
|
||||
S32 vcmClose();
|
||||
S32 vcmBegin();
|
||||
S32 vcmEnd();
|
||||
S32 vcmDrawStart();
|
||||
S32 vcmDrawStop();
|
||||
S32 vcmDraw(U64 dwICflags = 0);
|
||||
S32 vcmDrawIn(U64 dwICflags = 0);
|
||||
bool sndOpen();
|
||||
void sndStart();
|
||||
void sndStop();
|
||||
S32 getMilliseconds();
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiAviBitmapCtrl);
|
||||
|
||||
GuiAviBitmapCtrl();
|
||||
~GuiAviBitmapCtrl();
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
void setFilename(const char *filename);
|
||||
S32 movieStart();
|
||||
S32 movieStop();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
void onMouseDown(const GuiEvent&);
|
||||
bool onKeyDown(const GuiEvent&);
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif /* ENABLE_AVI_GUI */
|
||||
|
||||
#if ENABLE_MPG_GUI
|
||||
|
||||
class GuiAviBitmapCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mAviFilename;
|
||||
StringTableEntry mWavFilename;
|
||||
U32 mNumTextures;
|
||||
TextureHandle *mTextureHandles;
|
||||
U32 mWidthCount;
|
||||
U32 mHeightCount;
|
||||
U32 mBitmapWidth;
|
||||
U32 mBitmapAlignedWidth;
|
||||
U32 mBitmapHeight;
|
||||
|
||||
SDL_Surface *mSurface;
|
||||
U8 *mPBuf;
|
||||
SDL_mutex *mDecodeLock;
|
||||
ALint mAudioLatency;
|
||||
|
||||
SMPEG *mMPEG; // video stream to play
|
||||
|
||||
AUDIOHANDLE mWavHandle; // music to play along with it
|
||||
|
||||
bool mBPlaying;
|
||||
bool mDone;
|
||||
bool mLetterBox;
|
||||
SMPEG_Info mInfo;
|
||||
|
||||
S32 fileOpen();
|
||||
S32 fileClose();
|
||||
S32 movieOpen();
|
||||
S32 movieClose();
|
||||
bool sndOpen();
|
||||
void sndStart();
|
||||
void sndStop();
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiAviBitmapCtrl);
|
||||
|
||||
GuiAviBitmapCtrl();
|
||||
~GuiAviBitmapCtrl();
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
void setFilename(const char *filename);
|
||||
S32 movieStart();
|
||||
S32 movieStop();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
void onMouseDown(const GuiEvent&);
|
||||
bool onKeyDown(const GuiEvent&);
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif /* ENABLE_MPG_GUI */
|
||||
|
||||
#endif /* _GUIAVIBITMAPCTRL_H_ */
|
||||
26
gui/guiBackgroundCtrl.cc
Normal file
26
gui/guiBackgroundCtrl.cc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "gui/guiBackgroundCtrl.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiBackgroundCtrl::GuiBackgroundCtrl() : GuiControl()
|
||||
{
|
||||
mDraw = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiBackgroundCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
if ( mDraw )
|
||||
Parent::onRender( offset, updateRect, firstResponder );
|
||||
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
|
||||
30
gui/guiBackgroundCtrl.h
Normal file
30
gui/guiBackgroundCtrl.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIBACKGROUNDCTRL_H_
|
||||
#define _GUIBACKGROUNDCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiBackgroundCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
public:
|
||||
bool mDraw;
|
||||
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiBackgroundCtrl);
|
||||
GuiBackgroundCtrl();
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif
|
||||
120
gui/guiBitmapBorderCtrl.cc
Normal file
120
gui/guiBitmapBorderCtrl.cc
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2002 GarageGames.Com
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/guiControl.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
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);
|
||||
}
|
||||
148
gui/guiBitmapCtrl.cc
Normal file
148
gui/guiBitmapCtrl.cc
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
#include "GUI/guiBitmapCtrl.h"
|
||||
|
||||
|
||||
|
||||
GuiBitmapCtrl::GuiBitmapCtrl(void)
|
||||
{
|
||||
mBitmapName = StringTable->insert("");
|
||||
startPoint.set(0, 0);
|
||||
mWrap = false;
|
||||
}
|
||||
|
||||
|
||||
void GuiBitmapCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("bitmap", TypeString, Offset(mBitmapName, GuiBitmapCtrl));
|
||||
addField("wrap", TypeBool, Offset(mWrap, GuiBitmapCtrl));
|
||||
}
|
||||
|
||||
static void cBitmapSetValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiBitmapCtrl *ctrl = static_cast<GuiBitmapCtrl*>(obj);
|
||||
ctrl->setValue(dAtoi(argv[2]), dAtoi(argv[3]));
|
||||
}
|
||||
|
||||
static void cBitmapSetBitmap(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiBitmapCtrl *ctrl = static_cast<GuiBitmapCtrl*>(obj);
|
||||
ctrl->setBitmap(argv[2]);
|
||||
}
|
||||
|
||||
void GuiBitmapCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiBitmapCtrl", "setBitmap", cBitmapSetBitmap, "guiBitmapCtrl.setBitmap(blah)", 3, 3);
|
||||
Con::addCommand("GuiBitmapCtrl", "setValue", cBitmapSetValue, "guiBitmapCtrl.setValue(xAxis, yAxis)", 4, 4);
|
||||
}
|
||||
|
||||
|
||||
bool GuiBitmapCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
setActive(true);
|
||||
setBitmap(mBitmapName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiBitmapCtrl::onSleep()
|
||||
{
|
||||
mTextureHandle = NULL;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
void GuiBitmapCtrl::setBitmap(const char *name)
|
||||
{
|
||||
mBitmapName = StringTable->insert(name);
|
||||
if (*mBitmapName)
|
||||
mTextureHandle = TextureHandle(mBitmapName, BitmapTexture, true);
|
||||
else
|
||||
mTextureHandle = NULL;
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
|
||||
void GuiBitmapCtrl::setBitmap(const TextureHandle &handle)
|
||||
{
|
||||
mTextureHandle = handle;
|
||||
}
|
||||
|
||||
|
||||
void GuiBitmapCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
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);
|
||||
// RectI rect = mBounds;
|
||||
// rect.point += offset;
|
||||
dglDrawBitmapStretch(mTextureHandle, rect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RectI rect = mBounds;
|
||||
rect.point += offset;
|
||||
|
||||
glColor4f(0, 0, 0, 1);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(rect.point.x, rect.point.y);
|
||||
glVertex2i(rect.point.x + rect.extent.x - 1, rect.point.y);
|
||||
glVertex2i(rect.point.x + rect.extent.x - 1, rect.point.y + rect.extent.y - 1);
|
||||
glVertex2i(rect.point.x, rect.point.y + rect.extent.y - 1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
50
gui/guiBitmapCtrl.h
Normal file
50
gui/guiBitmapCtrl.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIBITMAPCTRL_H_
|
||||
#define _GUIBITMAPCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
|
||||
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();
|
||||
static void consoleInit();
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setBitmap(const char *name);
|
||||
void setBitmap(const TextureHandle &handle);
|
||||
|
||||
S32 getWidth() const { return(mTextureHandle.getWidth()); }
|
||||
S32 getHeight() const { return(mTextureHandle.getHeight()); }
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void setValue(S32 x, S32 y);
|
||||
};
|
||||
|
||||
#endif
|
||||
42
gui/guiBorderButton.cc
Normal file
42
gui/guiBorderButton.cc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "gui/guiCanvas.h"
|
||||
#include "gui/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);
|
||||
}
|
||||
|
||||
73
gui/guiBubbleTextCtrl.cc
Normal file
73
gui/guiBubbleTextCtrl.cc
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiBubbleTextCtrl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiBubbleTextCtrl);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiBubbleTextCtrl::popBubble()
|
||||
{
|
||||
// Release the mouse:
|
||||
mInAction = false;
|
||||
mouseUnlock();
|
||||
|
||||
// Pop the dialog
|
||||
getRoot()->popDialogControl(mDlg);
|
||||
|
||||
// Kill the popup
|
||||
mDlg->removeObject(mPopup);
|
||||
mPopup->removeObject(mMLText);
|
||||
mMLText->deleteObject();
|
||||
mPopup->deleteObject();
|
||||
mDlg->deleteObject();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiBubbleTextCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if (mInAction)
|
||||
{
|
||||
popBubble();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mDlg = new GuiControl();
|
||||
AssertFatal(mDlg, "Failed to create the GuiControl for the BubbleTextCtrl");
|
||||
mDlg->setField("profile","GuiModelessDialogProfile");
|
||||
mDlg->setField("horizSizing", "width");
|
||||
mDlg->setField("vertSizing", "height");
|
||||
mDlg->setField("extent", "640 480");
|
||||
|
||||
mPopup = new GuiControl();
|
||||
AssertFatal(mPopup, "Failed to create the GuiControl for the BubbleTextCtrl");
|
||||
mPopup->setField("profile","GuiBubblePopupProfile");
|
||||
|
||||
mMLText = new GuiMLTextCtrl();
|
||||
AssertFatal(mMLText, "Failed to create the GuiMLTextCtrl for the BubbleTextCtrl");
|
||||
mMLText->setField("profile","GuiBubbleTextProfile");
|
||||
mMLText->setField("position", "2 2");
|
||||
mMLText->setField("extent", "296 51");
|
||||
|
||||
mMLText->setText(mText,dStrlen(mText));
|
||||
|
||||
mMLText->registerObject();
|
||||
mPopup->registerObject();
|
||||
mDlg->registerObject();
|
||||
|
||||
mPopup->addObject(mMLText);
|
||||
mDlg->addObject(mPopup);
|
||||
|
||||
mPopup->resize(event.mousePoint,Point2I(300,55));
|
||||
|
||||
getRoot()->pushDialogControl(mDlg,0);
|
||||
mouseLock();
|
||||
|
||||
mInAction = true;
|
||||
}
|
||||
39
gui/guiBubbleTextCtrl.h
Normal file
39
gui/guiBubbleTextCtrl.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIBUBBLETEXTCTRL_H_
|
||||
#define _GUIBUBBLETEXTCTRL_H_
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUIMLTEXTCTRL_H_
|
||||
#include "GUI/guiMLTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiBubbleTextCtrl : public GuiTextCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
protected:
|
||||
bool mInAction;
|
||||
GuiControl *mDlg;
|
||||
GuiControl *mPopup;
|
||||
GuiMLTextCtrl *mMLText;
|
||||
|
||||
void popBubble();
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiBubbleTextCtrl);
|
||||
|
||||
GuiBubbleTextCtrl() { mInAction = false; }
|
||||
|
||||
virtual void onMouseDown(const GuiEvent &event);
|
||||
};
|
||||
|
||||
#endif /* _GUI_BUBBLE_TEXT_CONTROL_H_ */
|
||||
189
gui/guiButtonBaseCtrl.cc
Normal file
189
gui/guiButtonBaseCtrl.cc
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "platform/platformAudio.h"
|
||||
#include "gui/guiCanvas.h"
|
||||
#include "gui/guiButtonBaseCtrl.h"
|
||||
|
||||
GuiButtonBaseCtrl::GuiButtonBaseCtrl()
|
||||
{
|
||||
mDepressed = false;
|
||||
mMouseOver = false;
|
||||
mActive = true;
|
||||
mButtonText = StringTable->insert("");
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiButtonBaseCtrl, setText, void, 3, 3, "(string text) - sets the text of the button to the string." )
|
||||
{
|
||||
argc;
|
||||
GuiButtonBaseCtrl* ctrl = static_cast<GuiButtonBaseCtrl*>( object );
|
||||
ctrl->setText( argv[2] );
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiButtonBaseCtrl, getText, const char *, 2, 2, "() - returns the text of the button." )
|
||||
{
|
||||
argc; argv;
|
||||
GuiButtonBaseCtrl* ctrl = static_cast<GuiButtonBaseCtrl*>( object );
|
||||
return ctrl->getText( );
|
||||
}
|
||||
|
||||
void GuiButtonBaseCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("text", TypeCaseString, Offset(mButtonText, GuiButtonBaseCtrl));
|
||||
}
|
||||
|
||||
void GuiButtonBaseCtrl::setText(const char *text)
|
||||
{
|
||||
mButtonText = StringTable->insert(text);
|
||||
}
|
||||
|
||||
const char *GuiButtonBaseCtrl::getText()
|
||||
{
|
||||
return mButtonText;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiButtonBaseCtrl::AcceleratorKeyPress(void)
|
||||
{
|
||||
if (! mActive)
|
||||
return;
|
||||
|
||||
//set the bool
|
||||
mDepressed = true;
|
||||
|
||||
if (mProfile->mTabable)
|
||||
setFirstResponder();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiButtonBaseCtrl::AcceleratorKeyRelease(void)
|
||||
{
|
||||
if (! mActive)
|
||||
return;
|
||||
|
||||
//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 ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
|
||||
&& event.modifier == 0)
|
||||
{
|
||||
onAction();
|
||||
return true;
|
||||
}
|
||||
//otherwise, pass the event to it's parent
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
|
||||
42
gui/guiButtonBaseCtrl.h
Normal file
42
gui/guiButtonBaseCtrl.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIBUTTONBASECTRL_H_
|
||||
#define _GUIBUTTONBASECTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiButtonBaseCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mButtonText;
|
||||
bool mDepressed;
|
||||
bool mMouseOver;
|
||||
public:
|
||||
GuiButtonBaseCtrl();
|
||||
static void initPersistFields();
|
||||
|
||||
void setText(const char *text);
|
||||
const char *getText();
|
||||
|
||||
void AcceleratorKeyPress();
|
||||
void AcceleratorKeyRelease();
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
#endif
|
||||
262
gui/guiButtonCtrl.cc
Normal file
262
gui/guiButtonCtrl.cc
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "Platform/platformAudio.h"
|
||||
#include "audio/audioDataBlock.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiButtonCtrl.h"
|
||||
|
||||
GuiButtonCtrl::GuiButtonCtrl()
|
||||
{
|
||||
mActive = true;
|
||||
mBounds.extent.set(140, 30);
|
||||
mButtonText = 0;
|
||||
mButtonState = Normal;
|
||||
mMouseInControl = false;
|
||||
}
|
||||
|
||||
void GuiButtonCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiButtonCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("text", TypeCaseString, Offset(mButtonText, GuiButtonCtrl));
|
||||
}
|
||||
|
||||
const char * GuiButtonCtrl::getScriptValue()
|
||||
{
|
||||
return(mButtonText);
|
||||
}
|
||||
|
||||
void GuiButtonCtrl::setScriptValue(const char * value)
|
||||
{
|
||||
mButtonText = StringTable->insert(value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::AcceleratorKeyPress(void)
|
||||
{
|
||||
if ((! mVisible) || (! mActive) || (! mAwake))
|
||||
return;
|
||||
|
||||
onAction();
|
||||
setFirstResponder();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiButtonCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if the control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake))
|
||||
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 );
|
||||
alxSourcef( handle, AL_PAN, pan );
|
||||
alxPlay( handle );
|
||||
}
|
||||
|
||||
onAction();
|
||||
return true;
|
||||
}
|
||||
|
||||
//otherwise, pass the event to it's parent
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
// Are we answering the phone?
|
||||
if (!mVisible || !mActive || !mAwake)
|
||||
return;
|
||||
|
||||
// Ok, this is a bona-fide real click. Check our preconditions
|
||||
AssertFatal(mButtonState == Normal, "Error, we should never reach this state!");
|
||||
|
||||
setFirstResponder();
|
||||
mButtonState = MouseDown;
|
||||
getRoot()->mouseLock(this);
|
||||
|
||||
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);
|
||||
alxSourcef(handle, AL_PAN, pan);
|
||||
alxPlay(handle);
|
||||
//alxPlay(mProfile->mSoundButtonDown, NULL, NULL);
|
||||
//Audio::play2D(mProfile->mSoundButtonDown->getName(), mProfile->mSoundButtonDown->getDescription(), pan);
|
||||
}
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::onMouseUp(const GuiEvent&)
|
||||
{
|
||||
GuiCanvas* root = getRoot();
|
||||
if (mButtonState == Normal) {
|
||||
AssertFatal(root->getMouseLockedControl() != this, "Error, we should not have the mouse locked here!");
|
||||
return;
|
||||
}
|
||||
|
||||
mButtonState = Normal;
|
||||
setUpdate();
|
||||
|
||||
root->mouseUnlock(this);
|
||||
if (cursorInControl())
|
||||
onAction();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::onMouseEnter(const GuiEvent& event)
|
||||
{
|
||||
mMouseInControl = true;
|
||||
|
||||
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);
|
||||
alxSourcef(handle, AL_PAN, pan);
|
||||
alxPlay(handle);
|
||||
|
||||
//alxPlay(mProfile->mSoundButtonOver, NULL, NULL);
|
||||
//Audio::play2D(mProfile->mSoundButtonOver->getName(), mProfile->mSoundButtonOver->getDescription(), pan);
|
||||
}
|
||||
|
||||
Parent::onMouseEnter( event );
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::onMouseLeave(const GuiEvent& event)
|
||||
{
|
||||
mMouseInControl = false;
|
||||
Parent::onMouseLeave(event);
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::onSleep()
|
||||
{
|
||||
mMouseInControl = false;
|
||||
mButtonState = Normal;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiButtonCtrl::onRender(Point2I offset,
|
||||
const RectI& updateRect,
|
||||
GuiControl* firstResponder)
|
||||
{
|
||||
bool highlight = false;
|
||||
bool depressed = false;
|
||||
|
||||
if ( mActive )
|
||||
{
|
||||
if ( mButtonState == MouseDown )
|
||||
{
|
||||
highlight = true;
|
||||
depressed = cursorInControl();
|
||||
}
|
||||
else
|
||||
highlight = mMouseInControl;
|
||||
}
|
||||
|
||||
ColorI fontColor = mActive ? (highlight ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA;
|
||||
ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA;
|
||||
ColorI borderColor = mActive ? mProfile->mBorderColor : mProfile->mBorderColorNA;
|
||||
|
||||
#if 1
|
||||
// first draw the background
|
||||
Point2I extent( offset.x+mBounds.extent.x-1, offset.y+mBounds.extent.y-1);
|
||||
if ( mProfile->mOpaque )
|
||||
{
|
||||
if (depressed)
|
||||
renderLoweredBox(offset, extent, backColor);
|
||||
else
|
||||
renderRaisedBox(offset, extent, backColor);
|
||||
}
|
||||
else
|
||||
if ( mProfile->mBorder )
|
||||
dglDrawRect( offset, Point2I(extent.x+1, extent.y+1), backColor );
|
||||
|
||||
#else
|
||||
// first draw the background
|
||||
RectI r( offset, mBounds.extent );
|
||||
if ( mProfile->mOpaque )
|
||||
dglDrawRectFill( r, backColor );
|
||||
|
||||
if ( mProfile->mBorder )
|
||||
{
|
||||
dglDrawRect( r, borderColor );
|
||||
|
||||
if ( mActive && firstResponder == this )
|
||||
{
|
||||
r.point += Point2I(1, 1);
|
||||
r.extent -= Point2I(2, 2);
|
||||
dglDrawRect( r, mProfile->mBorderColorHL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// finally draw the text
|
||||
if ( mButtonText && mButtonText[0] != NULL )
|
||||
{
|
||||
S32 txt_w = mProfile->mFont->getStrWidth( mButtonText );
|
||||
Point2I localStart;
|
||||
|
||||
// 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 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// center the vertical
|
||||
localStart.y = ( mBounds.extent.y - ( mProfile->mFont->getHeight() - 2 ) ) / 2;
|
||||
|
||||
localStart.y -= 2;
|
||||
if ( depressed )
|
||||
{
|
||||
localStart.x += 1;
|
||||
localStart.y += 1;
|
||||
}
|
||||
Point2I globalStart = localToGlobalCoord( localStart );
|
||||
|
||||
dglSetBitmapModulation( fontColor );
|
||||
dglDrawText(mProfile->mFont, globalStart, mButtonText, mProfile->mFontColors);
|
||||
|
||||
//render the children
|
||||
renderChildControls( offset, updateRect, firstResponder );
|
||||
}
|
||||
}
|
||||
|
||||
54
gui/guiButtonCtrl.h
Normal file
54
gui/guiButtonCtrl.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIBUTTONCTRL_H_
|
||||
#define _GUIBUTTONCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiButtonCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
enum State {
|
||||
Normal,
|
||||
MouseDown
|
||||
};
|
||||
|
||||
bool mMouseInControl;
|
||||
State mButtonState;
|
||||
StringTableEntry mButtonText;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiButtonCtrl);
|
||||
GuiButtonCtrl();
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
void AcceleratorKeyPress(void);
|
||||
|
||||
bool onKeyDown(const GuiEvent&);
|
||||
|
||||
void onMouseUp(const GuiEvent&);
|
||||
void onMouseDown(const GuiEvent&);
|
||||
void onMouseEnter(const GuiEvent&);
|
||||
void onMouseLeave(const GuiEvent&);
|
||||
|
||||
const char * getScriptValue();
|
||||
void setScriptValue(const char *);
|
||||
|
||||
void onSleep();
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void drawBorder(const RectI &r, const ColorI &color);
|
||||
};
|
||||
|
||||
#endif //_GUI_BUTTON_CTRL_H
|
||||
1260
gui/guiCanvas.cc
Normal file
1260
gui/guiCanvas.cc
Normal file
File diff suppressed because it is too large
Load diff
147
gui/guiCanvas.h
Normal file
147
gui/guiCanvas.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICANVAS_H_
|
||||
#define _GUICANVAS_H_
|
||||
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "Platform/event.h"
|
||||
#endif
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiCanvas : public GuiControl
|
||||
{
|
||||
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
typedef SimObject Grandparent;
|
||||
|
||||
//Rendering members
|
||||
RectI mOldUpdateRects[2];
|
||||
RectI mCurUpdateRect;
|
||||
F32 rLastFrameTime;
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
//Mouse members
|
||||
F32 mPixelsPerMickey;
|
||||
bool cursorON;
|
||||
bool mShowCursor;
|
||||
bool mRenderFront;
|
||||
Point2F cursorPt;
|
||||
Point2I lastCursorPt;
|
||||
GuiCursor *defaultCursor;
|
||||
GuiCursor *lastCursor;
|
||||
bool lastCursorON;
|
||||
|
||||
//Input Members - mouse
|
||||
SimObjectPtr<GuiControl> mMouseCapturedControl; // All mouse events will go to this ctrl only
|
||||
SimObjectPtr<GuiControl> mMouseControl; // the control the mouse was last seen in unless some other on captured it
|
||||
bool mMouseControlClicked; // whether the current ctrl has been clicked - used by helpctrl
|
||||
U32 mPrevMouseTime; // this determines how long the mouse has been in the same control
|
||||
U32 mNextMouseTime; // used for onMouseRepeat()
|
||||
U32 mInitialMouseDelay; // also used for onMouseRepeat()
|
||||
bool mMouseButtonDown; // bool to determine if the button is depressed
|
||||
bool mMouseRightButtonDown; // bool to determine if the right button is depressed
|
||||
GuiEvent mLastMouseEvent;
|
||||
|
||||
//Input Members - keyboard
|
||||
GuiControl *keyboardControl; // All keyboard events will go to this ctrl first
|
||||
U32 nextKeyTime;
|
||||
//GuiEvent lastKeyEvent;
|
||||
|
||||
U8 mLastMouseClickCount;
|
||||
S32 mLastMouseDownTime;
|
||||
bool mLeftMouseLast;
|
||||
|
||||
//accelerator key map
|
||||
struct AccKeyMap
|
||||
{
|
||||
GuiControl *ctrl;
|
||||
U32 keyCode;
|
||||
U32 modifier;
|
||||
};
|
||||
Vector <AccKeyMap> mAcceleratorMap;
|
||||
void findMouseControl(const GuiEvent &event);
|
||||
void refreshMouseControl();
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiCanvas);
|
||||
GuiCanvas();
|
||||
~GuiCanvas();
|
||||
static void consoleInit();
|
||||
|
||||
//Rendering methods
|
||||
void renderFrame(bool preRenderOnly); //called ever cycle to repaint the updateRects
|
||||
void paint(); //causes the entire canvas to be repainted
|
||||
void addUpdateRegion(Point2I pos, Point2I ext);
|
||||
void resetUpdateRegions();
|
||||
void buildUpdateUnion(RectI *updateUnion);
|
||||
|
||||
//Control content methods
|
||||
void setContentControl(GuiControl *gui);
|
||||
GuiControl *getContentControl();
|
||||
|
||||
void pushDialogControl(GuiControl *gui, S32 layer = 0);
|
||||
void popDialogControl(S32 layer = 0);
|
||||
void popDialogControl(GuiControl *gui);
|
||||
|
||||
// general cursor commands
|
||||
void setCursor(GuiCursor *curs) { defaultCursor = curs; }
|
||||
void setRenderFront(bool front) { mRenderFront = front; }
|
||||
bool isCursorON() {return cursorON; }
|
||||
void setCursorON(bool onOff);
|
||||
void setCursorPos(const Point2I &pt) { cursorPt.x = F32(pt.x); cursorPt.y = F32(pt.y); }
|
||||
Point2I getCursorPos() { return Point2I(S32(cursorPt.x), S32(cursorPt.y)); }
|
||||
void showCursor(bool state) { mShowCursor = state; }
|
||||
bool isCursorShown() { return(mShowCursor); }
|
||||
|
||||
//all input events come through the canvas
|
||||
bool processInputEvent(const InputEvent *event);
|
||||
void processMouseMoveEvent(const MouseMoveEvent *event);
|
||||
|
||||
//mouse methods
|
||||
void mouseLock(GuiControl *lockingControl);
|
||||
void mouseUnlock(GuiControl *lockingControl);
|
||||
GuiControl* getMouseControl() { return mMouseControl; }
|
||||
GuiControl* getMouseLockedControl() { return mMouseCapturedControl; }
|
||||
bool mouseButtonDown(void) { return mMouseButtonDown; }
|
||||
bool mouseRightButtonDown(void) { return mMouseRightButtonDown; }
|
||||
|
||||
//Mouse input methods
|
||||
void rootMouseUp(const GuiEvent &event);
|
||||
void rootMouseDown(const GuiEvent &event);
|
||||
void rootMouseMove(const GuiEvent &event);
|
||||
void rootMouseDragged(const GuiEvent &event);
|
||||
|
||||
void rootRightMouseDown(const GuiEvent &event);
|
||||
void rootRightMouseUp(const GuiEvent &event);
|
||||
void rootRightMouseDragged(const GuiEvent &event);
|
||||
|
||||
void rootMouseWheelUp(const GuiEvent &event);
|
||||
void rootMouseWheelDown(const GuiEvent &event);
|
||||
|
||||
//Keyboard input methods
|
||||
void tabNext(void);
|
||||
void tabPrev(void);
|
||||
void AddAcceleratorKey(GuiControl *ctrl, U32 keyCode, U32 modifier);
|
||||
|
||||
void setFirstResponder(GuiControl *firstResponder);
|
||||
|
||||
//deleted? possibly
|
||||
//DWORD onMessage(SimObject *sender, DWORD msg); // root handles IDGUI and IDCMD messages
|
||||
};
|
||||
|
||||
extern GuiCanvas *Canvas;
|
||||
|
||||
#endif
|
||||
300
gui/guiChannelVectorCtrl.cc
Normal file
300
gui/guiChannelVectorCtrl.cc
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiChannelVectorCtrl.h"
|
||||
#include "GUI/channelVector.h"
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiChannelVectorCtrl);
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiChannelVectorCtrl::lineInserted(const U32 arg)
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
|
||||
GuiScrollCtrl* pScroll = NULL;
|
||||
GuiControl* pParent = getParent();
|
||||
if (pParent) {
|
||||
GuiControl* pGrandParent = pParent->getParent();
|
||||
if (pGrandParent)
|
||||
pScroll = dynamic_cast<GuiScrollCtrl*>(pGrandParent);
|
||||
}
|
||||
|
||||
bool scrollToBottom = false;
|
||||
if (pScroll != NULL)
|
||||
scrollToBottom = pScroll->getCurrVPos() == 1.0;
|
||||
|
||||
mSpecialMarkers.insert(arg);
|
||||
createSpecialMarkers(mSpecialMarkers[arg], mMessageVector->getLine(arg).message);
|
||||
|
||||
const ChannelVector::SpecialMarkers &tags = ((ChannelVector *) mMessageVector)->getLineTags(arg);
|
||||
|
||||
if (tags.numSpecials)
|
||||
{
|
||||
U32 n = mSpecialMarkers[arg].numSpecials+tags.numSpecials;
|
||||
SpecialMarkers::Special *s = new SpecialMarkers::Special[n];
|
||||
|
||||
for (U32 i = 0, j = 0, k = 0; k < n; ++k)
|
||||
{
|
||||
if (i < mSpecialMarkers[arg].numSpecials &&
|
||||
(j == tags.numSpecials ||
|
||||
mSpecialMarkers[arg].specials[i].start <= tags.specials[j].start))
|
||||
s[k] = mSpecialMarkers[arg].specials[i++];
|
||||
else
|
||||
{
|
||||
s[k].specialType = tags.specials[j].specialType;
|
||||
s[k].start = tags.specials[j].start;
|
||||
s[k].end = tags.specials[j].end;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
mSpecialMarkers[arg].numSpecials = n;
|
||||
delete [] mSpecialMarkers[arg].specials;
|
||||
mSpecialMarkers[arg].specials = s;
|
||||
}
|
||||
|
||||
mLineWrappings.insert(arg);
|
||||
createLineWrapping(mLineWrappings[arg], mMessageVector->getLine(arg).message);
|
||||
|
||||
mLineElements.insert(arg);
|
||||
createLineElement(mLineElements[arg], mLineWrappings[arg], mSpecialMarkers[arg]);
|
||||
|
||||
U32 numLines = 0;
|
||||
for (U32 i = 0; i < mLineWrappings.size(); i++) {
|
||||
// We need to rebuild the physicalLineStart markers at the same time as
|
||||
// we find out how many of them are left...
|
||||
mLineElements[i].physicalLineStart = numLines;
|
||||
|
||||
numLines += mLineWrappings[i].numLines;
|
||||
}
|
||||
|
||||
U32 newHeight = (mProfile->mFont->getHeight() + mLineSpacingPixels) * getMax(numLines, U32(1));
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, newHeight));
|
||||
|
||||
if (arg == mSpecialMarkers.size() - 1 && scrollToBottom == true)
|
||||
pScroll->scrollTo(0, 1);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiChannelVectorCtrl::onRender(Point2I offset,
|
||||
const RectI& updateRect,
|
||||
GuiControl*fr)
|
||||
{
|
||||
GuiControl::onRender(offset, updateRect,fr);
|
||||
if (isAttached()) {
|
||||
U32 linePixels = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
U32 currLine = 0;
|
||||
for (U32 i = 0; i < mMessageVector->getNumLines(); i++) {
|
||||
|
||||
TextElement* pElement = mLineElements[i].headLineElements;
|
||||
ColorI lastColor = mProfile->mFontColor;
|
||||
|
||||
dglSetBitmapModulation(lastColor);
|
||||
while (pElement != NULL) {
|
||||
Point2I localStart(pElement == mLineElements[i].headLineElements ? 0 : mLineContinuationIndent, currLine * linePixels);
|
||||
|
||||
Point2I globalCheck = localToGlobalCoord(localStart);
|
||||
U32 globalRangeStart = globalCheck.y;
|
||||
U32 globalRangeEnd = globalCheck.y + mProfile->mFont->getHeight();
|
||||
if (globalRangeStart > updateRect.point.y + updateRect.extent.y ||
|
||||
globalRangeEnd < updateRect.point.y) {
|
||||
currLine++;
|
||||
pElement = pElement->nextPhysicalLine;
|
||||
continue;
|
||||
}
|
||||
|
||||
TextElement* walkAcross = pElement;
|
||||
while (walkAcross) {
|
||||
if (walkAcross->start > walkAcross->end)
|
||||
break;
|
||||
|
||||
Point2I globalStart = localToGlobalCoord(localStart);
|
||||
|
||||
U32 strWidth;
|
||||
if (walkAcross->specialReference == -1) {
|
||||
dglSetBitmapModulation(lastColor);
|
||||
dglSetTextAnchorColor(mProfile->mFontColor);
|
||||
strWidth = dglDrawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
||||
walkAcross->end - walkAcross->start + 1, mProfile->mFontColors);
|
||||
dglGetBitmapModulation(&lastColor);
|
||||
} else {
|
||||
SpecialMarkers::Special &s = mSpecialMarkers[i].specials[walkAcross->specialReference];
|
||||
|
||||
dglGetBitmapModulation(&lastColor);
|
||||
if (s.specialType >= 0)
|
||||
dglSetBitmapModulation(mSpecialColor);
|
||||
else
|
||||
{
|
||||
U32 colorIndex;
|
||||
|
||||
switch(s.specialType)
|
||||
{
|
||||
case ChannelVector::NickTag:
|
||||
colorIndex = NickColor;
|
||||
|
||||
break;
|
||||
case ChannelVector::TribeTag:
|
||||
colorIndex = TribeColor;
|
||||
|
||||
break;
|
||||
case ChannelVector::ServerTag:
|
||||
colorIndex = ServerColor;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dglSetBitmapModulation(mProfile->mFontColors[colorIndex]);
|
||||
}
|
||||
dglSetTextAnchorColor(mProfile->mFontColor);
|
||||
strWidth = dglDrawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
||||
walkAcross->end - walkAcross->start + 1);
|
||||
|
||||
// in case we have 2 in a row...
|
||||
dglSetBitmapModulation(lastColor);
|
||||
}
|
||||
|
||||
if (walkAcross->specialReference != -1) {
|
||||
Point2I lineStart = localStart;
|
||||
Point2I lineEnd = localStart;
|
||||
SpecialMarkers::Special &s = mSpecialMarkers[i].specials[walkAcross->specialReference];
|
||||
|
||||
lineStart.y += mProfile->mFont->getBaseline() + 2;
|
||||
lineEnd.x += strWidth;
|
||||
lineEnd.y += mProfile->mFont->getBaseline() + 2;
|
||||
|
||||
if (s.specialType >= 0)
|
||||
dglDrawLine(localToGlobalCoord(lineStart),
|
||||
localToGlobalCoord(lineEnd),
|
||||
mSpecialColor);
|
||||
else
|
||||
{
|
||||
U32 colorIndex;
|
||||
|
||||
switch(s.specialType)
|
||||
{
|
||||
case ChannelVector::NickTag:
|
||||
colorIndex = NickColor;
|
||||
|
||||
break;
|
||||
case ChannelVector::TribeTag:
|
||||
colorIndex = TribeColor;
|
||||
|
||||
break;
|
||||
case ChannelVector::ServerTag:
|
||||
colorIndex = ServerColor;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dglDrawLine(localToGlobalCoord(lineStart),
|
||||
localToGlobalCoord(lineEnd),
|
||||
mProfile->mFontColors[colorIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
localStart.x += strWidth;
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
}
|
||||
|
||||
currLine++;
|
||||
pElement = pElement->nextPhysicalLine;
|
||||
}
|
||||
}
|
||||
dglClearBitmapModulation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiChannelVectorCtrl::onMouseUp(const GuiEvent& event)
|
||||
{
|
||||
GuiControl::onMouseUp(event);
|
||||
mouseUnlock();
|
||||
|
||||
// Is this an up from a dragged click?
|
||||
if (mMouseDown == false)
|
||||
return;
|
||||
|
||||
// Find the special we are in, if any...
|
||||
|
||||
S32 currSpecialLine;
|
||||
S32 currSpecialRef;
|
||||
findSpecialFromCoord(globalToLocalCoord(event.mousePoint), &currSpecialLine, &currSpecialRef);
|
||||
|
||||
if (currSpecialRef != -1 &&
|
||||
(currSpecialLine == mMouseSpecialLine &&
|
||||
currSpecialRef == mMouseSpecialRef))
|
||||
{
|
||||
// Execute the callback
|
||||
char type[16];
|
||||
const char *content;
|
||||
|
||||
SpecialMarkers& rSpecial = mSpecialMarkers[currSpecialLine];
|
||||
S32 specialStart = rSpecial.specials[currSpecialRef].start;
|
||||
S32 specialEnd = rSpecial.specials[currSpecialRef].end;
|
||||
|
||||
switch (rSpecial.specials[currSpecialRef].specialType)
|
||||
{
|
||||
case ChannelVector::TribeTag:
|
||||
if (currSpecialRef &&
|
||||
rSpecial.specials[currSpecialRef-1].specialType == ChannelVector::NickTag)
|
||||
{
|
||||
--currSpecialRef;
|
||||
specialStart = rSpecial.specials[currSpecialRef].start;
|
||||
specialEnd = rSpecial.specials[currSpecialRef].end;
|
||||
}
|
||||
else
|
||||
{
|
||||
++currSpecialRef;
|
||||
specialStart = rSpecial.specials[currSpecialRef].start;
|
||||
specialEnd = rSpecial.specials[currSpecialRef].end;
|
||||
}
|
||||
case ChannelVector::NickTag:
|
||||
dStrcpy(type,"warrior");
|
||||
content = "";
|
||||
|
||||
break;
|
||||
case ChannelVector::ServerTag:
|
||||
{
|
||||
const ChannelVector::SpecialMarkers &tags = ((ChannelVector *) mMessageVector)->getLineTags(currSpecialLine);
|
||||
|
||||
dStrcpy(type,"server");
|
||||
for (U32 i = 0; i < tags.numSpecials; ++i)
|
||||
if (tags.specials[i].start == specialStart)
|
||||
{
|
||||
content = tags.specials[i].content;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
dStrcpy(type,"http");
|
||||
content = "";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
char* copyURL = new char[specialEnd - specialStart + 2];
|
||||
|
||||
dStrncpy(copyURL, &mMessageVector->getLine(currSpecialLine).message[specialStart], specialEnd - specialStart + 1);
|
||||
copyURL[specialEnd - specialStart + 1] = '\0';
|
||||
|
||||
Con::executef(this, 4, "urlClickCallback", type, copyURL, content);
|
||||
|
||||
delete [] copyURL;
|
||||
}
|
||||
|
||||
mMouseDown = false;
|
||||
mMouseSpecialLine = -1;
|
||||
mMouseSpecialRef = -1;
|
||||
}
|
||||
35
gui/guiChannelVectorCtrl.h
Normal file
35
gui/guiChannelVectorCtrl.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICHANNELVECTORCTRL_H_
|
||||
#define _GUICHANNELVECTORCTRL_H_
|
||||
|
||||
#ifndef _CHANNELVECTOR_H_
|
||||
#include "GUI/channelVector.h"
|
||||
#endif
|
||||
|
||||
class GuiChannelVectorCtrl : public GuiMessageVectorCtrl
|
||||
{
|
||||
typedef GuiMessageVectorCtrl Parent;
|
||||
|
||||
protected:
|
||||
enum {
|
||||
NickColor = 1,
|
||||
TribeColor = 2,
|
||||
ServerColor = 3,
|
||||
};
|
||||
|
||||
virtual void onMouseUp(const GuiEvent &event);
|
||||
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
virtual void lineInserted(const U32);
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiChannelVectorCtrl);
|
||||
};
|
||||
|
||||
#endif // _H_GUICHANNELVECTORCTRL_
|
||||
262
gui/guiChatMenuTreeCtrl.cc
Normal file
262
gui/guiChatMenuTreeCtrl.cc
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiChatMenuTreeCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "Platform/event.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiChatMenuTreeCtrl);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GuiChatMenuTreeCtrl::GuiChatMenuTreeCtrl() : GuiTreeViewCtrl()
|
||||
{
|
||||
mTexRollover = NULL;
|
||||
mTexSelected = NULL;
|
||||
|
||||
// Default colors:
|
||||
mAltFontColor.set( 6, 215, 245 );
|
||||
mAltFontColorHL.set( 6, 215, 245 );
|
||||
mAltFontColorSE.set( 25, 56, 68 );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiChatMenuTreeCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField( "altFontColor", TypeColorI, Offset( mAltFontColor, GuiChatMenuTreeCtrl ) );
|
||||
addField( "altFontColorHL", TypeColorI, Offset( mAltFontColorHL, GuiChatMenuTreeCtrl ) );
|
||||
addField( "altFontColorSE", TypeColorI, Offset( mAltFontColorSE, GuiChatMenuTreeCtrl ) );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiChatMenuTreeCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GuiChatMenuTreeCtrl::onWake()
|
||||
{
|
||||
if ( !Parent::onWake() )
|
||||
return( false );
|
||||
|
||||
// Set the item height to the height of the bitmaps so we know they
|
||||
// will connect up right:
|
||||
mItemHeight = mImageBounds[BmpDunno].extent.y;
|
||||
|
||||
char buf[512];
|
||||
dSprintf( buf, sizeof( buf ), "%s_rol.png", mProfile->mBitmapBase );
|
||||
mTexRollover = TextureHandle( buf, BitmapTexture );
|
||||
dSprintf( buf, sizeof( buf ), "%s_act.png", mProfile->mBitmapBase );
|
||||
mTexSelected = TextureHandle( buf, BitmapTexture );
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiChatMenuTreeCtrl::onSleep()
|
||||
{
|
||||
mTexRollover = NULL;
|
||||
mTexSelected = NULL;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GuiChatMenuTreeCtrl::onKeyDown( const GuiEvent& event )
|
||||
{
|
||||
if ( !mVisible || !mActive || !mAwake )
|
||||
return true;
|
||||
|
||||
if ( !mSelectedItem )
|
||||
return true;
|
||||
|
||||
Item* item = getItem( mSelectedItem );
|
||||
if ( !item )
|
||||
return true;
|
||||
|
||||
if ( event.modifier == 0 )
|
||||
{
|
||||
if ( event.keyCode == KEY_RETURN )
|
||||
{
|
||||
if ( mAltConsoleCommand[0] )
|
||||
Con::evaluate( mAltConsoleCommand );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( event.keyCode == KEY_DELETE )
|
||||
{
|
||||
// Don't delete the root!
|
||||
if ( item->mParent )
|
||||
{
|
||||
removeItem( item->mId );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The Alt key lets you move items around:
|
||||
if ( event.modifier & SI_ALT )
|
||||
{
|
||||
switch ( event.keyCode )
|
||||
{
|
||||
case KEY_UP:
|
||||
if ( item->mPrevious )
|
||||
{
|
||||
moveItemUp( item->mId );
|
||||
buildVisibleTree();
|
||||
}
|
||||
return true;
|
||||
|
||||
case KEY_DOWN:
|
||||
if ( item->mNext )
|
||||
{
|
||||
moveItemUp( item->mNext->mId );
|
||||
buildVisibleTree();
|
||||
}
|
||||
return true;
|
||||
|
||||
case KEY_LEFT:
|
||||
if ( item->mParent )
|
||||
{
|
||||
if ( item->mParent->mParent )
|
||||
{
|
||||
// We're movin'...
|
||||
if ( item->mPrevious )
|
||||
item->mPrevious->mNext = item->mNext;
|
||||
else
|
||||
item->mParent->mChild = item->mNext;
|
||||
|
||||
if ( item->mNext )
|
||||
item->mNext->mPrevious = item->mPrevious;
|
||||
|
||||
// Make the item be its former parent's next sibling:
|
||||
item->mPrevious = item->mParent;
|
||||
item->mNext = item->mParent->mNext;
|
||||
|
||||
if ( item->mNext )
|
||||
item->mNext->mPrevious = item;
|
||||
item->mParent->mNext = item;
|
||||
|
||||
item->mParent = item->mParent->mParent;
|
||||
buildVisibleTree();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case KEY_RIGHT:
|
||||
if ( item->mPrevious )
|
||||
{
|
||||
// Make the item the last child of its previous sibling:
|
||||
if ( dStrcmp( item->mPrevious->mValue, "0" ) == 0 )
|
||||
{
|
||||
item->mPrevious->mNext = item->mNext;
|
||||
|
||||
if ( item->mNext )
|
||||
item->mNext->mPrevious = item->mPrevious;
|
||||
|
||||
item->mParent = item->mPrevious;
|
||||
item->mNext = NULL;
|
||||
|
||||
if ( item->mParent->mChild )
|
||||
{
|
||||
Item* temp = item->mParent->mChild;
|
||||
while ( temp->mNext )
|
||||
temp = temp->mNext;
|
||||
|
||||
temp->mNext = item;
|
||||
item->mPrevious = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// only child...<sniff>
|
||||
item->mParent->mChild = item;
|
||||
item->mPrevious = NULL;
|
||||
}
|
||||
|
||||
// Make sure the new parent is expanded:
|
||||
if ( !item->mParent->mState.test( Item::Expanded ) )
|
||||
expandItem( item->mParent->mId, true );
|
||||
buildVisibleTree();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Not handled, so pass to parent:
|
||||
return Parent::onKeyDown( event );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiChatMenuTreeCtrl::onRenderCell( Point2I offset, Point2I cell, bool, bool )
|
||||
{
|
||||
AssertFatal( cell.y < mVisibleItems.size(), "GuiChatMenuTreeCtrl::onRenderCell: invalid cell" );
|
||||
Item* item = mVisibleItems[cell.y];
|
||||
RectI drawRect( offset, mCellSize );
|
||||
U32 bitmap;
|
||||
dglClearBitmapModulation();
|
||||
|
||||
// Draw inheritance lines:
|
||||
drawRect.point.x += ( mTabSize * item->mTabLevel );
|
||||
Item* parent = item->mParent;
|
||||
for ( S32 i = item->mTabLevel; ( parent && i > 0 ); i-- )
|
||||
{
|
||||
drawRect.point.x -= mTabSize;
|
||||
if ( parent->mNext )
|
||||
dglDrawBitmapSR( mImagesHandle, drawRect.point, mImageBounds[BmpLine] );
|
||||
|
||||
parent = parent->mParent;
|
||||
}
|
||||
|
||||
// Draw the bitmap:
|
||||
drawRect.point.x = offset.x + mTabSize * item->mTabLevel;
|
||||
|
||||
if ( !item->mChild )
|
||||
bitmap = item->mNext ? BmpChild : BmpLastChild;
|
||||
else
|
||||
{
|
||||
bitmap = item->mState.test( Item::Expanded ) ? BmpExp : BmpCon;
|
||||
|
||||
if ( item->mParent || item->mPrevious )
|
||||
bitmap += ( item->mNext ? 3 : 2 );
|
||||
else
|
||||
bitmap += ( item->mNext ? 1 : 0 );
|
||||
}
|
||||
|
||||
if ( ( bitmap >= 0 ) && ( bitmap < mNumImages ) )
|
||||
{
|
||||
dglDrawBitmapSR( mImagesHandle, drawRect.point, mImageBounds[bitmap] );
|
||||
|
||||
// Draw the rollover glow if applicable:
|
||||
if ( bitmap > BmpChild && item->mState.test( Item::MouseOverBmp ) )
|
||||
dglDrawBitmapSR( mImagesHandle, drawRect.point, mImageBounds[BmpGlow] );
|
||||
|
||||
drawRect.point.x += ( mImageBounds[bitmap].extent.x + 2 );
|
||||
}
|
||||
|
||||
// Draw the rollover/selected bar if applicable:
|
||||
drawRect.extent.x = mProfile->mFont->getStrWidth( item->mText ) + ( 2 * mTextOffset );
|
||||
if ( item->mState.test( Item::Selected ) && mTexSelected )
|
||||
dglDrawBitmapStretch( mTexSelected, drawRect );
|
||||
else if ( item->mState.test( Item::MouseOverText ) && mTexRollover )
|
||||
dglDrawBitmapStretch( mTexRollover, drawRect );
|
||||
|
||||
drawRect.point.x += mTextOffset;
|
||||
ColorI fontColor;
|
||||
if ( dStrcmp( item->mValue, "0" ) )
|
||||
fontColor = item->mState.test( Item::Selected ) ? mProfile->mFontColorSEL : ( item->mState.test( Item::MouseOverText ) ? mProfile->mFontColorHL : mProfile->mFontColor );
|
||||
else
|
||||
fontColor = item->mState.test( Item::Selected ) ? mAltFontColorSE : ( item->mState.test( Item::MouseOverText ) ? mAltFontColorHL : mAltFontColor );
|
||||
dglSetBitmapModulation( fontColor );
|
||||
dglDrawText( mProfile->mFont, drawRect.point, item->mText, mProfile->mFontColors );
|
||||
}
|
||||
60
gui/guiChatMenuTreeCtrl.h
Normal file
60
gui/guiChatMenuTreeCtrl.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICHATMENUTREECTRL_H_
|
||||
#define _GUICHATMENUTREECTRL_H_
|
||||
|
||||
#ifndef _GUITREEVIEWCTRL_H_
|
||||
#include "GUI/guiTreeViewCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiChatMenuTreeCtrl : public GuiTreeViewCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTreeViewCtrl Parent;
|
||||
|
||||
protected:
|
||||
enum BmpIndices
|
||||
{
|
||||
BmpDunno,
|
||||
BmpLastChild,
|
||||
BmpChild,
|
||||
BmpExp,
|
||||
BmpExpN,
|
||||
BmpExpP,
|
||||
BmpExpPN,
|
||||
BmpCon,
|
||||
BmpConN,
|
||||
BmpConP,
|
||||
BmpConPN,
|
||||
BmpLine,
|
||||
BmpGlow,
|
||||
};
|
||||
|
||||
TextureHandle mTexRollover;
|
||||
TextureHandle mTexSelected;
|
||||
|
||||
ColorI mAltFontColor;
|
||||
ColorI mAltFontColorHL;
|
||||
ColorI mAltFontColorSE;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiChatMenuTreeCtrl);
|
||||
GuiChatMenuTreeCtrl();
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
bool onKeyDown( const GuiEvent& event );
|
||||
|
||||
void onRenderCell( Point2I offset, Point2I cell, bool, bool );
|
||||
};
|
||||
|
||||
#endif // _GUI_CHATMENUTREECTRL_H
|
||||
233
gui/guiCheckBoxCtrl.cc
Normal file
233
gui/guiCheckBoxCtrl.cc
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiCheckBoxCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
GuiCheckBoxCtrl::GuiCheckBoxCtrl()
|
||||
{
|
||||
mActive = true;
|
||||
mBounds.extent.set(140, 30);
|
||||
mKeyPressed = false;
|
||||
mStateOn = false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::setScriptValue(const char *value)
|
||||
{
|
||||
mStateOn = dAtob(value);
|
||||
|
||||
// Update the console variable:
|
||||
if ( mConsoleVariable[0] )
|
||||
Con::setBoolVariable( mConsoleVariable, mStateOn );
|
||||
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
const char *GuiCheckBoxCtrl::getScriptValue()
|
||||
{
|
||||
return mStateOn ? "1" : "0";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::AcceleratorKeyPress(void)
|
||||
{
|
||||
if (! mActive) return;
|
||||
|
||||
//set the bool
|
||||
mKeyPressed = true;
|
||||
|
||||
if (mProfile->mTabable)
|
||||
{
|
||||
setFirstResponder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::AcceleratorKeyRelease(void)
|
||||
{
|
||||
if (! mActive) return;
|
||||
|
||||
//set the bool
|
||||
mKeyPressed = false;
|
||||
//perform the action
|
||||
onAction();
|
||||
|
||||
//update
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool GuiCheckBoxCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if the control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake))
|
||||
return true;
|
||||
|
||||
//see if the key down is a <return> or not
|
||||
if (event.keyCode == KEY_RETURN && event.modifier == 0)
|
||||
{
|
||||
onAction();
|
||||
return true;
|
||||
}
|
||||
|
||||
//otherwise, pass the event to it's parent
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::drawBorder(const RectI &r, const ColorI &color)
|
||||
{
|
||||
Point2I p1, p2;
|
||||
p1 = r.point;
|
||||
p2 = r.point;
|
||||
p2.x += r.extent.x - 1;
|
||||
p2.y += r.extent.y - 1;
|
||||
|
||||
glColor4ub(color.red, color.green, color.blue, color.alpha);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(p1.x + 2, p1.y);
|
||||
glVertex2i(p2.x - 2, p1.y);
|
||||
glVertex2i(p2.x, p1.y + 2);
|
||||
glVertex2i(p2.x, p2.y - 2);
|
||||
glVertex2i(p2.x - 2, p2.y);
|
||||
glVertex2i(p1.x + 2, p2.y);
|
||||
glVertex2i(p1.x, p2.y - 2);
|
||||
glVertex2i(p1.x, p1.y + 2);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::onAction()
|
||||
{
|
||||
mStateOn = mStateOn ? false : true;
|
||||
|
||||
// Update the console variable:
|
||||
if ( mConsoleVariable[0] )
|
||||
Con::setBoolVariable( mConsoleVariable, mStateOn );
|
||||
|
||||
Parent::onAction();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiCheckBoxCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA;
|
||||
ColorI fontColor = (cursorInControl()) ? mProfile->mFontColorHL : mProfile->mFontColor;
|
||||
ColorI insideBorderColor = (firstResponder == this) ? mProfile->mBorderColorHL : mProfile->mBorderColor;
|
||||
|
||||
if(mText[0] != NULL)
|
||||
{
|
||||
ColorI outsideBorderColor = mProfile->mBorderColor;
|
||||
|
||||
S32 txt_w = mFont->getStrWidth(mText);
|
||||
|
||||
Point2I localStart;
|
||||
|
||||
// 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 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// center the vertical
|
||||
localStart.y = (mBounds.extent.y - (mFont->getHeight() - 2)) / 2;
|
||||
|
||||
// first draw the background
|
||||
RectI r(offset, mBounds.extent);
|
||||
dglDrawRectFill(r, backColor);
|
||||
r.point.x +=2;
|
||||
r.point.y +=2;
|
||||
r.extent.x -=4;
|
||||
r.extent.y -=4;
|
||||
dglDrawRectFill(r, backColor);
|
||||
|
||||
S32 incVal = mBounds.extent.y - 8;
|
||||
//draw the check box
|
||||
glColor3i(insideBorderColor.red, insideBorderColor.green, insideBorderColor.blue);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(r.point.x+3, r.point.y+3);
|
||||
glVertex2i(r.point.x+incVal, r.point.y+3);
|
||||
glVertex2i(r.point.x+incVal, r.point.y+incVal);
|
||||
glVertex2i(r.point.x+3, r.point.y+incVal);
|
||||
glEnd();
|
||||
|
||||
if (mStateOn)
|
||||
{
|
||||
glColor3i(fontColor.red, fontColor.green, fontColor.blue);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(r.point.x+3, r.point.y+3);
|
||||
glVertex2i(r.point.x+incVal, r.point.y+incVal);
|
||||
glVertex2i(r.point.x+incVal, r.point.y+3);
|
||||
glVertex2i(r.point.x+3, r.point.y+incVal);
|
||||
glEnd();
|
||||
}
|
||||
// draw the oustside border
|
||||
r.point.x -=1;
|
||||
r.point.y -=1;
|
||||
r.extent.x +=2;
|
||||
r.extent.y +=2;
|
||||
drawBorder(r, outsideBorderColor);
|
||||
|
||||
// finally draw the text
|
||||
localStart.y -= 2;
|
||||
localStart.x += 4;
|
||||
if (mStateOn)
|
||||
{
|
||||
localStart.x += 1;
|
||||
localStart.y += 1;
|
||||
}
|
||||
Point2I globalStart = localToGlobalCoord(localStart);
|
||||
|
||||
dglSetBitmapModulation(fontColor);
|
||||
dglDrawText(mFont, globalStart, mText, mProfile->mFontColors);
|
||||
}
|
||||
else
|
||||
{
|
||||
RectI r(Point2I(offset.x+3, offset.y+3), Point2I(mBounds.extent.x-3, mBounds.extent.y-3));
|
||||
dglDrawRectFill(r, backColor);
|
||||
|
||||
dglDrawRect(r,insideBorderColor);
|
||||
|
||||
if (mStateOn)
|
||||
{
|
||||
glColor3i(fontColor.red, fontColor.green, fontColor.blue);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(r.point.x-1, r.point.y);
|
||||
glVertex2i(r.point.x-1 + r.extent.x, r.point.y + r.extent.y);
|
||||
glVertex2i(r.point.x-1 + r.extent.x, r.point.y);
|
||||
glVertex2i(r.point.x-1, r.point.y + r.extent.y);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
//render the children
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// EOF //
|
||||
|
||||
|
||||
44
gui/guiCheckBoxCtrl.h
Normal file
44
gui/guiCheckBoxCtrl.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICHECKBOXCTRL_H_
|
||||
#define _GUICHECKBOXCTRL_H_
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiCheckBoxCtrl : public GuiTextCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
protected:
|
||||
bool mStateOn;
|
||||
bool mKeyPressed;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiCheckBoxCtrl);
|
||||
GuiCheckBoxCtrl();
|
||||
static void consoleInit();
|
||||
|
||||
void AcceleratorKeyPress(void);
|
||||
void AcceleratorKeyRelease(void);
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
|
||||
// GuiTextCtrl updates mText with the variable value, which is not desired
|
||||
void onPreRender() {}
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void drawBorder(const RectI &r, const ColorI &color);
|
||||
void onAction();
|
||||
void setScriptValue(const char *value);
|
||||
const char *getScriptValue();
|
||||
};
|
||||
|
||||
#endif //_GUI_CHECKBOX_CTRL_H
|
||||
127
gui/guiChunkedBitmapCtrl.cc
Normal file
127
gui/guiChunkedBitmapCtrl.cc
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "GUI/guiControl.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "dgl/gChunkedTexManager.h"
|
||||
|
||||
class GuiChunkedBitmapCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mBitmapName;
|
||||
ChunkedTextureHandle mTexHandle;
|
||||
bool mUseVariable;
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiChunkedBitmapCtrl);
|
||||
GuiChunkedBitmapCtrl();
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setBitmap(const char *name);
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiChunkedBitmapCtrl);
|
||||
|
||||
void GuiChunkedBitmapCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField( "bitmap", TypeString, Offset( mBitmapName, GuiChunkedBitmapCtrl ) );
|
||||
addField( "useVariable", TypeBool, Offset( mUseVariable, GuiChunkedBitmapCtrl ) );
|
||||
}
|
||||
|
||||
static void cChunkBmpSetBitmap( SimObject* obj, S32, const char** argv )
|
||||
{
|
||||
AssertFatal( dynamic_cast<GuiChunkedBitmapCtrl*>( obj ), "Object passed to cChunkBmpSetBitmap is not a GuiChunkedBitmapCtrl!" );
|
||||
GuiChunkedBitmapCtrl* ctrl = static_cast<GuiChunkedBitmapCtrl*>( obj );
|
||||
ctrl->setBitmap( argv[2] );
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand( "GuiChunkedBitmapCtrl", "setBitmap", cChunkBmpSetBitmap, "ctrl.setBitmap( name );", 3, 3 );
|
||||
}
|
||||
|
||||
GuiChunkedBitmapCtrl::GuiChunkedBitmapCtrl()
|
||||
{
|
||||
mBitmapName = StringTable->insert("");
|
||||
mUseVariable = false;
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::setBitmap(const char *name)
|
||||
{
|
||||
bool awake = mAwake;
|
||||
if(awake)
|
||||
onSleep();
|
||||
|
||||
mBitmapName = StringTable->insert(name);
|
||||
if(awake)
|
||||
onWake();
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
bool GuiChunkedBitmapCtrl::onWake()
|
||||
{
|
||||
if(!Parent::onWake())
|
||||
return false;
|
||||
if ( mUseVariable )
|
||||
mTexHandle = ChunkedTextureHandle( Con::getVariable( mConsoleVariable ) );
|
||||
else
|
||||
mTexHandle = ChunkedTextureHandle( mBitmapName );
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::onSleep()
|
||||
{
|
||||
mTexHandle = NULL;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
void GuiChunkedBitmapCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
if(mTexHandle)
|
||||
{
|
||||
U32 widthCount = mTexHandle.getTextureCountWidth();
|
||||
U32 heightCount = mTexHandle.getTextureCountHeight();
|
||||
if(!widthCount || !heightCount)
|
||||
return;
|
||||
|
||||
F32 widthScale = F32(mBounds.extent.x) / F32(mTexHandle.getWidth());
|
||||
F32 heightScale = F32(mBounds.extent.y) / F32(mTexHandle.getHeight());
|
||||
dglSetBitmapModulation(ColorF(1,1,1));
|
||||
for(U32 i = 0; i < widthCount; i++)
|
||||
{
|
||||
for(U32 j = 0; j < heightCount; j++)
|
||||
{
|
||||
TextureHandle t = mTexHandle.getSubTexture(i, j);
|
||||
RectI stretchRegion;
|
||||
stretchRegion.point.x = (S32)(i * 256 * widthScale + offset.x);
|
||||
stretchRegion.point.y = (S32)(j * 256 * heightScale + offset.y);
|
||||
stretchRegion.extent.x = (S32)((i * 256 + t.getWidth() ) * widthScale + offset.x - stretchRegion.point.x);
|
||||
stretchRegion.extent.y = (S32)((j * 256 + t.getHeight()) * heightScale + offset.y - stretchRegion.point.y);
|
||||
dglDrawBitmapStretch(t, stretchRegion);
|
||||
}
|
||||
}
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
else
|
||||
Parent::onRender(offset, updateRect, firstResponder);
|
||||
}
|
||||
102
gui/guiConsole.cc
Normal file
102
gui/guiConsole.cc
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiTypes.h"
|
||||
#include "GUI/guiControl.h"
|
||||
#include "GUI/guiConsole.h"
|
||||
|
||||
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::getLog(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(log[i].mString)));
|
||||
|
||||
return(result + 6);
|
||||
}
|
||||
|
||||
void GuiConsole::onPreRender()
|
||||
{
|
||||
//see if the size has changed
|
||||
U32 prevSize = mBounds.extent.y / mCellSize.y;
|
||||
U32 size;
|
||||
ConsoleLogEntry *log;
|
||||
|
||||
Con::getLog(log, size);
|
||||
|
||||
if(size != prevSize)
|
||||
{
|
||||
//first, find out if the console was scrolled up
|
||||
bool scrolled = false;
|
||||
GuiControl *parent = getParent();
|
||||
if (mBounds.point.y > parent->mBounds.extent.y - mBounds.extent.y)
|
||||
scrolled = true;
|
||||
|
||||
//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)
|
||||
{
|
||||
mSelectedCell.set(0, mSize.y - 1);
|
||||
scrollSelectionVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiConsole::onRenderCell(Point2I offset, Point2I cell, bool /*selected*/, bool /*mouseOver*/)
|
||||
{
|
||||
U32 size;
|
||||
ConsoleLogEntry *log;
|
||||
|
||||
Con::getLog(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);
|
||||
}
|
||||
34
gui/guiConsole.h
Normal file
34
gui/guiConsole.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICONSOLE_H_
|
||||
#define _GUICONSOLE_H_
|
||||
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "GUI/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
|
||||
97
gui/guiConsoleEditCtrl.cc
Normal file
97
gui/guiConsoleEditCtrl.cc
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiConsoleEditCtrl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiConsoleEditCtrl);
|
||||
|
||||
GuiConsoleEditCtrl::GuiConsoleEditCtrl()
|
||||
{
|
||||
tabBuffer[0] = 0;
|
||||
baseStart = 0;
|
||||
baseLen = 0;
|
||||
}
|
||||
|
||||
void GuiConsoleEditCtrl::handleTab(bool forwardTab)
|
||||
{
|
||||
char buf[GuiTextCtrl::MAX_STRING_LENGTH + 1];
|
||||
if(dStrcmp(tabBuffer, mText))
|
||||
{
|
||||
dStrcpy(tabBuffer, mText);
|
||||
// scan back from mCursorPos
|
||||
S32 p = mCursorPos;
|
||||
while(p > 0 && mText[p-1] != ' ' && mText[p-1] != '.' && mText[p-1] != '(')
|
||||
p--;
|
||||
baseStart = p;
|
||||
baseLen = mCursorPos-p;
|
||||
if(mText[p-1] == '.')
|
||||
{
|
||||
if(p <= 1)
|
||||
return;
|
||||
S32 objLast = --p;
|
||||
while(p > 0 && mText[p-1] != ' ')
|
||||
p--;
|
||||
if(objLast == p)
|
||||
return;
|
||||
dStrncpy(buf, mText + p, objLast - p);
|
||||
buf[objLast - p] = 0;
|
||||
tabObject = Sim::findObject(buf);
|
||||
if(!bool(tabObject))
|
||||
return;
|
||||
}
|
||||
else
|
||||
tabObject = 0;
|
||||
}
|
||||
const char *newText;
|
||||
mText[mCursorPos] = 0;
|
||||
|
||||
if(bool(tabObject))
|
||||
newText = tabObject->tabComplete(mText + baseStart, baseLen, forwardTab);
|
||||
else
|
||||
newText = Con::tabComplete(mText + baseStart, baseLen, forwardTab);
|
||||
if(newText)
|
||||
{
|
||||
S32 len = dStrlen(newText);
|
||||
if(len + baseStart > GuiTextCtrl::MAX_STRING_LENGTH)
|
||||
len = GuiTextCtrl::MAX_STRING_LENGTH - baseStart;
|
||||
dStrncpy(mText + baseStart, newText, len);
|
||||
mText[baseStart + len] = 0;
|
||||
mCursorPos = baseStart + len;
|
||||
}
|
||||
else
|
||||
{
|
||||
mText[baseStart + baseLen] = 0;
|
||||
mCursorPos = baseStart + baseLen;
|
||||
}
|
||||
dStrcpy(tabBuffer, mText);
|
||||
}
|
||||
|
||||
bool GuiConsoleEditCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
S32 stringLen = dStrlen(mText);
|
||||
setUpdate();
|
||||
|
||||
if (event.keyCode == KEY_TAB)
|
||||
{
|
||||
if (event.modifier & SI_SHIFT)
|
||||
{
|
||||
handleTab(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
handleTab(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
36
gui/guiConsoleEditCtrl.h
Normal file
36
gui/guiConsoleEditCtrl.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICONSOLEEDITCTRL_H_
|
||||
#define _GUICONSOLEEDITCTRL_H_
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "GUI/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUITEXTEDITCTRL_H_
|
||||
#include "GUI/guiTextEditCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiConsoleEditCtrl : public GuiTextEditCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextEditCtrl Parent;
|
||||
|
||||
// max string len, must be less then or equal to 255
|
||||
SimObjectPtr<SimObject> tabObject;
|
||||
S32 baseStart;
|
||||
S32 baseLen;
|
||||
char tabBuffer[GuiTextCtrl::MAX_STRING_LENGTH + 1];
|
||||
public:
|
||||
GuiConsoleEditCtrl();
|
||||
DECLARE_CONOBJECT(GuiConsoleEditCtrl);
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void handleTab(bool forwardTab);
|
||||
};
|
||||
|
||||
#endif //_GUI_TEXTEDIT_CTRL_H
|
||||
160
gui/guiConsoleTextCtrl.cc
Normal file
160
gui/guiConsoleTextCtrl.cc
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "Core/color.h"
|
||||
#include "GUI/guiConsoleTextCtrl.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
GuiConsoleTextCtrl::GuiConsoleTextCtrl()
|
||||
{
|
||||
//default fonts
|
||||
mConsoleExpression = NULL;
|
||||
mResult = NULL;
|
||||
}
|
||||
|
||||
void GuiConsoleTextCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiConsoleTextCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("expression", TypeCaseString, Offset(mConsoleExpression, GuiConsoleTextCtrl));
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
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(mResult) + 4, mFont->getHeight() + 4));
|
||||
else
|
||||
resize(mBounds.point, Point2I(mFont->getStrWidth(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, GuiControl *firstResponder)
|
||||
{
|
||||
// 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(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, firstResponder);
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
const char *GuiConsoleTextCtrl::getScriptValue()
|
||||
{
|
||||
return getText();
|
||||
}
|
||||
|
||||
void GuiConsoleTextCtrl::setScriptValue(const char *val)
|
||||
{
|
||||
setText(val);
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// EOF //
|
||||
61
gui/guiConsoleTextCtrl.h
Normal file
61
gui/guiConsoleTextCtrl.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICONSOLETEXTCTRL_H_
|
||||
#define _GUICONSOLETEXTCTRL_H_
|
||||
|
||||
#ifndef _GFONT_H_
|
||||
#include "dgl/gFont.h"
|
||||
#endif
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "GUI/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/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 consoleInit();
|
||||
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, GuiControl *firstResponder);
|
||||
|
||||
//Console methods
|
||||
const char *getScriptValue();
|
||||
void setScriptValue(const char *value);
|
||||
};
|
||||
|
||||
#endif //_GUI_TEXT_CONTROL_H_
|
||||
1276
gui/guiControl.cc
Normal file
1276
gui/guiControl.cc
Normal file
File diff suppressed because it is too large
Load diff
243
gui/guiControl.h
Normal file
243
gui/guiControl.h
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#define _GUICONTROL_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "Math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MRECT_H_
|
||||
#include "Math/mRect.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "GUI/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "Platform/event.h"
|
||||
#endif
|
||||
|
||||
class GuiCanvas;
|
||||
|
||||
class GuiControl : public SimGroup
|
||||
{
|
||||
|
||||
private:
|
||||
typedef SimGroup Parent;
|
||||
|
||||
|
||||
public:
|
||||
GuiControlProfile *mProfile;
|
||||
|
||||
bool mVisible;
|
||||
bool mActive;
|
||||
bool mAwake;
|
||||
bool mSetFirstResponder;
|
||||
|
||||
S32 mLayer;
|
||||
RectI mBounds;
|
||||
Point2I mMinExtent;
|
||||
|
||||
//keyboard input
|
||||
GuiControl *mFirstResponder;
|
||||
static GuiControl *gPrevResponder;
|
||||
static GuiControl *gCurResponder;
|
||||
|
||||
enum horizSizingOptions
|
||||
{
|
||||
horizResizeRight = 0, // fixed on the left and width
|
||||
horizResizeWidth, // fixed on the left and right
|
||||
horizResizeLeft, // fixed on the right and width
|
||||
horizResizeCenter,
|
||||
horizResizeRelative //resize relative
|
||||
};
|
||||
enum vertSizingOptions
|
||||
{
|
||||
vertResizeBottom = 0, // fixed on the top and in height
|
||||
vertResizeHeight, // fixed on the top and bottom
|
||||
vertResizeTop, // fixed in height and on the bottom
|
||||
vertResizeCenter,
|
||||
vertResizeRelative // resize relative
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
S32 mHorizSizing;
|
||||
S32 mVertSizing;
|
||||
|
||||
StringTableEntry mConsoleVariable;
|
||||
StringTableEntry mConsoleCommand;
|
||||
StringTableEntry mAltConsoleCommand;
|
||||
|
||||
StringTableEntry mAcceleratorKey;
|
||||
|
||||
S32 mHelpTag;
|
||||
StringTableEntry mHelpText;
|
||||
|
||||
// console variable and command methods
|
||||
void setVariable(const char *value);
|
||||
void setIntVariable(S32 value);
|
||||
void setFloatVariable(F32 value);
|
||||
|
||||
const char* getVariable();
|
||||
S32 getIntVariable();
|
||||
F32 getFloatVariable();
|
||||
|
||||
public:
|
||||
void setConsoleVariable(const char *variable);
|
||||
void setConsoleCommand(const char *newCmd);
|
||||
const char * getConsoleCommand();
|
||||
void setSizing(S32 horz, S32 vert);
|
||||
void inspectPreApply();
|
||||
void inspectPostApply();
|
||||
|
||||
public:
|
||||
static GuiControl* find(const char *name);
|
||||
|
||||
DECLARE_CONOBJECT(GuiControl);
|
||||
GuiControl();
|
||||
virtual ~GuiControl();
|
||||
bool onAdd();
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
const Point2I& getPosition() { return mBounds.point; }
|
||||
const Point2I& getExtent() { return mBounds.extent; }
|
||||
const Point2I& getMinExtent() { return mMinExtent; }
|
||||
|
||||
virtual void setVisible(bool value);
|
||||
inline bool isVisible() { return mVisible; }
|
||||
virtual void makeFirstResponder(bool value);
|
||||
|
||||
void setActive(bool value);
|
||||
bool isActive() { return mActive; }
|
||||
|
||||
bool isAwake()
|
||||
{
|
||||
return( mAwake );
|
||||
}
|
||||
|
||||
//tag, mouseTag and helpTag related calls
|
||||
virtual void setHelp(S32 helpTag);
|
||||
virtual void setHelp(const char *);
|
||||
virtual S32 getHelpTag(F32) { return mHelpTag; }
|
||||
virtual const char *getHelpText(F32) { return mHelpText; }
|
||||
virtual GuiCursor *getCursor() {return NULL; }
|
||||
|
||||
//methods for organizing the children
|
||||
void addObject(SimObject*);
|
||||
void removeObject(SimObject*);
|
||||
GuiControl *getParent();
|
||||
GuiCanvas *getRoot();
|
||||
|
||||
//parents//children coordinate and sizing methods
|
||||
Point2I localToGlobalCoord(const Point2I &src);
|
||||
Point2I globalToLocalCoord(const Point2I &src);
|
||||
|
||||
virtual void resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual void childResized(GuiControl *child);
|
||||
virtual void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
|
||||
|
||||
//rendering related methods
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void renderChildControls(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void setUpdateRegion(Point2I pos, Point2I ext);
|
||||
void setUpdate();
|
||||
|
||||
//child hierarchy calls
|
||||
void awaken(); // called when this control and it's children have been wired up.
|
||||
void sleep(); // called when this control are no longer
|
||||
void preRender(); //prerender it and all it's children
|
||||
|
||||
//parent hierarchy calls - should call Parent::..();
|
||||
virtual bool onWake();
|
||||
virtual void onSleep(); //mostly resource stuff
|
||||
virtual void onPreRender(); // do special pre render processing
|
||||
virtual void onRemove();
|
||||
|
||||
//console related methods
|
||||
virtual const char *getScriptValue();
|
||||
virtual void setScriptValue(const char *value);
|
||||
|
||||
//mouse/keyboard input related methods
|
||||
virtual bool pointInControl(const Point2I& parentCoordPoint);
|
||||
bool cursorInControl();
|
||||
virtual GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1);
|
||||
|
||||
void mouseLock(GuiControl *lockingControl);
|
||||
void mouseLock();
|
||||
void mouseUnlock();
|
||||
|
||||
// General input handler -- for in-GUI control mapping:
|
||||
virtual bool onInputEvent(const InputEvent &event);
|
||||
|
||||
virtual void onMouseUp(const GuiEvent &event);
|
||||
virtual void onMouseDown(const GuiEvent &event);
|
||||
virtual void onMouseMove(const GuiEvent &event);
|
||||
virtual void onMouseDragged(const GuiEvent &event);
|
||||
virtual void onMouseEnter(const GuiEvent &event);
|
||||
virtual void onMouseLeave(const GuiEvent &event);
|
||||
|
||||
virtual bool onMouseWheelUp(const GuiEvent &event);
|
||||
virtual bool onMouseWheelDown(const GuiEvent &event);
|
||||
|
||||
virtual void onRightMouseDown(const GuiEvent &event);
|
||||
virtual void onRightMouseUp(const GuiEvent &event);
|
||||
virtual void onRightMouseDragged(const GuiEvent &event);
|
||||
|
||||
virtual GuiControl* findFirstTabable();
|
||||
virtual GuiControl* findLastTabable(bool firstCall = true);
|
||||
virtual GuiControl* findPrevTabable(GuiControl *curResponder, bool firstCall = true);
|
||||
virtual GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);
|
||||
virtual bool ControlIsChild(GuiControl *child);
|
||||
virtual void setFirstResponder(GuiControl *firstResponder);
|
||||
void setFirstResponder();
|
||||
void clearFirstResponder();
|
||||
GuiControl *getFirstResponder() { return mFirstResponder; }
|
||||
virtual void onLoseFirstResponder();
|
||||
|
||||
void AddAcceleratorKey();
|
||||
void BuildAcceleratorMap();
|
||||
virtual void AcceleratorKeyPress();
|
||||
virtual void AcceleratorKeyRelease();
|
||||
virtual bool onKeyDown(const GuiEvent &event);
|
||||
virtual bool onKeyUp(const GuiEvent &event);
|
||||
virtual bool onKeyRepeat(const GuiEvent &event);
|
||||
|
||||
//misc
|
||||
void setControlProfile(GuiControlProfile *prof);
|
||||
|
||||
//the action
|
||||
virtual void onAction();
|
||||
|
||||
//peer messaging
|
||||
void messageSiblings(S32 message); //send a message to all siblings
|
||||
virtual void onMessage(GuiControl *sender, S32 msg); //receive a message from another control
|
||||
|
||||
//functions called by the canvas
|
||||
virtual void onDialogPush();
|
||||
virtual void onDialogPop();
|
||||
|
||||
//this will move into the graphics library at some poing
|
||||
bool createBitmapArray(GBitmap *bmp, RectI *boundsArray, S32 numStates, S32 numBitmaps);
|
||||
};
|
||||
|
||||
|
||||
// default renderer helper functions
|
||||
void renderRaisedBox(const Point2I &offset, const Point2I &extent, const ColorI &color);
|
||||
void renderLoweredBox(const Point2I &offset, const Point2I &extent, const ColorI &color);
|
||||
|
||||
#endif
|
||||
40
gui/guiControlListPopup.cc
Normal file
40
gui/guiControlListPopup.cc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiPopUpCtrl.h"
|
||||
|
||||
class GuiControlListPopUp : public GuiPopUpMenuCtrl
|
||||
{
|
||||
typedef GuiPopUpMenuCtrl Parent;
|
||||
public:
|
||||
bool onAdd();
|
||||
static void consoleInit();
|
||||
|
||||
DECLARE_CONOBJECT(GuiControlListPopUp);
|
||||
};
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiControlListPopUp);
|
||||
|
||||
void GuiControlListPopUp::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
bool GuiControlListPopUp::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
clear();
|
||||
|
||||
for(AbstractClassRep *rep = AbstractClassRep::getClassList(); rep; rep = rep->getNextClass())
|
||||
{
|
||||
ConsoleObject *obj = rep->create();
|
||||
if(obj && dynamic_cast<GuiControl *>(obj))
|
||||
addEntry(rep->getClassName(), 0);
|
||||
delete obj;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
1462
gui/guiDebugger.cc
Normal file
1462
gui/guiDebugger.cc
Normal file
File diff suppressed because it is too large
Load diff
85
gui/guiDebugger.h
Normal file
85
gui/guiDebugger.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIDEBUGGER_H_
|
||||
#define _GUIDEBUGGER_H_
|
||||
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "GUI/guiArrayCtrl.h"
|
||||
#endif
|
||||
|
||||
class DbgFileView : public GuiArrayCtrl
|
||||
{
|
||||
private:
|
||||
|
||||
typedef GuiArrayCtrl Parent;
|
||||
|
||||
struct FileLine
|
||||
{
|
||||
bool breakPosition;
|
||||
bool breakOnLine;
|
||||
char *text;
|
||||
};
|
||||
|
||||
Vector<FileLine> mFileView;
|
||||
|
||||
StringTableEntry mFileName;
|
||||
|
||||
void AdjustCellSize();
|
||||
|
||||
//used to display the program counter
|
||||
StringTableEntry mPCFileName;
|
||||
S32 mPCCurrentLine;
|
||||
|
||||
//vars used to highlight the selected line segment for copying
|
||||
bool mbMouseDragging;
|
||||
S32 mMouseDownChar;
|
||||
S32 mBlockStart;
|
||||
S32 mBlockEnd;
|
||||
|
||||
char mMouseOverVariable[256];
|
||||
char mMouseOverValue[256];
|
||||
S32 findMouseOverChar(const char *text, S32 stringPosition);
|
||||
bool findMouseOverVariable();
|
||||
S32 mMouseVarStart;
|
||||
S32 mMouseVarEnd;
|
||||
|
||||
//find vars
|
||||
char mFindString[256];
|
||||
S32 mFindLineNumber;
|
||||
|
||||
public:
|
||||
|
||||
DbgFileView();
|
||||
~DbgFileView();
|
||||
DECLARE_CONOBJECT(DbgFileView);
|
||||
static void consoleInit();
|
||||
|
||||
bool onWake();
|
||||
|
||||
void clear();
|
||||
void clearBreakPositions();
|
||||
|
||||
void setCurrentLine(S32 lineNumber, bool setCurrentLine);
|
||||
const char *getCurrentLine(S32 &lineNumber);
|
||||
bool openFile(const char *fileName);
|
||||
void scrollToLine(S32 lineNumber);
|
||||
void setBreakPointStatus(U32 lineNumber, bool value);
|
||||
void setBreakPosition(U32 line);
|
||||
void addLine(const char *text, U32 textLen);
|
||||
|
||||
bool findString(const char *text);
|
||||
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
|
||||
void onPreRender();
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
|
||||
};
|
||||
|
||||
#endif //_GUI_DEBUGGER_H
|
||||
51
gui/guiDefaultControlRender.cc
Normal file
51
gui/guiDefaultControlRender.cc
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "gui/guiDefaultControlRender.h"
|
||||
#include "core/color.h"
|
||||
#include "math/mRect.h"
|
||||
|
||||
static ColorI colorLightGray(192, 192, 192);
|
||||
static ColorI colorGray(128, 128, 128);
|
||||
static ColorI colorDarkGray(64, 64, 64);
|
||||
static ColorI colorWhite(255,255,255);
|
||||
static ColorI colorBlack(0,0,0);
|
||||
|
||||
void renderRaisedBox(RectI &bounds)
|
||||
{
|
||||
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;
|
||||
|
||||
dglDrawRectFill( bounds, colorLightGray);
|
||||
dglDrawLine(l, t, l, b - 1, colorWhite);
|
||||
dglDrawLine(l, t, r - 1, t, colorWhite);
|
||||
|
||||
dglDrawLine(l, b, r, b, colorBlack);
|
||||
dglDrawLine(r, b - 1, r, t, colorBlack);
|
||||
|
||||
dglDrawLine(l + 1, b - 1, r - 1, b - 1, colorGray);
|
||||
dglDrawLine(r - 1, b - 2, r - 1, t + 1, colorGray);
|
||||
}
|
||||
|
||||
|
||||
void renderLoweredBox(RectI &bounds)
|
||||
{
|
||||
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;
|
||||
|
||||
dglDrawRectFill( bounds, colorLightGray);
|
||||
|
||||
dglDrawLine(l, b, r, b, colorWhite);
|
||||
dglDrawLine(r, b - 1, r, t, colorWhite);
|
||||
|
||||
dglDrawLine(l, t, r - 1, t, colorBlack);
|
||||
dglDrawLine(l, t + 1, l, b - 1, colorBlack);
|
||||
|
||||
dglDrawLine(l + 1, t + 1, r - 2, t + 1, colorGray);
|
||||
dglDrawLine(l + 1, t + 2, l + 1, b - 2, colorGray);
|
||||
}
|
||||
|
||||
13
gui/guiDefaultControlRender.h
Normal file
13
gui/guiDefaultControlRender.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _H_GUIDEFAULTCONTROLRENDER_
|
||||
#define _H_GUIDEFAULTCONTROLRENDER_
|
||||
|
||||
void renderRaisedBox(RectI &bounds);
|
||||
void renderLoweredBox(RectI &bounds);
|
||||
|
||||
#endif
|
||||
775
gui/guiEditCtrl.cc
Normal file
775
gui/guiEditCtrl.cc
Normal file
|
|
@ -0,0 +1,775 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/simBase.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiEditCtrl.h"
|
||||
#include "Platform/event.h"
|
||||
#include "Core/fileStream.h"
|
||||
|
||||
GuiEditCtrl::GuiEditCtrl()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mSelectedControls);
|
||||
|
||||
mActive = true;
|
||||
mCurrentAddSet = NULL;
|
||||
mGridSnap.set(0, 0);
|
||||
}
|
||||
|
||||
|
||||
static void cGuiEditCtrlSetRoot(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiControl *ctrl;
|
||||
if(!Sim::findObject(argv[2], ctrl))
|
||||
return;
|
||||
((GuiEditCtrl *) obj)->setRoot(ctrl);
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlAdd(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiControl *ctrl;
|
||||
if(!Sim::findObject(argv[2], ctrl))
|
||||
return;
|
||||
((GuiEditCtrl *) obj)->addNewControl(ctrl);
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlSelect(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiControl *ctrl;
|
||||
if(!Sim::findObject(argv[2], ctrl))
|
||||
return;
|
||||
((GuiEditCtrl *) obj)->select(ctrl);
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlSetAddSet(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiEditCtrl *editor = static_cast<GuiEditCtrl*>(obj);
|
||||
GuiControl *addSet = NULL;
|
||||
SimObject *target = Sim::findObject(argv[2]);
|
||||
if (target)
|
||||
addSet = dynamic_cast<GuiControl*>(target);
|
||||
if (! addSet)
|
||||
{
|
||||
Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
|
||||
return;
|
||||
}
|
||||
editor->setCurrentAddSet(addSet);
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlToggle(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiEditCtrl *editor = static_cast<GuiEditCtrl*>(obj);
|
||||
editor->setEditMode(! editor->mActive);
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlJustify(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiEditCtrl *editor = static_cast<GuiEditCtrl*>(obj);
|
||||
editor->justifySelection((GuiEditCtrl::Justification)dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlBringToFront(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiEditCtrl *editor = static_cast<GuiEditCtrl*>(obj);
|
||||
editor->bringToFront();
|
||||
}
|
||||
|
||||
static void cGuiEditCtrlPushToBack(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiEditCtrl *editor = static_cast<GuiEditCtrl*>(obj);
|
||||
editor->pushToBack();
|
||||
}
|
||||
|
||||
void GuiEditCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiEditCtrl", "addNewCtrl", cGuiEditCtrlAdd, "editCtrl.addNewCtrl(ctrl)", 3, 3);
|
||||
Con::addCommand("GuiEditCtrl", "select", cGuiEditCtrlSelect, "editCtrl.select(ctrl)", 3, 3);
|
||||
Con::addCommand("GuiEditCtrl", "setRoot", cGuiEditCtrlSetRoot, "editCtrl.setRoot(root)", 3, 3);
|
||||
Con::addCommand("GuiEditCtrl", "setCurrentAddSet", cGuiEditCtrlSetAddSet, "editCtrl.setCurrentAddSet(ctrl)", 3, 3);
|
||||
Con::addCommand("GuiEditCtrl", "toggle", cGuiEditCtrlToggle, "editCtrl.toggle()", 2, 2);
|
||||
Con::addCommand("GuiEditCtrl", "justify", cGuiEditCtrlJustify, "editCtrl.justify(mode)", 3, 3);
|
||||
Con::addCommand("GuiEditCtrl", "bringToFront", cGuiEditCtrlBringToFront, "editCtrl.bringToFront()", 2, 2);
|
||||
Con::addCommand("GuiEditCtrl", "pushToBack", cGuiEditCtrlPushToBack, "editCtrl.pushToBack()", 2, 2);
|
||||
}
|
||||
|
||||
bool GuiEditCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
setEditMode(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::setRoot(GuiControl *root)
|
||||
{
|
||||
mContentControl = root;
|
||||
}
|
||||
|
||||
enum { GUI_BLACK = 0, GUI_WHITE = 255 };
|
||||
enum { NUT_SIZE = 3 };
|
||||
|
||||
void GuiEditCtrl::setEditMode(bool value)
|
||||
{
|
||||
mActive = value;
|
||||
mSelectedControls.clear();
|
||||
if (mActive && mAwake)
|
||||
mCurrentAddSet = NULL;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::setCurrentAddSet(GuiControl *ctrl)
|
||||
{
|
||||
if (ctrl != mCurrentAddSet)
|
||||
{
|
||||
mSelectedControls.clear();
|
||||
mCurrentAddSet = ctrl;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiEditCtrl::setSelection(GuiControl *ctrl, bool inclusive)
|
||||
{
|
||||
//sanity check
|
||||
if (! ctrl)
|
||||
return;
|
||||
|
||||
// otherwise, we hit a new control...
|
||||
GuiControl *newAddSet = ctrl->getParent();
|
||||
|
||||
//see if we should clear the old selection set
|
||||
if (newAddSet != mCurrentAddSet || (! inclusive))
|
||||
mSelectedControls.clear();
|
||||
|
||||
//set the selection
|
||||
mCurrentAddSet = newAddSet;
|
||||
mSelectedControls.push_back(ctrl);
|
||||
}
|
||||
|
||||
void GuiEditCtrl::addNewControl(GuiControl *ctrl)
|
||||
{
|
||||
if (! mCurrentAddSet)
|
||||
mCurrentAddSet = mContentControl;
|
||||
|
||||
mCurrentAddSet->addObject(ctrl);
|
||||
mSelectedControls.clear();
|
||||
mSelectedControls.push_back(ctrl);
|
||||
}
|
||||
|
||||
void GuiEditCtrl::drawNut(const Point2I &nut, bool multisel)
|
||||
{
|
||||
RectI r(nut.x - NUT_SIZE, nut.y - NUT_SIZE, 2 * NUT_SIZE + 1, 2 * NUT_SIZE + 1);
|
||||
dglDrawRect(r, multisel ? ColorI(0, 0, 0) : ColorI(255, 255, 255));
|
||||
r.point += Point2I(1, 1);
|
||||
r.extent -= Point2I(1, 1);
|
||||
dglDrawRectFill(r, multisel ? ColorI(255, 255, 255) : ColorI(0, 0, 0));
|
||||
}
|
||||
|
||||
static inline bool inNut(const Point2I &pt, S32 x, S32 y)
|
||||
{
|
||||
S32 dx = pt.x - x;
|
||||
S32 dy = pt.y - y;
|
||||
return dx <= NUT_SIZE && dx >= -NUT_SIZE && dy <= NUT_SIZE && dy >= -NUT_SIZE;
|
||||
}
|
||||
|
||||
S32 GuiEditCtrl::getSizingHitKnobs(const Point2I &pt, const RectI &box)
|
||||
{
|
||||
S32 lx = box.point.x, rx = box.point.x + box.extent.x - 1;
|
||||
S32 cx = (lx + rx) >> 1;
|
||||
S32 ty = box.point.y, by = box.point.y + box.extent.y - 1;
|
||||
S32 cy = (ty + by) >> 1;
|
||||
|
||||
if (inNut(pt, lx, ty))
|
||||
return sizingLeft | sizingTop;
|
||||
if (inNut(pt, cx, ty))
|
||||
return sizingTop;
|
||||
if (inNut(pt, rx, ty))
|
||||
return sizingRight | sizingTop;
|
||||
if (inNut(pt, lx, by))
|
||||
return sizingLeft | sizingBottom;
|
||||
if (inNut(pt, cx, by))
|
||||
return sizingBottom;
|
||||
if (inNut(pt, rx, by))
|
||||
return sizingRight | sizingBottom;
|
||||
if (inNut(pt, lx, cy))
|
||||
return sizingLeft;
|
||||
if (inNut(pt, rx, cy))
|
||||
return sizingRight;
|
||||
return sizingNone;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::drawNuts(RectI &box, bool multisel)
|
||||
{
|
||||
S32 lx = box.point.x, rx = box.point.x + box.extent.x - 1;
|
||||
S32 cx = (lx + rx) >> 1;
|
||||
S32 ty = box.point.y, by = box.point.y + box.extent.y - 1;
|
||||
S32 cy = (ty + by) >> 1;
|
||||
drawNut(Point2I(lx, ty), multisel);
|
||||
drawNut(Point2I(lx, cy), multisel);
|
||||
drawNut(Point2I(lx, by), multisel);
|
||||
drawNut(Point2I(rx, ty), multisel);
|
||||
drawNut(Point2I(rx, cy), multisel);
|
||||
drawNut(Point2I(rx, by), multisel);
|
||||
drawNut(Point2I(cx, ty), multisel);
|
||||
drawNut(Point2I(cx, by), multisel);
|
||||
}
|
||||
|
||||
void GuiEditCtrl::getDragRect(RectI &box)
|
||||
{
|
||||
box.point.x = getMin(mLastMousePos.x, mSelectionAnchor.x);
|
||||
box.extent.x = getMax(mLastMousePos.x, mSelectionAnchor.x) - box.point.x + 1;
|
||||
box.point.y = getMin(mLastMousePos.y, mSelectionAnchor.y);
|
||||
box.extent.y = getMax(mLastMousePos.y, mSelectionAnchor.y) - box.point.y + 1;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::onPreRender()
|
||||
{
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiEditCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
Point2I ctOffset;
|
||||
Point2I cext;
|
||||
|
||||
if (mActive)
|
||||
{
|
||||
if (mCurrentAddSet)
|
||||
{
|
||||
// draw a white frame inset around the current add set.
|
||||
cext = mCurrentAddSet->getExtent();
|
||||
ctOffset = mCurrentAddSet->localToGlobalCoord(Point2I(0,0));
|
||||
RectI box(ctOffset.x + 1,ctOffset.y + 1, cext.x - 2, cext.y - 2);
|
||||
dglDrawRect(box, ColorI(255, 255, 255));
|
||||
box.point -= Point2I(1, 1);
|
||||
box.extent += Point2I(1, 1);
|
||||
dglDrawRect(box, ColorI(0, 0, 0));
|
||||
}
|
||||
Vector<GuiControl *>::iterator i;
|
||||
bool multisel = mSelectedControls.size() > 1;
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
{
|
||||
GuiControl *ctrl = (*i);
|
||||
cext = ctrl->getExtent();
|
||||
ctOffset = ctrl->localToGlobalCoord(Point2I(0,0));
|
||||
RectI box(ctOffset.x,ctOffset.y, cext.x, cext.y);
|
||||
drawNuts(box, multisel);
|
||||
}
|
||||
if (mMouseDownMode == DragSelecting)
|
||||
{
|
||||
RectI b;
|
||||
getDragRect(b);
|
||||
dglDrawRect(b, ColorI(255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
bool GuiEditCtrl::selectionContains(GuiControl *ctrl)
|
||||
{
|
||||
Vector<GuiControl *>::iterator i;
|
||||
for (i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
if (ctrl == *i) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::onRightMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if (! mActive)
|
||||
{
|
||||
Parent::onRightMouseDown(event);
|
||||
return;
|
||||
}
|
||||
setFirstResponder();
|
||||
|
||||
//search for the control hit in any layer below the edit layer
|
||||
GuiControl *hitCtrl = mContentControl->findHitControl(event.mousePoint, mLayer - 1);
|
||||
if (hitCtrl != mCurrentAddSet)
|
||||
{
|
||||
mSelectedControls.clear();
|
||||
mCurrentAddSet = hitCtrl;
|
||||
}
|
||||
}
|
||||
void GuiEditCtrl::select(GuiControl *ctrl)
|
||||
{
|
||||
mSelectedControls.clear();
|
||||
if(ctrl != mContentControl)
|
||||
mSelectedControls.push_back(ctrl);
|
||||
else
|
||||
mCurrentAddSet = mContentControl;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if (! mActive)
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
return;
|
||||
}
|
||||
if(!mContentControl)
|
||||
return;
|
||||
|
||||
setFirstResponder();
|
||||
//lock the mouse
|
||||
mouseLock();
|
||||
|
||||
Point2I ctOffset;
|
||||
Point2I cext;
|
||||
GuiControl *ctrl;
|
||||
|
||||
mLastMousePos = event.mousePoint;
|
||||
|
||||
// first see if we hit a sizing knob on the currently selected control...
|
||||
if (mSelectedControls.size() == 1)
|
||||
{
|
||||
ctrl = mSelectedControls.first();
|
||||
cext = ctrl->getExtent();
|
||||
ctOffset = ctrl->localToGlobalCoord(Point2I(0,0));
|
||||
RectI box(ctOffset.x,ctOffset.y,cext.x, cext.y);
|
||||
|
||||
if ((mSizingMode = (GuiEditCtrl::sizingModes)getSizingHitKnobs(event.mousePoint, box)) != 0)
|
||||
{
|
||||
mMouseDownMode = SizingSelection;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!mCurrentAddSet)
|
||||
mCurrentAddSet = mContentControl;
|
||||
|
||||
//find the control we clicked
|
||||
ctrl = mContentControl->findHitControl(event.mousePoint, mCurrentAddSet->mLayer);
|
||||
|
||||
if (selectionContains(ctrl))
|
||||
{
|
||||
//if we're holding shift, de-select the clicked ctrl
|
||||
if (event.modifier & SI_SHIFT)
|
||||
{
|
||||
Vector<GuiControl *>::iterator i;
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
{
|
||||
if (*i == ctrl)
|
||||
{
|
||||
mSelectedControls.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//set the mode
|
||||
mMouseDownMode = Selecting;
|
||||
}
|
||||
|
||||
//else we hit a ctrl we've already selected, so set the mode to moving
|
||||
else
|
||||
mMouseDownMode = MovingSelection;
|
||||
}
|
||||
|
||||
//else we clicked on an unselected control
|
||||
else
|
||||
{
|
||||
//if we clicked in the current add set
|
||||
if (ctrl == mCurrentAddSet)
|
||||
{
|
||||
// start dragging a rectangle
|
||||
// if the shift is not down, nuke prior selection
|
||||
if (!(event.modifier & SI_SHIFT))
|
||||
mSelectedControls.clear();
|
||||
mSelectionAnchor = event.mousePoint;
|
||||
mMouseDownMode = DragSelecting;
|
||||
}
|
||||
else
|
||||
{
|
||||
//find the new add set
|
||||
GuiControl *newAddSet = ctrl->getParent();
|
||||
|
||||
//if we're holding shift and the ctrl is in the same add set
|
||||
if (event.modifier & SI_SHIFT && newAddSet == mCurrentAddSet)
|
||||
{
|
||||
mSelectedControls.push_back(ctrl);
|
||||
mMouseDownMode = Selecting;
|
||||
}
|
||||
else if (ctrl != mContentControl)
|
||||
{
|
||||
//find and set the new add set
|
||||
mCurrentAddSet = ctrl->getParent();
|
||||
|
||||
//clear and set the selected controls
|
||||
mSelectedControls.clear();
|
||||
mSelectedControls.push_back(ctrl);
|
||||
mMouseDownMode = Selecting;
|
||||
}
|
||||
else
|
||||
mMouseDownMode = Selecting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiEditCtrl::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
if (! mActive)
|
||||
{
|
||||
Parent::onMouseUp(event);
|
||||
return;
|
||||
}
|
||||
|
||||
//unlock the mouse
|
||||
mouseUnlock();
|
||||
|
||||
mLastMousePos = event.mousePoint;
|
||||
if (mMouseDownMode == DragSelecting)
|
||||
{
|
||||
RectI b;
|
||||
getDragRect(b);
|
||||
GuiControl::iterator i;
|
||||
for(i = mCurrentAddSet->begin(); i != mCurrentAddSet->end(); i++)
|
||||
{
|
||||
GuiControl *ctrl = dynamic_cast<GuiControl *>(*i);
|
||||
Point2I upperL = ctrl->localToGlobalCoord(Point2I(0,0));
|
||||
Point2I lowerR = upperL + ctrl->mBounds.extent - Point2I(1, 1);
|
||||
|
||||
if (b.pointInRect(upperL) && b.pointInRect(lowerR) && !selectionContains(ctrl))
|
||||
mSelectedControls.push_back(ctrl);
|
||||
}
|
||||
}
|
||||
if (mSelectedControls.size() == 1)
|
||||
Con::executef(this, 2, "onSelect", avar("%d", mSelectedControls[0]->getId()));
|
||||
|
||||
setFirstResponder();
|
||||
//reset the mouse mode
|
||||
mMouseDownMode = Selecting;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
if (! mActive)
|
||||
{
|
||||
Parent::onMouseDragged(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!mCurrentAddSet)
|
||||
mCurrentAddSet = mContentControl;
|
||||
|
||||
Point2I mousePoint = event.mousePoint;
|
||||
|
||||
if (mMouseDownMode == SizingSelection)
|
||||
{
|
||||
if (mGridSnap.x)
|
||||
mousePoint.x -= mousePoint.x % mGridSnap.x;
|
||||
if (mGridSnap.y)
|
||||
mousePoint.y -= mousePoint.y % mGridSnap.y;
|
||||
|
||||
GuiControl *ctrl = mSelectedControls.first();
|
||||
Point2I ctrlPoint = mCurrentAddSet->globalToLocalCoord(mousePoint);
|
||||
Point2I newPosition = ctrl->getPosition();
|
||||
Point2I newExtent = ctrl->getExtent();
|
||||
Point2I minExtent = ctrl->getMinExtent();
|
||||
|
||||
if (mSizingMode & sizingLeft)
|
||||
{
|
||||
newPosition.x = ctrlPoint.x;
|
||||
newExtent.x = ctrl->mBounds.extent.x + ctrl->mBounds.point.x - ctrlPoint.x;
|
||||
if(newExtent.x < minExtent.x)
|
||||
{
|
||||
newPosition.x -= minExtent.x - newExtent.x;
|
||||
newExtent.x = minExtent.x;
|
||||
}
|
||||
}
|
||||
else if (mSizingMode & sizingRight)
|
||||
{
|
||||
newExtent.x = ctrlPoint.x - ctrl->mBounds.point.x;
|
||||
if(newExtent.x < minExtent.x)
|
||||
newExtent.x = minExtent.x;
|
||||
}
|
||||
|
||||
if (mSizingMode & sizingTop)
|
||||
{
|
||||
newPosition.y = ctrlPoint.y;
|
||||
newExtent.y = ctrl->mBounds.extent.y + ctrl->mBounds.point.y - ctrlPoint.y;
|
||||
if(newExtent.y < minExtent.y)
|
||||
{
|
||||
newPosition.y -= minExtent.y - newExtent.y;
|
||||
newExtent.y = minExtent.y;
|
||||
}
|
||||
}
|
||||
else if (mSizingMode & sizingBottom)
|
||||
{
|
||||
newExtent.y = ctrlPoint.y - ctrl->mBounds.point.y;
|
||||
if(newExtent.y < minExtent.y)
|
||||
newExtent.y = minExtent.y;
|
||||
}
|
||||
|
||||
ctrl->resize(newPosition, newExtent);
|
||||
mCurrentAddSet->childResized(ctrl);
|
||||
}
|
||||
else if (mMouseDownMode == MovingSelection && mSelectedControls.size())
|
||||
{
|
||||
Vector<GuiControl *>::iterator i = mSelectedControls.begin();
|
||||
Point2I minPos = (*i)->mBounds.point;
|
||||
for(; i != mSelectedControls.end(); i++)
|
||||
{
|
||||
if ((*i)->mBounds.point.x < minPos.x)
|
||||
minPos.x = (*i)->mBounds.point.x;
|
||||
if ((*i)->mBounds.point.y < minPos.y)
|
||||
minPos.y = (*i)->mBounds.point.y;
|
||||
}
|
||||
Point2I delta = mousePoint - mLastMousePos;
|
||||
delta += minPos; // find new minPos;
|
||||
|
||||
if (mGridSnap.x)
|
||||
delta.x -= delta.x % mGridSnap.x;
|
||||
if (mGridSnap.y)
|
||||
delta.y -= delta.y % mGridSnap.y;
|
||||
|
||||
delta -= minPos;
|
||||
moveSelection(delta);
|
||||
mLastMousePos += delta;
|
||||
}
|
||||
else
|
||||
mLastMousePos = mousePoint;
|
||||
}
|
||||
|
||||
void GuiEditCtrl::moveSelection(const Point2I &delta)
|
||||
{
|
||||
Vector<GuiControl *>::iterator i;
|
||||
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->resize((*i)->mBounds.point + delta, (*i)->mBounds.extent);
|
||||
}
|
||||
|
||||
void GuiEditCtrl::justifySelection(Justification j)
|
||||
{
|
||||
S32 minX, maxX;
|
||||
S32 minY, maxY;
|
||||
S32 extentX, extentY;
|
||||
|
||||
if (mSelectedControls.size() < 2)
|
||||
return;
|
||||
|
||||
Vector<GuiControl *>::iterator i = mSelectedControls.begin();
|
||||
minX = (*i)->mBounds.point.x;
|
||||
maxX = minX + (*i)->mBounds.extent.x;
|
||||
minY = (*i)->mBounds.point.y;
|
||||
maxY = minY + (*i)->mBounds.extent.y;
|
||||
extentX = (*i)->mBounds.extent.x;
|
||||
extentY = (*i)->mBounds.extent.y;
|
||||
i++;
|
||||
for(;i != mSelectedControls.end(); i++)
|
||||
{
|
||||
minX = getMin(minX, (*i)->mBounds.point.x);
|
||||
maxX = getMax(maxX, (*i)->mBounds.point.x + (*i)->mBounds.extent.x);
|
||||
minY = getMin(minY, (*i)->mBounds.point.y);
|
||||
maxY = getMax(maxY, (*i)->mBounds.point.y + (*i)->mBounds.extent.y);
|
||||
extentX += (*i)->mBounds.extent.x;
|
||||
extentY += (*i)->mBounds.extent.y;
|
||||
}
|
||||
S32 deltaX = maxX - minX;
|
||||
S32 deltaY = maxY - minY;
|
||||
switch(j)
|
||||
{
|
||||
case JUSTIFY_LEFT:
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->resize(Point2I(minX, (*i)->mBounds.point.y), (*i)->mBounds.extent);
|
||||
break;
|
||||
case JUSTIFY_TOP:
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->resize(Point2I((*i)->mBounds.point.x, minY), (*i)->mBounds.extent);
|
||||
break;
|
||||
case JUSTIFY_RIGHT:
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->resize(Point2I(maxX - (*i)->mBounds.extent.x + 1, (*i)->mBounds.point.y), (*i)->mBounds.extent);
|
||||
break;
|
||||
case JUSTIFY_BOTTOM:
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->resize(Point2I((*i)->mBounds.point.x, maxY - (*i)->mBounds.extent.y + 1), (*i)->mBounds.extent);
|
||||
break;
|
||||
case JUSTIFY_CENTER:
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->resize(Point2I(minX + ((deltaX - (*i)->mBounds.extent.x) >> 1), (*i)->mBounds.point.y),
|
||||
(*i)->mBounds.extent);
|
||||
break;
|
||||
case SPACING_VERTICAL:
|
||||
{
|
||||
Vector<GuiControl *> sortedList;
|
||||
Vector<GuiControl *>::iterator k;
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
{
|
||||
for(k = sortedList.begin(); k != sortedList.end(); k++)
|
||||
{
|
||||
if ((*i)->mBounds.point.y < (*k)->mBounds.point.y)
|
||||
break;
|
||||
}
|
||||
sortedList.insert(k, *i);
|
||||
}
|
||||
S32 space = (deltaY - extentY) / (mSelectedControls.size() - 1);
|
||||
S32 curY = minY;
|
||||
for(k = sortedList.begin(); k != sortedList.end(); k++)
|
||||
{
|
||||
(*k)->resize(Point2I((*k)->mBounds.point.x, curY), (*k)->mBounds.extent);
|
||||
curY += (*k)->mBounds.extent.y + space;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPACING_HORIZONTAL:
|
||||
{
|
||||
Vector<GuiControl *> sortedList;
|
||||
Vector<GuiControl *>::iterator k;
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
{
|
||||
for(k = sortedList.begin(); k != sortedList.end(); k++)
|
||||
{
|
||||
if ((*i)->mBounds.point.x < (*k)->mBounds.point.x)
|
||||
break;
|
||||
}
|
||||
sortedList.insert(k, *i);
|
||||
}
|
||||
S32 space = (deltaX - extentX) / (mSelectedControls.size() - 1);
|
||||
S32 curX = minX;
|
||||
for(k = sortedList.begin(); k != sortedList.end(); k++)
|
||||
{
|
||||
(*k)->resize(Point2I(curX, (*k)->mBounds.point.y), (*k)->mBounds.extent);
|
||||
curX += (*k)->mBounds.extent.x + space;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiEditCtrl::deleteSelection(void)
|
||||
{
|
||||
|
||||
Vector<GuiControl *>::iterator i;
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
(*i)->deleteObject();
|
||||
mSelectedControls.clear();
|
||||
}
|
||||
|
||||
void GuiEditCtrl::loadSelection(const char* filename)
|
||||
{
|
||||
if (! mCurrentAddSet)
|
||||
mCurrentAddSet = mContentControl;
|
||||
|
||||
Con::executef(2, "exec", filename);
|
||||
SimSet *set;
|
||||
if(!Sim::findObject("guiClipboard", set))
|
||||
return;
|
||||
|
||||
if(set->size())
|
||||
{
|
||||
mSelectedControls.clear();
|
||||
for(U32 i = 0; i < set->size(); i++)
|
||||
{
|
||||
GuiControl *ctrl = dynamic_cast<GuiControl *>((*set)[i]);
|
||||
if(ctrl)
|
||||
{
|
||||
mCurrentAddSet->addObject(ctrl);
|
||||
mSelectedControls.push_back(ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
set->deleteObject();
|
||||
}
|
||||
|
||||
void GuiEditCtrl::saveSelection(const char* filename)
|
||||
{
|
||||
FileStream stream;
|
||||
if(!ResourceManager->openFileForWrite(stream, NULL, filename))
|
||||
return;
|
||||
SimSet *clipboardSet = new SimSet;
|
||||
clipboardSet->registerObject();
|
||||
Sim::getRootGroup()->addObject(clipboardSet, "guiClipboard");
|
||||
|
||||
Vector<GuiControl *>::iterator i;
|
||||
for(i = mSelectedControls.begin(); i != mSelectedControls.end(); i++)
|
||||
clipboardSet->addObject(*i);
|
||||
|
||||
clipboardSet->write(stream, 0);
|
||||
clipboardSet->deleteObject();
|
||||
}
|
||||
|
||||
void GuiEditCtrl::selectAll()
|
||||
{
|
||||
GuiControl::iterator i;
|
||||
if (!mCurrentAddSet)
|
||||
return;
|
||||
mSelectedControls.clear();
|
||||
for(i = mCurrentAddSet->begin(); i != mCurrentAddSet->end(); i++)
|
||||
{
|
||||
GuiControl *ctrl = dynamic_cast<GuiControl *>(*i);
|
||||
mSelectedControls.push_back(ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiEditCtrl::bringToFront()
|
||||
{
|
||||
if (mSelectedControls.size() != 1)
|
||||
return;
|
||||
|
||||
GuiControl *ctrl = *(mSelectedControls.begin());
|
||||
mCurrentAddSet->bringObjectToFront(ctrl);
|
||||
}
|
||||
|
||||
void GuiEditCtrl::pushToBack()
|
||||
{
|
||||
if (mSelectedControls.size() != 1)
|
||||
return;
|
||||
|
||||
GuiControl *ctrl = *(mSelectedControls.begin());
|
||||
mCurrentAddSet->pushObjectToBack(ctrl);
|
||||
}
|
||||
|
||||
bool GuiEditCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
if (! mActive)
|
||||
return Parent::onKeyDown(event);
|
||||
|
||||
if (event.modifier & SI_CTRL)
|
||||
{
|
||||
switch(event.keyCode)
|
||||
{
|
||||
case KEY_A:
|
||||
selectAll();
|
||||
break;
|
||||
case KEY_C:
|
||||
saveSelection("gui/clipboard.gui");
|
||||
break;
|
||||
case KEY_X:
|
||||
saveSelection("gui/clipboard.gui");
|
||||
deleteSelection();
|
||||
break;
|
||||
case KEY_V:
|
||||
loadSelection("gui/clipboard.gui");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 delta = (event.modifier & SI_SHIFT) ? 10 : 1;
|
||||
|
||||
switch(event.keyCode)
|
||||
{
|
||||
case KEY_RIGHT:
|
||||
moveSelection(Point2I(delta, 0));
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
moveSelection(Point2I(-delta, 0));
|
||||
break;
|
||||
case KEY_UP:
|
||||
moveSelection(Point2I(0, -delta));
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
moveSelection(Point2I(0, delta));
|
||||
break;
|
||||
case KEY_BACKSPACE:
|
||||
case KEY_DELETE:
|
||||
deleteSelection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
79
gui/guiEditCtrl.h
Normal file
79
gui/guiEditCtrl.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIEDITCTRL_H_
|
||||
#define _GUIEDITCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiEditCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
Vector<GuiControl *> mSelectedControls;
|
||||
GuiControl* mCurrentAddSet;
|
||||
GuiControl* mContentControl;
|
||||
Point2I mLastMousePos;
|
||||
Point2I mSelectionAnchor;
|
||||
Point2I mGridSnap;
|
||||
|
||||
enum mouseModes { Selecting, MovingSelection, SizingSelection, DragSelecting };
|
||||
enum sizingModes { sizingNone = 0, sizingLeft = 1, sizingRight = 2, sizingTop = 4, sizingBottom = 8 };
|
||||
|
||||
mouseModes mMouseDownMode;
|
||||
sizingModes mSizingMode;
|
||||
|
||||
public:
|
||||
GuiEditCtrl();
|
||||
DECLARE_CONOBJECT(GuiEditCtrl);
|
||||
static void consoleInit();
|
||||
|
||||
bool onWake();
|
||||
|
||||
void select(GuiControl *ctrl);
|
||||
void setRoot(GuiControl *ctrl);
|
||||
void setEditMode(bool value);
|
||||
S32 getSizingHitKnobs(const Point2I &pt, const RectI &box);
|
||||
void getDragRect(RectI &b);
|
||||
void drawNut(const Point2I &nut, bool);
|
||||
void drawNuts(RectI &box, bool);
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void addNewControl(GuiControl *ctrl);
|
||||
bool selectionContains(GuiControl *ctrl);
|
||||
void setCurrentAddSet(GuiControl *ctrl);
|
||||
void setSelection(GuiControl *ctrl, bool inclusive = false);
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onRightMouseDown(const GuiEvent &event);
|
||||
|
||||
enum Justification {
|
||||
JUSTIFY_LEFT,
|
||||
JUSTIFY_CENTER,
|
||||
JUSTIFY_RIGHT,
|
||||
JUSTIFY_TOP,
|
||||
JUSTIFY_BOTTOM,
|
||||
SPACING_VERTICAL,
|
||||
SPACING_HORIZONTAL
|
||||
};
|
||||
|
||||
void justifySelection( Justification j);
|
||||
void moveSelection(const Point2I &delta);
|
||||
void saveSelection(const char *filename);
|
||||
void loadSelection(const char *filename);
|
||||
void deleteSelection();
|
||||
void selectAll();
|
||||
void bringToFront();
|
||||
void pushToBack();
|
||||
};
|
||||
|
||||
#endif //_GUI_EDIT_CTRL_H
|
||||
251
gui/guiFilterCtrl.cc
Normal file
251
gui/guiFilterCtrl.cc
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "GUI/guiFilterCtrl.h"
|
||||
#include "Platform/event.h"
|
||||
#include "Math/mMath.h"
|
||||
|
||||
|
||||
GuiFilterCtrl::GuiFilterCtrl()
|
||||
{
|
||||
mControlPointRequest = 7;
|
||||
mFilter.setSize(7);
|
||||
identity();
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("controlPoints", TypeS32, Offset(mControlPointRequest, GuiFilterCtrl));
|
||||
addField("filter", TypeF32Vector, Offset(mFilter, GuiFilterCtrl));
|
||||
}
|
||||
|
||||
static const char* cGuiFilter_GetValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
argv;
|
||||
static char buffer[512];
|
||||
const Filter *filter = static_cast<GuiFilterCtrl*>(obj)->get();
|
||||
*buffer = 0;
|
||||
|
||||
for (U32 i=0; i < filter->size(); i++)
|
||||
{
|
||||
char value[32];
|
||||
dSprintf(value, 31, "%1.5f ", *(filter->begin()+i) );
|
||||
dStrcat(buffer, value);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void cGuiFilter_SetValue(SimObject *obj, S32 argc, const char **argv)
|
||||
{
|
||||
GuiFilterCtrl *ctrl = static_cast<GuiFilterCtrl*>(obj);
|
||||
Filter filter;
|
||||
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
filter.set(argc, argv);
|
||||
ctrl->set(filter);
|
||||
}
|
||||
|
||||
static void cGuiFilter_Identity(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiFilterCtrl *ctrl = static_cast<GuiFilterCtrl*>(obj);
|
||||
ctrl->identity();
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiFilterCtrl", "getValue", cGuiFilter_GetValue, "guiFilterCtrl.getValue()", 2, 2);
|
||||
Con::addCommand("GuiFilterCtrl", "setValue", cGuiFilter_SetValue, "guiFilterCtrl.setValue(f1, f2, ...)", 3, 20);
|
||||
Con::addCommand("GuiFilterCtrl", "identity", cGuiFilter_Identity, "guiFilterCtrl.identity()", 2, 2);
|
||||
}
|
||||
|
||||
|
||||
bool GuiFilterCtrl::onWake()
|
||||
{
|
||||
if (!Parent::onWake())
|
||||
return false;
|
||||
|
||||
if (U32(mControlPointRequest) != mFilter.size())
|
||||
{
|
||||
mFilter.setSize(mControlPointRequest);
|
||||
identity();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::identity()
|
||||
{
|
||||
S32 size = mFilter.size()-1;
|
||||
for (U32 i=0; S32(i) <= size; i++)
|
||||
mFilter[i] = (F32)i/(F32)size;
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
Point2I p = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
// determine which knot (offset same as in onRender)
|
||||
F32 w = F32(mBounds.extent.x-4) / F32(mFilter.size()-1);
|
||||
F32 val = (F32(p.x) + (w / 2.f)) / w;
|
||||
mCurKnot = S32(val);
|
||||
|
||||
mFilter[mCurKnot] = 1.0f - F32(getMin(getMax(0, p.y), mBounds.extent.y)/(F32)mBounds.extent.y);
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
|
||||
void GuiFilterCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
Point2I p = globalToLocalCoord(event.mousePoint);
|
||||
mFilter[mCurKnot] = 1.0f - F32(getMin(getMax(0, p.y), mBounds.extent.y)/(F32)mBounds.extent.y);
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::onMouseUp(const GuiEvent &)
|
||||
{
|
||||
mouseUnlock();
|
||||
if (mConsoleCommand[0])
|
||||
Con::evaluate(mConsoleCommand, false);
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::onPreRender()
|
||||
{
|
||||
if(U32(mControlPointRequest) != mFilter.size())
|
||||
{
|
||||
mFilter.setSize(mControlPointRequest);
|
||||
identity();
|
||||
setUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiFilterCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
Point2I pos = offset;
|
||||
Point2I ext = mBounds.extent;
|
||||
|
||||
RectI r(pos, ext);
|
||||
dglDrawRectFill(r, ColorI(255,255,255));
|
||||
dglDrawRect(r, ColorI(0,0,0));
|
||||
|
||||
// shrink by 2 pixels
|
||||
pos.x += 2;
|
||||
pos.y += 2;
|
||||
ext.x -= 4;
|
||||
ext.y -= 4;
|
||||
|
||||
// draw the identity line
|
||||
glColor3f(0.9, 0.9, 0.9);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(pos.x, pos.y+ext.y);
|
||||
glVertex2i(pos.x+ext.x, pos.y);
|
||||
glEnd();
|
||||
|
||||
// draw the curv
|
||||
glColor3f(0.4, 0.4, 0.4);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
||||
F32 scale = 1.0f/F32(ext.x);
|
||||
for (U32 i=0; S32(i) < ext.x; i++)
|
||||
{
|
||||
F32 index = F32(i)*scale;
|
||||
S32 y = (S32)(ext.y*(1.0f-mFilter.getValue(index)));
|
||||
glVertex2i(pos.x+i, pos.y+y );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// draw the knots
|
||||
for (U32 k=0; k < mFilter.size(); k++)
|
||||
{
|
||||
RectI r;
|
||||
r.point.x = (S32)(((F32)ext.x/(F32)(mFilter.size()-1)*(F32)k));
|
||||
r.point.y = (S32)(ext.y - ((F32)ext.y * mFilter[k]));
|
||||
r.point += pos + Point2I(-2,-2);
|
||||
r.extent = Point2I(5,5);
|
||||
|
||||
dglDrawRectFill(r, ColorI(255,0,0));
|
||||
}
|
||||
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
void Filter::set(S32 argc, const char *argv[])
|
||||
{
|
||||
setSize(0);
|
||||
if (argc == 1)
|
||||
{ // in the form of one string "1.0 1.0 1.0"
|
||||
char list[1024];
|
||||
dStrcpy(list, *argv); // strtok modifies the string so we need to copy it
|
||||
char *value = dStrtok(list, " ");
|
||||
while (value)
|
||||
{
|
||||
push_back(dAtof(value));
|
||||
value = dStrtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // in the form of seperate strings "1.0" "1.0" "1.0"
|
||||
for (; argc ; argc--, argv++)
|
||||
push_back(dAtof(*argv));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
F32 Filter::getValue(F32 x) const
|
||||
{
|
||||
if (size() < 2)
|
||||
return 0.0f;
|
||||
|
||||
x = mClampF(x, 0.0f, 1.0f);
|
||||
x *= F32(size()-1);
|
||||
|
||||
F32 p0,p1,p2,p3;
|
||||
S32 i1 = (S32)mFloor(x);
|
||||
S32 i2 = i1+1;
|
||||
F32 dt = x - F32(i1);
|
||||
|
||||
p1 = *(begin()+i1);
|
||||
p2 = *(begin()+i2);
|
||||
|
||||
if (i1 == 0)
|
||||
p0 = p1 + (p1 - p2);
|
||||
else
|
||||
p0 = *(begin()+i1-1);
|
||||
|
||||
if (i2 == S32(size()-1))
|
||||
p3 = p2 + (p2 - p1);
|
||||
else
|
||||
p3 = *(begin()+i2+1);
|
||||
|
||||
return mClampF( mCatmullrom(dt, p0, p1, p2, p3), 0.0f, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
77
gui/guiFilterCtrl.h
Normal file
77
gui/guiFilterCtrl.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIFILTERCTRL_H_
|
||||
#define _GUIFILTERCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
// helper class
|
||||
class Filter: public Vector<F32>
|
||||
{
|
||||
public:
|
||||
Filter() : Vector<F32>(__FILE__, __LINE__) { }
|
||||
|
||||
void set(S32 argc, const char *argv[]);
|
||||
F32 getValue(F32 t) const;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
class GuiFilterCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
S32 mControlPointRequest;
|
||||
S32 mCurKnot;
|
||||
Filter mFilter;
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiFilterCtrl);
|
||||
GuiFilterCtrl();
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
//Parental methods
|
||||
bool onWake();
|
||||
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &);
|
||||
|
||||
F32 getValue(S32 n);
|
||||
const Filter* get() { return &mFilter; }
|
||||
void set(const Filter &f);
|
||||
S32 getNumControlPoints() {return mFilter.size(); }
|
||||
void identity();
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
|
||||
inline F32 GuiFilterCtrl::getValue(S32 n)
|
||||
{
|
||||
S32 index = getMin(getMax(n,0), (S32)mFilter.size()-1);
|
||||
return mFilter[n];
|
||||
}
|
||||
|
||||
|
||||
inline void GuiFilterCtrl::set(const Filter &f)
|
||||
{
|
||||
mControlPointRequest = f.size();
|
||||
mFilter = f;
|
||||
}
|
||||
|
||||
#endif
|
||||
1048
gui/guiFrameCtrl.cc
Normal file
1048
gui/guiFrameCtrl.cc
Normal file
File diff suppressed because it is too large
Load diff
182
gui/guiFrameCtrl.h
Normal file
182
gui/guiFrameCtrl.h
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/******************************************************************************
|
||||
* FILENAME: D:\Tribes\darkstar\GUI\guiFrameCtrl.h
|
||||
*
|
||||
* DESCRIPTION: A gui control allowing a window to be subdivided into panes,
|
||||
* each of which displays a gui control child of the
|
||||
* GuiFrameSetCtrl. Each gui control child will have an associated
|
||||
* FrameDetail through which frame-specific details can be
|
||||
* assigned. Frame-specific values override the values specified
|
||||
* for the entire frameset.
|
||||
*
|
||||
* Note that it is possible to have more children than frames,
|
||||
* or more frames than children. In the former case, the extra
|
||||
* children will not be visible (they are moved beyond the
|
||||
* visible extent of the frameset). In the latter case, frames
|
||||
* will be empty.
|
||||
*
|
||||
* If a frameset had two columns and two rows but only three
|
||||
* gui control children they would be assigned to frames as
|
||||
* follows:
|
||||
* 1 | 2
|
||||
* -----
|
||||
* 3 |
|
||||
*
|
||||
* The last frame would be blank.
|
||||
*
|
||||
* CREATED: 10/08/99 14:40:24
|
||||
*
|
||||
* BY: PeteW
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _GUIFRAMECTRL_H_
|
||||
#define _GUIFRAMECTRL_H_
|
||||
|
||||
#define DISABLE_COPY_CTOR(className) \
|
||||
className(const className &)
|
||||
|
||||
#define DISABLE_ASSIGNMENT(className) \
|
||||
className& operator=(const className &)
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
// for debugging porpoises...
|
||||
#define GUI_FRAME_DEBUG
|
||||
// ...save the porpoises
|
||||
|
||||
class GuiFrameSetCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
public:
|
||||
enum
|
||||
{
|
||||
FRAME_STATE_ON, // ON overrides OFF
|
||||
FRAME_STATE_OFF, // OFF overrides AUTO
|
||||
FRAME_STATE_AUTO, // AUTO == ON, unless overridden
|
||||
|
||||
NO_HIT = -1,
|
||||
|
||||
DEFAULT_BORDER_WIDTH = 4,
|
||||
DEFAULT_COLUMNS = 1,
|
||||
DEFAULT_ROWS = 1,
|
||||
DEFAULT_MIN_FRAME_EXTENT = 20
|
||||
};
|
||||
enum Region
|
||||
{
|
||||
VERTICAL_DIVIDER,
|
||||
HORIZONTAL_DIVIDER,
|
||||
DIVIDER_INTERSECTION,
|
||||
NONE
|
||||
};
|
||||
struct FrameDetail
|
||||
{
|
||||
U32 mBorderWidth;
|
||||
ColorI mBorderColor;
|
||||
S32 mBorderEnable;
|
||||
S32 mBorderMovable;
|
||||
Point2I mMinExtent;
|
||||
FrameDetail() { mBorderWidth = DEFAULT_BORDER_WIDTH; mBorderEnable = FRAME_STATE_AUTO; mBorderMovable = FRAME_STATE_AUTO; mMinExtent.set(DEFAULT_MIN_FRAME_EXTENT, DEFAULT_MIN_FRAME_EXTENT); }
|
||||
};
|
||||
DECLARE_CONOBJECT(GuiFrameSetCtrl);
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
GuiFrameSetCtrl();
|
||||
GuiFrameSetCtrl(U32 columns, U32 rows, const U32 columnOffsets[] = NULL, const U32 rowOffsets[] = NULL);
|
||||
virtual ~GuiFrameSetCtrl();
|
||||
|
||||
void addObject(SimObject *object);
|
||||
void removeObject(SimObject *object);
|
||||
|
||||
virtual void resize(const Point2I &newPos, const Point2I &newExtent);
|
||||
|
||||
virtual void onMouseMove(const GuiEvent &event);
|
||||
virtual void onMouseDown(const GuiEvent &event);
|
||||
virtual void onMouseUp(const GuiEvent &event);
|
||||
virtual void onMouseDragged(const GuiEvent &event);
|
||||
virtual void onMouseEnter(const GuiEvent &event);
|
||||
virtual void onMouseLeave(const GuiEvent &event);
|
||||
|
||||
bool onAdd();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
protected:
|
||||
/* member variables */
|
||||
Vector<S32> mColumnOffsets;
|
||||
Vector<S32> mRowOffsets;
|
||||
GuiCursor *mMoveCursor;
|
||||
GuiCursor *mUpDownCursor;
|
||||
GuiCursor *mLeftRightCursor;
|
||||
GuiCursor *mDefaultCursor;
|
||||
FrameDetail mFramesetDetails;
|
||||
VectorPtr<FrameDetail *> mFrameDetails;
|
||||
bool mAutoBalance;
|
||||
S32 mFudgeFactor;
|
||||
|
||||
/* divider activation member variables */
|
||||
Region mCurHitRegion;
|
||||
Point2I mLocOnDivider;
|
||||
S32 mCurVerticalHit;
|
||||
S32 mCurHorizontalHit;
|
||||
|
||||
bool init(U32 columns, U32 rows, const U32 columnOffsets[], const U32 rowOffsets[]);
|
||||
bool initCursors();
|
||||
|
||||
Region findHitRegion(const Point2I &point);
|
||||
Region pointInAnyRegion(const Point2I &point);
|
||||
S32 findResizableFrames(S32 indexes[]);
|
||||
bool hitVerticalDivider(S32 x, const Point2I &point);
|
||||
bool hitHorizontalDivider(S32 y, const Point2I &point);
|
||||
|
||||
void rebalance(const Point2I &newExtent);
|
||||
|
||||
void computeSizes(bool balanceFrames = false);
|
||||
void computeMovableRange(Region hitRegion, S32 vertHit, S32 horzHit, S32 numIndexes, const S32 indexes[], S32 ranges[]);
|
||||
|
||||
void drawDividers(const Point2I &offset);
|
||||
public:
|
||||
U32 columns() const { return(mColumnOffsets.size()); }
|
||||
U32 rows() const { return(mRowOffsets.size()); }
|
||||
U32 borderWidth() const { return(mFramesetDetails.mBorderWidth); }
|
||||
Vector<S32>* columnOffsets() { return(&mColumnOffsets); }
|
||||
Vector<S32>* rowOffsets() { return(&mRowOffsets); }
|
||||
FrameDetail* framesetDetails() { return(&mFramesetDetails); }
|
||||
|
||||
bool findFrameContents(S32 index, GuiControl **gc, FrameDetail **fd);
|
||||
|
||||
void frameBorderEnable(S32 index, const char *state = NULL);
|
||||
void frameBorderMovable(S32 index, const char *state = NULL);
|
||||
void frameMinExtent(S32 index, const Point2I &extent);
|
||||
|
||||
void balanceFrames() { computeSizes(true); }
|
||||
void updateSizes() { computeSizes(); }
|
||||
|
||||
private:
|
||||
DISABLE_COPY_CTOR(GuiFrameSetCtrl);
|
||||
DISABLE_ASSIGNMENT(GuiFrameSetCtrl);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// x is the first value inside the next column, so the divider x-coords
|
||||
// precede x.
|
||||
inline bool GuiFrameSetCtrl::hitVerticalDivider(S32 x, const Point2I &point)
|
||||
{
|
||||
return((point.x >= S32(x - mFramesetDetails.mBorderWidth)) && (point.x < x) && (point.y >= 0) && (point.y < S32(mBounds.extent.y)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// y is the first value inside the next row, so the divider y-coords precede y.
|
||||
inline bool GuiFrameSetCtrl::hitHorizontalDivider(S32 y, const Point2I &point)
|
||||
{
|
||||
return((point.x >= 0) && (point.x < S32(mBounds.extent.x)) && (point.y >= S32(y - mFramesetDetails.mBorderWidth)) && (point.y < y));
|
||||
}
|
||||
|
||||
#endif // _GUI_FRAME_CTRL_H
|
||||
99
gui/guiHelpCtrl.cc
Normal file
99
gui/guiHelpCtrl.cc
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "g_surfac.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiHelpCtrl.h"
|
||||
|
||||
GuiHelpCtrl::GuiHelpCtrl(void)
|
||||
{
|
||||
//set the id
|
||||
id = guiHelpObjectID;
|
||||
|
||||
mHelpTag = 0;
|
||||
mHelpText = NULL;
|
||||
}
|
||||
|
||||
GuiHelpCtrl::~GuiHelpCtrl()
|
||||
{
|
||||
if (mHelpText)
|
||||
{
|
||||
delete [] (char*)mHelpText;
|
||||
mHelpText = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiHelpCtrl::onAdd(void)
|
||||
{
|
||||
if (! Parent::onAdd())
|
||||
return FALSE;
|
||||
|
||||
setGFXFont(mFont, mFontString);
|
||||
setGFXFont(mFontHL, mFontStringHL);
|
||||
setGFXFont(mFontNA, mFontStringNA);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void GuiHelpCtrl::render(GFXSurface *sfc)
|
||||
{
|
||||
if ((! mHelpText) || (! mHelpText[0]))
|
||||
return;
|
||||
|
||||
//if opaque, fill the update rect with the fill color
|
||||
if (mOpaque)
|
||||
{
|
||||
sfc->drawRect2d_f(&RectI(mPosition, Point2I(mPosition.x + mExtent.x - 1, mPosition.y + mExtent.y - 1)), mFillColor);
|
||||
}
|
||||
|
||||
//if there's a boarder, draw the boarder
|
||||
if (mBorder)
|
||||
{
|
||||
sfc->drawRect2d(&RectI(mPosition, Point2I(mPosition.x + mExtent.x - 1, mPosition.y + mExtent.y - 1)), mBorderColor);
|
||||
}
|
||||
|
||||
//draw the help text
|
||||
sfc->drawText_p(mFont, &Point2I(mPosition.x + 2, mPosition.y), mHelpText);
|
||||
}
|
||||
|
||||
void GuiHelpCtrl::setHelpText(guiCanvas *root, const char *text, F32 /* rElapsedTime */, bool /*mouseClicked*/)
|
||||
{
|
||||
Point2I newPos, newExt;
|
||||
if (mHelpText)
|
||||
{
|
||||
delete [] (char*)mHelpText;
|
||||
mHelpText = NULL;
|
||||
newPos.set(0, 0);
|
||||
newExt.set(1, 1);
|
||||
}
|
||||
|
||||
if (text && text[0])
|
||||
{
|
||||
mHelpText = strnew(text);
|
||||
mHelpTag = 0;
|
||||
|
||||
if (bool(mFont) && root)
|
||||
{
|
||||
newExt.set(mFont->getStrWidth(text) + 4, mFont->getHeight() + 4);
|
||||
newPos = root->getCursorPos();
|
||||
newPos.x = MAX(0, MIN(newPos.x, root->mExtent.x - newExt.x));
|
||||
newPos.y = MAX(0, MIN(newPos.y, root->mExtent.y - newExt.y));
|
||||
}
|
||||
}
|
||||
resize(newPos, newExt);
|
||||
}
|
||||
|
||||
void GuiHelpCtrl::setHelpTag(guiCanvas *root, S32 helpTag, F32 /* rElapsedTime */, bool /*mouseClicked*/)
|
||||
{
|
||||
if (mHelpText)
|
||||
{
|
||||
delete [] (char*)mHelpText;
|
||||
mHelpText = NULL;
|
||||
}
|
||||
|
||||
mHelpTag = helpTag;
|
||||
}
|
||||
40
gui/guiHelpCtrl.h
Normal file
40
gui/guiHelpCtrl.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIHELPCTRL_H_
|
||||
#define _GUIHELPCTRL_H_
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class guiCanvas;
|
||||
|
||||
class GuiHelpCtrl : public guiTextCtrl
|
||||
{
|
||||
|
||||
private:
|
||||
typedef guiTextCtrl Parent;
|
||||
|
||||
protected:
|
||||
S32 mHelpTag;
|
||||
const char *mHelpText;
|
||||
|
||||
public:
|
||||
GuiHelpCtrl();
|
||||
~GuiHelpCtrl();
|
||||
|
||||
bool onAdd(void);
|
||||
|
||||
virtual void setHelpText(guiCanvas *root, const char *text, F32 timeElapsed, bool mouseClicked = FALSE);
|
||||
virtual void setHelpTag(guiCanvas *root, S32 helpTag, F32 timeElapsed, bool mouseClicked = FALSE);
|
||||
virtual void render(GFXSurface *sfc);
|
||||
|
||||
DECLARE_PERSISTENT(GuiHelpCtrl);
|
||||
};
|
||||
|
||||
#endif //_GUI_HELP_CTRL_H
|
||||
94
gui/guiInputCtrl.cc
Normal file
94
gui/guiInputCtrl.cc
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "gui/guiInputCtrl.h"
|
||||
#include "sim/actionMap.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInputCtrl);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GuiInputCtrl::onWake()
|
||||
{
|
||||
// Set the default profile on start-up:
|
||||
if ( !mProfile )
|
||||
{
|
||||
SimObject *obj = Sim::findObject("GuiInputCtrlProfile");
|
||||
if ( obj )
|
||||
mProfile = dynamic_cast<GuiControlProfile*>( obj );
|
||||
}
|
||||
|
||||
if ( !Parent::onWake() )
|
||||
return( false );
|
||||
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiInputCtrl::onSleep()
|
||||
{
|
||||
Parent::onSleep();
|
||||
mouseUnlock();
|
||||
clearFirstResponder();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool isModifierKey( U16 keyCode )
|
||||
{
|
||||
switch ( keyCode )
|
||||
{
|
||||
case KEY_LCONTROL:
|
||||
case KEY_RCONTROL:
|
||||
case KEY_LALT:
|
||||
case KEY_RALT:
|
||||
case KEY_LSHIFT:
|
||||
case KEY_RSHIFT:
|
||||
return( true );
|
||||
}
|
||||
|
||||
return( false );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GuiInputCtrl::onInputEvent( const InputEvent &event )
|
||||
{
|
||||
// TODO - add POV support...
|
||||
if ( event.action == SI_MAKE )
|
||||
{
|
||||
if ( event.objType == SI_BUTTON
|
||||
|| event.objType == SI_POV
|
||||
|| ( ( event.objType == SI_KEY ) && !isModifierKey( event.objInst ) ) )
|
||||
{
|
||||
char deviceString[32];
|
||||
if ( !ActionMap::getDeviceName( event.deviceType, event.deviceInst, deviceString ) )
|
||||
return( false );
|
||||
|
||||
const char* actionString = ActionMap::buildActionString( &event );
|
||||
|
||||
Con::executef( this, 3, "onInputEvent", deviceString, actionString );
|
||||
return( true );
|
||||
}
|
||||
}
|
||||
else if ( event.action == SI_BREAK )
|
||||
{
|
||||
if ( ( event.objType == SI_KEY ) && isModifierKey( event.objInst ) )
|
||||
{
|
||||
char keyString[32];
|
||||
if ( !ActionMap::getKeyString( event.objInst, keyString ) )
|
||||
return( false );
|
||||
|
||||
Con::executef( this, 3, "onInputEvent", "keyboard", keyString );
|
||||
return( true );
|
||||
}
|
||||
}
|
||||
|
||||
return( false );
|
||||
}
|
||||
32
gui/guiInputCtrl.h
Normal file
32
gui/guiInputCtrl.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIINPUTCTRL_H_
|
||||
#define _GUIINPUTCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "Platform/event.h"
|
||||
#endif
|
||||
|
||||
class GuiInputCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInputCtrl);
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
bool onInputEvent( const InputEvent &event );
|
||||
};
|
||||
|
||||
#endif // _GUI_INPUTCTRL_H
|
||||
491
gui/guiInspector.cc
Normal file
491
gui/guiInspector.cc
Normal file
|
|
@ -0,0 +1,491 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "gui/guiTypes.h"
|
||||
#include "gui/guiTextCtrl.h"
|
||||
#include "gui/guiTextEditCtrl.h"
|
||||
#include "gui/guiInspector.h"
|
||||
#include "gui/guiCheckBoxCtrl.h"
|
||||
#include "gui/guiPopUpCtrl.h"
|
||||
#include "platform/event.h"
|
||||
|
||||
// datablocks
|
||||
#include "game/gameBase.h"
|
||||
#include "game/explosion.h"
|
||||
#include "game/particleEngine.h"
|
||||
#include "game/projectile.h"
|
||||
#include "sim/cannedChatDataBlock.h"
|
||||
#include "game/Debris.h"
|
||||
#include "game/commanderMapIcon.h"
|
||||
#include "game/shockwave.h"
|
||||
#include "game/splash.h"
|
||||
#include "game/shieldImpact.h"
|
||||
#include "game/projEnergy.h"
|
||||
#include "game/projBomb.h"
|
||||
|
||||
#define NULL_STRING "<NULL>"
|
||||
|
||||
GuiInspector::GuiInspector()
|
||||
{
|
||||
mEditControlOffset = 5;
|
||||
mEntryHeight = 16;
|
||||
mTextExtent = 80;
|
||||
mEntrySpacing = 2;
|
||||
mMaxMenuExtent = 80;
|
||||
}
|
||||
|
||||
void GuiInspector::onRemove()
|
||||
{
|
||||
mTarget = 0;
|
||||
while(size())
|
||||
first()->deleteObject();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static S32 QSORT_CALLBACK stringCompare(const void *a,const void *b)
|
||||
{
|
||||
StringTableEntry sa = *(StringTableEntry*)a;
|
||||
StringTableEntry sb = *(StringTableEntry*)b;
|
||||
return(dStricmp(sa, sb));
|
||||
}
|
||||
|
||||
void GuiInspector::inspect(SimObject * obj)
|
||||
{
|
||||
mTarget = obj;
|
||||
|
||||
while(size())
|
||||
first()->deleteObject();
|
||||
|
||||
S32 curYOffset = mEntrySpacing;
|
||||
|
||||
if(!bool(mTarget))
|
||||
{
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, curYOffset));
|
||||
return;
|
||||
}
|
||||
|
||||
// add in the static fields
|
||||
AbstractClassRep::FieldList fieldList = mTarget->getFieldList();
|
||||
AbstractClassRep::FieldList::iterator itr;
|
||||
for(itr = fieldList.begin(); itr != fieldList.end(); itr++)
|
||||
{
|
||||
if(itr->type == AbstractClassRep::DepricatedFieldType)
|
||||
continue;
|
||||
|
||||
char fdata[1024];
|
||||
const char * dstr = Con::getData(itr->type, (void *)(S32(obj) + itr->offset), 0, itr->table, itr->flag);
|
||||
if(!dstr)
|
||||
dstr = "";
|
||||
expandEscape(fdata, dstr);
|
||||
|
||||
GuiTextCtrl * textCtrl = new GuiTextCtrl();
|
||||
textCtrl->setField("profile", "GuiTextProfile");
|
||||
textCtrl->setField("text", itr->pFieldname);
|
||||
textCtrl->registerObject();
|
||||
addObject(textCtrl);
|
||||
|
||||
S32 textWidth = textCtrl->mProfile->mFont->getStrWidth(itr->pFieldname);
|
||||
S32 xStartPoint = (textWidth < (mTextExtent + mEntrySpacing + mEditControlOffset)) ?
|
||||
(mEntrySpacing + mTextExtent) : textWidth + mEditControlOffset;
|
||||
|
||||
textCtrl->mBounds.point = Point2I(mEntrySpacing, curYOffset);
|
||||
textCtrl->mBounds.extent = Point2I(textWidth, mEntryHeight);
|
||||
|
||||
S32 maxWidth = mBounds.extent.x - xStartPoint - mEntrySpacing;
|
||||
|
||||
//now add the field
|
||||
GuiControl * editControl = NULL;
|
||||
|
||||
switch(itr->type)
|
||||
{
|
||||
// text control
|
||||
default:
|
||||
{
|
||||
GuiTextEditCtrl * edit = new GuiTextEditCtrl();
|
||||
edit->setField("profile", "GuiInspectorTextEditProfile");
|
||||
edit->setField("text", fdata);
|
||||
editControl = edit;
|
||||
|
||||
edit->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
edit->mBounds.extent = Point2I(maxWidth, mEntryHeight);
|
||||
edit->setSizing(GuiControl::horizResizeWidth, GuiControl::vertResizeBottom);
|
||||
break;
|
||||
}
|
||||
|
||||
// checkbox
|
||||
case TypeBool:
|
||||
case TypeFlag:
|
||||
{
|
||||
GuiCheckBoxCtrl * checkBox = new GuiCheckBoxCtrl();
|
||||
checkBox->setField("profile", "GuiCheckBoxProfile");
|
||||
checkBox->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
checkBox->mBounds.extent = Point2I(mEntryHeight, mEntryHeight);
|
||||
checkBox->setScriptValue(fdata);
|
||||
|
||||
editControl = checkBox;
|
||||
break;
|
||||
}
|
||||
|
||||
// dropdown list
|
||||
case TypeEnum:
|
||||
{
|
||||
AssertFatal(itr->table, "TypeEnum declared with NULL table");
|
||||
GuiPopUpMenuCtrl * menu = new GuiPopUpMenuCtrl();
|
||||
menu->setField("profile", "GuiPopUpMenuProfile");
|
||||
menu->setField("text", fdata);
|
||||
|
||||
menu->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
menu->mBounds.extent = Point2I(getMin(maxWidth, mMaxMenuExtent), mEntryHeight);
|
||||
|
||||
//now add the entries
|
||||
for(S32 i = 0; i < itr->table->size; i++)
|
||||
menu->addEntry(itr->table->table[i].label, itr->table->table[i].index);
|
||||
|
||||
editControl = menu;
|
||||
break;
|
||||
}
|
||||
|
||||
// guiprofiles
|
||||
case TypeGuiProfile:
|
||||
{
|
||||
GuiPopUpMenuCtrl * menu = new GuiPopUpMenuCtrl();
|
||||
menu->setField("profile", "GuiPopUpMenuProfile");
|
||||
menu->setField("text", *fdata ? fdata : NULL_STRING);
|
||||
menu->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
menu->mBounds.extent = Point2I(getMin(maxWidth, mMaxMenuExtent), mEntryHeight);
|
||||
|
||||
// add 'NULL'
|
||||
menu->addEntry(NULL_STRING, -1);
|
||||
|
||||
// add entries to list so they can be sorted prior to adding to menu (want null on top)
|
||||
Vector<StringTableEntry> entries;
|
||||
|
||||
SimGroup * grp = Sim::getGuiDataGroup();
|
||||
for(SimGroup::iterator i = grp->begin(); i != grp->end(); i++)
|
||||
{
|
||||
GuiControlProfile * profile = dynamic_cast<GuiControlProfile *>(*i);
|
||||
if(profile)
|
||||
entries.push_back(profile->getName());
|
||||
}
|
||||
|
||||
// sort the entries
|
||||
dQsort(entries.address(), entries.size(), sizeof(StringTableEntry), stringCompare);
|
||||
for(U32 j = 0; j < entries.size(); j++)
|
||||
menu->addEntry(entries[j], 0);
|
||||
|
||||
editControl = menu;
|
||||
break;
|
||||
}
|
||||
|
||||
// datablock types
|
||||
case TypeGameBaseDataPtr:
|
||||
case TypeExplosionDataPtr:
|
||||
case TypeShockwaveDataPtr:
|
||||
case TypeSplashDataPtr:
|
||||
case TypeEnergyProjectileDataPtr:
|
||||
case TypeBombProjectileDataPtr:
|
||||
case TypeParticleEmitterDataPtr:
|
||||
case TypeAudioDescriptionPtr:
|
||||
case TypeAudioProfilePtr:
|
||||
case TypeProjectileDataPtr:
|
||||
case TypeCannedChatItemPtr:
|
||||
case TypeDebrisDataPtr:
|
||||
case TypeCommanderIconDataPtr:
|
||||
{
|
||||
GuiPopUpMenuCtrl * menu = new GuiPopUpMenuCtrl();
|
||||
menu->setField("profile", "GuiPopUpMenuProfile");
|
||||
menu->setField("text", *fdata ? fdata : NULL_STRING);
|
||||
menu->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
menu->mBounds.extent = Point2I(getMin(maxWidth, mMaxMenuExtent), mEntryHeight);
|
||||
|
||||
// add the 'NULL' entry on top
|
||||
menu->addEntry(NULL_STRING, -1);
|
||||
|
||||
// add to a list so they can be sorted
|
||||
Vector<StringTableEntry> entries;
|
||||
|
||||
SimGroup * grp = Sim::getDataBlockGroup();
|
||||
for(SimGroup::iterator i = grp->begin(); i != grp->end(); i++)
|
||||
{
|
||||
SimObject * obj = 0;
|
||||
switch(itr->type)
|
||||
{
|
||||
case TypeGameBaseDataPtr:
|
||||
obj = dynamic_cast<GameBaseData*>(*i);
|
||||
break;
|
||||
case TypeExplosionDataPtr:
|
||||
obj = dynamic_cast<ExplosionData*>(*i);
|
||||
break;
|
||||
case TypeShockwaveDataPtr:
|
||||
obj = dynamic_cast<ShockwaveData*>(*i);
|
||||
break;
|
||||
case TypeSplashDataPtr:
|
||||
obj = dynamic_cast<SplashData*>(*i);
|
||||
break;
|
||||
case TypeEnergyProjectileDataPtr:
|
||||
obj = dynamic_cast<EnergyProjectileData*>(*i);
|
||||
break;
|
||||
case TypeBombProjectileDataPtr:
|
||||
obj = dynamic_cast<BombProjectileData*>(*i);
|
||||
break;
|
||||
case TypeParticleEmitterDataPtr:
|
||||
obj = dynamic_cast<ParticleEmitterData*>(*i);
|
||||
break;
|
||||
case TypeAudioDescriptionPtr:
|
||||
obj = dynamic_cast<AudioDescription*>(*i);
|
||||
break;
|
||||
case TypeAudioProfilePtr:
|
||||
obj = dynamic_cast<AudioProfile*>(*i);
|
||||
break;
|
||||
case TypeProjectileDataPtr:
|
||||
obj = dynamic_cast<ProjectileData*>(*i);
|
||||
break;
|
||||
case TypeCannedChatItemPtr:
|
||||
obj = dynamic_cast<CannedChatItem*>(*i);
|
||||
break;
|
||||
case TypeDebrisDataPtr:
|
||||
obj = dynamic_cast<DebrisData*>(*i);
|
||||
break;
|
||||
case TypeCommanderIconDataPtr:
|
||||
obj = dynamic_cast<CommanderIconData*>(*i);
|
||||
break;
|
||||
}
|
||||
|
||||
if(obj)
|
||||
entries.push_back(obj->getName());
|
||||
}
|
||||
|
||||
// sort the entries
|
||||
dQsort(entries.address(), entries.size(), sizeof(StringTableEntry), stringCompare);
|
||||
for(U32 j = 0; j < entries.size(); j++)
|
||||
menu->addEntry(entries[j], 0);
|
||||
|
||||
editControl = menu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(editControl)
|
||||
{
|
||||
char buf[256];
|
||||
dSprintf(buf, sizeof(buf), "InspectStatic%s", itr->pFieldname);
|
||||
editControl->registerObject(buf);
|
||||
addObject(editControl);
|
||||
}
|
||||
|
||||
curYOffset += (mEntryHeight + mEntrySpacing);
|
||||
}
|
||||
|
||||
// dynamic field seperator: text
|
||||
GuiTextCtrl * textCtrl = new GuiTextCtrl();
|
||||
textCtrl->setField("profile", "GuiTextProfile");
|
||||
textCtrl->setField("text", " Dynamic Fields");
|
||||
textCtrl->registerObject();
|
||||
textCtrl->mBounds.point = Point2I(mEntrySpacing, curYOffset);
|
||||
textCtrl->mBounds.extent = Point2I(mTextExtent, mEntryHeight);
|
||||
addObject(textCtrl);
|
||||
|
||||
// button
|
||||
GuiButtonCtrl * button = new GuiButtonCtrl();
|
||||
button->setField("profile", "GuiButtonProfile");
|
||||
button->setField("text", "Add");
|
||||
|
||||
Con::setIntVariable("InspectingObject", mTarget->getId());
|
||||
Con::setIntVariable("Inspector", getId());
|
||||
|
||||
S32 textWidth = textCtrl->mProfile->mFont->getStrWidth(textCtrl->getScriptValue());
|
||||
S32 xStartPoint = (textWidth < (mTextExtent + mEntrySpacing + mEditControlOffset)) ?
|
||||
(mEntrySpacing + mTextExtent) : textWidth + mEditControlOffset;
|
||||
S32 maxWidth = mBounds.extent.x - xStartPoint - mEntrySpacing;
|
||||
|
||||
button->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
button->mBounds.extent = Point2I(getMin(maxWidth, mMaxMenuExtent), mEntryHeight);
|
||||
button->registerObject();
|
||||
|
||||
char buf[1024];
|
||||
dSprintf(buf, sizeof(buf), "%d.addDynamicField(%d);", getId(), mTarget->getId());
|
||||
button->setField("command", buf);
|
||||
addObject(button);
|
||||
|
||||
// offset
|
||||
curYOffset += (mEntryHeight + mEntrySpacing);
|
||||
|
||||
// add the dynamic fields
|
||||
SimFieldDictionary * fieldDictionary = mTarget->getFieldDictionary();
|
||||
for(SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
|
||||
{
|
||||
SimFieldDictionary::Entry * entry = (*ditr);
|
||||
|
||||
// create the name ctrl
|
||||
GuiTextCtrl * nameCtrl = new GuiTextCtrl();
|
||||
|
||||
nameCtrl->setField("profile", "GuiTextProfile");
|
||||
nameCtrl->setField("text", entry->slotName);
|
||||
nameCtrl->registerObject();
|
||||
addObject(nameCtrl);
|
||||
|
||||
nameCtrl->mBounds.point = Point2I(mEntrySpacing, curYOffset);
|
||||
nameCtrl->mBounds.extent = Point2I(mTextExtent, mEntryHeight);
|
||||
|
||||
// add a 'remove' button
|
||||
GuiButtonCtrl * button = new GuiButtonCtrl();
|
||||
|
||||
button->setField("profile", "GuiButtonProfile");
|
||||
button->setField("text", "x");
|
||||
button->registerObject();
|
||||
addObject(button);
|
||||
|
||||
char buf[1024];
|
||||
dSprintf(buf, sizeof(buf), "%d.%s = \"\";%d.inspect(%d);", mTarget->getId(), entry->slotName, getId(), mTarget->getId());
|
||||
button->setField("command", buf);
|
||||
|
||||
S32 textWidth = mProfile->mFont->getStrWidth(entry->slotName);
|
||||
|
||||
// 10x10 with 2x2 frame
|
||||
button->mBounds.point.set(textWidth + 4, curYOffset + 2);
|
||||
button->mBounds.extent.set(10, 10);
|
||||
|
||||
textWidth += 14;
|
||||
S32 xStartPoint = (textWidth < (mTextExtent + mEntrySpacing + mEditControlOffset)) ?
|
||||
(mEntrySpacing + mTextExtent) : textWidth + mEditControlOffset;
|
||||
S32 maxWidth = mBounds.extent.x - xStartPoint - mEntrySpacing;
|
||||
|
||||
expandEscape(buf, entry->value ? entry->value : "");
|
||||
|
||||
// create the edit ctrl
|
||||
GuiTextEditCtrl * editCtrl = new GuiTextEditCtrl();
|
||||
editCtrl->setField("profile", "GuiInspectorTextEditProfile");
|
||||
editCtrl->setField("text", buf);
|
||||
editCtrl->setSizing(GuiControl::horizResizeWidth, GuiControl::vertResizeBottom);
|
||||
|
||||
dSprintf(buf, sizeof(buf), "InspectDynamic%s", entry->slotName);
|
||||
editCtrl->registerObject(buf);
|
||||
addObject(editCtrl);
|
||||
|
||||
editCtrl->mBounds.point = Point2I(xStartPoint, curYOffset);
|
||||
editCtrl->mBounds.extent = Point2I(maxWidth, mEntryHeight);
|
||||
|
||||
curYOffset += (mEntryHeight + mEntrySpacing);
|
||||
}
|
||||
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, curYOffset));
|
||||
}
|
||||
|
||||
void GuiInspector::apply(const char * newName)
|
||||
{
|
||||
if(!bool(mTarget))
|
||||
{
|
||||
while(size())
|
||||
first()->deleteObject();
|
||||
return;
|
||||
}
|
||||
|
||||
mTarget->assignName(newName);
|
||||
mTarget->inspectPreApply();
|
||||
|
||||
SimObject * obj = static_cast<SimObject*>(mTarget);
|
||||
|
||||
//now add in the fields
|
||||
AbstractClassRep::FieldList fieldList = mTarget->getFieldList();
|
||||
AbstractClassRep::FieldList::iterator itr;
|
||||
for(itr = fieldList.begin(); itr != fieldList.end(); itr++)
|
||||
{
|
||||
if(itr->type == AbstractClassRep::DepricatedFieldType)
|
||||
continue;
|
||||
|
||||
char fdata[1024];
|
||||
dSprintf(fdata, sizeof(fdata), "InspectStatic%s", itr->pFieldname);
|
||||
GuiControl * editCtrl = NULL;
|
||||
SimObject * inspectObj = Sim::findObject(fdata);
|
||||
if(inspectObj)
|
||||
editCtrl = dynamic_cast<GuiControl*>(inspectObj);
|
||||
if(!editCtrl)
|
||||
continue;
|
||||
|
||||
const char * newValue = 0;
|
||||
|
||||
// check for null on profiles (-1 popup id)
|
||||
GuiPopUpMenuCtrl * menu = dynamic_cast<GuiPopUpMenuCtrl*>(editCtrl);
|
||||
if(!(menu && (menu->getSelected() == -1)))
|
||||
newValue = editCtrl->getScriptValue();
|
||||
|
||||
if(!newValue)
|
||||
newValue = "";
|
||||
|
||||
dStrcpy(fdata, newValue);
|
||||
collapseEscape(fdata);
|
||||
|
||||
//now set the field
|
||||
const char *argv[1];
|
||||
argv[0] = &fdata[0];
|
||||
Con::setData(itr->type, (void *)(S32(obj) + itr->offset), 0, 1, argv, itr->table, itr->flag);
|
||||
}
|
||||
|
||||
// get the dynamic field data
|
||||
SimFieldDictionary * fieldDictionary = mTarget->getFieldDictionary();
|
||||
for(SimFieldDictionaryIterator ditr(fieldDictionary); *ditr; ++ditr)
|
||||
{
|
||||
SimFieldDictionary::Entry * entry = (*ditr);
|
||||
|
||||
char buf[1024];
|
||||
dSprintf(buf, sizeof(buf), "InspectDynamic%s", entry->slotName);
|
||||
|
||||
GuiControl * editCtrl = static_cast<GuiControl*>(Sim::findObject(buf));
|
||||
if(!editCtrl)
|
||||
continue;
|
||||
|
||||
const char * newValue = editCtrl->getScriptValue();
|
||||
dStrcpy(buf, newValue ? newValue : "");
|
||||
collapseEscape(buf);
|
||||
|
||||
fieldDictionary->setFieldValue(entry->slotName, buf);
|
||||
}
|
||||
|
||||
mTarget->inspectPostApply();
|
||||
|
||||
//now re-inspect the object
|
||||
inspect(mTarget);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void cInspect(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiInspector * inspector = static_cast<GuiInspector*>(obj);
|
||||
SimObject * target = Sim::findObject(argv[2]);
|
||||
if(!target)
|
||||
{
|
||||
Con::printf("%s(): invalid object: %s", argv[0], argv[2]);
|
||||
return;
|
||||
}
|
||||
inspector->inspect(target);
|
||||
}
|
||||
|
||||
static void cApply(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiInspector *inspector = static_cast<GuiInspector*>(obj);
|
||||
inspector->apply(argv[2]);
|
||||
}
|
||||
|
||||
void GuiInspector::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiInspector", "inspect", cInspect, "inspector.inspect(obj)", 3, 3);
|
||||
Con::addCommand("GuiInspector", "apply", cApply, "inspector.apply(newName)", 3, 3);
|
||||
}
|
||||
|
||||
void GuiInspector::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("editControlOffset", TypeS32, Offset(mEditControlOffset, GuiInspector));
|
||||
addField("entryHeight", TypeS32, Offset(mEntryHeight, GuiInspector));
|
||||
addField("textExtent", TypeS32, Offset(mTextExtent, GuiInspector));
|
||||
addField("entrySpacing", TypeS32, Offset(mEntrySpacing, GuiInspector));
|
||||
addField("maxMenuExtent", TypeS32, Offset(mMaxMenuExtent, GuiInspector));
|
||||
}
|
||||
44
gui/guiInspector.h
Normal file
44
gui/guiInspector.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIINSPECTOR_H_
|
||||
#define _GUIINSPECTOR_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "GUI/guiArrayCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiInspector : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
SimObjectPtr<SimObject> mTarget;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiInspector);
|
||||
|
||||
GuiInspector();
|
||||
|
||||
// field data
|
||||
S32 mEditControlOffset;
|
||||
S32 mEntryHeight;
|
||||
S32 mTextExtent;
|
||||
S32 mEntrySpacing;
|
||||
S32 mMaxMenuExtent;
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
void onRemove();
|
||||
|
||||
void inspect(SimObject *);
|
||||
void apply(const char *);
|
||||
};
|
||||
|
||||
#endif
|
||||
1990
gui/guiMLTextCtrl.cc
Normal file
1990
gui/guiMLTextCtrl.cc
Normal file
File diff suppressed because it is too large
Load diff
257
gui/guiMLTextCtrl.h
Normal file
257
gui/guiMLTextCtrl.h
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIMLTEXTCTRL_H_
|
||||
#define _GUIMLTEXTCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/guiControl.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;
|
||||
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();
|
||||
|
||||
// Text substitution functions
|
||||
void setText(const char* textBuffer, const U32 numChars);
|
||||
void addText(const char* textBuffer, const U32 numChars, bool reformat);
|
||||
|
||||
bool setCursorPosition(const S32);
|
||||
void ensureCursorOnScreen();
|
||||
|
||||
// Scroll functions
|
||||
void scrollToTag( U32 id );
|
||||
void scrollToTop();
|
||||
|
||||
DECLARE_CONOBJECT(GuiMLTextCtrl);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
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;
|
||||
|
||||
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();
|
||||
virtual void reflow();
|
||||
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);
|
||||
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
|
||||
char* mTextBuffer;
|
||||
U32 mCurrTextSize;
|
||||
U32 mCurrBufferSize;
|
||||
U32 mLineStart;
|
||||
S32 mMaxBufferSize;
|
||||
|
||||
// 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 insertChars(const char* inputChars,
|
||||
const U32 numInputChars,
|
||||
const U32 position);
|
||||
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 onWake();
|
||||
void onSleep();
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
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&);
|
||||
};
|
||||
|
||||
#endif // _H_GUIMLTEXTCTRL_
|
||||
365
gui/guiMLTextEditCtrl.cc
Normal file
365
gui/guiMLTextEditCtrl.cc
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiMLTextEditCtrl.h"
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "Platform/event.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 ) );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMLTextEditCtrl::consoleInit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
char ascii = char(event.ascii);
|
||||
insertChars(&ascii, 1, 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 != mCurrTextSize)
|
||||
{
|
||||
// delete one character right
|
||||
deleteChars(mCursorPosition, mCursorPosition);
|
||||
setUpdate();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Should not be here!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
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 != mCurrTextSize )
|
||||
{
|
||||
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, "Should not be here!");
|
||||
}
|
||||
|
||||
ensureCursorOnScreen();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMLTextEditCtrl::onRender(Point2I offset, const RectI& updateRect, GuiControl* firstResponder)
|
||||
{
|
||||
Parent::onRender(offset, updateRect, firstResponder);
|
||||
|
||||
// We are the first responder, draw our cursor in the appropriate position...
|
||||
if (firstResponder == this) {
|
||||
Point2I top, bottom;
|
||||
ColorI color;
|
||||
getCursorPositionAndColor(top, bottom, color);
|
||||
dglDrawLine(top + offset, bottom + offset, mProfile->mCursorColor);
|
||||
}
|
||||
}
|
||||
|
||||
44
gui/guiMLTextEditCtrl.h
Normal file
44
gui/guiMLTextEditCtrl.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIMLTEXTEDITCTRL_H_
|
||||
#define _GUIMLTEXTEDITCTRL_H_
|
||||
|
||||
#ifndef _GUIMLTEXTCTRL_H_
|
||||
#include "GUI/guiMLTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiMLTextEditCtrl : public GuiMLTextCtrl
|
||||
{
|
||||
typedef GuiMLTextCtrl Parent;
|
||||
|
||||
//-------------------------------------- Overrides
|
||||
protected:
|
||||
StringTableEntry mEscapeCommand;
|
||||
|
||||
// Events
|
||||
bool onKeyDown(const GuiEvent&);
|
||||
|
||||
// Event forwards
|
||||
void handleMoveKeys(const GuiEvent&);
|
||||
void handleDeleteKeys(const GuiEvent&);
|
||||
|
||||
// rendering
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
|
||||
public:
|
||||
GuiMLTextEditCtrl();
|
||||
~GuiMLTextEditCtrl();
|
||||
|
||||
void resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
|
||||
DECLARE_CONOBJECT(GuiMLTextEditCtrl);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
#endif // _H_GUIMLTEXTEDITCTRL_
|
||||
693
gui/guiMenuBar.cc
Normal file
693
gui/guiMenuBar.cc
Normal file
|
|
@ -0,0 +1,693 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "gui/guiCanvas.h"
|
||||
#include "gui/guiDefaultControlRender.h"
|
||||
#include "gui/guiTextListCtrl.h"
|
||||
#include "sim/actionMap.h"
|
||||
#include "gui/guiMenuBar.h"
|
||||
|
||||
// menu bar:
|
||||
// basic idea - fixed height control bar at the top of a window, placed and sized in gui editor
|
||||
// menu text for menus or menu items should not begin with a digit
|
||||
// all menus can be removed via the clearMenus() console command
|
||||
// each menu is added via the addMenu(menuText, menuId) console command
|
||||
// each menu is added with a menu id
|
||||
// menu items are added to menus via that addMenuItem(menu, menuItemText, menuItemId, accelerator) console command
|
||||
// each menu item is added with a menu item id and an optional accelerator
|
||||
// menu items are initially enabled, but can be disabled/re-enabled via the setMenuItemEnable(menu,menuItem,bool)
|
||||
// menu text can be set via the setMenuText(menu, newMenuText) console method
|
||||
// menu item text can be set via the setMenuItemText console method
|
||||
// menu items can be removed via the removeMenuItem(menu, menuItem) console command
|
||||
// menu items can be cleared via the clearMenuItems(menu) console command
|
||||
// menus can be removed via the removeMenu console command
|
||||
// specification arguments for menus and menu items can be either the id or the text of the menu or menu item
|
||||
// adding the menu item "-" will add an un-selectable seperator to the menu
|
||||
// callbacks:
|
||||
// when a menu is clicked, before it is displayed, the menu calls its onMenuSelect(menuId, menuText) method -
|
||||
// this allows the callback to enable/disable menu items, or add menu items in a context-sensitive way
|
||||
// when a menu item is clicked, the menu removes itself from display, then calls onMenuItemSelect(menuId, menuText, menuItemId, menuItemText)
|
||||
|
||||
// the initial implementation does not support:
|
||||
// hierarchal menus
|
||||
// keyboard accelerators on menu text (i.e. via alt-key combos)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// console methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ConsoleMethod(GuiMenuBar, clearMenus, void, 2, 2, "() - clears all the menus from the menu bar.")
|
||||
{
|
||||
((GuiMenuBar *)object)->clearMenus();
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, addMenu, void, 4, 4, "(string menuText, int menuId) - adds a new menu to the menu bar.")
|
||||
{
|
||||
if(dIsdigit(argv[2][0]))
|
||||
{
|
||||
Con::errorf("Cannot add menu %s (id = %s). First character of a menu's text cannot be a digit.", argv[2], argv[3]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
menuBar->addMenu(argv[2], dAtoi(argv[3]));
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, addMenuItem, void, 5, 6, "(string menu, string menuItemText, int menuItemId, string accelerator = NULL) - adds a menu item to the specified menu. The menu argument can be either the text of a menu or its id.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
if(dIsdigit(argv[3][0]))
|
||||
{
|
||||
Con::errorf("Cannot add menu item %s (id = %s). First character of a menu item's text cannot be a digit.", argv[3], argv[4]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for addMenuItem.", argv[2]);
|
||||
return;
|
||||
}
|
||||
menuBar->addMenuItem(menu, argv[3], dAtoi(argv[4]), argc == 5 ? NULL : argv[5]);
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, setMenuItemEnable, void, 5, 5, "(string menu, string menuItem, bool enabled) - sets the menu item to enabled or disabled based on the enable parameter. The specified menu and menu item can either be text or ids.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for setMenuItemEnable.", argv[2]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar::MenuItem *menuItem = menuBar->findMenuItem(menu, argv[3]);
|
||||
if(!menuItem)
|
||||
{
|
||||
Con::errorf("Cannot find menu item %s for setMenuItemEnable.", argv[3]);
|
||||
return;
|
||||
}
|
||||
menuItem->enabled = dAtob(argv[4]);
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, setMenuText, void, 4, 4, "(string menu, string newMenuText) - sets the text of the specified menu to the new string.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
if(dIsdigit(argv[3][0]))
|
||||
{
|
||||
Con::errorf("Cannot name menu %s to %s. First character of a menu's text cannot be a digit.", argv[2], argv[3]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for setMenuText.", argv[2]);
|
||||
return;
|
||||
}
|
||||
dFree(menu->text);
|
||||
menu->text = dStrdup(argv[3]);
|
||||
menuBar->menuBarDirty = true;
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, setMenuItemText, void, 5, 5, "(string menu, string menuItem, string newMenuItemText) - sets the text of the specified menu item to the new string.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
if(dIsdigit(argv[4][0]))
|
||||
{
|
||||
Con::errorf("Cannot name menu item %s to %s. First character of a menu item's text cannot be a digit.", argv[3], argv[4]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for setMenuItemText.", argv[2]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar::MenuItem *menuItem = menuBar->findMenuItem(menu, argv[3]);
|
||||
if(!menuItem)
|
||||
{
|
||||
Con::errorf("Cannot find menu item %s for setMenuItemText.", argv[3]);
|
||||
return;
|
||||
}
|
||||
dFree(menuItem->text);
|
||||
menuItem->text = dStrdup(argv[4]);
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, removeMenuItem, void, 4, 4, "(string menu, string menuItem) - removes the specified menu item from the menu.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for removeMenuItem.", argv[2]);
|
||||
return;
|
||||
}
|
||||
GuiMenuBar::MenuItem *menuItem = menuBar->findMenuItem(menu, argv[3]);
|
||||
if(!menuItem)
|
||||
{
|
||||
Con::errorf("Cannot find menu item %s for removeMenuItem.", argv[3]);
|
||||
return;
|
||||
}
|
||||
menuBar->removeMenuItem(menu, menuItem);
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, clearMenuItems, void, 3, 3, "(string menu) - removes all the menu items from the specified menu.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for clearMenuItems.", argv[2]);
|
||||
return;
|
||||
}
|
||||
menuBar->clearMenuItems(menu);
|
||||
}
|
||||
|
||||
ConsoleMethod(GuiMenuBar, removeMenu, void, 3, 3, "(string menu) - removes the specified menu from the menu bar.")
|
||||
{
|
||||
GuiMenuBar *menuBar = (GuiMenuBar *) object;
|
||||
|
||||
GuiMenuBar::Menu *menu = menuBar->findMenu(argv[2]);
|
||||
if(!menu)
|
||||
{
|
||||
Con::errorf("Cannot find menu %s for removeMenu.", argv[2]);
|
||||
return;
|
||||
}
|
||||
menuBar->clearMenuItems(menu);
|
||||
menuBar->menuBarDirty = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// menu management methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
|
||||
{
|
||||
// allocate the menu
|
||||
Menu *newMenu = new Menu;
|
||||
newMenu->text = dStrdup(menuText);
|
||||
newMenu->id = menuId;
|
||||
newMenu->nextMenu = NULL;
|
||||
newMenu->firstMenuItem = NULL;
|
||||
|
||||
// add it to the menu list
|
||||
menuBarDirty = true;
|
||||
Menu **walk;
|
||||
for(walk = &menuList; *walk; walk = &(*walk)->nextMenu)
|
||||
;
|
||||
*walk = newMenu;
|
||||
}
|
||||
|
||||
GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu)
|
||||
{
|
||||
if(dIsdigit(menu[0]))
|
||||
{
|
||||
U32 id = dAtoi(menu);
|
||||
for(Menu *walk = menuList; walk; walk = walk->nextMenu)
|
||||
if(id == walk->id)
|
||||
return walk;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(Menu *walk = menuList; walk; walk = walk->nextMenu)
|
||||
if(!dStricmp(menu, walk->text))
|
||||
return walk;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GuiMenuBar::MenuItem *GuiMenuBar::findMenuItem(Menu *menu, const char *menuItem)
|
||||
{
|
||||
if(dIsdigit(menuItem[0]))
|
||||
{
|
||||
U32 id = dAtoi(menuItem);
|
||||
for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
|
||||
if(id == walk->id)
|
||||
return walk;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
|
||||
if(!dStricmp(menuItem, walk->text))
|
||||
return walk;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::removeMenu(Menu *menu)
|
||||
{
|
||||
menuBarDirty = true;
|
||||
clearMenuItems(menu);
|
||||
for(Menu **walk = &menuList; *walk; walk = &(*walk)->nextMenu)
|
||||
{
|
||||
if(*walk == menu)
|
||||
{
|
||||
*walk = menu->nextMenu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dFree(menu->text);
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void GuiMenuBar::removeMenuItem(Menu *menu, MenuItem *menuItem)
|
||||
{
|
||||
for(MenuItem **walk = &menu->firstMenuItem; *walk; walk = &(*walk)->nextMenuItem)
|
||||
{
|
||||
if(*walk == menuItem)
|
||||
{
|
||||
*walk = menuItem->nextMenuItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dFree(menuItem->text);
|
||||
dFree(menuItem->accelerator);
|
||||
delete menuItem;
|
||||
}
|
||||
|
||||
void GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator)
|
||||
{
|
||||
// allocate the new menu item
|
||||
MenuItem *newMenuItem = new MenuItem;
|
||||
newMenuItem->text = dStrdup(text);
|
||||
if(accelerator)
|
||||
newMenuItem->accelerator = dStrdup(accelerator);
|
||||
else
|
||||
newMenuItem->accelerator = NULL;
|
||||
newMenuItem->id = id;
|
||||
newMenuItem->nextMenuItem = NULL;
|
||||
newMenuItem->acceleratorIndex = 0;
|
||||
newMenuItem->enabled = true;
|
||||
|
||||
// link it into the menu's menu item list
|
||||
MenuItem **walk = &menu->firstMenuItem;
|
||||
while(*walk)
|
||||
walk = &(*walk)->nextMenuItem;
|
||||
*walk = newMenuItem;
|
||||
|
||||
}
|
||||
|
||||
void GuiMenuBar::clearMenuItems(Menu *menu)
|
||||
{
|
||||
while(menu->firstMenuItem)
|
||||
removeMenuItem(menu, menu->firstMenuItem);
|
||||
}
|
||||
|
||||
void GuiMenuBar::clearMenus()
|
||||
{
|
||||
while(menuList)
|
||||
removeMenu(menuList);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// initialization, input and render methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
GuiMenuBar::GuiMenuBar()
|
||||
{
|
||||
menuList = NULL;
|
||||
menuBarDirty = true;
|
||||
mouseDownMenu = NULL;
|
||||
mouseOverMenu = NULL;
|
||||
mCurAcceleratorIndex = 0;
|
||||
}
|
||||
|
||||
GuiMenuBar::Menu *GuiMenuBar::findHitMenu(Point2I mousePoint)
|
||||
{
|
||||
Point2I pos = globalToLocalCoord(mousePoint);
|
||||
|
||||
for(Menu *walk = menuList; walk; walk = walk->nextMenu)
|
||||
if(walk->bounds.pointInRect(pos))
|
||||
return walk;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GuiMenuBar::onPreRender()
|
||||
{
|
||||
Parent::onPreRender();
|
||||
if(menuBarDirty)
|
||||
{
|
||||
menuBarDirty = false;
|
||||
U32 curX = 0;
|
||||
for(Menu *walk = menuList; walk; walk = walk->nextMenu)
|
||||
{
|
||||
walk->bounds.set(curX, 1, mProfile->mFont->getStrWidth(walk->text) + 12, mBounds.extent.y - 2);
|
||||
curX += walk->bounds.extent.x;
|
||||
}
|
||||
mouseOverMenu = NULL;
|
||||
mouseDownMenu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event)
|
||||
{
|
||||
Menu *hit = findHitMenu(event.mousePoint);
|
||||
if(hit && hit != mouseDownMenu)
|
||||
{
|
||||
// gotta close out the current menu...
|
||||
mTextList->setSelectedCell(Point2I(-1, -1));
|
||||
closeMenu();
|
||||
mouseOverMenu = mouseDownMenu = hit;
|
||||
setUpdate();
|
||||
onAction();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::onMouseMove(const GuiEvent &event)
|
||||
{
|
||||
Menu *hit = findHitMenu(event.mousePoint);
|
||||
if(hit != mouseOverMenu)
|
||||
{
|
||||
mouseOverMenu = hit;
|
||||
setUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::onMouseLeave(const GuiEvent &event)
|
||||
{
|
||||
if(mouseOverMenu)
|
||||
setUpdate();
|
||||
mouseOverMenu = NULL;
|
||||
}
|
||||
|
||||
void GuiMenuBar::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
Menu *hit = findHitMenu(event.mousePoint);
|
||||
|
||||
if(hit != mouseOverMenu)
|
||||
{
|
||||
mouseOverMenu = hit;
|
||||
mouseDownMenu = hit;
|
||||
setUpdate();
|
||||
onAction();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
mouseDownMenu = mouseOverMenu = findHitMenu(event.mousePoint);
|
||||
setUpdate();
|
||||
onAction();
|
||||
}
|
||||
|
||||
void GuiMenuBar::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
mouseDownMenu = NULL;
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
//if opaque, fill the update rect with the fill color
|
||||
if (mProfile->mOpaque)
|
||||
dglDrawRectFill(RectI(offset, mBounds.extent), mProfile->mFillColor);
|
||||
|
||||
for(Menu *walk = menuList; walk; walk = walk->nextMenu)
|
||||
{
|
||||
ColorI fontColor = mProfile->mFontColor;
|
||||
RectI bounds = walk->bounds;
|
||||
bounds.point += offset;
|
||||
|
||||
Point2I start;
|
||||
|
||||
start.x = walk->bounds.point.x + 6;
|
||||
start.y = walk->bounds.point.y + ( walk->bounds.extent.y - ( mProfile->mFont->getHeight() - 2 ) ) / 2;
|
||||
|
||||
if(walk == mouseDownMenu)
|
||||
renderSlightlyLoweredBox(bounds);
|
||||
else if(walk == mouseOverMenu && mouseDownMenu == NULL)
|
||||
renderSlightlyRaisedBox(bounds);
|
||||
|
||||
dglSetBitmapModulation( fontColor );
|
||||
|
||||
dglDrawText( mProfile->mFont, start + offset, walk->text, mProfile->mFontColors );
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::buildAcceleratorMap()
|
||||
{
|
||||
Parent::buildAcceleratorMap();
|
||||
// ok, accelerator map is cleared...
|
||||
// add all our keys:
|
||||
mCurAcceleratorIndex = 1;
|
||||
|
||||
for(Menu *menu = menuList; menu; menu = menu->nextMenu)
|
||||
{
|
||||
for(MenuItem *item = menu->firstMenuItem; item; item = item->nextMenuItem)
|
||||
{
|
||||
if(!item->accelerator)
|
||||
{
|
||||
item->accelerator = 0;
|
||||
continue;
|
||||
}
|
||||
EventDescriptor accelEvent;
|
||||
ActionMap::createEventDescriptor(item->accelerator, &accelEvent);
|
||||
|
||||
//now we have a modifier, and a key, add them to the canvas
|
||||
GuiCanvas *root = getRoot();
|
||||
if (root)
|
||||
root->addAcceleratorKey(this, mCurAcceleratorIndex, accelEvent.eventCode, accelEvent.flags);
|
||||
item->acceleratorIndex = mCurAcceleratorIndex;
|
||||
mCurAcceleratorIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiMenuBar::acceleratorKeyPress(U32 index)
|
||||
{
|
||||
// loop through all the menus
|
||||
// and find the item that corresponds to the accelerator index
|
||||
for(Menu *menu = menuList; menu; menu = menu->nextMenu)
|
||||
{
|
||||
for(MenuItem *item = menu->firstMenuItem; item; item = item->nextMenuItem)
|
||||
{
|
||||
if(item->acceleratorIndex == index)
|
||||
{
|
||||
menuItemSelected(menu, item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Menu display class methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
GuiMenuBackgroundCtrl::GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList)
|
||||
{
|
||||
mMenuBarCtrl = ctrl;
|
||||
mTextList = textList;
|
||||
}
|
||||
|
||||
void GuiMenuBackgroundCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
mTextList->setSelectedCell(Point2I(-1,-1));
|
||||
mMenuBarCtrl->closeMenu();
|
||||
}
|
||||
|
||||
void GuiMenuBackgroundCtrl::onMouseMove(const GuiEvent &event)
|
||||
{
|
||||
GuiCanvas *root = getRoot();
|
||||
GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1);
|
||||
if(ctrlHit == mMenuBarCtrl) // see if the current mouse over menu is right...
|
||||
mMenuBarCtrl->checkMenuMouseMove(event);
|
||||
}
|
||||
|
||||
void GuiMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
GuiCanvas *root = getRoot();
|
||||
GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1);
|
||||
if(ctrlHit == mMenuBarCtrl) // see if the current mouse over menu is right...
|
||||
mMenuBarCtrl->checkMenuMouseMove(event);
|
||||
}
|
||||
|
||||
GuiMenuTextListCtrl::GuiMenuTextListCtrl(GuiMenuBar *ctrl)
|
||||
{
|
||||
mMenuBarCtrl = ctrl;
|
||||
}
|
||||
|
||||
void GuiMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
|
||||
{
|
||||
if(dStrcmp(mList[cell.y].text, "-\t"))
|
||||
Parent::onRenderCell(offset, cell, selected, mouseOver);
|
||||
else
|
||||
{
|
||||
S32 yp = offset.y + mCellSize.y / 2;
|
||||
dglDrawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128,128,128));
|
||||
dglDrawLine(offset.x, yp+1, offset.x + mCellSize.x, yp+1, ColorI(255,255,255));
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiMenuTextListCtrl::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 )
|
||||
{
|
||||
mMenuBarCtrl->closeMenu();
|
||||
return true;
|
||||
}
|
||||
else if ( event.keyCode == KEY_ESCAPE )
|
||||
{
|
||||
mSelectedCell.set( -1, -1 );
|
||||
mMenuBarCtrl->closeMenu();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//otherwise, pass the event to it's parent
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
void GuiMenuTextListCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
mMenuBarCtrl->closeMenu();
|
||||
}
|
||||
|
||||
void GuiMenuTextListCtrl::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
// ok, this is kind of strange... but!
|
||||
// here's the deal: if we get a mouse up in this control
|
||||
// it means the mouse was dragged from the initial menu mouse click
|
||||
// so: activate the menu result as though this event were,
|
||||
// instead, a mouse down.
|
||||
|
||||
onMouseDown(event);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void GuiMenuBar::menuItemSelected(GuiMenuBar::Menu *menu, GuiMenuBar::MenuItem *item)
|
||||
{
|
||||
if(item->enabled)
|
||||
Con::executef( this, 6, "onMenuItemSelect", Con::getIntArg(menu->id),
|
||||
menu->text, Con::getIntArg(item->id), item->text);
|
||||
}
|
||||
|
||||
void GuiMenuBar::closeMenu()
|
||||
{
|
||||
// Get the selection from the text list:
|
||||
S32 selectionIndex = mTextList->getSelectedCell().y;
|
||||
|
||||
// Pop the background:
|
||||
getRoot()->popDialogControl(mBackground);
|
||||
|
||||
// Kill the popup:
|
||||
mBackground->deleteObject();
|
||||
|
||||
// Now perform the popup action:
|
||||
if ( selectionIndex != -1 )
|
||||
{
|
||||
MenuItem *list = mouseDownMenu->firstMenuItem;
|
||||
|
||||
while(selectionIndex && list)
|
||||
{
|
||||
list = list->nextMenuItem;
|
||||
selectionIndex--;
|
||||
}
|
||||
if(list)
|
||||
menuItemSelected(mouseDownMenu, list);
|
||||
}
|
||||
mouseDownMenu = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiMenuBar::onAction()
|
||||
{
|
||||
if(!mouseDownMenu)
|
||||
return;
|
||||
|
||||
// first, call the script callback for menu selection:
|
||||
Con::executef( this, 4, "onMenuSelect", Con::getIntArg(mouseDownMenu->id),
|
||||
mouseDownMenu->text);
|
||||
|
||||
if(!mouseDownMenu->firstMenuItem)
|
||||
{
|
||||
mouseDownMenu = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
mTextList = new GuiMenuTextListCtrl(this);
|
||||
mTextList->mProfile = mProfile;
|
||||
|
||||
mBackground = new GuiMenuBackgroundCtrl(this, mTextList);
|
||||
|
||||
GuiCanvas *root = getRoot();
|
||||
Point2I windowExt = root->mBounds.extent;
|
||||
|
||||
mBackground->mBounds.point.set(0,0);
|
||||
mBackground->mBounds.extent = root->mBounds.extent;
|
||||
|
||||
S32 textWidth = 0, width = 0;
|
||||
S32 acceleratorWidth = 0;
|
||||
|
||||
GFont *font = mProfile->mFont;
|
||||
|
||||
for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem)
|
||||
{
|
||||
S32 iTextWidth = font->getStrWidth(walk->text);
|
||||
S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0;
|
||||
|
||||
if(iTextWidth > textWidth)
|
||||
textWidth = iTextWidth;
|
||||
if(iAcceleratorWidth > acceleratorWidth)
|
||||
acceleratorWidth = iAcceleratorWidth;
|
||||
}
|
||||
width = textWidth + acceleratorWidth + 8;
|
||||
|
||||
mTextList->setCellSize(Point2I(width, font->getHeight()+3));
|
||||
mTextList->addColumnOffset(textWidth + 4);
|
||||
|
||||
U32 entryCount = 0;
|
||||
|
||||
for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem)
|
||||
{
|
||||
char buf[512];
|
||||
dSprintf(buf, sizeof(buf), "%s\t%s", walk->text, walk->accelerator ? walk->accelerator : "");
|
||||
mTextList->addEntry(entryCount, buf);
|
||||
|
||||
if(!walk->enabled)
|
||||
mTextList->setEntryActive(entryCount, false);
|
||||
|
||||
entryCount++;
|
||||
}
|
||||
Point2I menuPoint = localToGlobalCoord(mouseDownMenu->bounds.point);
|
||||
menuPoint.y += mouseDownMenu->bounds.extent.y + 2;
|
||||
|
||||
GuiControl *ctrl = new GuiControl;
|
||||
ctrl->mBounds.point = menuPoint;
|
||||
ctrl->mBounds.extent = mTextList->mBounds.extent + Point2I(6, 6);
|
||||
ctrl->mProfile = mProfile;
|
||||
mTextList->mBounds.point += Point2I(3,3);
|
||||
|
||||
//mTextList->mBounds.point = Point2I(3,3);
|
||||
|
||||
mTextList->registerObject();
|
||||
mBackground->registerObject();
|
||||
ctrl->registerObject();
|
||||
|
||||
mBackground->addObject( ctrl );
|
||||
ctrl->addObject( mTextList );
|
||||
|
||||
root->pushDialogControl(mBackground, mLayer + 1);
|
||||
mTextList->setFirstResponder();
|
||||
}
|
||||
|
||||
|
||||
125
gui/guiMenuBar.h
Normal file
125
gui/guiMenuBar.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIMENUBAR_H_
|
||||
#define _GUIMENUBAR_H_
|
||||
|
||||
#ifndef _GUITEXTLISTCTRL_H_
|
||||
#include "gui/guiTextListCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiMenuBar;
|
||||
class GuiMenuTextListCtrl;
|
||||
|
||||
class GuiMenuBackgroundCtrl : public GuiControl
|
||||
{
|
||||
protected:
|
||||
GuiMenuBar *mMenuBarCtrl;
|
||||
GuiMenuTextListCtrl *mTextList;
|
||||
public:
|
||||
GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class GuiMenuTextListCtrl : public GuiTextListCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextListCtrl Parent;
|
||||
|
||||
protected:
|
||||
GuiMenuBar *mMenuBarCtrl;
|
||||
|
||||
public:
|
||||
GuiMenuTextListCtrl(); // for inheritance
|
||||
GuiMenuTextListCtrl(GuiMenuBar *ctrl);
|
||||
|
||||
// GuiControl overloads:
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class GuiMenuBar : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
public:
|
||||
|
||||
struct MenuItem // an individual item in a pull-down menu
|
||||
{
|
||||
char *text; // the text of the menu item
|
||||
U32 id; // a script-assigned identifier
|
||||
char *accelerator; // the keyboard accelerator shortcut for the menu item
|
||||
U32 acceleratorIndex; // index of this accelerator
|
||||
bool enabled; // true if the menu item is selectable
|
||||
MenuItem *nextMenuItem; // next menu item in the linked list
|
||||
};
|
||||
struct Menu
|
||||
{
|
||||
char *text;
|
||||
U32 id;
|
||||
RectI bounds;
|
||||
|
||||
Menu *nextMenu;
|
||||
MenuItem *firstMenuItem;
|
||||
};
|
||||
|
||||
GuiMenuBackgroundCtrl *mBackground;
|
||||
GuiMenuTextListCtrl *mTextList;
|
||||
|
||||
Menu *menuList;
|
||||
Menu *mouseDownMenu;
|
||||
Menu *mouseOverMenu;
|
||||
|
||||
bool menuBarDirty;
|
||||
U32 mCurAcceleratorIndex;
|
||||
|
||||
GuiMenuBar();
|
||||
|
||||
// internal menu handling functions
|
||||
// these are used by the script manipulation functions to add/remove/change menu items
|
||||
|
||||
void addMenu(const char *menuText, U32 menuId);
|
||||
Menu *findMenu(const char *menu); // takes either a menu text or a string id
|
||||
MenuItem *findMenuItem(Menu *menu, const char *menuItem); // takes either a menu text or a string id
|
||||
void removeMenu(Menu *menu);
|
||||
void removeMenuItem(Menu *menu, MenuItem *menuItem);
|
||||
void addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator);
|
||||
void clearMenuItems(Menu *menu);
|
||||
void clearMenus();
|
||||
|
||||
// display/mouse functions
|
||||
|
||||
Menu *findHitMenu(Point2I mousePoint);
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
|
||||
void checkMenuMouseMove(const GuiEvent &event);
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseLeave(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
|
||||
void onAction();
|
||||
void closeMenu();
|
||||
void buildAcceleratorMap();
|
||||
void acceleratorKeyPress(U32 index);
|
||||
|
||||
void menuItemSelected(Menu *menu, MenuItem *item);
|
||||
|
||||
DECLARE_CONOBJECT(GuiMenuBar);
|
||||
};
|
||||
|
||||
#endif
|
||||
840
gui/guiMessageVectorCtrl.cc
Normal file
840
gui/guiMessageVectorCtrl.cc
Normal file
|
|
@ -0,0 +1,840 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiMessageVectorCtrl.h"
|
||||
#include "GUI/messageVector.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiMessageVectorCtrl);
|
||||
|
||||
|
||||
//-------------------------------------- Console functions
|
||||
namespace {
|
||||
|
||||
bool cGMVCAttach(SimObject* obj, S32, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<GuiMessageVectorCtrl*>(obj) != NULL, "How did this get here?");
|
||||
GuiMessageVectorCtrl* pGMVC = static_cast<GuiMessageVectorCtrl*>(obj);
|
||||
|
||||
MessageVector* pMV = NULL;
|
||||
Sim::findObject(argv[2], pMV);
|
||||
if (pMV == NULL) {
|
||||
Con::errorf(ConsoleLogEntry::General, "Could not find MessageVector: %s", argv[2]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return pGMVC->attach(pMV);
|
||||
}
|
||||
|
||||
void cGMVCDetach(SimObject* obj, S32, const char**)
|
||||
{
|
||||
AssertFatal(dynamic_cast<GuiMessageVectorCtrl*>(obj) != NULL, "How did this get here?");
|
||||
GuiMessageVectorCtrl* pGMVC = static_cast<GuiMessageVectorCtrl*>(obj);
|
||||
|
||||
if (pGMVC->isAttached() == false) {
|
||||
Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl: double detach");
|
||||
return;
|
||||
}
|
||||
|
||||
pGMVC->detach();
|
||||
}
|
||||
|
||||
|
||||
struct TempLineBreak
|
||||
{
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
|
||||
|
||||
} // namespace {}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Callback for messageVector
|
||||
void sMVCtrlCallback(const U32 spectatorKey,
|
||||
const MessageVector::MessageCode code,
|
||||
const U32 argument)
|
||||
{
|
||||
GuiMessageVectorCtrl* pMVC = reinterpret_cast<GuiMessageVectorCtrl*>(spectatorKey);
|
||||
pMVC->callbackRouter(code, argument);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiMessageVectorCtrl::GuiMessageVectorCtrl()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mLineWrappings);
|
||||
VECTOR_SET_ASSOCIATION(mSpecialMarkers);
|
||||
VECTOR_SET_ASSOCIATION(mLineElements);
|
||||
|
||||
mMessageVector = NULL;
|
||||
mLineSpacingPixels = 0;
|
||||
mLineContinuationIndent = 10;
|
||||
|
||||
mMouseDown = false;
|
||||
mMouseSpecialLine = -1;
|
||||
mMouseSpecialRef = -1;
|
||||
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
mAllowedMatches[i] = "";
|
||||
mSpecialColor.set(0, 0, 255);
|
||||
|
||||
mMaxColorIndex = 9;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GuiMessageVectorCtrl::~GuiMessageVectorCtrl()
|
||||
{
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
AssertFatal(mSpecialMarkers.size() == 0, "Error, special markers not properly cleared!");
|
||||
AssertFatal(mLineElements.size() == 0, "Error, line elements not properly cleared!");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("lineSpacing", TypeS32, Offset(mLineSpacingPixels, GuiMessageVectorCtrl));
|
||||
addField("lineContinuedIndex", TypeS32, Offset(mLineContinuationIndent, GuiMessageVectorCtrl));
|
||||
addField("allowedMatches", TypeString, Offset(mAllowedMatches, GuiMessageVectorCtrl), 16);
|
||||
addField("matchColor", TypeColorI, Offset(mSpecialColor, GuiMessageVectorCtrl));
|
||||
addField("maxColorIndex", TypeS32, Offset(mMaxColorIndex, GuiMessageVectorCtrl));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiMessageVectorCtrl", "attach", cGMVCAttach, "[GuiMessageVectorCtrl].attach(MessageVectorId)", 3, 3);
|
||||
Con::addCommand("GuiMessageVectorCtrl", "detach", cGMVCDetach, "[GuiMessageVectorCtrl].detach()", 2, 2);
|
||||
}
|
||||
|
||||
|
||||
bool GuiMessageVectorCtrl::onAdd()
|
||||
{
|
||||
return Parent::onAdd();
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiMessageVectorCtrl::isAttached() const
|
||||
{
|
||||
return (mMessageVector != NULL);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiMessageVectorCtrl::attach(MessageVector* newAttachment)
|
||||
{
|
||||
AssertFatal(newAttachment, "No attachment!");
|
||||
if (newAttachment == NULL)
|
||||
return false;
|
||||
|
||||
if (isAttached()) {
|
||||
Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl::attach: overriding attachment");
|
||||
detach();
|
||||
}
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
|
||||
mMessageVector = newAttachment;
|
||||
mMessageVector->registerSpectator(sMVCtrlCallback, U32(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::detach()
|
||||
{
|
||||
if (isAttached() == false) {
|
||||
Con::warnf(ConsoleLogEntry::General, "GuiMessageVectorCtrl::detach: not attached!");
|
||||
return;
|
||||
}
|
||||
|
||||
mMessageVector->unregisterSpectator(U32(this));
|
||||
mMessageVector = NULL;
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::lineInserted(const U32 arg)
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
|
||||
GuiScrollCtrl* pScroll = NULL;
|
||||
GuiControl* pParent = getParent();
|
||||
if (pParent) {
|
||||
GuiControl* pGrandParent = pParent->getParent();
|
||||
if (pGrandParent)
|
||||
pScroll = dynamic_cast<GuiScrollCtrl*>(pGrandParent);
|
||||
}
|
||||
|
||||
bool scrollToBottom = false;
|
||||
if (pScroll != NULL)
|
||||
scrollToBottom = pScroll->getCurrVPos() == 1.0;
|
||||
|
||||
mSpecialMarkers.insert(arg);
|
||||
createSpecialMarkers(mSpecialMarkers[arg], mMessageVector->getLine(arg).message);
|
||||
|
||||
mLineWrappings.insert(arg);
|
||||
createLineWrapping(mLineWrappings[arg], mMessageVector->getLine(arg).message);
|
||||
|
||||
mLineElements.insert(arg);
|
||||
createLineElement(mLineElements[arg], mLineWrappings[arg], mSpecialMarkers[arg]);
|
||||
|
||||
U32 numLines = 0;
|
||||
for (U32 i = 0; i < mLineWrappings.size(); i++) {
|
||||
// We need to rebuild the physicalLineStart markers at the same time as
|
||||
// we find out how many of them are left...
|
||||
mLineElements[i].physicalLineStart = numLines;
|
||||
|
||||
numLines += mLineWrappings[i].numLines;
|
||||
}
|
||||
|
||||
U32 newHeight = (mProfile->mFont->getHeight() + mLineSpacingPixels) * getMax(numLines, U32(1));
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, newHeight));
|
||||
|
||||
if (arg == mSpecialMarkers.size() - 1 && scrollToBottom == true)
|
||||
pScroll->scrollTo(0, 1);
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::lineDeleted(const U32 arg)
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
AssertFatal(arg < mLineWrappings.size(), "Error, out of bounds line deleted!");
|
||||
|
||||
// It's a somewhat involved process to delete the lineelements...
|
||||
LineElement& rElement = mLineElements[arg];
|
||||
|
||||
TextElement* walk = rElement.headLineElements;
|
||||
while (walk != NULL) {
|
||||
TextElement* lineWalk = walk->nextInLine;
|
||||
while (lineWalk != NULL) {
|
||||
TextElement* temp = lineWalk;
|
||||
lineWalk = lineWalk->nextPhysicalLine;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
TextElement* temp = walk;
|
||||
walk = walk->nextPhysicalLine;
|
||||
delete temp;
|
||||
}
|
||||
rElement.headLineElements = NULL;
|
||||
mLineElements.erase(arg);
|
||||
|
||||
delete [] mLineWrappings[arg].startEndPairs;
|
||||
mLineWrappings.erase(arg);
|
||||
|
||||
delete [] mSpecialMarkers[arg].specials;
|
||||
mSpecialMarkers.erase(arg);
|
||||
|
||||
U32 numLines = 0;
|
||||
for (U32 i = 0; i < mLineWrappings.size(); i++) {
|
||||
// We need to rebuild the physicalLineStart markers at the same time as
|
||||
// we find out how many of them are left...
|
||||
mLineElements[i].physicalLineStart = numLines;
|
||||
|
||||
numLines += mLineWrappings[i].numLines;
|
||||
}
|
||||
|
||||
U32 newHeight = (mProfile->mFont->getHeight() + mLineSpacingPixels) * getMax(numLines, U32(1));
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, newHeight));
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::vectorDeleted()
|
||||
{
|
||||
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared out!");
|
||||
|
||||
mMessageVector = NULL;
|
||||
U32 newHeight = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, newHeight));
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::callbackRouter(const MessageVector::MessageCode code,
|
||||
const U32 arg)
|
||||
{
|
||||
switch (code) {
|
||||
case MessageVector::LineInserted:
|
||||
lineInserted(arg);
|
||||
break;
|
||||
case MessageVector::LineDeleted:
|
||||
lineDeleted(arg);
|
||||
break;
|
||||
case MessageVector::VectorDeletion:
|
||||
vectorDeleted();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::createSpecialMarkers(SpecialMarkers& rSpecial, const char* string)
|
||||
{
|
||||
// The first thing we need to do is create a version of the string with no uppercase
|
||||
// chars for matching...
|
||||
char* pLCCopy = new char[dStrlen(string) + 1];
|
||||
for (U32 i = 0; string[i] != '\0'; i++)
|
||||
pLCCopy[i] = dTolower(string[i]);
|
||||
pLCCopy[dStrlen(string)] = '\0';
|
||||
|
||||
Vector<TempLineBreak> tempSpecials(__FILE__, __LINE__);
|
||||
Vector<S32> tempTypes(__FILE__, __LINE__);
|
||||
|
||||
const char* pCurr = pLCCopy;
|
||||
while (pCurr[0] != '\0') {
|
||||
const char* pMinMatch = &pLCCopy[dStrlen(string)];
|
||||
U32 minMatchType = 0xFFFFFFFF;
|
||||
AssertFatal(pMinMatch[0] == '\0', "Error, bad positioning of sentry...");
|
||||
|
||||
for (U32 i = 0; i < 16; i++) {
|
||||
if (mAllowedMatches[i][0] == '\0')
|
||||
continue;
|
||||
|
||||
// Not the most efficient...
|
||||
char matchBuffer[512];
|
||||
dStrncpy(matchBuffer, mAllowedMatches[i], 500);
|
||||
matchBuffer[499] = '\0';
|
||||
dStrcat(matchBuffer, "://");
|
||||
|
||||
const char* pMatch = dStrstr(pCurr, (const char*)matchBuffer);
|
||||
if (pMatch != NULL && pMatch < pMinMatch) {
|
||||
pMinMatch = pMatch;
|
||||
minMatchType = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (pMinMatch[0] != '\0') {
|
||||
AssertFatal(minMatchType != 0xFFFFFFFF, "Hm, that's bad");
|
||||
// Found a match...
|
||||
U32 start = pMinMatch - pLCCopy;
|
||||
U32 j;
|
||||
for (j = 0; pLCCopy[start + j] != '\0'; j++) {
|
||||
if (pLCCopy[start + j] == '\n' ||
|
||||
pLCCopy[start + j] == ' ' ||
|
||||
pLCCopy[start + j] == '\t')
|
||||
break;
|
||||
}
|
||||
AssertFatal(j > 0, "Error, j must be > 0 at this point!");
|
||||
U32 end = start + j - 1;
|
||||
|
||||
tempSpecials.increment();
|
||||
tempSpecials.last().start = start;
|
||||
tempSpecials.last().end = end;
|
||||
tempTypes.push_back(minMatchType);
|
||||
|
||||
pCurr = &pLCCopy[end + 1];
|
||||
} else {
|
||||
// No match. This will cause the while loop to terminate...
|
||||
pCurr = pMinMatch;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rSpecial.numSpecials = tempSpecials.size()) != 0) {
|
||||
rSpecial.specials = new SpecialMarkers::Special[tempSpecials.size()];
|
||||
for (U32 i = 0; i < tempSpecials.size(); i++) {
|
||||
rSpecial.specials[i].start = tempSpecials[i].start;
|
||||
rSpecial.specials[i].end = tempSpecials[i].end;
|
||||
rSpecial.specials[i].specialType = tempTypes[i];
|
||||
}
|
||||
} else {
|
||||
rSpecial.specials = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::createLineWrapping(LineWrapping& rWrapping, const char* string)
|
||||
{
|
||||
Vector<TempLineBreak> tempBreaks(__FILE__, __LINE__);
|
||||
|
||||
U32 i;
|
||||
U32 currStart = 0;
|
||||
if (dStrlen(string) != 0) {
|
||||
for (i = 0; i < dStrlen(string); i++) {
|
||||
if (string[i] == '\n') {
|
||||
tempBreaks.increment();
|
||||
tempBreaks.last().start = currStart;
|
||||
tempBreaks.last().end = i-1;
|
||||
currStart = i+1;
|
||||
} else if (i == dStrlen(string) - 1) {
|
||||
tempBreaks.increment();
|
||||
tempBreaks.last().start = currStart;
|
||||
tempBreaks.last().end = i;
|
||||
currStart = i+1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tempBreaks.increment();
|
||||
tempBreaks.last().start = 0;
|
||||
tempBreaks.last().end = -1;
|
||||
}
|
||||
|
||||
bool used = false;
|
||||
U32 splitWidth = mBounds.extent.x;
|
||||
U32 currLine = 0;
|
||||
while (currLine < tempBreaks.size()) {
|
||||
TempLineBreak& rLine = tempBreaks[currLine];
|
||||
if (rLine.start >= rLine.end) {
|
||||
if (currLine == 0)
|
||||
splitWidth -= mLineContinuationIndent;
|
||||
currLine++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, there's some actual text in this line. How long is it?
|
||||
U32 baseLength = mProfile->mFont->getStrNWidthPrecise(&string[rLine.start], rLine.end-rLine.start+1);
|
||||
if (baseLength > splitWidth) {
|
||||
// DMMNOTE: Replace with bin search eventually
|
||||
U32 currPos;
|
||||
U32 breakPos;
|
||||
for (currPos = 0; currPos < rLine.end-rLine.start+1; currPos++) {
|
||||
U32 currLength = mProfile->mFont->getStrNWidthPrecise(&string[rLine.start], currPos+1);
|
||||
if (currLength > splitWidth) {
|
||||
// Make sure that the currPos has advanced, then set the breakPoint.
|
||||
breakPos = currPos != 0 ? currPos - 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currPos == rLine.end-rLine.start+1) {
|
||||
AssertFatal(false, "Error, if the line must be broken, the position must be before this point!");
|
||||
currLine++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok, the character at breakPos is the last valid char we can render. We
|
||||
// want to scan back to the first whitespace character (which, in the bounds
|
||||
// of the line, is guaranteed to be a space or a tab).
|
||||
U32 originalBreak = breakPos;
|
||||
while (true) {
|
||||
if (string[rLine.start + breakPos] == ' ' || string[rLine.start + breakPos] == '\t') {
|
||||
break;
|
||||
} else {
|
||||
AssertFatal(string[rLine.start + breakPos] != '\n',
|
||||
"Bad characters in line range...");
|
||||
if (breakPos == 0) {
|
||||
breakPos = originalBreak;
|
||||
break;
|
||||
}
|
||||
breakPos--;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, everything up to and including breakPos is in the currentLine. Insert
|
||||
// a new line at this point, and put everything after in that line.
|
||||
S32 oldStart = rLine.start;
|
||||
S32 oldEnd = rLine.end;
|
||||
rLine.end = rLine.start + breakPos;
|
||||
|
||||
// Note that rLine is NOTNOTNOTNOT valid after this point!
|
||||
tempBreaks.insert(currLine+1);
|
||||
tempBreaks[currLine+1].start = oldStart + breakPos + 1;
|
||||
tempBreaks[currLine+1].end = oldEnd;
|
||||
}
|
||||
|
||||
if (currLine == 0)
|
||||
splitWidth -= mLineContinuationIndent;
|
||||
currLine++;
|
||||
}
|
||||
|
||||
rWrapping.numLines = tempBreaks.size();
|
||||
rWrapping.startEndPairs = new LineWrapping::SEPair[tempBreaks.size()];
|
||||
for (i = 0; i < tempBreaks.size(); i++) {
|
||||
rWrapping.startEndPairs[i].start = tempBreaks[i].start;
|
||||
rWrapping.startEndPairs[i].end = tempBreaks[i].end;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::createLineElement(LineElement& rElement,
|
||||
LineWrapping& rWrapping,
|
||||
SpecialMarkers& rSpecial)
|
||||
{
|
||||
// First, do a straighforward translation of the wrapping...
|
||||
TextElement** ppWalk = &rElement.headLineElements;
|
||||
for (U32 i = 0; i < rWrapping.numLines; i++) {
|
||||
*ppWalk = new TextElement;
|
||||
|
||||
(*ppWalk)->nextInLine = NULL;
|
||||
(*ppWalk)->nextPhysicalLine = NULL;
|
||||
(*ppWalk)->specialReference = -1;
|
||||
|
||||
(*ppWalk)->start = rWrapping.startEndPairs[i].start;
|
||||
(*ppWalk)->end = rWrapping.startEndPairs[i].end;
|
||||
|
||||
ppWalk = &((*ppWalk)->nextPhysicalLine);
|
||||
}
|
||||
|
||||
if (rSpecial.numSpecials != 0) {
|
||||
// Ok. Now, walk down the lines, and split the elements into their contiuent parts...
|
||||
//
|
||||
TextElement* walk = rElement.headLineElements;
|
||||
while (walk) {
|
||||
TextElement* walkAcross = walk;
|
||||
while (walkAcross) {
|
||||
S32 specialMatch = -1;
|
||||
for (U32 i = 0; i < rSpecial.numSpecials; i++) {
|
||||
if (walkAcross->start <= rSpecial.specials[i].end &&
|
||||
walkAcross->end >= rSpecial.specials[i].start) {
|
||||
specialMatch = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialMatch != -1) {
|
||||
// We have a match here. Break it into the appropriate number of segments.
|
||||
// this will vary depending on how the overlap is occuring...
|
||||
if (walkAcross->start >= rSpecial.specials[specialMatch].start) {
|
||||
if (walkAcross->end <= rSpecial.specials[specialMatch].end) {
|
||||
// The whole thing is part of the special
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->specialReference = specialMatch;
|
||||
} else {
|
||||
// The first part is in the special, the tail is out
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->specialReference = -1;
|
||||
|
||||
walkAcross->specialReference = specialMatch;
|
||||
walkAcross->nextInLine->end = walkAcross->end;
|
||||
walkAcross->end = rSpecial.specials[specialMatch].end;
|
||||
walkAcross->nextInLine->start = rSpecial.specials[specialMatch].end + 1;
|
||||
|
||||
AssertFatal(walkAcross->end >= walkAcross->start && walkAcross->nextInLine->end >= walkAcross->nextInLine->start, "Bad textelements generated!");
|
||||
}
|
||||
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
} else {
|
||||
if (walkAcross->end <= rSpecial.specials[specialMatch].end) {
|
||||
// The first part is out of the special, the second part in.
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->specialReference = specialMatch;
|
||||
|
||||
walkAcross->specialReference = -1;
|
||||
walkAcross->nextInLine->end = walkAcross->end;
|
||||
walkAcross->end = rSpecial.specials[specialMatch].start - 1;
|
||||
walkAcross->nextInLine->start = rSpecial.specials[specialMatch].start;
|
||||
|
||||
AssertFatal(walkAcross->end >= walkAcross->start && walkAcross->nextInLine->end >= walkAcross->nextInLine->start, "Bad textelements generated!");
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
} else {
|
||||
// First out, middle in, last out. Oy.
|
||||
AssertFatal(walkAcross->nextInLine == NULL, "Bad assumption!");
|
||||
walkAcross->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->specialReference = specialMatch;
|
||||
|
||||
walkAcross->nextInLine->nextInLine = new TextElement;
|
||||
walkAcross->nextInLine->nextInLine->nextInLine = NULL;
|
||||
walkAcross->nextInLine->nextInLine->nextPhysicalLine = NULL;
|
||||
walkAcross->nextInLine->nextInLine->specialReference = -1;
|
||||
|
||||
walkAcross->nextInLine->start = rSpecial.specials[specialMatch].start;
|
||||
walkAcross->nextInLine->end = rSpecial.specials[specialMatch].end;
|
||||
walkAcross->nextInLine->nextInLine->start = rSpecial.specials[specialMatch].end+1;
|
||||
walkAcross->nextInLine->nextInLine->end = walkAcross->end;
|
||||
walkAcross->end = walkAcross->nextInLine->start - 1;
|
||||
AssertFatal((walkAcross->end >= walkAcross->start &&
|
||||
walkAcross->nextInLine->end >= walkAcross->nextInLine->start &&
|
||||
walkAcross->nextInLine->nextInLine->end >= walkAcross->nextInLine->nextInLine->start),
|
||||
"Bad textelements generated!");
|
||||
walkAcross = walkAcross->nextInLine->nextInLine;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
}
|
||||
}
|
||||
|
||||
walk = walk->nextPhysicalLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool GuiMessageVectorCtrl::onWake()
|
||||
{
|
||||
if (Parent::onWake() == false)
|
||||
return false;
|
||||
|
||||
if (bool(mProfile->mFont) == false)
|
||||
return false;
|
||||
|
||||
mMinSensibleWidth = 1;
|
||||
|
||||
for (U32 i = 0; i < 256; i++) {
|
||||
if (mProfile->mFont->isValidChar(U8(i))) {
|
||||
if (mProfile->mFont->getCharWidth(U8(i)) > mMinSensibleWidth)
|
||||
mMinSensibleWidth = mProfile->mFont->getCharWidth(U8(i));
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(mLineWrappings.size() == 0, "Error, line wrappings not properly cleared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::onSleep()
|
||||
{
|
||||
if (isAttached())
|
||||
detach();
|
||||
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::onRender(Point2I offset,
|
||||
const RectI& updateRect,
|
||||
GuiControl*fr)
|
||||
{
|
||||
Parent::onRender(offset, updateRect,fr);
|
||||
if (isAttached()) {
|
||||
U32 linePixels = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
U32 currLine = 0;
|
||||
for (U32 i = 0; i < mMessageVector->getNumLines(); i++) {
|
||||
|
||||
TextElement* pElement = mLineElements[i].headLineElements;
|
||||
ColorI lastColor = mProfile->mFontColor;
|
||||
while (pElement != NULL) {
|
||||
Point2I localStart(pElement == mLineElements[i].headLineElements ? 0 : mLineContinuationIndent, currLine * linePixels);
|
||||
|
||||
Point2I globalCheck = localToGlobalCoord(localStart);
|
||||
U32 globalRangeStart = globalCheck.y;
|
||||
U32 globalRangeEnd = globalCheck.y + mProfile->mFont->getHeight();
|
||||
if (globalRangeStart > updateRect.point.y + updateRect.extent.y ||
|
||||
globalRangeEnd < updateRect.point.y) {
|
||||
currLine++;
|
||||
pElement = pElement->nextPhysicalLine;
|
||||
continue;
|
||||
}
|
||||
|
||||
TextElement* walkAcross = pElement;
|
||||
while (walkAcross) {
|
||||
if (walkAcross->start > walkAcross->end)
|
||||
break;
|
||||
|
||||
Point2I globalStart = localToGlobalCoord(localStart);
|
||||
|
||||
U32 strWidth;
|
||||
if (walkAcross->specialReference == -1) {
|
||||
dglSetBitmapModulation(lastColor);
|
||||
dglSetTextAnchorColor(mProfile->mFontColor);
|
||||
strWidth = dglDrawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
||||
walkAcross->end - walkAcross->start + 1, mProfile->mFontColors, mMaxColorIndex);
|
||||
dglGetBitmapModulation(&lastColor);
|
||||
} else {
|
||||
dglGetBitmapModulation(&lastColor);
|
||||
dglSetBitmapModulation(mSpecialColor);
|
||||
dglSetTextAnchorColor(mProfile->mFontColor);
|
||||
strWidth = dglDrawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
||||
walkAcross->end - walkAcross->start + 1);
|
||||
|
||||
// in case we have 2 in a row...
|
||||
dglSetBitmapModulation(lastColor);
|
||||
}
|
||||
|
||||
if (walkAcross->specialReference != -1) {
|
||||
Point2I lineStart = localStart;
|
||||
Point2I lineEnd = localStart;
|
||||
lineStart.y += mProfile->mFont->getBaseline() + 1;
|
||||
lineEnd.x += strWidth;
|
||||
lineEnd.y += mProfile->mFont->getBaseline() + 1;
|
||||
|
||||
dglDrawLine(localToGlobalCoord(lineStart),
|
||||
localToGlobalCoord(lineEnd),
|
||||
mSpecialColor);
|
||||
}
|
||||
|
||||
localStart.x += strWidth;
|
||||
walkAcross = walkAcross->nextInLine;
|
||||
}
|
||||
|
||||
currLine++;
|
||||
pElement = pElement->nextPhysicalLine;
|
||||
}
|
||||
}
|
||||
dglClearBitmapModulation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::parentResized(const Point2I& oldSize,
|
||||
const Point2I& newSize)
|
||||
{
|
||||
Parent::parentResized(oldSize, newSize);
|
||||
|
||||
if (mMessageVector)
|
||||
{
|
||||
MessageVector *reflowme = mMessageVector;
|
||||
|
||||
detach();
|
||||
attach(reflowme);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void GuiMessageVectorCtrl::findSpecialFromCoord(const Point2I& point, S32* specialLine, S32* specialRef)
|
||||
{
|
||||
if (mLineElements.size() == 0) {
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
U32 linePixels = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
||||
|
||||
if ((point.x < 0 || point.x >= mBounds.extent.x) ||
|
||||
(point.y < 0 || point.y >= mBounds.extent.y)) {
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ok, we have real work to do here. Let's determine the physical line that it's on...
|
||||
U32 physLine = point.y / linePixels;
|
||||
AssertFatal(physLine >= 0, "Bad physical line!");
|
||||
|
||||
// And now we find the LineElement that contains that physicalline...
|
||||
U32 elemIndex;
|
||||
for (elemIndex = 0; elemIndex < mLineElements.size(); elemIndex++) {
|
||||
if (mLineElements[elemIndex].physicalLineStart > physLine) {
|
||||
// We've passed it.
|
||||
AssertFatal(elemIndex != 0, "Error, bad elemIndex, check assumptions.");
|
||||
elemIndex--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (elemIndex == mLineElements.size()) {
|
||||
// On the last line...
|
||||
elemIndex = mLineElements.size() - 1;
|
||||
}
|
||||
|
||||
TextElement* line = mLineElements[elemIndex].headLineElements;
|
||||
for (U32 i = 0; i < physLine - mLineElements[elemIndex].physicalLineStart; i++) {
|
||||
line = line->nextPhysicalLine;
|
||||
AssertFatal(line != NULL, "Error, moved too far!");
|
||||
}
|
||||
|
||||
// Ok, line represents the current line. We now need to find out which textelement
|
||||
// the points x coord falls in.
|
||||
U32 currX = 0;
|
||||
if ((physLine - mLineElements[elemIndex].physicalLineStart) != 0) {
|
||||
currX = mLineContinuationIndent;
|
||||
// First, if this isn't the first line in this wrapping, we have to make sure
|
||||
// that the coord isn't in the margin...
|
||||
if (point.x < mLineContinuationIndent) {
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (line->start > line->end) {
|
||||
// Empty line special case...
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
U32 currElem = 0;
|
||||
while (line) {
|
||||
U32 newX = currX + mProfile->mFont->getStrNWidth(mMessageVector->getLine(elemIndex).message,
|
||||
line->end - line->start + 1);
|
||||
if (point.x < newX) {
|
||||
// That's the one!
|
||||
*specialLine = elemIndex;
|
||||
*specialRef = line->specialReference;
|
||||
return;
|
||||
}
|
||||
|
||||
currX = newX;
|
||||
line = line->nextInLine;
|
||||
}
|
||||
|
||||
// Off to the right. Aw...
|
||||
*specialLine = -1;
|
||||
*specialRef = -1;
|
||||
}
|
||||
|
||||
|
||||
void GuiMessageVectorCtrl::onMouseDown(const GuiEvent& event)
|
||||
{
|
||||
Parent::onMouseDown(event);
|
||||
mouseUnlock();
|
||||
|
||||
mMouseDown = true;
|
||||
|
||||
// Find the special we are in, if any...
|
||||
findSpecialFromCoord(globalToLocalCoord(event.mousePoint),
|
||||
&mMouseSpecialLine, &mMouseSpecialRef);
|
||||
}
|
||||
|
||||
void GuiMessageVectorCtrl::onMouseUp(const GuiEvent& event)
|
||||
{
|
||||
Parent::onMouseUp(event);
|
||||
mouseUnlock();
|
||||
|
||||
// Is this an up from a dragged click?
|
||||
if (mMouseDown == false)
|
||||
return;
|
||||
|
||||
// Find the special we are in, if any...
|
||||
|
||||
S32 currSpecialLine;
|
||||
S32 currSpecialRef;
|
||||
findSpecialFromCoord(globalToLocalCoord(event.mousePoint), &currSpecialLine, &currSpecialRef);
|
||||
|
||||
if (currSpecialRef != -1 &&
|
||||
(currSpecialLine == mMouseSpecialLine &&
|
||||
currSpecialRef == mMouseSpecialRef)) {
|
||||
// Execute the callback
|
||||
SpecialMarkers& rSpecial = mSpecialMarkers[currSpecialLine];
|
||||
S32 specialStart = rSpecial.specials[currSpecialRef].start;
|
||||
S32 specialEnd = rSpecial.specials[currSpecialRef].end;
|
||||
|
||||
char* copyURL = new char[specialEnd - specialStart + 2];
|
||||
dStrncpy(copyURL, &mMessageVector->getLine(currSpecialLine).message[specialStart], specialEnd - specialStart + 1);
|
||||
copyURL[specialEnd - specialStart + 1] = '\0';
|
||||
|
||||
Con::executef(this, 2, "urlClickCallback", copyURL);
|
||||
delete [] copyURL;
|
||||
}
|
||||
|
||||
mMouseDown = false;
|
||||
mMouseSpecialLine = -1;
|
||||
mMouseSpecialRef = -1;
|
||||
}
|
||||
|
||||
130
gui/guiMessageVectorCtrl.h
Normal file
130
gui/guiMessageVectorCtrl.h
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIMESSAGEVECTORCTRL_H_
|
||||
#define _GUIMESSAGEVECTORCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _MESSAGEVECTOR_H_
|
||||
#include "GUI/messageVector.h"
|
||||
#endif
|
||||
|
||||
class GuiMessageVectorCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
//-------------------------------------- Public interfaces...
|
||||
public:
|
||||
struct SpecialMarkers {
|
||||
struct Special {
|
||||
S32 specialType;
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
|
||||
U32 numSpecials;
|
||||
Special* specials;
|
||||
};
|
||||
|
||||
GuiMessageVectorCtrl();
|
||||
~GuiMessageVectorCtrl();
|
||||
|
||||
bool isAttached() const;
|
||||
bool attach(MessageVector*);
|
||||
void detach();
|
||||
|
||||
// Gui control overrides
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void inspectPostApply();
|
||||
void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
|
||||
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
// void onMouseMove(const GuiEvent &event);
|
||||
|
||||
// Overrideables
|
||||
protected:
|
||||
virtual void lineInserted(const U32);
|
||||
virtual void lineDeleted(const U32);
|
||||
virtual void vectorDeleted();
|
||||
|
||||
MessageVector* mMessageVector;
|
||||
|
||||
// Font resource
|
||||
protected:
|
||||
U32 mMinSensibleWidth;
|
||||
|
||||
U32 mLineSpacingPixels;
|
||||
U32 mLineContinuationIndent;
|
||||
|
||||
StringTableEntry mAllowedMatches[16];
|
||||
ColorI mSpecialColor;
|
||||
|
||||
U32 mMaxColorIndex;
|
||||
|
||||
bool mMouseDown;
|
||||
S32 mMouseSpecialLine;
|
||||
S32 mMouseSpecialRef;
|
||||
|
||||
// Derived classes must keep this set of variables consistent if they
|
||||
// use this classes onRender. Note that this has the fairly large
|
||||
// disadvantage of requiring lots of ugly, tiny mem allocs. A rewrite
|
||||
// to a more memory friendly version might be a good idea...
|
||||
struct LineWrapping {
|
||||
struct SEPair {
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
|
||||
U32 numLines;
|
||||
SEPair* startEndPairs; // start[linex] = startEndPairs[linex*2+0]
|
||||
// end[linex] = startEndPairs[linex*2+1]
|
||||
// if end < start, line is empty...
|
||||
};
|
||||
|
||||
struct TextElement {
|
||||
TextElement* nextInLine;
|
||||
TextElement* nextPhysicalLine;
|
||||
|
||||
S32 specialReference; // if (!= -1), indicates a special reference
|
||||
|
||||
S32 start;
|
||||
S32 end;
|
||||
};
|
||||
struct LineElement {
|
||||
U32 physicalLineStart;
|
||||
|
||||
TextElement* headLineElements;
|
||||
};
|
||||
|
||||
Vector<LineWrapping> mLineWrappings;
|
||||
Vector<SpecialMarkers> mSpecialMarkers;
|
||||
Vector<LineElement> mLineElements;
|
||||
|
||||
void createLineWrapping(LineWrapping&, const char*);
|
||||
void createSpecialMarkers(SpecialMarkers&, const char*);
|
||||
void createLineElement(LineElement&, LineWrapping&, SpecialMarkers&);
|
||||
|
||||
void findSpecialFromCoord(const Point2I&, S32*, S32*);
|
||||
|
||||
public:
|
||||
void callbackRouter(const MessageVector::MessageCode, const U32);
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiMessageVectorCtrl);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
#endif // _H_GUIMESSAGEVECTORCTRL_
|
||||
100
gui/guiMouseEventCtrl.cc
Normal file
100
gui/guiMouseEventCtrl.cc
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiMouseEventCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiMouseEventCtrl);
|
||||
|
||||
GuiMouseEventCtrl::GuiMouseEventCtrl()
|
||||
{
|
||||
mLockMouse = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiMouseEventCtrl::sendMouseEvent(const char * name, const GuiEvent & event)
|
||||
{
|
||||
char buf[3][32];
|
||||
dSprintf(buf[0], 32, "%d", event.modifier);
|
||||
dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
|
||||
dSprintf(buf[2], 32, "%d", event.mouseClickCount);
|
||||
Con::executef(this, 4, name, buf[0], buf[1], buf[2]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiMouseEventCtrl::consoleInit()
|
||||
{
|
||||
Con::setIntVariable("$EventModifier::LSHIFT", SI_LSHIFT);
|
||||
Con::setIntVariable("$EventModifier::RSHIFT", SI_RSHIFT);
|
||||
Con::setIntVariable("$EventModifier::SHIFT", SI_SHIFT);
|
||||
Con::setIntVariable("$EventModifier::LCTRL", SI_LCTRL);
|
||||
Con::setIntVariable("$EventModifier::RCTRL", SI_RCTRL);
|
||||
Con::setIntVariable("$EventModifier::CTRL", SI_CTRL);
|
||||
Con::setIntVariable("$EventModifier::LALT", SI_LALT);
|
||||
Con::setIntVariable("$EventModifier::RALT", SI_RALT);
|
||||
Con::setIntVariable("$EventModifier::ALT", SI_ALT);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("lockMouse", TypeBool, Offset(mLockMouse, GuiMouseEventCtrl));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiMouseEventCtrl::onMouseDown(const GuiEvent & event)
|
||||
{
|
||||
if(mLockMouse)
|
||||
mouseLock();
|
||||
sendMouseEvent("onMouseDown", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onMouseUp(const GuiEvent & event)
|
||||
{
|
||||
if(mLockMouse)
|
||||
mouseUnlock();
|
||||
sendMouseEvent("onMouseUp", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onMouseMove(const GuiEvent & event)
|
||||
{
|
||||
sendMouseEvent("onMouseMove", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onMouseDragged(const GuiEvent & event)
|
||||
{
|
||||
sendMouseEvent("onMouseDragged", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onMouseEnter(const GuiEvent & event)
|
||||
{
|
||||
sendMouseEvent("onMouseEnter", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onMouseLeave(const GuiEvent & event)
|
||||
{
|
||||
sendMouseEvent("onMouseLeave", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onRightMouseDown(const GuiEvent & event)
|
||||
{
|
||||
if(mLockMouse)
|
||||
mouseLock();
|
||||
sendMouseEvent("onRightMouseDown", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onRightMouseUp(const GuiEvent & event)
|
||||
{
|
||||
if(mLockMouse)
|
||||
mouseUnlock();
|
||||
sendMouseEvent("onRightMouseUp", event);
|
||||
}
|
||||
|
||||
void GuiMouseEventCtrl::onRightMouseDragged(const GuiEvent & event)
|
||||
{
|
||||
sendMouseEvent("onRightMouseDragged", event);
|
||||
}
|
||||
49
gui/guiMouseEventCtrl.h
Normal file
49
gui/guiMouseEventCtrl.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIMOUSEEVENTCTRL_H_
|
||||
#define _GUIMOUSEEVENTCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "Platform/event.h"
|
||||
#endif
|
||||
|
||||
|
||||
class GuiMouseEventCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
void sendMouseEvent(const char * name, const GuiEvent &);
|
||||
|
||||
// field info
|
||||
bool mLockMouse;
|
||||
|
||||
public:
|
||||
|
||||
GuiMouseEventCtrl();
|
||||
|
||||
// GuiControl
|
||||
void onMouseDown(const GuiEvent & event);
|
||||
void onMouseUp(const GuiEvent & event);
|
||||
void onMouseMove(const GuiEvent & event);
|
||||
void onMouseDragged(const GuiEvent & event);
|
||||
void onMouseEnter(const GuiEvent & event);
|
||||
void onMouseLeave(const GuiEvent & event);
|
||||
void onRightMouseDown(const GuiEvent & event);
|
||||
void onRightMouseUp(const GuiEvent & event);
|
||||
void onRightMouseDragged(const GuiEvent & event);
|
||||
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(GuiMouseEventCtrl);
|
||||
};
|
||||
|
||||
#endif
|
||||
929
gui/guiPopUpCtrl.cc
Normal file
929
gui/guiPopUpCtrl.cc
Normal file
|
|
@ -0,0 +1,929 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiPopUpCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GuiPopUpTextListCtrl::GuiPopUpTextListCtrl()
|
||||
{
|
||||
mPopUpCtrl = NULL;
|
||||
mMouseDown = AlreadyDown;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GuiPopUpTextListCtrl::GuiPopUpTextListCtrl(GuiPopUpMenuCtrl *ctrl)
|
||||
{
|
||||
mPopUpCtrl = ctrl;
|
||||
mMouseDown = AlreadyDown;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GuiPopUpTextListCtrl::~GuiPopUpTextListCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiPopUpTextListCtrl::onSleep()
|
||||
{
|
||||
mMouseDown = None;
|
||||
Parent::onSleep();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
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)
|
||||
{
|
||||
mMouseDown = None;
|
||||
|
||||
// See if it's within the scroll content ctrl:
|
||||
GuiControl *parent = getParent();
|
||||
if ( !parent )
|
||||
return;
|
||||
|
||||
if ( parent->cursorInControl() )
|
||||
{
|
||||
//let the parent handle the event
|
||||
Parent::onMouseDown(event);
|
||||
mMouseDown = TextListArea;
|
||||
//we're done
|
||||
return;
|
||||
}
|
||||
|
||||
//see if it's within the scroll control
|
||||
GuiControl *grandParent = parent->getParent();
|
||||
if ( !grandParent )
|
||||
return;
|
||||
|
||||
if ( grandParent->cursorInControl() )
|
||||
{
|
||||
//let the scroll control deal with it
|
||||
grandParent->onMouseDown(event);
|
||||
mMouseDown = ScrollArea;
|
||||
//and we're done
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiPopUpTextListCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
//the only way to get here, is if the scroll control is dragging
|
||||
//else see if it's within the scroll control
|
||||
GuiControl *parent = getParent();
|
||||
if ( !parent )
|
||||
return;
|
||||
|
||||
GuiControl *grandParent = parent->getParent();
|
||||
if ( !grandParent )
|
||||
return;
|
||||
|
||||
//let the scroll control deal with it
|
||||
grandParent->onMouseDragged( event );
|
||||
//will highlight the text while dragging
|
||||
onMouseMove( event );
|
||||
|
||||
if ( mMouseDown == AlreadyDown )
|
||||
{
|
||||
if ( parent->cursorInControl() )
|
||||
mMouseDown = TextListArea;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mMouseDown != ScrollArea )
|
||||
mPopUpCtrl->setupAutoScroll( event );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiPopUpTextListCtrl::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
mPopUpCtrl->mScrollDir = GuiScrollCtrl::None;
|
||||
|
||||
//see if it's within the scroll content ctrl
|
||||
GuiControl *parent = getParent();
|
||||
if ( !parent )
|
||||
return;
|
||||
|
||||
// Initial case--this control locks the mouse upon creation.
|
||||
// If mouse is released outside of the menu, just move to next stage
|
||||
// else if dragged over menu and released, select the appropriate entry
|
||||
if ( mMouseDown == AlreadyDown )
|
||||
{
|
||||
if ( !parent->cursorInControl() )
|
||||
{
|
||||
mMouseDown = None;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( parent->cursorInControl() )
|
||||
{
|
||||
// Select the item the mouse is over:
|
||||
Point2I localPt = globalToLocalCoord( event.mousePoint );
|
||||
Point2I cell( 0, ( localPt.y < 0 ? -1 : localPt.y / mCellSize.y ) );
|
||||
if ( cell.y >= 0 && cell.y < mSize.y )
|
||||
cellSelected( Point2I( 0, cell.y ) );
|
||||
|
||||
//now let the pop up know a cell has been selected...
|
||||
mPopUpCtrl->closePopUp();
|
||||
//we're done
|
||||
return;
|
||||
}
|
||||
|
||||
//see if it's within the scroll control
|
||||
GuiControl *grandParent = parent->getParent();
|
||||
if ( !grandParent )
|
||||
return;
|
||||
|
||||
if ( grandParent->cursorInControl() )
|
||||
{
|
||||
//let the scroll control deal with it
|
||||
grandParent->onMouseUp( event );
|
||||
//and we're done
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, we clicked outside the popup, and we're done
|
||||
// let the pop up know a cell has been selected...
|
||||
if ( mMouseDown == None )
|
||||
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));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void cGuiPopUpMenuAdd(SimObject *obj, S32 argc, const char **argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
if ( argc > 4 )
|
||||
ctrl->addEntry(argv[2],dAtoi(argv[3]),dAtoi(argv[4]));
|
||||
else
|
||||
ctrl->addEntry(argv[2],dAtoi(argv[3]),0);
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuAddScheme(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
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 );
|
||||
|
||||
ctrl->addScheme( dAtoi( argv[2] ), fontColor, fontColorHL, fontColorSEL );
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuSetText(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
ctrl->setText(argv[2]);
|
||||
}
|
||||
|
||||
static const char * cGuiPopUpMenuGetText(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
return ctrl->getText();
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuClear(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
ctrl->clear();
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuSort(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
ctrl->sort();
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuOnAction(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
ctrl->onAction();
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuClose(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiPopUpMenuCtrl *ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
ctrl->closePopUp();
|
||||
}
|
||||
|
||||
static S32 cGuiPopUpMenuGetSelected(SimObject * obj, S32, const char **)
|
||||
{
|
||||
GuiPopUpMenuCtrl * ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
return ctrl->getSelected();
|
||||
}
|
||||
|
||||
static void cGuiPopUpMenuSetSelected(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl * ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
ctrl->setSelected(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
static const char * cGuiPopUpMenuGetTextById(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl * ctrl = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
return(ctrl->getTextById(dAtoi(argv[2])));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// this fills the popup with a classrep's field enumeration type info - 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..
|
||||
//
|
||||
// args:
|
||||
// argv[2] - class
|
||||
// argv[3] - field
|
||||
static void cGuiPopUpMenuSetEnumContent(SimObject * obj, S32, const char ** argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl * menu = static_cast<GuiPopUpMenuCtrl*>(obj);
|
||||
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++)
|
||||
menu->addEntry(field.table->table[i].label, field.table->table[i].index);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static S32 cGuiPopUpMenuFindText( SimObject* obj, S32, const char** argv )
|
||||
{
|
||||
AssertFatal( dynamic_cast<GuiPopUpMenuCtrl*>( obj ), "Object passed to cGuiPopUpMenuFindText is not a GuiPopUpMenuCtrl!" );
|
||||
GuiPopUpMenuCtrl* ctrl = static_cast<GuiPopUpMenuCtrl*>( obj );
|
||||
return( ctrl->findText( argv[2] ) );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static S32 cGuiPopUpSize( SimObject* obj, S32, const char** )
|
||||
{
|
||||
AssertFatal( dynamic_cast<GuiPopUpMenuCtrl*>( obj ), "Object passed to cGuiPopUpSize is not a GuiPopUpMenuCtrl!" );
|
||||
GuiPopUpMenuCtrl* ctrl = static_cast<GuiPopUpMenuCtrl*>( obj );
|
||||
return( ctrl->getNumEntries() );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void cGuiReplaceText( SimObject* obj, S32, const char** argv)
|
||||
{
|
||||
GuiPopUpMenuCtrl* ctrl = static_cast<GuiPopUpMenuCtrl*>( obj );
|
||||
ctrl->replaceText(dAtoi(argv[2]));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiPopUpMenuCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "sort", cGuiPopUpMenuSort, "menu.sort()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "add", cGuiPopUpMenuAdd, "menu.add(name,idNum{,scheme})", 4, 5);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "addScheme", cGuiPopUpMenuAddScheme, "menu.addScheme(id, fontColor, fontColorHL, fontColorSEL)", 6, 6);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "getText", cGuiPopUpMenuGetText, "menu.getText()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "setText", cGuiPopUpMenuSetText, "menu.setText(text)", 3, 3);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "getValue", cGuiPopUpMenuGetText, "menu.getValue()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "setValue", cGuiPopUpMenuSetText, "menu.setValue(text)", 3, 3);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "clear", cGuiPopUpMenuClear, "menu.clear()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "forceOnAction", cGuiPopUpMenuOnAction, "menu.forceOnAction()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "forceClose", cGuiPopUpMenuClose, "menu.forceClose()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "getSelected", cGuiPopUpMenuGetSelected, "menu.getSelected()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "setSelected", cGuiPopUpMenuSetSelected, "menu.setSelected(id)", 3, 3);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "getTextById", cGuiPopUpMenuGetTextById, "menu.getTextById(id)", 3, 3);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "setEnumContent", cGuiPopUpMenuSetEnumContent, "menu.setEnumContent(class, enum)", 4, 4);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "findText", cGuiPopUpMenuFindText, "menu.findText(text)", 3, 3);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "size", cGuiPopUpSize, "menu.size()", 2, 2);
|
||||
Con::addCommand("GuiPopUpMenuCtrl", "replaceText", cGuiReplaceText, "menu.replaceText(bool)", 3, 3);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
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(eb->buf, ea->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);
|
||||
return;
|
||||
}
|
||||
|
||||
setText("");
|
||||
mSelIndex = -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const char *GuiPopUpMenuCtrl::getScriptValue()
|
||||
{
|
||||
return getText();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiPopUpMenuCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
updateRect;
|
||||
firstResponder;
|
||||
Point2I localStart;
|
||||
|
||||
if(mScrollDir != GuiScrollCtrl::None)
|
||||
autoScroll();
|
||||
RectI r(offset, mBounds.extent);
|
||||
dglDrawRectFill(r, mProfile->mBorderColor);
|
||||
r.point.x +=2;
|
||||
r.point.y +=2;
|
||||
r.extent.x -=4;
|
||||
r.extent.y -=4;
|
||||
dglDrawRectFill(r, mProfile->mFillColor);
|
||||
|
||||
S32 txt_w = mFont->getStrWidth(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 = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
//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(mEntries[i].buf)) > textWidth)
|
||||
textWidth = mFont->getStrWidth(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 );
|
||||
|
||||
root->pushDialogControl(mBackground,canCtrl->mLayer);
|
||||
|
||||
if ( setScroll )
|
||||
{
|
||||
if ( mSelIndex )
|
||||
mTl->scrollSelectionTop();
|
||||
else
|
||||
mTl->scrollCellVisible( Point2I( 0, 0 ) );
|
||||
}
|
||||
|
||||
mTl->setFirstResponder();
|
||||
mTl->mouseLock();
|
||||
|
||||
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 GuiBackgroundCtrl;
|
||||
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 //
|
||||
139
gui/guiPopUpCtrl.h
Normal file
139
gui/guiPopUpCtrl.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIPOPUPCTRL_H_
|
||||
#define _GUIPOPUPCTRL_H_
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUITEXTLISTCTRL_H_
|
||||
#include "GUI/guiTextListCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUIBUTTONCTRL_H_
|
||||
#include "GUI/guiButtonCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUIBACKGROUNDCTRL_H_
|
||||
#include "GUI/guiBackgroundCtrl.h"
|
||||
#endif
|
||||
#ifndef _GUISCROLLCTRL_H_
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
#endif
|
||||
class GuiPopUpMenuCtrl;
|
||||
|
||||
class GuiPopUpTextListCtrl : public GuiTextListCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextListCtrl Parent;
|
||||
|
||||
public:
|
||||
enum ButtonDown
|
||||
{
|
||||
None = 0,
|
||||
AlreadyDown = 1,
|
||||
ScrollArea = 2,
|
||||
TextListArea = 3
|
||||
};
|
||||
|
||||
protected:
|
||||
GuiPopUpMenuCtrl *mPopUpCtrl;
|
||||
ButtonDown mMouseDown;
|
||||
|
||||
public:
|
||||
GuiPopUpTextListCtrl(); // for inheritance
|
||||
GuiPopUpTextListCtrl(GuiPopUpMenuCtrl *ctrl);
|
||||
~GuiPopUpTextListCtrl();
|
||||
|
||||
void onSleep();
|
||||
|
||||
// GuiArrayCtrl overload:
|
||||
void onCellSelected(Point2I cell);
|
||||
|
||||
// GuiControl overloads:
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
bool onKeyDown(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;
|
||||
GuiScrollContentCtrl *mSContentc;
|
||||
GuiScrollCtrl *mSc;
|
||||
GuiBackgroundCtrl *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();
|
||||
static void consoleInit();
|
||||
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, GuiControl *firstResponder);
|
||||
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
|
||||
84
gui/guiProgressCtrl.cc
Normal file
84
gui/guiProgressCtrl.cc
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
#include "GUI/guiProgressCtrl.h"
|
||||
|
||||
GuiProgressCtrl::GuiProgressCtrl()
|
||||
{
|
||||
mProgress = 0.0f;
|
||||
}
|
||||
|
||||
const char* GuiProgressCtrl::getScriptValue()
|
||||
{
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%f", mProgress);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GuiProgressCtrl::setScriptValue(const char *value)
|
||||
{
|
||||
//set the value
|
||||
if (! value)
|
||||
mProgress = 0.0f;
|
||||
else
|
||||
mProgress = dAtof(value);
|
||||
|
||||
//validate the value
|
||||
mProgress = mClampF(mProgress, 0.f, 1.f);
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
void GuiProgressCtrl::onPreRender()
|
||||
{
|
||||
const char * var = getVariable();
|
||||
if(var)
|
||||
{
|
||||
F32 value = mClampF(dAtof(var), 0.f, 1.f);
|
||||
if(value != mProgress)
|
||||
{
|
||||
mProgress = value;
|
||||
setUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiProgressCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
RectI ctrlRect(offset, mBounds.extent);
|
||||
|
||||
//draw the progress
|
||||
S32 width = (S32)((F32)mBounds.extent.x * mProgress);
|
||||
if (width > 0)
|
||||
{
|
||||
RectI progressRect = ctrlRect;
|
||||
progressRect.extent.x = width;
|
||||
dglDrawRectFill(progressRect, mProfile->mFillColor);
|
||||
}
|
||||
|
||||
//now draw the border
|
||||
if (mProfile->mBorder)
|
||||
{
|
||||
dglDrawRect(ctrlRect, mProfile->mBorderColor);
|
||||
|
||||
RectI copyRect = ctrlRect;
|
||||
copyRect.point.x += 1;
|
||||
copyRect.point.y += 1;
|
||||
copyRect.extent.x -= 2;
|
||||
copyRect.extent.y -= 2;
|
||||
ColorI color = mProfile->mBorderColor*0.75;
|
||||
color.alpha = 255;
|
||||
dglDrawRect(copyRect, color);
|
||||
}
|
||||
|
||||
//render the children
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
35
gui/guiProgressCtrl.h
Normal file
35
gui/guiProgressCtrl.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIPROGRESSCTRL_H_
|
||||
#define _GUIPROGRESSCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiProgressCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
F32 mProgress;
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiProgressCtrl);
|
||||
GuiProgressCtrl();
|
||||
|
||||
//console related methods
|
||||
virtual const char *getScriptValue();
|
||||
virtual void setScriptValue(const char *value);
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif
|
||||
228
gui/guiRadioCtrl.cc
Normal file
228
gui/guiRadioCtrl.cc
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiRadioCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
GuiRadioCtrl::GuiRadioCtrl()
|
||||
{
|
||||
mActive = true;
|
||||
mBounds.extent.set(140, 30);
|
||||
mKeyPressed = false;
|
||||
mStateOn = false;
|
||||
mGroupNum = -1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("groupNum", TypeS32, Offset(mGroupNum, GuiRadioCtrl));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::AcceleratorKeyPress(void)
|
||||
{
|
||||
if (! mActive) return;
|
||||
|
||||
//set the bool
|
||||
mKeyPressed = true;
|
||||
|
||||
if (mProfile->mTabable)
|
||||
{
|
||||
setFirstResponder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::AcceleratorKeyRelease(void)
|
||||
{
|
||||
if (! mActive) return;
|
||||
|
||||
//set the bool
|
||||
mKeyPressed = false;
|
||||
//perform the action
|
||||
onAction();
|
||||
|
||||
//update
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool GuiRadioCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if the control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake))
|
||||
return true;
|
||||
|
||||
//see if the key down is a <return> or not
|
||||
if (event.keyCode == KEY_RETURN && event.modifier == 0)
|
||||
{
|
||||
onAction();
|
||||
return true;
|
||||
}
|
||||
|
||||
//otherwise, pass the event to it's parent
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::drawBorder(const RectI &r, const ColorI &color)
|
||||
{
|
||||
Point2I p1, p2;
|
||||
p1 = r.point;
|
||||
p2 = r.point;
|
||||
p2.x += r.extent.x - 1;
|
||||
p2.y += r.extent.y - 1;
|
||||
|
||||
glColor4ub(color.red, color.green, color.blue, color.alpha);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(p1.x + 2, p1.y);
|
||||
glVertex2i(p2.x - 2, p1.y);
|
||||
glVertex2i(p2.x, p1.y + 2);
|
||||
glVertex2i(p2.x, p2.y - 2);
|
||||
glVertex2i(p2.x - 2, p2.y);
|
||||
glVertex2i(p1.x + 2, p2.y);
|
||||
glVertex2i(p1.x, p2.y - 2);
|
||||
glVertex2i(p1.x, p1.y + 2);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::onAction()
|
||||
{
|
||||
mStateOn = true;
|
||||
if (mGroupNum >= 0)
|
||||
messageSiblings(mGroupNum);
|
||||
|
||||
setUpdate();
|
||||
Parent::onAction();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::onMessage(GuiControl *sender, S32 msg)
|
||||
{
|
||||
Parent::onMessage(sender, msg);
|
||||
if (mGroupNum == msg)
|
||||
{
|
||||
setUpdate();
|
||||
mStateOn = (sender == this);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
bool stateOver = cursorInControl();
|
||||
bool stateDepressed = mGroupNum >= 0 && mStateOn;
|
||||
ColorI fontColor = (stateOver ? mProfile->mFontColorHL : mProfile->mFontColor);
|
||||
ColorI backColor = mActive ? mProfile->mFillColor : mProfile->mFillColorNA;
|
||||
ColorI insideBorderColor = (firstResponder == this) ? mProfile->mBorderColorHL : mProfile->mBorderColor;
|
||||
ColorI outsideBorderColor = mProfile->mBorderColor;
|
||||
|
||||
S32 txt_w = mFont->getStrWidth(mText);
|
||||
|
||||
Point2I localStart;
|
||||
|
||||
// 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 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// center the vertical
|
||||
localStart.y = (mBounds.extent.y - (mFont->getHeight() - 2)) / 2;
|
||||
|
||||
// first draw the background
|
||||
RectI r(offset, mBounds.extent);
|
||||
dglDrawRectFill(r, backColor);
|
||||
r.point.x +=2;
|
||||
r.point.y +=2;
|
||||
r.extent.x -=4;
|
||||
r.extent.y -=4;
|
||||
dglDrawRectFill(r, backColor);
|
||||
|
||||
//draw the radio box
|
||||
glColor3f(0.4f,0.4f,0.4f);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(r.point.x+3, r.point.y+3);
|
||||
glVertex2i(r.point.x+12, r.point.y+3);
|
||||
glVertex2i(r.point.x+12, r.point.y+12);
|
||||
glVertex2i(r.point.x+3, r.point.y+12);
|
||||
glEnd();
|
||||
|
||||
if (stateDepressed)
|
||||
{
|
||||
glColor3f(0.0f,0.0f,0.0f);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2i(r.point.x+6, r.point.y+6);
|
||||
glVertex2i(r.point.x+10, r.point.y+6);
|
||||
glVertex2i(r.point.x+10, r.point.y+10);
|
||||
glVertex2i(r.point.x+6, r.point.y+10);
|
||||
glEnd();
|
||||
}
|
||||
// draw the oustside border
|
||||
r.point.x -=1;
|
||||
r.point.y -=1;
|
||||
r.extent.x +=2;
|
||||
r.extent.y +=2;
|
||||
drawBorder(r, outsideBorderColor);
|
||||
|
||||
// finally draw the text
|
||||
localStart.y -= 2;
|
||||
localStart.x += 4;
|
||||
if (stateDepressed)
|
||||
{
|
||||
localStart.x += 1;
|
||||
localStart.y += 1;
|
||||
}
|
||||
Point2I globalStart = localToGlobalCoord(localStart);
|
||||
|
||||
dglSetBitmapModulation(fontColor);
|
||||
dglDrawText(mFont, globalStart, mText, mProfile->mFontColors);
|
||||
|
||||
//render the children
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void GuiRadioCtrl::setScriptValue(const char *newState)
|
||||
{
|
||||
if(dAtob(newState))
|
||||
onAction();
|
||||
else
|
||||
mStateOn = false;
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
const char *GuiRadioCtrl::getScriptValue()
|
||||
{
|
||||
return mStateOn ? "1" : "0";
|
||||
}
|
||||
|
||||
// EOF //
|
||||
|
||||
47
gui/guiRadioCtrl.h
Normal file
47
gui/guiRadioCtrl.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIRADIOCTRL_H_
|
||||
#define _GUIRADIOCTRL_H_
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiRadioCtrl : public GuiTextCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
protected:
|
||||
bool mKeyPressed;
|
||||
bool mStateOn;
|
||||
S32 mGroupNum;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiRadioCtrl);
|
||||
GuiRadioCtrl();
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
void AcceleratorKeyPress(void);
|
||||
void AcceleratorKeyRelease(void);
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
|
||||
// GuiTextCtrl updates mText with the variable value, which is not desired
|
||||
void onPreRender() {}
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
void drawBorder(const RectI &r, const ColorI &color);
|
||||
void onAction();
|
||||
void onMessage(GuiControl *,S32 msg);
|
||||
void setScriptValue(const char *);
|
||||
const char *getScriptValue();
|
||||
};
|
||||
|
||||
#endif //_GUI_RADIO_CTRL_H
|
||||
956
gui/guiScrollCtrl.cc
Normal file
956
gui/guiScrollCtrl.cc
Normal file
|
|
@ -0,0 +1,956 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "Core/resManager.h"
|
||||
#include "Platform/event.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiArrayCtrl.h"
|
||||
#include "GUI/guiScrollCtrl.h"
|
||||
|
||||
void GuiScrollContentCtrl::childResized(GuiControl *child)
|
||||
{
|
||||
GuiControl *parent = getParent();
|
||||
if (parent)
|
||||
{
|
||||
((GuiScrollCtrl *)parent)->computeSizes();
|
||||
}
|
||||
|
||||
Parent::childResized(child);
|
||||
}
|
||||
|
||||
void GuiScrollContentCtrl::removeObject(SimObject *object)
|
||||
{
|
||||
Parent::removeObject(object);
|
||||
GuiScrollCtrl *sctrl = NULL;
|
||||
GuiControl *parent = getParent();
|
||||
if (parent)
|
||||
{
|
||||
sctrl = dynamic_cast<GuiScrollCtrl *>(parent);
|
||||
}
|
||||
if (sctrl)
|
||||
{
|
||||
sctrl->computeSizes();
|
||||
}
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
GuiScrollCtrl::GuiScrollCtrl()
|
||||
{
|
||||
mBounds.extent.set(200,200);
|
||||
mChildMargin.set(0,0);
|
||||
mBorderThickness = 1;
|
||||
mScrollBarThickness = 16;
|
||||
mScrollBarArrowBtnLength = 16;
|
||||
stateDepressed = false;
|
||||
curHitRegion = None;
|
||||
|
||||
mBitmapBounds = NULL;
|
||||
|
||||
mLine_V = 0.1f;
|
||||
mLine_H = 0.1f;
|
||||
mPage_V = 0.2f;
|
||||
mPage_H = 0.2f;
|
||||
|
||||
mWillFirstRespond = true;
|
||||
mThumbAnchorPos = 0.0f;
|
||||
mUseConstantHeightThumb = false;
|
||||
|
||||
mForceVScrollBar = ScrollBarAlwaysOn;
|
||||
mForceHScrollBar = ScrollBarAlwaysOn;
|
||||
|
||||
mVBarThumbPos = 0;
|
||||
mHBarThumbPos = 0;
|
||||
|
||||
mDefaultLineHeight = 15;
|
||||
|
||||
mContentCtrl = NULL;
|
||||
}
|
||||
|
||||
GuiScrollCtrl::~GuiScrollCtrl()
|
||||
{
|
||||
if ( mBitmapBounds != NULL )
|
||||
{
|
||||
delete [] mBitmapBounds;
|
||||
mBitmapBounds = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static EnumTable::Enums scrollBarEnums[] =
|
||||
{
|
||||
{ GuiScrollCtrl::ScrollBarAlwaysOn, "alwaysOn" },
|
||||
{ GuiScrollCtrl::ScrollBarAlwaysOff, "alwaysOff" },
|
||||
{ GuiScrollCtrl::ScrollBarDynamic, "dynamic" },
|
||||
};
|
||||
static EnumTable gScrollBarTable(3, &scrollBarEnums[0]);
|
||||
|
||||
static void cGuiScrollCtrlScrollToTop( SimObject* obj, S32, const char** )
|
||||
{
|
||||
AssertFatal( dynamic_cast<GuiScrollCtrl*>( obj ), "Control passed to cGuiScrollCtrlScrollToTop is not a GuiScrollCtrl!" );
|
||||
GuiScrollCtrl* control = static_cast<GuiScrollCtrl*>( obj );
|
||||
control->scrollTo( 0, 0 );
|
||||
}
|
||||
|
||||
static void cGuiScrollCtrlScrollToBottom( SimObject* obj, S32, const char** )
|
||||
{
|
||||
AssertFatal( dynamic_cast<GuiScrollCtrl*>( obj ), "Control passed to cGuiScrollCtrlScrollToBottom is not a GuiScrollCtrl!" );
|
||||
GuiScrollCtrl* control = static_cast<GuiScrollCtrl*>( obj );
|
||||
control->scrollTo( 0, 1 );
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand( "GuiScrollCtrl", "scrollToTop", cGuiScrollCtrlScrollToTop, "control.scrollToTop();", 2, 2 );
|
||||
Con::addCommand( "GuiScrollCtrl", "scrollToBottom", cGuiScrollCtrlScrollToBottom, "control.scrollToBottom();", 2, 2 );
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("willFirstRespond", TypeBool, Offset(mWillFirstRespond, GuiScrollCtrl));
|
||||
addField("hScrollBar", TypeEnum, Offset(mForceHScrollBar, GuiScrollCtrl), 1, &gScrollBarTable);
|
||||
addField("vScrollBar", TypeEnum, Offset(mForceVScrollBar, GuiScrollCtrl), 1, &gScrollBarTable);
|
||||
addField("constantThumbHeight", TypeBool, Offset(mUseConstantHeightThumb, GuiScrollCtrl));
|
||||
addField("defaultLineHeight", TypeS32, Offset(mDefaultLineHeight, GuiScrollCtrl));
|
||||
addField("childMargin", TypePoint2I, Offset(mChildMargin, GuiScrollCtrl));
|
||||
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::resize(const Point2I &newPos, const Point2I &newExt)
|
||||
{
|
||||
Parent::resize(newPos, newExt);
|
||||
computeSizes();
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
GuiScrollContentCtrl *content = new GuiScrollContentCtrl;
|
||||
|
||||
if (!content->registerObject())
|
||||
Con::errorf(ConsoleLogEntry::General, "Unhandled execption, could not add content in GuiScrollCtrl::onAdd()");
|
||||
addObject(content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
AssertFatal(size(), "Scroll control created with no content control.");
|
||||
|
||||
mTextureHandle = mProfile->mTextureHandle;
|
||||
|
||||
mBitmapBounds = new RectI[BmpStates * BmpCount];
|
||||
AssertFatal( mBitmapBounds, "Failed to allocate memory for bitmap array!" );
|
||||
|
||||
bool result = createBitmapArray(mTextureHandle.getBitmap(), mBitmapBounds, BmpStates, BmpCount);
|
||||
AssertFatal(result, "Failed to create the bitmap array");
|
||||
|
||||
for(S32 i = 0; i < BmpStates; i++)
|
||||
{
|
||||
mBitmapBounds[BmpStates * BmpVThumb + i].inset(0, 1);
|
||||
mBitmapBounds[BmpStates * BmpVPage + i].inset(0, 1);
|
||||
mBitmapBounds[BmpStates * BmpHThumb + i].inset(1, 0);
|
||||
mBitmapBounds[BmpStates * BmpHPage + i].inset(1, 0);
|
||||
}
|
||||
|
||||
//init
|
||||
mBaseThumbSize = mBitmapBounds[BmpStates * BmpVThumbTopCap].extent.y +
|
||||
mBitmapBounds[BmpStates * BmpVThumbBottomCap].extent.y;
|
||||
mScrollBarThickness = mBitmapBounds[BmpStates * BmpVPage].extent.x;
|
||||
mScrollBarArrowBtnLength = mBitmapBounds[BmpStates * BmpUp].extent.y;
|
||||
computeSizes();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::onSleep()
|
||||
{
|
||||
Parent::onSleep();
|
||||
|
||||
if ( mBitmapBounds )
|
||||
{
|
||||
delete [] mBitmapBounds;
|
||||
mBitmapBounds = NULL;
|
||||
}
|
||||
|
||||
mTextureHandle = NULL;
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::calcChildExtents(Point2I *pos, Point2I *ext)
|
||||
{
|
||||
// loop through the children of this scroll view...
|
||||
if (! mContentCtrl->size())
|
||||
return false;
|
||||
#if 1
|
||||
GuiControl *ctrl = (GuiControl *) (mContentCtrl->front());
|
||||
*ext = ctrl->mBounds.extent;
|
||||
*pos = ctrl->mBounds.point;
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
bool anyVisible = false;
|
||||
SimGroup::iterator i;
|
||||
for(i = mContentCtrl->begin(); i != mContentCtrl->end();i++)
|
||||
{
|
||||
GuiControl *ctrl = (GuiControl *) (*i);
|
||||
if (ctrl->isVisible())
|
||||
{
|
||||
anyVisible = true;
|
||||
pos->x = getMin(pos->x, ctrl->mBounds.point.x);
|
||||
pos->y = getMin(pos->y, ctrl->mBounds.point.y);
|
||||
if (ctrl->mBounds.point.x + ctrl->mBounds.extent.x > pos->x + ext->x)
|
||||
ext->x = ctrl->mBounds.point.x + ctrl->mBounds.extent.x - pos->x;
|
||||
if (ctrl->mBounds.point.y + ctrl->mBounds.extent.y > pos->y + ext->y)
|
||||
ext->y = ctrl->mBounds.point.y + ctrl->mBounds.extent.y - pos->y;
|
||||
}
|
||||
}
|
||||
return anyVisible;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::addObject(SimObject *object)
|
||||
{
|
||||
GuiScrollContentCtrl *content = dynamic_cast<GuiScrollContentCtrl *>(object);
|
||||
if(content)
|
||||
{
|
||||
if(mContentCtrl)
|
||||
mContentCtrl->deleteObject();
|
||||
Parent::addObject(object);
|
||||
mContentCtrl = content;
|
||||
computeSizes();
|
||||
return;
|
||||
}
|
||||
AssertFatal(mContentCtrl, "ERROR - no content control for a scroll control");
|
||||
|
||||
mContentCtrl->addObject(object);
|
||||
computeSizes();
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::computeSizes()
|
||||
{
|
||||
Point2I pos(mBorderThickness, mBorderThickness);
|
||||
Point2I ext(mBounds.extent.x - (mBorderThickness << 1), mBounds.extent.y - (mBorderThickness << 1));
|
||||
Point2I cpos;
|
||||
Point2I cext;
|
||||
mHBarEnabled = false;
|
||||
mVBarEnabled = false;
|
||||
mHasVScrollBar = (mForceVScrollBar == ScrollBarAlwaysOn);
|
||||
mHasHScrollBar = (mForceHScrollBar == ScrollBarAlwaysOn);
|
||||
|
||||
setUpdate();
|
||||
|
||||
if (calcChildExtents(&cpos, &cext))
|
||||
{
|
||||
if (mHasVScrollBar)
|
||||
ext.x -= mScrollBarThickness;
|
||||
if (mHasHScrollBar)
|
||||
{
|
||||
ext.y -= mScrollBarThickness;
|
||||
}
|
||||
if (cext.x > ext.x && (mForceHScrollBar == ScrollBarDynamic))
|
||||
{
|
||||
mHasHScrollBar = true;
|
||||
ext.y -= mScrollBarThickness;
|
||||
}
|
||||
if (cext.y > ext.y && (mForceVScrollBar == ScrollBarDynamic))
|
||||
{
|
||||
mHasVScrollBar = true;
|
||||
ext.x -= mScrollBarThickness;
|
||||
// doh! ext.x changed, so check hscrollbar again
|
||||
if (cext.x > ext.x && !mHasHScrollBar && (mForceHScrollBar == ScrollBarDynamic))
|
||||
{
|
||||
mHasHScrollBar = true;
|
||||
ext.y -= mScrollBarThickness;
|
||||
}
|
||||
}
|
||||
|
||||
mContentCtrl->mBounds.point = pos + mChildMargin;
|
||||
mContentCtrl->mBounds.extent = (ext - mChildMargin) - mChildMargin;
|
||||
ext = mContentCtrl->mBounds.extent;
|
||||
// see if the child controls need to be repositioned (null space in control)
|
||||
Point2I delta(0,0);
|
||||
|
||||
if (cpos.x > 0)
|
||||
delta.x = -cpos.x;
|
||||
else if (ext.x > cpos.x + cext.x)
|
||||
{
|
||||
S32 diff = ext.x - (cpos.x + cext.x);
|
||||
delta.x = getMin(-cpos.x, diff);
|
||||
}
|
||||
|
||||
//reposition the children if the child extent > the scroll content extent
|
||||
if (cpos.y > 0)
|
||||
delta.y = -cpos.y;
|
||||
else if (ext.y > cpos.y + cext.y)
|
||||
{
|
||||
S32 diff = ext.y - (cpos.y + cext.y);
|
||||
delta.y = getMin(-cpos.y, diff);
|
||||
}
|
||||
|
||||
// apply the deltas to the children...
|
||||
if (delta.x || delta.y)
|
||||
{
|
||||
SimGroup::iterator i;
|
||||
for(i = mContentCtrl->begin(); i != mContentCtrl->end();i++)
|
||||
{
|
||||
GuiControl *ctrl = (GuiControl *) (*i);
|
||||
ctrl->mBounds.point += delta;
|
||||
}
|
||||
cpos += delta;
|
||||
}
|
||||
if (cext.x < ext.x)
|
||||
cext.x = ext.x;
|
||||
if (cext.y < ext.y)
|
||||
cext.y = ext.y;
|
||||
|
||||
// enable needed scroll bars
|
||||
if (cext.x > ext.x)
|
||||
mHBarEnabled = true;
|
||||
if (cext.y > ext.y)
|
||||
mVBarEnabled = true;
|
||||
|
||||
}
|
||||
// build all the rectangles and such...
|
||||
calcScrollRects();
|
||||
mLine_V = 0.1f;
|
||||
mLine_H = 0.1f;
|
||||
mPage_V = 0.2f;
|
||||
mPage_H = 0.2f;
|
||||
|
||||
/*
|
||||
SimGroup::iterator i;
|
||||
i = mContentCtrl->begin();
|
||||
if (i != mContentCtrl->end())
|
||||
{
|
||||
GuiControl *ctrl = (GuiControl *) (*i);
|
||||
RectI clientR(0,0,mContentCtrl->mBounds.extent.x, mContentCtrl->mBounds.extent.y);
|
||||
if (ctrl->mBounds.extent.y)
|
||||
{
|
||||
mLine_V = ctrl->scroll_mLine_V(clientR) / (F32)ctrl->mBounds.extent.y;
|
||||
|
||||
mPage_V = ctrl->scroll_mPage_V(clientR) / (F32)ctrl->mBounds.extent.y;
|
||||
}
|
||||
if (ctrl->mBounds.extent.x)
|
||||
{
|
||||
mLine_H = ctrl->scroll_mLine_H(clientR) / (F32)ctrl->mBounds.extent.x;
|
||||
mPage_H = ctrl->scroll_mPage_H(clientR) / (F32)ctrl->mBounds.extent.x;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
calcThumbs(cpos, cext);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::calcScrollRects(void)
|
||||
{
|
||||
if (mHasHScrollBar)
|
||||
{
|
||||
mLeftArrowRect.set(mBorderThickness,
|
||||
mBounds.extent.y - mBorderThickness - mScrollBarThickness - 1,
|
||||
mScrollBarArrowBtnLength,
|
||||
mScrollBarThickness);
|
||||
|
||||
mRightArrowRect.set(mBounds.extent.x - mBorderThickness - (mHasVScrollBar ? mScrollBarThickness : 0) - mScrollBarArrowBtnLength,
|
||||
mBounds.extent.y - mBorderThickness - mScrollBarThickness - 1,
|
||||
mScrollBarArrowBtnLength,
|
||||
mScrollBarThickness);
|
||||
mHTrackRect.set(mLeftArrowRect.point.x + mLeftArrowRect.extent.x,
|
||||
mLeftArrowRect.point.y,
|
||||
mRightArrowRect.point.x - (mLeftArrowRect.point.x + mLeftArrowRect.extent.x),
|
||||
mScrollBarThickness);
|
||||
}
|
||||
if (mHasVScrollBar)
|
||||
{
|
||||
mUpArrowRect.set(mBounds.extent.x - mBorderThickness - mScrollBarThickness,
|
||||
mBorderThickness,
|
||||
mScrollBarThickness,
|
||||
mScrollBarArrowBtnLength);
|
||||
mDownArrowRect.set(mBounds.extent.x - mBorderThickness - mScrollBarThickness,
|
||||
mBounds.extent.y - mBorderThickness - mScrollBarArrowBtnLength - (mHasHScrollBar ? ( mScrollBarThickness + 1 ) : 0),
|
||||
mScrollBarThickness,
|
||||
mScrollBarArrowBtnLength);
|
||||
mVTrackRect.set(mUpArrowRect.point.x,
|
||||
mUpArrowRect.point.y + mUpArrowRect.extent.y,
|
||||
mScrollBarThickness,
|
||||
mDownArrowRect.point.y - (mUpArrowRect.point.y + mUpArrowRect.extent.y) );
|
||||
}
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::calcThumbs(Point2I cpos, Point2I cext)
|
||||
{
|
||||
Point2I ext = mContentCtrl->mBounds.extent;
|
||||
if (mHBarEnabled)
|
||||
{
|
||||
mHBarThumbPos = -cpos.x / F32(cext.x - ext.x);
|
||||
mHBarThumbWidth = ext.x / F32(cext.x);
|
||||
|
||||
if (mUseConstantHeightThumb)
|
||||
mHThumbSize = mBaseThumbSize;
|
||||
else
|
||||
mHThumbSize = getMax(mBaseThumbSize, S32(mHBarThumbWidth * mHTrackRect.len_x()));
|
||||
mHThumbPos = (S32)(mHTrackRect.point.x + mHBarThumbPos * (mHTrackRect.len_x() - mHThumbSize));
|
||||
}
|
||||
if (mVBarEnabled)
|
||||
{
|
||||
mVBarThumbPos = -cpos.y / F32(cext.y - ext.y);
|
||||
mVBarThumbWidth = ext.y / F32(cext.y);
|
||||
|
||||
if (mUseConstantHeightThumb)
|
||||
mVThumbSize = mBaseThumbSize;
|
||||
else
|
||||
mVThumbSize = getMax(mBaseThumbSize, S32(mVBarThumbWidth * mVTrackRect.len_y()));
|
||||
mVThumbPos = (S32)(mVTrackRect.point.y + mVBarThumbPos * (mVTrackRect.len_y() - mVThumbSize));
|
||||
}
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::scrollTo(F32 x, F32 y)
|
||||
{
|
||||
setUpdate();
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
else if (x > 1)
|
||||
x = 1;
|
||||
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
else if (y > 1)
|
||||
y = 1;
|
||||
|
||||
if (x == mHBarThumbPos && y == mVBarThumbPos)
|
||||
return;
|
||||
|
||||
Point2I cpos, cext;
|
||||
|
||||
if (calcChildExtents(&cpos, &cext))
|
||||
{
|
||||
Point2I ext = mContentCtrl->mBounds.extent;
|
||||
Point2I npos;
|
||||
if (ext.x < cext.x)
|
||||
npos.x = (S32)(-x * (cext.x - ext.x));
|
||||
else
|
||||
npos.x = 0;
|
||||
if (ext.y < cext.y)
|
||||
npos.y = (S32)(-y * (cext.y - ext.y));
|
||||
else
|
||||
npos.y = 0;
|
||||
|
||||
Point2I delta(npos.x - cpos.x, npos.y - cpos.y);
|
||||
// get rid of bad (roundoff) deltas
|
||||
if (x == mHBarThumbPos)
|
||||
delta.x = 0;
|
||||
if (y == mVBarThumbPos)
|
||||
delta.y = 0;
|
||||
SimGroup::iterator i;
|
||||
|
||||
for(i = mContentCtrl->begin(); i != mContentCtrl->end();i++)
|
||||
{
|
||||
GuiControl *ctrl = (GuiControl *) (*i);
|
||||
ctrl->mBounds.point += delta;
|
||||
}
|
||||
cpos += delta;
|
||||
calcThumbs(cpos, cext);
|
||||
}
|
||||
}
|
||||
|
||||
GuiScrollCtrl::Region GuiScrollCtrl::findHitRegion(const Point2I &pt)
|
||||
{
|
||||
if (mVBarEnabled && mHasVScrollBar)
|
||||
{
|
||||
if (mUpArrowRect.pointInRect(pt))
|
||||
return UpArrow;
|
||||
else if (mDownArrowRect.pointInRect(pt))
|
||||
return DownArrow;
|
||||
else if (mVTrackRect.pointInRect(pt))
|
||||
{
|
||||
if (pt.y < mVThumbPos)
|
||||
return UpPage;
|
||||
else if (pt.y < mVThumbPos + mVThumbSize)
|
||||
return VertThumb;
|
||||
else
|
||||
return DownPage;
|
||||
}
|
||||
}
|
||||
if (mHBarEnabled && mHasHScrollBar)
|
||||
{
|
||||
if (mLeftArrowRect.pointInRect(pt))
|
||||
return LeftArrow;
|
||||
else if (mRightArrowRect.pointInRect(pt))
|
||||
return RightArrow;
|
||||
else if (mHTrackRect.pointInRect(pt))
|
||||
{
|
||||
if (pt.x < mHThumbPos)
|
||||
return LeftPage;
|
||||
else if (pt.x < mHThumbPos + mHThumbSize)
|
||||
return HorizThumb;
|
||||
else
|
||||
return RightPage;
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::wantsTabListMembership()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::loseFirstResponder()
|
||||
{
|
||||
setUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::becomeFirstResponder()
|
||||
{
|
||||
setUpdate();
|
||||
return mWillFirstRespond;
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
if (mWillFirstRespond)
|
||||
{
|
||||
switch (event.keyCode)
|
||||
{
|
||||
case KEY_RIGHT:
|
||||
scrollByRegion(RightArrow);
|
||||
return true;
|
||||
|
||||
case KEY_LEFT:
|
||||
scrollByRegion(LeftArrow);
|
||||
return true;
|
||||
|
||||
case KEY_DOWN:
|
||||
scrollByRegion(DownArrow);
|
||||
return true;
|
||||
|
||||
case KEY_UP:
|
||||
scrollByRegion(UpArrow);
|
||||
return true;
|
||||
|
||||
case KEY_PAGE_UP:
|
||||
scrollByRegion(UpPage);
|
||||
return true;
|
||||
|
||||
case KEY_PAGE_DOWN:
|
||||
scrollByRegion(DownPage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
mouseLock();
|
||||
setFirstResponder();
|
||||
|
||||
setUpdate();
|
||||
|
||||
Point2I curMousePos = globalToLocalCoord(event.mousePoint);
|
||||
curHitRegion = findHitRegion(curMousePos);
|
||||
stateDepressed = true;
|
||||
|
||||
scrollByRegion(curHitRegion);
|
||||
|
||||
if (curHitRegion == VertThumb)
|
||||
{
|
||||
mThumbAnchorPos = mVBarThumbPos;
|
||||
mThumbDelta = curMousePos.y - mVThumbPos;
|
||||
}
|
||||
else if (curHitRegion == HorizThumb)
|
||||
{
|
||||
mThumbAnchorPos = mHBarThumbPos;
|
||||
mThumbDelta = curMousePos.x - mHThumbPos;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::onMouseUp(const GuiEvent &)
|
||||
{
|
||||
mouseUnlock();
|
||||
|
||||
setUpdate();
|
||||
|
||||
curHitRegion = None;
|
||||
stateDepressed = false;
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
Point2I curMousePos = globalToLocalCoord(event.mousePoint);
|
||||
setUpdate();
|
||||
|
||||
if ( (curHitRegion != VertThumb) && (curHitRegion != HorizThumb) )
|
||||
{
|
||||
Region hit = findHitRegion(curMousePos);
|
||||
if (hit != curHitRegion)
|
||||
stateDepressed = false;
|
||||
else
|
||||
stateDepressed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// ok... if the mouse is 'near' the scroll bar, scroll with it
|
||||
// otherwise, snap back to the previous position.
|
||||
|
||||
if (curHitRegion == VertThumb)
|
||||
{
|
||||
if (curMousePos.x >= mVTrackRect.point.x - mScrollBarThickness &&
|
||||
curMousePos.x <= mVTrackRect.point.x + mVTrackRect.extent.x - 1 + mScrollBarThickness &&
|
||||
curMousePos.y >= mVTrackRect.point.y - mScrollBarThickness &&
|
||||
curMousePos.y <= mVTrackRect.point.y + mVTrackRect.extent.y - 1 + mScrollBarThickness)
|
||||
{
|
||||
scrollTo(mHBarThumbPos,
|
||||
(curMousePos.y - mThumbDelta - mVTrackRect.point.y) /
|
||||
F32(mVTrackRect.len_y() - mVThumbSize));
|
||||
}
|
||||
else
|
||||
scrollTo(mHBarThumbPos, mThumbAnchorPos);
|
||||
}
|
||||
else if (curHitRegion == HorizThumb)
|
||||
{
|
||||
if (curMousePos.x >= mHTrackRect.point.x - mScrollBarThickness &&
|
||||
curMousePos.x <= mHTrackRect.point.x + mHTrackRect.extent.x - 1 + mScrollBarThickness &&
|
||||
curMousePos.y >= mHTrackRect.point.y - mScrollBarThickness &&
|
||||
curMousePos.y <= mHTrackRect.point.y + mHTrackRect.extent.y - 1 + mScrollBarThickness)
|
||||
{
|
||||
scrollTo((curMousePos.x - mThumbDelta - mHTrackRect.point.x) /
|
||||
F32(mHTrackRect.len_x() - mHThumbSize),
|
||||
mVBarThumbPos);
|
||||
}
|
||||
else
|
||||
scrollTo(mThumbAnchorPos, mVBarThumbPos);
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::onMouseWheelUp(const GuiEvent &event)
|
||||
{
|
||||
if ( !mAwake || !mVisible )
|
||||
return( false );
|
||||
|
||||
scrollByRegion((event.modifier & SI_CTRL) ? UpPage : UpArrow);
|
||||
|
||||
// Tell the kids that the mouse moved (relatively):
|
||||
iterator itr;
|
||||
for ( itr = mContentCtrl->begin(); itr != mContentCtrl->end(); itr++ )
|
||||
{
|
||||
GuiControl* grandKid = static_cast<GuiControl*>( *itr );
|
||||
grandKid->onMouseMove( event );
|
||||
}
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
bool GuiScrollCtrl::onMouseWheelDown(const GuiEvent &event)
|
||||
{
|
||||
if ( !mAwake || !mVisible )
|
||||
return( false );
|
||||
|
||||
scrollByRegion((event.modifier & SI_CTRL) ? DownPage : DownArrow);
|
||||
|
||||
// Tell the kids that the mouse moved (relatively):
|
||||
iterator itr;
|
||||
for ( itr = mContentCtrl->begin(); itr != mContentCtrl->end(); itr++ )
|
||||
{
|
||||
GuiControl* grandKid = static_cast<GuiControl *>( *itr );
|
||||
grandKid->onMouseMove( event );
|
||||
}
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
void GuiScrollCtrl::scrollByRegion(Region reg)
|
||||
{
|
||||
setUpdate();
|
||||
if (mVBarEnabled)
|
||||
{
|
||||
bool alreadyScrolled = false;
|
||||
GuiControl* grandKid = NULL;
|
||||
GuiArrayCtrl *ac = NULL;
|
||||
if (mContentCtrl->begin())
|
||||
{
|
||||
grandKid = (GuiControl *)(mContentCtrl->front());
|
||||
ac = dynamic_cast<GuiArrayCtrl*>(grandKid);
|
||||
}
|
||||
|
||||
if ( ac || ( grandKid && mDefaultLineHeight > 0 ) )
|
||||
{
|
||||
S32 lineHeight, numCells;
|
||||
if ( ac )
|
||||
ac->getScrollDimensions(lineHeight, numCells);
|
||||
else
|
||||
{
|
||||
lineHeight = mDefaultLineHeight;
|
||||
numCells = 47; // OK, we're just fakin'...
|
||||
}
|
||||
|
||||
if (lineHeight > 0 && numCells > 0)
|
||||
{
|
||||
S32 pageHeight = S32(mContentCtrl->mBounds.extent.y / lineHeight) * (lineHeight - 1) - 1;
|
||||
switch(reg)
|
||||
{
|
||||
case UpPage:
|
||||
grandKid->mBounds.point.y = getMin(0, getMax(mContentCtrl->mBounds.extent.y - grandKid->mBounds.extent.y, grandKid->mBounds.point.y + pageHeight));
|
||||
break;
|
||||
case DownPage:
|
||||
grandKid->mBounds.point.y = getMin(0, getMax(mContentCtrl->mBounds.extent.y - grandKid->mBounds.extent.y, grandKid->mBounds.point.y - pageHeight));
|
||||
break;
|
||||
case UpArrow:
|
||||
grandKid->mBounds.point.y = getMin(0, getMax(mContentCtrl->mBounds.extent.y - grandKid->mBounds.extent.y, grandKid->mBounds.point.y + lineHeight));
|
||||
break;
|
||||
case DownArrow:
|
||||
grandKid->mBounds.point.y = getMin(0, getMax(mContentCtrl->mBounds.extent.y - grandKid->mBounds.extent.y, grandKid->mBounds.point.y - lineHeight));
|
||||
break;
|
||||
}
|
||||
calcThumbs(grandKid->mBounds.point, grandKid->mBounds.extent);
|
||||
alreadyScrolled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! alreadyScrolled)
|
||||
{
|
||||
// If all else fails, scroll by percentage:
|
||||
mPage_V = 0.1f;
|
||||
mLine_V = 0.1f;
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case UpPage:
|
||||
scrollTo(mHBarThumbPos, mVBarThumbPos - mPage_V);
|
||||
break;
|
||||
case DownPage:
|
||||
scrollTo(mHBarThumbPos, mVBarThumbPos + mPage_V);
|
||||
break;
|
||||
case UpArrow:
|
||||
scrollTo(mHBarThumbPos, mVBarThumbPos - mLine_V);
|
||||
break;
|
||||
case DownArrow:
|
||||
scrollTo(mHBarThumbPos, mVBarThumbPos + mLine_V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mHBarEnabled)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
case LeftPage:
|
||||
scrollTo(mHBarThumbPos - mPage_H, mVBarThumbPos);
|
||||
break;
|
||||
case RightPage:
|
||||
scrollTo(mHBarThumbPos + mPage_H, mVBarThumbPos);
|
||||
break;
|
||||
case LeftArrow:
|
||||
scrollTo(mHBarThumbPos - mLine_H, mVBarThumbPos);
|
||||
break;
|
||||
case RightArrow:
|
||||
scrollTo(mHBarThumbPos + mLine_H, mVBarThumbPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiScrollCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
// draw border
|
||||
drawBorder( offset, ( firstResponder == this ) );
|
||||
|
||||
// draw scroll bars
|
||||
if (mHasVScrollBar)
|
||||
drawVScrollBar(offset);
|
||||
|
||||
if (mHasHScrollBar)
|
||||
drawHScrollBar(offset);
|
||||
|
||||
//draw the scroll corner
|
||||
if (mHasVScrollBar && mHasHScrollBar)
|
||||
drawScrollCorner(offset);
|
||||
|
||||
// draw content and its children
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::drawBorder( const Point2I &offset, bool /*isFirstResponder*/ )
|
||||
{
|
||||
RectI r(offset.x, offset.y, mBounds.extent.x, mBounds.extent.y);
|
||||
|
||||
if (mProfile->mOpaque)
|
||||
dglDrawRectFill(r, mProfile->mFillColor);
|
||||
|
||||
if (mProfile->mBorder)
|
||||
dglDrawRect(r, mProfile->mBorderColor);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::drawVScrollBar(const Point2I &offset)
|
||||
{
|
||||
Point2I pos = offset + mUpArrowRect.point;
|
||||
S32 bitmap = (mVBarEnabled ? ((curHitRegion == UpArrow && stateDepressed) ?
|
||||
BmpStates * BmpUp + BmpHilite : BmpStates * BmpUp) : BmpStates * BmpUp + BmpDisabled);
|
||||
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[bitmap]);
|
||||
|
||||
pos.y += mScrollBarArrowBtnLength;
|
||||
S32 end;
|
||||
if (mVBarEnabled)
|
||||
end = mVThumbPos + offset.y;
|
||||
else
|
||||
end = mDownArrowRect.point.y + offset.y;
|
||||
|
||||
bitmap = (mVBarEnabled ? ((curHitRegion == DownPage && stateDepressed) ?
|
||||
BmpStates * BmpVPage + BmpHilite : BmpStates * BmpVPage) : BmpStates * BmpVPage + BmpDisabled);
|
||||
|
||||
if (end > pos.y)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretchSR(mTextureHandle, RectI(pos, Point2I(mBitmapBounds[bitmap].extent.x, end - pos.y)), mBitmapBounds[bitmap]);
|
||||
}
|
||||
|
||||
pos.y = end;
|
||||
if (mVBarEnabled)
|
||||
{
|
||||
bool thumbSelected = (curHitRegion == VertThumb && stateDepressed);
|
||||
S32 ttop = (thumbSelected ? BmpStates * BmpVThumbTopCap + BmpHilite : BmpStates * BmpVThumbTopCap);
|
||||
S32 tmid = (thumbSelected ? BmpStates * BmpVThumb + BmpHilite : BmpStates * BmpVThumb);
|
||||
S32 tbot = (thumbSelected ? BmpStates * BmpVThumbBottomCap + BmpHilite : BmpStates * BmpVThumbBottomCap);
|
||||
|
||||
// draw the thumb
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[ttop]);
|
||||
pos.y += mBitmapBounds[ttop].extent.y;
|
||||
end = mVThumbPos + mVThumbSize - mBitmapBounds[tbot].extent.y + offset.y;
|
||||
|
||||
if (end > pos.y)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretchSR(mTextureHandle, RectI(pos, Point2I(mBitmapBounds[tmid].extent.x, end - pos.y)), mBitmapBounds[tmid]);
|
||||
}
|
||||
|
||||
pos.y = end;
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[tbot]);
|
||||
pos.y += mBitmapBounds[tbot].extent.y;
|
||||
end = mVTrackRect.point.y + mVTrackRect.extent.y - 1 + offset.y;
|
||||
|
||||
bitmap = (curHitRegion == DownPage && stateDepressed) ? BmpStates * BmpVPage + BmpHilite : BmpStates * BmpVPage;
|
||||
if (end > pos.y)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretchSR(mTextureHandle, RectI(pos, Point2I(mBitmapBounds[bitmap].extent.x, end - pos.y)), mBitmapBounds[bitmap]);
|
||||
}
|
||||
|
||||
pos.y = end;
|
||||
}
|
||||
|
||||
bitmap = (mVBarEnabled ? ((curHitRegion == DownArrow && stateDepressed ) ?
|
||||
BmpStates * BmpDown + BmpHilite : BmpStates * BmpDown) : BmpStates * BmpDown + BmpDisabled);
|
||||
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[bitmap]);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::drawHScrollBar(const Point2I &offset)
|
||||
{
|
||||
S32 bitmap;
|
||||
|
||||
//draw the left arrow
|
||||
bitmap = (mHBarEnabled ? ((curHitRegion == LeftArrow && stateDepressed) ?
|
||||
BmpStates * BmpLeft + BmpHilite : BmpStates * BmpLeft) : BmpStates * BmpLeft + BmpDisabled);
|
||||
|
||||
Point2I pos = offset;
|
||||
pos += mLeftArrowRect.point;
|
||||
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[bitmap]);
|
||||
|
||||
pos.x += mLeftArrowRect.extent.x;
|
||||
|
||||
//draw the left page
|
||||
S32 end;
|
||||
if (mHBarEnabled)
|
||||
end = mHThumbPos + offset.x;
|
||||
else
|
||||
end = mRightArrowRect.point.x + offset.x;
|
||||
|
||||
bitmap = (mHBarEnabled ? ((curHitRegion == LeftPage && stateDepressed) ?
|
||||
BmpStates * BmpHPage + BmpHilite : BmpStates * BmpHPage) : BmpStates * BmpHPage + BmpDisabled);
|
||||
|
||||
if (end > pos.x)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretchSR(mTextureHandle, RectI(pos, Point2I(end - pos.x, mBitmapBounds[bitmap].extent.y)), mBitmapBounds[bitmap]);
|
||||
}
|
||||
pos.x = end;
|
||||
|
||||
//draw the thumb and the rightPage
|
||||
if (mHBarEnabled)
|
||||
{
|
||||
bool thumbSelected = (curHitRegion == HorizThumb && stateDepressed);
|
||||
S32 ttop = (thumbSelected ? BmpStates * BmpHThumbLeftCap + BmpHilite : BmpStates * BmpHThumbLeftCap );
|
||||
S32 tmid = (thumbSelected ? BmpStates * BmpHThumb + BmpHilite : BmpStates * BmpHThumb);
|
||||
S32 tbot = (thumbSelected ? BmpStates * BmpHThumbRightCap + BmpHilite : BmpStates * BmpHThumbRightCap);
|
||||
|
||||
// draw the thumb
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[ttop]);
|
||||
pos.x += mBitmapBounds[ttop].extent.x;
|
||||
end = mHThumbPos + mHThumbSize - mBitmapBounds[tbot].extent.x + offset.x;
|
||||
if (end > pos.x)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretchSR(mTextureHandle, RectI(pos, Point2I(end - pos.x, mBitmapBounds[tmid].extent.y)), mBitmapBounds[tmid]);
|
||||
}
|
||||
|
||||
pos.x = end;
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[tbot]);
|
||||
pos.x += mBitmapBounds[tbot].extent.x;
|
||||
end = mHTrackRect.point.x + mHTrackRect.extent.x - 1 + offset.x;
|
||||
|
||||
bitmap = ((curHitRegion == RightPage && stateDepressed) ? BmpStates * BmpHPage + BmpHilite : BmpStates * BmpHPage);
|
||||
|
||||
if (end > pos.x)
|
||||
{
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapStretchSR(mTextureHandle, RectI(pos, Point2I(end - pos.x, mBitmapBounds[bitmap].extent.y)), mBitmapBounds[bitmap]);
|
||||
}
|
||||
|
||||
pos.x = end;
|
||||
}
|
||||
bitmap = (mHBarEnabled ? ((curHitRegion == RightArrow && stateDepressed) ?
|
||||
BmpStates * BmpRight + BmpHilite : BmpStates * BmpRight) : BmpStates * BmpRight + BmpDisabled);
|
||||
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[bitmap]);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::drawScrollCorner(const Point2I &offset)
|
||||
{
|
||||
Point2I pos = offset;
|
||||
pos.x += mRightArrowRect.point.x + mRightArrowRect.extent.x;
|
||||
pos.y += mRightArrowRect.point.y;
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, pos, mBitmapBounds[BmpStates * BmpResize]);
|
||||
}
|
||||
|
||||
void GuiScrollCtrl::autoScroll(Region reg)
|
||||
{
|
||||
scrollByRegion(reg);
|
||||
}
|
||||
238
gui/guiScrollCtrl.h
Normal file
238
gui/guiScrollCtrl.h
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUISCROLLCTRL_H_
|
||||
#define _GUISCROLLCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
// the function of the scroll content control class
|
||||
// is to notify the parent class that children have resized.
|
||||
// basically it just calls it's parent (enclosing) control's
|
||||
// childResized method which turns around and computes new sizes
|
||||
// for the scroll bars
|
||||
|
||||
class GuiScrollContentCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
void childResized(GuiControl *child);
|
||||
void removeObject(SimObject *object);
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiScrollContentCtrl);
|
||||
};
|
||||
|
||||
class GuiScrollCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
// the scroll control uses a bitmap array to draw all its
|
||||
// stuff... these are the bitmaps it needs:
|
||||
|
||||
enum BitmapIndices
|
||||
{
|
||||
BmpUp,
|
||||
BmpDown,
|
||||
BmpVThumbTopCap,
|
||||
BmpVThumb,
|
||||
BmpVThumbBottomCap,
|
||||
BmpVPage,
|
||||
BmpLeft,
|
||||
BmpRight,
|
||||
BmpHThumbLeftCap,
|
||||
BmpHThumb,
|
||||
BmpHThumbRightCap,
|
||||
BmpHPage,
|
||||
BmpResize,
|
||||
|
||||
BmpCount
|
||||
};
|
||||
|
||||
enum BitmapStates
|
||||
{
|
||||
BmpDefault = 0,
|
||||
BmpHilite,
|
||||
BmpDisabled,
|
||||
|
||||
BmpStates
|
||||
};
|
||||
RectI* mBitmapBounds; //bmp is [3*n], bmpHL is [3*n + 1], bmpNA is [3*n + 2]
|
||||
TextureHandle mTextureHandle;
|
||||
|
||||
GuiScrollContentCtrl *mContentCtrl; // always have a pointer to the content control
|
||||
|
||||
S32 mBorderThickness; // this gets set per class in the constructor
|
||||
Point2I mChildMargin; // the thickeness of the margin around the child controls
|
||||
// note - it is implicit in the scroll view that the buttons all have the same
|
||||
// arrow length and that horizontal and vertical scroll bars have the
|
||||
// same thickness
|
||||
|
||||
S32 mScrollBarThickness; // determined by the width of the vertical page bmp
|
||||
S32 mScrollBarArrowBtnLength; // determined by the height of the up arrow
|
||||
|
||||
bool mHBarEnabled;
|
||||
bool mVBarEnabled;
|
||||
bool mHasHScrollBar;
|
||||
bool mHasVScrollBar;
|
||||
|
||||
F32 mHBarThumbPos;
|
||||
F32 mHBarThumbWidth;
|
||||
F32 mVBarThumbPos;
|
||||
F32 mVBarThumbWidth;
|
||||
|
||||
S32 mHThumbSize;
|
||||
S32 mHThumbPos;
|
||||
|
||||
S32 mVThumbSize;
|
||||
S32 mVThumbPos;
|
||||
|
||||
S32 mBaseThumbSize;
|
||||
|
||||
RectI mUpArrowRect;
|
||||
RectI mDownArrowRect;
|
||||
RectI mLeftArrowRect;
|
||||
RectI mRightArrowRect;
|
||||
RectI mHTrackRect;
|
||||
RectI mVTrackRect;
|
||||
|
||||
S32 mDefaultLineHeight; // line height for scroll controls that DO NOT have array controls in them
|
||||
// ignored if left at zero
|
||||
|
||||
F32 mLine_V; // percentage to scroll line Vertically
|
||||
F32 mLine_H;
|
||||
F32 mPage_V; // percentage to scroll page Vertically
|
||||
F32 mPage_H;
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
// for determing hit area
|
||||
public: //called by the ComboPopUp class
|
||||
enum Region
|
||||
{
|
||||
UpArrow,
|
||||
DownArrow,
|
||||
LeftArrow,
|
||||
RightArrow,
|
||||
UpPage,
|
||||
DownPage,
|
||||
LeftPage,
|
||||
RightPage,
|
||||
VertThumb,
|
||||
HorizThumb,
|
||||
None
|
||||
};
|
||||
Region findHitRegion(const Point2I &);
|
||||
|
||||
protected:
|
||||
bool stateDepressed;
|
||||
Region curHitRegion;
|
||||
|
||||
virtual bool calcChildExtents(Point2I *pos, Point2I *ext);
|
||||
virtual void calcScrollRects(void);
|
||||
void calcThumbs(Point2I cpos, Point2I cext);
|
||||
void scrollByRegion(Region reg);
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
//--------------------------------------
|
||||
// for mouse dragging the thumb
|
||||
F32 mThumbAnchorPos;
|
||||
S32 mThumbDelta;
|
||||
//--------------------------------------
|
||||
|
||||
public:
|
||||
GuiScrollCtrl();
|
||||
~GuiScrollCtrl();
|
||||
DECLARE_CONOBJECT(GuiScrollCtrl);
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
void autoScroll(Region reg);
|
||||
bool disabled;
|
||||
|
||||
F32 getCurrVPos() const;
|
||||
F32 getCurrHPos() const;
|
||||
|
||||
void scrollTo(F32 x, F32 y);
|
||||
void computeSizes();
|
||||
|
||||
enum {
|
||||
ScrollBarAlwaysOn = 0,
|
||||
ScrollBarAlwaysOff = 1,
|
||||
ScrollBarDynamic = 2
|
||||
};
|
||||
// you can change the bitmap array dynamically.
|
||||
void loadBitmapArray();
|
||||
|
||||
S32 mForceHScrollBar;
|
||||
S32 mForceVScrollBar;
|
||||
|
||||
bool mUseConstantHeightThumb;
|
||||
bool mWillFirstRespond; // for automatically handling arrow keys
|
||||
|
||||
GuiScrollContentCtrl *getScrollContentCtrl() { return mContentCtrl; }
|
||||
|
||||
void addObject(SimObject *object);
|
||||
void resize(const Point2I &newPos, const Point2I &newExt);
|
||||
S32 getBorderThickness(void) { return mBorderThickness; }
|
||||
S32 scrollBarThickness() const { return(mScrollBarThickness); }
|
||||
S32 scrollBarArrowBtnLength() const { return(mScrollBarArrowBtnLength); }
|
||||
bool hasHScrollBar() const { return(mHasHScrollBar); }
|
||||
bool hasVScrollBar() const { return(mHasVScrollBar); }
|
||||
bool enabledHScrollBar() const { return(mHBarEnabled); }
|
||||
bool enabledVScrollBar() const { return(mVBarEnabled); }
|
||||
|
||||
bool wantsTabListMembership();
|
||||
bool becomeFirstResponder();
|
||||
bool loseFirstResponder();
|
||||
|
||||
Region getCurHitRegion(void) { return curHitRegion; }
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseRepeat(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
bool onMouseWheelUp(const GuiEvent &event);
|
||||
bool onMouseWheelDown(const GuiEvent &event);
|
||||
|
||||
bool onAdd();
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
virtual void drawBorder(const Point2I &offset, bool isFirstResponder);
|
||||
virtual void drawVScrollBar(const Point2I &offset);
|
||||
virtual void drawHScrollBar(const Point2I &offset);
|
||||
virtual void drawScrollCorner(const Point2I &offset);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline F32 GuiScrollCtrl::getCurrVPos() const
|
||||
{
|
||||
if (mHasVScrollBar)
|
||||
return mVBarThumbPos;
|
||||
else
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
inline F32 GuiScrollCtrl::getCurrHPos() const
|
||||
{
|
||||
if (mHasVScrollBar)
|
||||
return mVBarThumbPos;
|
||||
else
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
#endif //_GUI_SCROLL_CTRL_H
|
||||
256
gui/guiSliderCtrl.cc
Normal file
256
gui/guiSliderCtrl.cc
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "GUI/guiSliderCtrl.h"
|
||||
#include "Platform/event.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
GuiSliderCtrl::GuiSliderCtrl(void)
|
||||
{
|
||||
mActive = true;
|
||||
mRange.set( 0.0f, 1.0f );
|
||||
mTicks = 1000;
|
||||
mValue = 0.5f;
|
||||
mThumbSize.set(8,20);
|
||||
mShiftPoint = 5;
|
||||
mShiftExtent = 10;
|
||||
mDisplayValue = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void GuiSliderCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("range", TypePoint2F, Offset(mRange, GuiSliderCtrl));
|
||||
addField("ticks", TypeS32, Offset(mTicks, GuiSliderCtrl));
|
||||
addField("value", TypeF32, Offset(mValue, GuiSliderCtrl));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static F32 cGuiSlider_GetValue(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiSliderCtrl *ctrl = static_cast<GuiSliderCtrl*>(obj);
|
||||
return ctrl->getValue();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void GuiSliderCtrl::setScriptValue(const char *val)
|
||||
{
|
||||
mValue = dAtof(val);
|
||||
updateThumb(mValue);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void GuiSliderCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiSliderCtrl", "getValue", cGuiSlider_GetValue, "guiSliderCtrl.getValue()", 2, 2);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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
|
||||
Con::printf("snapping");
|
||||
|
||||
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 );
|
||||
// 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;
|
||||
}
|
||||
setConsoleVariable("value");
|
||||
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, GuiControl *firstResponder)
|
||||
{
|
||||
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;
|
||||
dglDrawRectFill(thumb, ColorI(255,255,255));
|
||||
dglDrawRect(thumb, ColorI(0,0,0));
|
||||
|
||||
if(mDisplayValue)
|
||||
{
|
||||
char buf[20];
|
||||
dSprintf(buf,sizeof(buf),"%0.3f",mValue);
|
||||
|
||||
Point2I textStart = thumb.point;
|
||||
|
||||
S32 txt_w = mProfile->mFont->getStrWidth(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, firstResponder);
|
||||
}
|
||||
|
||||
51
gui/guiSliderCtrl.h
Normal file
51
gui/guiSliderCtrl.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUISLIDERCTRL_H_
|
||||
#define _GUISLIDERCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/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();
|
||||
static void consoleInit();
|
||||
|
||||
//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, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif
|
||||
130
gui/guiTSControl.cc
Normal file
130
gui/guiTSControl.cc
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/guiTSControl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "sceneGraph/sceneLighting.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiTSCtrl);
|
||||
|
||||
U32 GuiTSCtrl::smFrameCount = 0;
|
||||
|
||||
GuiTSCtrl::GuiTSCtrl()
|
||||
{
|
||||
for(U32 i = 0; i < 16; i++)
|
||||
{
|
||||
mSaveModelview[i] = 0;
|
||||
mSaveProjection[i] = 0;
|
||||
}
|
||||
mSaveModelview[0] = 1;
|
||||
mSaveModelview[5] = 1;
|
||||
mSaveModelview[10] = 1;
|
||||
mSaveModelview[15] = 1;
|
||||
mSaveProjection[0] = 1;
|
||||
mSaveProjection[5] = 1;
|
||||
mSaveProjection[10] = 1;
|
||||
mSaveProjection[15] = 1;
|
||||
|
||||
mSaveViewport[0] = 0;
|
||||
mSaveViewport[1] = 0;
|
||||
mSaveViewport[2] = 2;
|
||||
mSaveViewport[3] = 2;
|
||||
}
|
||||
|
||||
void GuiTSCtrl::consoleInit()
|
||||
{
|
||||
Con::addVariable("$TSControl::frameCount", TypeS32, &smFrameCount);
|
||||
}
|
||||
|
||||
void GuiTSCtrl::onPreRender()
|
||||
{
|
||||
setUpdate();
|
||||
}
|
||||
|
||||
bool GuiTSCtrl::processCameraQuery(CameraQuery *)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuiTSCtrl::renderWorld(const RectI& /*updateRect*/)
|
||||
{
|
||||
}
|
||||
|
||||
bool GuiTSCtrl::project(const Point3F &pt, Point3F *dest)
|
||||
{
|
||||
GLdouble winx, winy, winz;
|
||||
GLint result = gluProject(pt.x, pt.y, pt.z,
|
||||
mSaveModelview, mSaveProjection, mSaveViewport,
|
||||
&winx, &winy, &winz);
|
||||
if(result == GL_FALSE || winz < 0 || winz > 1)
|
||||
return false;
|
||||
dest->set(winx, winy, winz);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuiTSCtrl::unproject(const Point3F &pt, Point3F *dest)
|
||||
{
|
||||
GLdouble objx, objy, objz;
|
||||
GLint result = gluUnProject(pt.x, pt.y, pt.z,
|
||||
mSaveModelview, mSaveProjection, mSaveViewport,
|
||||
&objx, &objy, &objz);
|
||||
if(result == GL_FALSE)
|
||||
return false;
|
||||
dest->set(objx, objy, objz);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl* /*firstResponder*/)
|
||||
{
|
||||
if(SceneLighting::isLighting())
|
||||
return;
|
||||
|
||||
if(!processCameraQuery(&mLastCameraQuery))
|
||||
return;
|
||||
|
||||
// set up the camera and viewport stuff:
|
||||
F32 wwidth = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2);
|
||||
F32 wheight = F32(mBounds.extent.y) / F32(mBounds.extent.x) * wwidth;
|
||||
|
||||
F32 hscale = wwidth * 2 / F32(mBounds.extent.x);
|
||||
F32 vscale = wheight * 2 / F32(mBounds.extent.y);
|
||||
|
||||
F32 left = (updateRect.point.x - offset.x) * hscale - wwidth;
|
||||
F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth;
|
||||
F32 top = wheight - vscale * (updateRect.point.y - offset.y);
|
||||
F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y);
|
||||
|
||||
dglSetViewport(updateRect);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
dglSetFrustum(left, right, bottom, top, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
//Point3F refPt = query.position + query.viewVector;
|
||||
|
||||
mLastCameraQuery.cameraMatrix.inverse();
|
||||
dglMultMatrix(&mLastCameraQuery.cameraMatrix);
|
||||
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, mSaveProjection);
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, mSaveModelview);
|
||||
//glGetIntegerv(GL_VIEWPORT, mSaveViewport);
|
||||
|
||||
//U32 screenHeight = Platform::getWindowSize().y;
|
||||
mSaveViewport[0] = updateRect.point.x;
|
||||
mSaveViewport[1] = updateRect.point.y + updateRect.extent.y;
|
||||
mSaveViewport[2] = updateRect.extent.x;
|
||||
mSaveViewport[3] = -updateRect.extent.y;
|
||||
|
||||
|
||||
//gluLookAt(query.position.x, query.position.y, query.position.z,
|
||||
// refPt.x, refPt.y, refPt.z,
|
||||
// query.upVector.x, query.upVector.y, query.upVector.z);
|
||||
|
||||
renderWorld(updateRect);
|
||||
smFrameCount++;
|
||||
}
|
||||
61
gui/guiTSControl.h
Normal file
61
gui/guiTSControl.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITSCONTROL_H_
|
||||
#define _GUITSCONTROL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _MMATH_H_
|
||||
#include "Math/mMath.h"
|
||||
#endif
|
||||
#ifndef _DGL_H_
|
||||
#include "dgl/dgl.h"
|
||||
#endif
|
||||
|
||||
struct CameraQuery
|
||||
{
|
||||
SimObject* object;
|
||||
F32 nearPlane;
|
||||
F32 farPlane;
|
||||
F32 fov;
|
||||
MatrixF cameraMatrix;
|
||||
|
||||
//Point3F position;
|
||||
//Point3F viewVector;
|
||||
//Point3F upVector;
|
||||
};
|
||||
|
||||
class GuiTSCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
GLdouble mSaveModelview[16];
|
||||
GLdouble mSaveProjection[16];
|
||||
GLint mSaveViewport[4];
|
||||
|
||||
static U32 smFrameCount;
|
||||
|
||||
public:
|
||||
CameraQuery mLastCameraQuery;
|
||||
GuiTSCtrl();
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
virtual bool processCameraQuery(CameraQuery *query);
|
||||
virtual void renderWorld(const RectI &updateRect);
|
||||
|
||||
static void consoleInit();
|
||||
|
||||
bool project(const Point3F &pt, Point3F *dest); // returns screen space X,Y and Z for world space point
|
||||
bool unproject(const Point3F &pt, Point3F *dest); // returns world space point for X, Y and Z
|
||||
|
||||
DECLARE_CONOBJECT(GuiTSCtrl);
|
||||
};
|
||||
|
||||
#endif
|
||||
191
gui/guiTextCtrl.cc
Normal file
191
gui/guiTextCtrl.cc
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "Core/color.h"
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
GuiTextCtrl::GuiTextCtrl()
|
||||
{
|
||||
//default fonts
|
||||
mInitialText = StringTable->insert("");
|
||||
mText[0] = '\0';
|
||||
mMaxStrLen = GuiTextCtrl::MAX_STRING_LENGTH;
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiTextCtrl, setText, void, 3, 3, "obj.setText( newText )" )
|
||||
{
|
||||
argc;
|
||||
GuiTextCtrl* ctrl = static_cast<GuiTextCtrl*>( object );
|
||||
ctrl->setText( argv[2] );
|
||||
}
|
||||
|
||||
void GuiTextCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiTextCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField( "text", TypeCaseString, Offset( mInitialText, GuiTextCtrl ) );
|
||||
addField( "maxLength", TypeS32, Offset( mMaxStrLen, GuiTextCtrl ) );
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
bool GuiTextCtrl::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
dStrncpy(mText, mInitialText, MAX_STRING_LENGTH);
|
||||
mText[MAX_STRING_LENGTH] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiTextCtrl::inspectPostApply()
|
||||
{
|
||||
Parent::inspectPostApply();
|
||||
setText(mInitialText);
|
||||
}
|
||||
|
||||
bool GuiTextCtrl::onWake()
|
||||
{
|
||||
if ( !Parent::onWake() )
|
||||
return false;
|
||||
|
||||
mFont = mProfile->mFont;
|
||||
AssertFatal( bool( mFont ), "GuiTextCtrl::onWake: invalid font in profile" );
|
||||
|
||||
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( mText ), mFont->getHeight() + 4 ) );
|
||||
else
|
||||
resize( mBounds.point, Point2I( mFont->getStrWidth( 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();
|
||||
AssertFatal(mProfile, "Can't call setText() until setProfile() has been called.");
|
||||
|
||||
if (txt)
|
||||
dStrncpy(mText, 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(mText), mFont->getHeight() + 4));
|
||||
else
|
||||
resize(mBounds.point, Point2I(mFont->getStrWidth(mText), mBounds.extent.y));
|
||||
}
|
||||
else if (mProfile->mAutoSizeHeight)
|
||||
{
|
||||
resize(mBounds.point, Point2I(mBounds.extent.x, mFont->getHeight() + 4));
|
||||
}
|
||||
|
||||
setVariable(mText);
|
||||
setUpdate();
|
||||
|
||||
//decrement the profile referrence
|
||||
mProfile->decRefCount();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiTextCtrl::onPreRender()
|
||||
{
|
||||
const char * var = getVariable();
|
||||
if(var && var[0] && dStricmp(mText, var))
|
||||
setText(var);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiTextCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
S32 txt_w = mFont->getStrWidth(mText);
|
||||
|
||||
Point2I localStart;
|
||||
switch (mProfile->mAlignment)
|
||||
{
|
||||
case GuiControlProfile::RightJustify:
|
||||
localStart.set(mBounds.extent.x - txt_w, 0);
|
||||
break;
|
||||
case GuiControlProfile::CenterJustify:
|
||||
localStart.set((mBounds.extent.x - txt_w) / 2, 0);
|
||||
break;
|
||||
default:
|
||||
// GuiControlProfile::LeftJustify
|
||||
localStart.set(0,0);
|
||||
break;
|
||||
}
|
||||
|
||||
Point2I globalStart = localToGlobalCoord(localStart);
|
||||
|
||||
//draw the text
|
||||
dglSetBitmapModulation(mProfile->mFontColor);
|
||||
dglDrawText(mFont, globalStart, mText, mProfile->mFontColors);
|
||||
|
||||
//render the child controls
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
const char *GuiTextCtrl::getScriptValue()
|
||||
{
|
||||
return getText();
|
||||
}
|
||||
|
||||
void GuiTextCtrl::setScriptValue(const char *val)
|
||||
{
|
||||
setText(val);
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
// EOF //
|
||||
63
gui/guiTextCtrl.h
Normal file
63
gui/guiTextCtrl.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#define _GUITEXTCTRL_H_
|
||||
|
||||
#ifndef _GFONT_H_
|
||||
#include "dgl/gFont.h"
|
||||
#endif
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "GUI/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiTextCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
public:
|
||||
enum Constants { MAX_STRING_LENGTH = 255 };
|
||||
|
||||
|
||||
protected:
|
||||
StringTableEntry mInitialText;
|
||||
char 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 consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
//Parental methods
|
||||
bool onAdd();
|
||||
virtual bool onWake();
|
||||
virtual void onSleep();
|
||||
|
||||
//text methods
|
||||
virtual void setText(const char *txt = NULL);
|
||||
const char *getText() { return mText; }
|
||||
|
||||
void inspectPostApply();
|
||||
//rendering methods
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
|
||||
//Console methods
|
||||
const char *getScriptValue();
|
||||
void setScriptValue(const char *value);
|
||||
};
|
||||
|
||||
#endif //_GUI_TEXT_CONTROL_H_
|
||||
1110
gui/guiTextEditCtrl.cc
Normal file
1110
gui/guiTextEditCtrl.cc
Normal file
File diff suppressed because it is too large
Load diff
99
gui/guiTextEditCtrl.h
Normal file
99
gui/guiTextEditCtrl.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITEXTEDITCTRL_H_
|
||||
#define _GUITEXTEDITCTRL_H_
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "gui/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "gui/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiTextEditCtrl : public GuiTextCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
static U32 mNumAwake;
|
||||
|
||||
protected:
|
||||
StringTableEntry mValidateCommand;
|
||||
StringTableEntry mEscapeCommand;
|
||||
AudioProfile* mDeniedSound;
|
||||
|
||||
// for animating the cursor
|
||||
S32 mNumFramesElapsed;
|
||||
U32 mTimeLastCursorFlipped;
|
||||
ColorI mCursorColor;
|
||||
bool mCursorOn;
|
||||
|
||||
bool mInsertOn;
|
||||
S32 mMouseDragStart;
|
||||
Point2I mTextOffset;
|
||||
bool mDragHit;
|
||||
bool mTabComplete;
|
||||
S32 mScrollDir;
|
||||
|
||||
//undo members
|
||||
char mUndoText[GuiTextCtrl::MAX_STRING_LENGTH + 1];
|
||||
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;
|
||||
char **mHistoryBuf;
|
||||
void updateHistory(const char *txt, bool moveIndex);
|
||||
|
||||
void playDeniedSound();
|
||||
|
||||
public:
|
||||
GuiTextEditCtrl();
|
||||
~GuiTextEditCtrl();
|
||||
DECLARE_CONOBJECT(GuiTextEditCtrl);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
bool onAdd();
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void getText(char *dest); // dest must be of size
|
||||
// StructDes::MAX_STRING_LEN + 1
|
||||
|
||||
void setText(S32 tag);
|
||||
virtual void setText(const char *txt);
|
||||
S32 getCursorPos() { return( mCursorPos ); }
|
||||
void reallySetCursorPos( const S32 newPos );
|
||||
|
||||
bool onKeyDown(const GuiEvent &event);
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
|
||||
void onLoseFirstResponder();
|
||||
|
||||
void parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent);
|
||||
bool hasText();
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
virtual void DrawText( const RectI &drawRect, bool isFocused );
|
||||
};
|
||||
|
||||
#endif //_GUI_TEXTEDIT_CTRL_H
|
||||
280
gui/guiTextEditSliderCtrl.cc
Normal file
280
gui/guiTextEditSliderCtrl.cc
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiTextEditSliderCtrl.h"
|
||||
|
||||
GuiTextEditSliderCtrl::GuiTextEditSliderCtrl()
|
||||
{
|
||||
mRange.set(0, 1);
|
||||
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", TypePoint2I, Offset(mRange, GuiTextEditSliderCtrl));
|
||||
addField("increment", TypeF32, Offset(mIncAmount, GuiTextEditSliderCtrl));
|
||||
}
|
||||
|
||||
void GuiTextEditSliderCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
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, GuiControl *firstResponder)
|
||||
{
|
||||
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, firstResponder);
|
||||
|
||||
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()
|
||||
{
|
||||
bool focused = false;
|
||||
GuiCanvas *canvas = getRoot();
|
||||
if (canvas)
|
||||
focused = (canvas->getFirstResponder() == this);
|
||||
|
||||
if (focused)
|
||||
{
|
||||
U32 timeElapsed = Platform::getVirtualMilliseconds() - mTimeLastCursorFlipped;
|
||||
mNumFramesElapsed++;
|
||||
if ((timeElapsed > 500) && (mNumFramesElapsed > 3))
|
||||
{
|
||||
mCursorOn = 1 - 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
70
gui/guiTextEditSliderCtrl.h
Normal file
70
gui/guiTextEditSliderCtrl.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITEXTEDITSLIDERCTRL_H_
|
||||
#define _GUITEXTEDITSLIDERCTRL_H_
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "GUI/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUITEXTEDITCTRL_H_
|
||||
#include "GUI/guiTextEditCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiTextEditSliderCtrl : public GuiTextEditCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextEditCtrl Parent;
|
||||
Point2I 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();
|
||||
static void consoleInit();
|
||||
|
||||
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, GuiControl *firstResponder);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //_GUI_TEXTEDIT_CTRL_H
|
||||
584
gui/guiTextListCtrl.cc
Normal file
584
gui/guiTextListCtrl.cc
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Platform/platform.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiTextListCtrl.h"
|
||||
|
||||
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 );
|
||||
char* aBuf = new char[dStrlen( aCol ) + 1];
|
||||
char* bBuf = new char[dStrlen( bCol ) + 1];
|
||||
dStrcpy( aBuf, aCol );
|
||||
dStrcpy( bBuf, bCol );
|
||||
char* ptr = dStrchr( aBuf, '\t' );
|
||||
if ( ptr )
|
||||
*ptr = '\0';
|
||||
ptr = dStrchr( bBuf, '\t' );
|
||||
if ( ptr )
|
||||
*ptr = '\0';
|
||||
S32 result = dAtoi( aBuf ) - dAtoi( bBuf );
|
||||
if ( result == 0 )
|
||||
return( dStricmp( ea->text, eb->text ) );
|
||||
delete [] aBuf;
|
||||
delete [] bBuf;
|
||||
return ( sIncreasing ? result : -result );
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static S32 cTextListGetSelectedCellId(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
return ctrl->getSelectedId();
|
||||
}
|
||||
|
||||
static void cTextListSetSelectedCellId(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
U32 id = dAtoi(argv[2]);
|
||||
S32 index = ctrl->findEntryById(id);
|
||||
if(index < 0)
|
||||
return ;
|
||||
|
||||
ctrl->setSelectedCell(Point2I(0, index));
|
||||
}
|
||||
|
||||
static void cTextListSetSelectedRow(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>( obj );
|
||||
ctrl->setSelectedCell( Point2I( 0, dAtoi( argv[2] ) ) );
|
||||
}
|
||||
|
||||
static void cTextListClearSelection(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
ctrl->setSelectedCell(Point2I(-1, -1));
|
||||
}
|
||||
|
||||
static S32 cTextListAdd(SimObject *obj, S32 argc, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
S32 ret = ctrl->mList.size();
|
||||
if(argc < 5)
|
||||
ctrl->addEntry(dAtoi(argv[2]), argv[3]);
|
||||
else
|
||||
ctrl->insertEntry(dAtoi(argv[2]), argv[3], dAtoi(argv[4]));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cTextListSet(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
ctrl->setEntry(dAtoi(argv[2]), argv[3]);
|
||||
}
|
||||
|
||||
static void cTextListSort(SimObject *obj, S32 argc, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
if ( argc == 3 )
|
||||
ctrl->sort(dAtoi(argv[2]));
|
||||
else
|
||||
ctrl->sort( dAtoi( argv[2] ), dAtob( argv[3] ) );
|
||||
}
|
||||
|
||||
static void cTextListSortNumerical( SimObject *obj, S32 argc, const char **argv )
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
if ( argc == 3 )
|
||||
ctrl->sortNumerical( dAtoi( argv[2] ) );
|
||||
else
|
||||
ctrl->sortNumerical( dAtoi( argv[2] ), dAtob( argv[3] ) );
|
||||
}
|
||||
|
||||
static void cTextListClear(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
ctrl->clear();
|
||||
}
|
||||
|
||||
static S32 cTextListCount(SimObject *obj, S32, const char **)
|
||||
{
|
||||
return ((GuiTextListCtrl *) obj)->getNumEntries();
|
||||
}
|
||||
|
||||
static S32 cTextListGetRowId(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
U32 index = dAtoi(argv[2]);
|
||||
if(index >= ctrl->getNumEntries())
|
||||
return -1;
|
||||
|
||||
return ctrl->mList[index].id;
|
||||
}
|
||||
|
||||
static const char *cTextListGetRowTextById(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
U32 id = dAtoi(argv[2]);
|
||||
S32 index = ctrl->findEntryById(id);
|
||||
if(index < 0)
|
||||
return "";
|
||||
return ctrl->mList[index].text;
|
||||
}
|
||||
|
||||
static S32 cTextListGetRowNumById(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
U32 id = dAtoi(argv[2]);
|
||||
|
||||
S32 index = ctrl->findEntryById(id);
|
||||
if(index < 0)
|
||||
return -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
static const char *cTextListGetRowText(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
S32 index = dAtoi(argv[2]);
|
||||
if(index < 0 || index >= ctrl->mList.size())
|
||||
return "";
|
||||
return ctrl->mList[index].text;
|
||||
}
|
||||
|
||||
static void cTextListRemoveRowById(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
U32 id = dAtoi(argv[2]);
|
||||
ctrl->removeEntry(id);
|
||||
}
|
||||
|
||||
static void cTextListRemoveRow(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
U32 index = dAtoi(argv[2]);
|
||||
ctrl->removeEntryByIndex(index);
|
||||
}
|
||||
|
||||
static void cTextListScrollRowVisible(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiTextListCtrl *ctrl = static_cast<GuiTextListCtrl*>(obj);
|
||||
ctrl->scrollCellVisible(Point2I(0, dAtoi(argv[2])));
|
||||
}
|
||||
|
||||
static S32 cTextListFindText( SimObject* obj, S32, const char** argv )
|
||||
{
|
||||
GuiTextListCtrl* ctrl = static_cast<GuiTextListCtrl*>( obj );
|
||||
return( ctrl->findEntryByText( argv[2] ) );
|
||||
}
|
||||
|
||||
static void cTextListSetRowActive( SimObject* obj, S32, const char** argv )
|
||||
{
|
||||
GuiTextListCtrl* ctrl = static_cast<GuiTextListCtrl*>( obj );
|
||||
ctrl->setEntryActive( U32( dAtoi( argv[2] ) ), dAtob( argv[3] ) );
|
||||
}
|
||||
|
||||
static bool cTextListIsRowActive( SimObject* obj, S32, const char** argv )
|
||||
{
|
||||
GuiTextListCtrl* ctrl = static_cast<GuiTextListCtrl*>( obj );
|
||||
return( ctrl->isEntryActive( U32( dAtoi( argv[2] ) ) ) );
|
||||
}
|
||||
|
||||
void GuiTextListCtrl::consoleInit()
|
||||
{
|
||||
Con::addCommand("GuiTextListCtrl", "getSelectedId", cTextListGetSelectedCellId, "textList.getSelectedId()", 2, 2);
|
||||
Con::addCommand("GuiTextListCtrl", "setSelectedById", cTextListSetSelectedCellId, "textList.setSelectedById(id)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "setSelectedRow", cTextListSetSelectedRow, "textList.setSelectedRow(index)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "clearSelection", cTextListClearSelection, "textList.clearSelection()", 2, 2);
|
||||
Con::addCommand("GuiTextListCtrl", "clear", cTextListClear, "textList.clear()", 2, 2);
|
||||
Con::addCommand("GuiTextListCtrl", "addRow", cTextListAdd, "textList.addRow(id,text,index)", 4, 5);
|
||||
Con::addCommand("GuiTextListCtrl", "setRowById", cTextListSet, "textList.setRow(id,text)", 4, 4);
|
||||
Con::addCommand("GuiTextListCtrl", "getRowId", cTextListGetRowId, "textList.getRowId(index)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "removeRowById", cTextListRemoveRowById, "textList.removeRowById(id)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "getRowTextById", cTextListGetRowTextById, "textList.getRowTextById(id)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "getRowNumById", cTextListGetRowNumById, "textList.getRowNumById(id)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "getRowText", cTextListGetRowText, "textList.getRowText(index)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "removeRow", cTextListRemoveRow, "textList.removeRow(index)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "rowCount", cTextListCount, "textList.rowCount()", 2, 2);
|
||||
Con::addCommand("GuiTextListCtrl", "scrollVisible", cTextListScrollRowVisible, "textList.scrollVisible(index)", 3, 3);
|
||||
Con::addCommand("GuiTextListCtrl", "sort", cTextListSort, "textList.sort(colId{, increasing})", 3, 4);
|
||||
Con::addCommand("GuiTextListCtrl", "sortNumerical", cTextListSortNumerical, "textList.sortNumerical(colId{, increasing})", 3, 4);
|
||||
Con::addCommand("GuiTextListCtrl", "findTextIndex", cTextListFindText, "textList.findText(text)", 3, 3 );
|
||||
Con::addCommand("GuiTextListCtrl", "setRowActive", cTextListSetRowActive, "textlist.setRowActive(id, <bool>)", 4, 4 );
|
||||
Con::addCommand("GuiTextListCtrl", "isRowActive", cTextListIsRowActive, "textlist.isRowActive(id)", 3, 3 );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
U32 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(text, nextCol - text);
|
||||
else
|
||||
textWidth = mFont->getStrWidth(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 )
|
||||
{
|
||||
GuiControl* parent = getParent();
|
||||
if ( parent )
|
||||
mCellSize.x = parent->mBounds.extent.x - mBounds.point.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;
|
||||
|
||||
if ( event.keyCode == KEY_RETURN )
|
||||
{
|
||||
if ( mAltConsoleCommand[0] )
|
||||
Con::evaluate( mAltConsoleCommand, false );
|
||||
return( true );
|
||||
}
|
||||
|
||||
if ( event.keyCode == KEY_DELETE && ( mSelectedCell.y >= 0 && mSelectedCell.y < mList.size() ) )
|
||||
{
|
||||
Con::executef( this, 2, "onDeleteKey", Con::getIntArg( mList[mSelectedCell.y].id ) );
|
||||
return( true );
|
||||
}
|
||||
|
||||
return( Parent::onKeyDown( event ) );
|
||||
}
|
||||
|
||||
93
gui/guiTextListCtrl.h
Normal file
93
gui/guiTextListCtrl.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITEXTLISTCTRL_H_
|
||||
#define _GUITEXTLISTCTRL_H_
|
||||
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "GUI/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();
|
||||
static void consoleInit();
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
#endif //_GUI_TEXTLIST_CTRL_H
|
||||
1473
gui/guiTreeViewCtrl.cc
Normal file
1473
gui/guiTreeViewCtrl.cc
Normal file
File diff suppressed because it is too large
Load diff
253
gui/guiTreeViewCtrl.h
Normal file
253
gui/guiTreeViewCtrl.h
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITREEVIEWCTRL_H_
|
||||
#define _GUITREEVIEWCTRL_H_
|
||||
|
||||
#ifndef _MRECT_H_
|
||||
#include "Math/mRect.h"
|
||||
#endif
|
||||
#ifndef _GFONT_H_
|
||||
#include "dgl/gFont.h"
|
||||
#endif
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#include "GUI/guiArrayCtrl.h"
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _BITSET_H_
|
||||
#include "Core/bitSet.h"
|
||||
#endif
|
||||
class GuiTreeViewCtrl : public GuiArrayCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiArrayCtrl Parent;
|
||||
|
||||
protected:
|
||||
|
||||
struct Item
|
||||
{
|
||||
enum ItemState {
|
||||
Selected = BIT(0),
|
||||
Expanded = BIT(1),
|
||||
Focus = BIT(2),
|
||||
MouseOverBmp = BIT(3),
|
||||
MouseOverText = BIT(4),
|
||||
};
|
||||
|
||||
BitSet32 mState;
|
||||
char* mText;
|
||||
char* mValue;
|
||||
S16 mNormalImage;
|
||||
S16 mExpandedImage;
|
||||
|
||||
S32 mId;
|
||||
U32 mTabLevel;
|
||||
Item * mParent;
|
||||
Item * mChild;
|
||||
Item * mNext;
|
||||
Item * mPrevious;
|
||||
|
||||
Item();
|
||||
~Item();
|
||||
};
|
||||
|
||||
Vector<Item*> mItems;
|
||||
Vector<Item*> mVisibleItems;
|
||||
|
||||
S32 mItemCount;
|
||||
Item * mItemFreeList;
|
||||
Item * mRoot;
|
||||
S32 mMaxWidth;
|
||||
S32 mSelectedItem;
|
||||
|
||||
enum TreeState {
|
||||
RebuildVisible = BIT(0)
|
||||
};
|
||||
BitSet32 mFlags;
|
||||
|
||||
TextureHandle mImagesHandle;
|
||||
Vector<RectI> mImageBounds;
|
||||
|
||||
// persist field info...
|
||||
S32 mTabSize;
|
||||
StringTableEntry mImagesBitmap;
|
||||
S32 mNumImages;
|
||||
S32 mTextOffset;
|
||||
bool mFullRowSelect;
|
||||
S32 mItemHeight;
|
||||
|
||||
Item * getItem(S32 itemId);
|
||||
Item * createItem();
|
||||
void destroyItem(Item * item);
|
||||
void destroyTree();
|
||||
|
||||
//
|
||||
void buildItem(Item * item, U32 tabLevel);
|
||||
void buildVisibleTree();
|
||||
|
||||
//
|
||||
enum HitFlags {
|
||||
OnIndent = BIT(0),
|
||||
OnImage = BIT(1),
|
||||
OnText = BIT(2),
|
||||
OnRow = BIT(3),
|
||||
};
|
||||
bool hitTest(const Point2I & pnt, Item* & item, BitSet32 & flags);
|
||||
|
||||
public:
|
||||
|
||||
GuiTreeViewCtrl();
|
||||
virtual ~GuiTreeViewCtrl();
|
||||
|
||||
//
|
||||
bool selectItem(S32 itemId, bool select);
|
||||
bool expandItem(S32 itemId, bool expand);
|
||||
const char * getItemText(S32 itemId);
|
||||
const char * getItemValue(S32 itemId);
|
||||
|
||||
bool editItem( S32 itemId, const char* newText, const char* newValue );
|
||||
|
||||
// insertion/removal
|
||||
S32 insertItem(S32 parentId, const char * text, const char * value, S16 normalImage, S16 expandedImage);
|
||||
bool removeItem(S32 itemId);
|
||||
|
||||
// tree items
|
||||
S32 getFirstRootItem();
|
||||
S32 getChildItem(S32 itemId);
|
||||
S32 getParentItem(S32 itemId);
|
||||
S32 getNextSiblingItem(S32 itemId);
|
||||
S32 getPrevSiblingItem(S32 itemId);
|
||||
S32 getItemCount();
|
||||
S32 getSelectedItem();
|
||||
void moveItemUp( S32 itemId );
|
||||
|
||||
// // visible items
|
||||
// S32 getFirstVisible();
|
||||
// S32 getLastVisible();
|
||||
// S32 getNextVisible(S32 itemId);
|
||||
// S32 getPrevVisible(S32 itemId);
|
||||
// S32 getVisibleCount();
|
||||
|
||||
// // misc.
|
||||
//bool scrollVisible( S32 itemId );
|
||||
|
||||
// GuiControl
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
void onPreRender();
|
||||
bool onKeyDown( const GuiEvent &event );
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseMove(const GuiEvent &event);
|
||||
void onMouseEnter(const GuiEvent &event);
|
||||
void onMouseLeave(const GuiEvent &event);
|
||||
void onRightMouseDown(const GuiEvent &event);
|
||||
|
||||
// GuiArrayCtrl
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool, bool);
|
||||
|
||||
//
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
DECLARE_CONOBJECT(GuiTreeViewCtrl);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class GuiTreeView : public GuiArrayCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiArrayCtrl Parent;
|
||||
|
||||
struct ObjNode
|
||||
{
|
||||
S32 level;
|
||||
SimObject *object;
|
||||
bool lastInGroup;
|
||||
S32 parentIndex;
|
||||
ObjNode(S32 in_level, SimObject *in_object, bool in_last, S32 in_pi)
|
||||
{
|
||||
level = in_level;
|
||||
object = in_object;
|
||||
lastInGroup = in_last;
|
||||
parentIndex = in_pi;
|
||||
}
|
||||
};
|
||||
|
||||
Vector<ObjNode> mObjectList;
|
||||
|
||||
enum BitmapIndices
|
||||
{
|
||||
BmpNone = -1,
|
||||
BmpChildAbove,
|
||||
BmpChildBelow,
|
||||
BmpChildBetween,
|
||||
|
||||
BmpParentOpen,
|
||||
BmpParentOpenAbove,
|
||||
BmpParentOpenBelow,
|
||||
BmpParentOpenBetween,
|
||||
|
||||
BmpParentClosed,
|
||||
BmpParentClosedAbove,
|
||||
BmpParentClosedBelow,
|
||||
BmpParentClosedBetween,
|
||||
|
||||
BmpParentContinue,
|
||||
|
||||
BmpCount
|
||||
};
|
||||
RectI mBitmapBounds[BmpCount]; //bmp is [3*n], bmpHL is [3*n + 1], bmpNA is [3*n + 2]
|
||||
TextureHandle mTextureHandle;
|
||||
|
||||
//font
|
||||
Resource<GFont> mFont;
|
||||
|
||||
SimSet *mRootObject;
|
||||
|
||||
// persist data
|
||||
bool mAllowMultipleSelections;
|
||||
bool mRecurseSets;
|
||||
|
||||
ObjNode * getHitNode(const GuiEvent & event);
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiTreeView);
|
||||
GuiTreeView();
|
||||
static void consoleInit();
|
||||
static void initPersistFields();
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
void setTreeRoot(SimSet *srcObj);
|
||||
void buildTree(SimSet *srcObj, S32 srcLevel, S32 srcParentIndex);
|
||||
|
||||
void onPreRender();
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onRightMouseDown(const GuiEvent & event);
|
||||
void onRightMouseUp(const GuiEvent & event);
|
||||
|
||||
void setInstantGroup(SimObject * obj);
|
||||
void inspectObject(SimObject * obj);
|
||||
void selectObject(SimObject * obj);
|
||||
void unselectObject(SimObject * obj);
|
||||
void toggleSelected(SimObject * obj);
|
||||
void clearSelected();
|
||||
void setSelected(SimObject *selObj);
|
||||
|
||||
void onRenderCell(Point2I offset, Point2I cell, bool, bool);
|
||||
};
|
||||
|
||||
#endif
|
||||
233
gui/guiTypes.cc
Normal file
233
gui/guiTypes.cc
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/gFont.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiTypes.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
|
||||
GuiCursor::GuiCursor()
|
||||
{
|
||||
mHotSpot.set(0,0);
|
||||
}
|
||||
|
||||
GuiCursor::~GuiCursor()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiCursor::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addField("hotSpot", TypePoint2I, Offset(mHotSpot, GuiCursor));
|
||||
addField("bitmapName", TypeString, Offset(mBitmapName, GuiCursor));
|
||||
}
|
||||
|
||||
bool GuiCursor::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
mTextureHandle = TextureHandle(mBitmapName);
|
||||
if(!mTextureHandle)
|
||||
return false;
|
||||
|
||||
mExtent.set(mTextureHandle.getWidth(), mTextureHandle.getHeight());
|
||||
Sim::getGuiDataGroup()->addObject(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiCursor::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
static EnumTable::Enums alignEnums[] =
|
||||
{
|
||||
{ GuiControlProfile::LeftJustify, "left" },
|
||||
{ GuiControlProfile::CenterJustify, "center" },
|
||||
{ GuiControlProfile::RightJustify, "right" }
|
||||
};
|
||||
static EnumTable gAlignTable(3, &alignEnums[0]);
|
||||
|
||||
GuiControlProfile::GuiControlProfile(void) :
|
||||
mFontColor(mFontColors[BaseColor]),
|
||||
mFontColorHL(mFontColors[ColorHL]),
|
||||
mFontColorNA(mFontColors[ColorNA]),
|
||||
mFontColorSEL(mFontColors[ColorSEL])
|
||||
{
|
||||
mRefCount = 0;
|
||||
|
||||
GuiControlProfile *def = dynamic_cast<GuiControlProfile*>(Sim::findObject("GuiDefaultProfile"));
|
||||
if (def)
|
||||
{
|
||||
mTabable = def->mTabable;
|
||||
mCanKeyFocus = def->mCanKeyFocus;
|
||||
|
||||
mOpaque = def->mOpaque;
|
||||
mFillColor = def->mFillColor;
|
||||
mFillColorHL = def->mFillColorHL;
|
||||
mFillColorNA = def->mFillColorNA;
|
||||
|
||||
mBorder = def->mBorder;
|
||||
mBorderColor = def->mBorderColor;
|
||||
mBorderColorHL = def->mBorderColorHL;
|
||||
mBorderColorNA = def->mBorderColorNA;
|
||||
|
||||
// default font
|
||||
mFontType = def->mFontType;
|
||||
mFontSize = def->mFontSize;
|
||||
|
||||
for(U32 i = 0; i < 10; i++)
|
||||
mFontColors[i] = def->mFontColors[i];
|
||||
|
||||
// default bitmap
|
||||
mBitmapName = def->mBitmapName;
|
||||
mBitmapBase = def->mBitmapBase;
|
||||
mTextOffset = def->mTextOffset;
|
||||
|
||||
// default sound
|
||||
mSoundButtonDown = def->mSoundButtonDown;
|
||||
mSoundButtonOver = def->mSoundButtonOver;
|
||||
|
||||
//used by GuiTextCtrl
|
||||
mModal = def->mModal;
|
||||
mAlignment = def->mAlignment;
|
||||
mAutoSizeWidth = def->mAutoSizeWidth;
|
||||
mAutoSizeHeight= def->mAutoSizeHeight;
|
||||
mReturnTab = def->mReturnTab;
|
||||
mNumbersOnly = def->mNumbersOnly;
|
||||
mCursorColor = def->mCursorColor;
|
||||
}
|
||||
}
|
||||
|
||||
GuiControlProfile::~GuiControlProfile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GuiControlProfile::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("tab", TypeBool, Offset(mTabable, GuiControlProfile));
|
||||
addField("canKeyFocus", TypeBool, Offset(mCanKeyFocus, GuiControlProfile));
|
||||
|
||||
addField("modal", TypeBool, Offset(mModal, GuiControlProfile));
|
||||
addField("opaque", TypeBool, Offset(mOpaque, GuiControlProfile));
|
||||
addField("fillColor", TypeColorI, Offset(mFillColor, GuiControlProfile));
|
||||
addField("fillColorHL", TypeColorI, Offset(mFillColorHL, GuiControlProfile));
|
||||
addField("fillColorNA", TypeColorI, Offset(mFillColorNA, GuiControlProfile));
|
||||
addField("border", TypeBool, Offset(mBorder, GuiControlProfile));
|
||||
addField("borderColor", TypeColorI, Offset(mBorderColor, GuiControlProfile));
|
||||
addField("borderColorHL", TypeColorI, Offset(mBorderColorHL, GuiControlProfile));
|
||||
addField("borderColorNA", TypeColorI, Offset(mBorderColorNA, GuiControlProfile));
|
||||
|
||||
addField("fontType", TypeString, Offset(mFontType, GuiControlProfile));
|
||||
addField("fontSize", TypeS32, Offset(mFontSize, GuiControlProfile));
|
||||
addField("fontColors", TypeColorI, Offset(mFontColors, GuiControlProfile), 10);
|
||||
addField("fontColor", TypeColorI, Offset(mFontColors[BaseColor], GuiControlProfile));
|
||||
addField("fontColorHL", TypeColorI, Offset(mFontColors[ColorHL], GuiControlProfile));
|
||||
addField("fontColorNA", TypeColorI, Offset(mFontColors[ColorNA], GuiControlProfile));
|
||||
addField("fontColorSEL", TypeColorI, Offset(mFontColors[ColorSEL], GuiControlProfile));
|
||||
|
||||
addField("justify", TypeEnum, Offset(mAlignment, GuiControlProfile), 1, &gAlignTable);
|
||||
addField("textOffset", TypePoint2I, Offset(mTextOffset, GuiControlProfile));
|
||||
addField("bitmapBase", TypeString, Offset(mBitmapBase, GuiControlProfile));
|
||||
addField("autoSizeWidth", TypeBool, Offset(mAutoSizeWidth, GuiControlProfile));
|
||||
addField("autoSizeHeight",TypeBool, Offset(mAutoSizeHeight, GuiControlProfile));
|
||||
addField("returnTab", TypeBool, Offset(mReturnTab, GuiControlProfile));
|
||||
addField("numbersOnly", TypeBool, Offset(mNumbersOnly, GuiControlProfile));
|
||||
addField("cursorColor", TypeColorI, Offset(mCursorColor, GuiControlProfile));
|
||||
|
||||
addField("bitmap", TypeString, Offset(mBitmapName, GuiControlProfile));
|
||||
|
||||
addField("soundButtonDown", TypeAudioProfilePtr, Offset(mSoundButtonDown, GuiControlProfile));
|
||||
addField("soundButtonOver", TypeAudioProfilePtr, Offset(mSoundButtonOver, GuiControlProfile));
|
||||
}
|
||||
|
||||
bool GuiControlProfile::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
Sim::getGuiDataGroup()->addObject(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiControlProfile::incRefCount()
|
||||
{
|
||||
if(!mRefCount++)
|
||||
{
|
||||
//verify the font
|
||||
mFont = GFont::create(mFontType, mFontSize);
|
||||
AssertFatal(bool(mFont), "Failed to create the font.");
|
||||
|
||||
//verify the bitmap
|
||||
mTextureHandle = TextureHandle(mBitmapName, BitmapKeepTexture);
|
||||
AssertFatal(bool(mTextureHandle), "Profile has no bitmap");
|
||||
}
|
||||
|
||||
AssertFatal(bool(mFont), "GuiControlProfile::incRefCount: invalid font");
|
||||
AssertFatal(bool(mTextureHandle), "GuiControlProfile::incRefCount: invalid bitmap");
|
||||
}
|
||||
|
||||
void GuiControlProfile::decRefCount()
|
||||
{
|
||||
AssertFatal(mRefCount, "GuiControlProfile::decRefCount: zero ref count");
|
||||
if(!mRefCount)
|
||||
return;
|
||||
|
||||
if(!--mRefCount)
|
||||
{
|
||||
mFont = NULL;
|
||||
mTextureHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void setDataTypeGuiProfile(void *dptr, S32 argc, const char **argv, EnumTable *, BitSet32)
|
||||
{
|
||||
GuiControlProfile *profile = NULL;
|
||||
if(argc == 1)
|
||||
Sim::findObject(argv[0], profile);
|
||||
|
||||
AssertWarn(profile != NULL, avar("GuiControlProfile: requested gui profile (%s) does not exist.", argv[0]));
|
||||
if(!profile)
|
||||
profile = dynamic_cast<GuiControlProfile*>(Sim::findObject("GuiDefaultProfile"));
|
||||
|
||||
AssertFatal(profile != NULL, avar("GuiControlProfile: unable to find specified profile (%s) and GuiDefaultProfile does not exist!", argv[0]));
|
||||
|
||||
GuiControlProfile **obj = (GuiControlProfile **)dptr;
|
||||
if((*obj) == profile)
|
||||
return;
|
||||
|
||||
if(*obj)
|
||||
(*obj)->decRefCount();
|
||||
|
||||
*obj = profile;
|
||||
(*obj)->incRefCount();
|
||||
}
|
||||
|
||||
static const char *getDataTypeGuiProfile(void *dptr, EnumTable *, BitSet32)
|
||||
{
|
||||
static char returnBuffer[256];
|
||||
|
||||
GuiControlProfile **obj = (GuiControlProfile**)dptr;
|
||||
dSprintf(returnBuffer, sizeof(returnBuffer), "%s", *obj ? (*obj)->getName() : "");
|
||||
return returnBuffer;
|
||||
}
|
||||
|
||||
void RegisterGuiTypes(void)
|
||||
{
|
||||
Con::registerType(TypeGuiProfile, sizeof(GuiControlProfile *), getDataTypeGuiProfile, setDataTypeGuiProfile);
|
||||
}
|
||||
148
gui/guiTypes.h
Normal file
148
gui/guiTypes.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#define _GUITYPES_H_
|
||||
|
||||
#ifndef _GFONT_H_
|
||||
#include "dgl/gFont.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _PLATFORMAUDIO_H_
|
||||
#include "Platform/platformAudio.h"
|
||||
#endif
|
||||
#ifndef _AUDIODATABLOCK_H_
|
||||
#include "audio/audioDataBlock.h"
|
||||
#endif
|
||||
|
||||
class GBitmap;
|
||||
|
||||
struct GuiEvent
|
||||
{
|
||||
U16 ascii; // ascii character code 'a', 'A', 'b', '*', etc (if device==keyboard) - possibly a uchar or something
|
||||
U8 modifier; // SI_LSHIFT, etc
|
||||
U8 keyCode; // for unprintables, 'tab', 'return', ...
|
||||
Point2I mousePoint; // for mouse events
|
||||
U8 mouseClickCount; // to determine double clicks, etc...
|
||||
};
|
||||
|
||||
class GuiCursor : public SimObject
|
||||
{
|
||||
private:
|
||||
typedef SimObject Parent;
|
||||
StringTableEntry mBitmapName;
|
||||
|
||||
Point2I mHotSpot;
|
||||
Point2I mExtent;
|
||||
TextureHandle mTextureHandle;
|
||||
|
||||
public:
|
||||
TextureHandle getTextureHandle() { return mTextureHandle; }
|
||||
Point2I getHotSpot() { return mHotSpot; }
|
||||
Point2I getExtent() { return mExtent; }
|
||||
|
||||
DECLARE_CONOBJECT(GuiCursor);
|
||||
GuiCursor(void);
|
||||
~GuiCursor(void);
|
||||
static void initPersistFields();
|
||||
|
||||
bool onAdd(void);
|
||||
void onRemove();
|
||||
};
|
||||
|
||||
|
||||
class GuiControlProfile : public SimObject
|
||||
{
|
||||
private:
|
||||
typedef SimObject Parent;
|
||||
|
||||
public:
|
||||
S32 mRefCount;
|
||||
bool mTabable;
|
||||
bool mCanKeyFocus;
|
||||
bool mModal;
|
||||
|
||||
bool mOpaque;
|
||||
ColorI mFillColor;
|
||||
ColorI mFillColorHL;
|
||||
ColorI mFillColorNA;
|
||||
|
||||
bool mBorder;
|
||||
ColorI mBorderColor;
|
||||
ColorI mBorderColorHL;
|
||||
ColorI mBorderColorNA;
|
||||
|
||||
// font members
|
||||
StringTableEntry mFontType;
|
||||
S32 mFontSize;
|
||||
enum {
|
||||
BaseColor = 0,
|
||||
ColorHL,
|
||||
ColorNA,
|
||||
ColorSEL,
|
||||
ColorUser0,
|
||||
ColorUser1,
|
||||
ColorUser2,
|
||||
ColorUser3,
|
||||
ColorUser4,
|
||||
ColorUser5,
|
||||
};
|
||||
ColorI mFontColors[10];
|
||||
ColorI & mFontColor;
|
||||
ColorI & mFontColorHL;
|
||||
ColorI & mFontColorNA;
|
||||
ColorI & mFontColorSEL;
|
||||
|
||||
Resource<GFont> mFont;
|
||||
|
||||
enum AlignmentType
|
||||
{
|
||||
LeftJustify,
|
||||
RightJustify,
|
||||
CenterJustify
|
||||
};
|
||||
|
||||
AlignmentType mAlignment;
|
||||
bool mAutoSizeWidth;
|
||||
bool mAutoSizeHeight;
|
||||
bool mReturnTab;
|
||||
bool mNumbersOnly;
|
||||
ColorI mCursorColor;
|
||||
|
||||
StringTableEntry mBitmapBase;
|
||||
Point2I mTextOffset;
|
||||
|
||||
// bitmap members
|
||||
StringTableEntry mBitmapName;
|
||||
TextureHandle mTextureHandle;
|
||||
|
||||
// sound members
|
||||
AudioProfile *mSoundButtonDown;
|
||||
AudioProfile *mSoundButtonOver;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiControlProfile);
|
||||
GuiControlProfile();
|
||||
~GuiControlProfile();
|
||||
static void initPersistFields();
|
||||
bool onAdd();
|
||||
|
||||
void incRefCount();
|
||||
void decRefCount();
|
||||
};
|
||||
|
||||
void RegisterGuiTypes(void);
|
||||
|
||||
#endif //_GUITYPES_H
|
||||
231
gui/guiVoteCtrl.cc
Normal file
231
gui/guiVoteCtrl.cc
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
#include "GUI/guiVoteCtrl.h"
|
||||
|
||||
GuiVoteCtrl::GuiVoteCtrl()
|
||||
{
|
||||
mYesProgress = 0.0f;
|
||||
mNoProgress = 0.0f;
|
||||
mQuorum = 0.5f;
|
||||
mPassHash = 0.25f;
|
||||
}
|
||||
|
||||
const char* GuiVoteCtrl::getScriptValue()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::setScriptValue(const char *)
|
||||
{
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::setQuorumValue(F32 value)
|
||||
{
|
||||
if(!value)
|
||||
mQuorum = 0.0f;
|
||||
else
|
||||
mQuorum = value;
|
||||
|
||||
//validate the value
|
||||
mQuorum = mClampF(mQuorum, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::setPassValue(F32 value)
|
||||
{
|
||||
if(!value)
|
||||
mPassHash = 0.0f;
|
||||
else
|
||||
mPassHash = value;
|
||||
|
||||
//validate the value
|
||||
mPassHash = mClampF(mPassHash, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::setYesValue(F32 value)
|
||||
{
|
||||
if(!value)
|
||||
mYesProgress = 0.0f;
|
||||
else
|
||||
mYesProgress = value;
|
||||
|
||||
//validate the value
|
||||
mYesProgress = mClampF(mYesProgress, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::setNoValue(F32 value)
|
||||
{
|
||||
if(!value)
|
||||
mNoProgress = 0.0f;
|
||||
else
|
||||
mNoProgress = value;
|
||||
|
||||
//validate the value
|
||||
mNoProgress = mClampF(mNoProgress, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::onPreRender()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::onRender(Point2I offset, const RectI & /*updateRect*/, GuiControl * /*firstResponder*/)
|
||||
{
|
||||
RectI ctrlRect(offset, mBounds.extent);
|
||||
RectI yesProgressRect = ctrlRect;
|
||||
RectI noProgressRect = ctrlRect;
|
||||
S32 yesWidth;
|
||||
S32 noWidth;
|
||||
|
||||
ColorI fill;
|
||||
|
||||
//draw the "Yes" progress
|
||||
if(mYesProgress < 1)
|
||||
yesWidth = (S32)((F32)mBounds.extent.x * (1 - mYesProgress));
|
||||
else
|
||||
yesWidth = ctrlRect.extent.x;
|
||||
|
||||
if(yesWidth > 0)
|
||||
{
|
||||
yesProgressRect.point.y += 10;
|
||||
yesProgressRect.point.x = ctrlRect.point.x;
|
||||
yesProgressRect.extent.y -= 20;
|
||||
|
||||
if(mYesProgress < 1)
|
||||
yesProgressRect.extent.x = ctrlRect.extent.x - yesWidth;
|
||||
else
|
||||
yesProgressRect.extent.x = ctrlRect.extent.x;
|
||||
|
||||
fill.set(0, 255, 0, 255);
|
||||
|
||||
if(mYesProgress >= mPassHash)
|
||||
{
|
||||
S32 time = (S32)Platform::getVirtualMilliseconds();
|
||||
F32 alpha = F32(time % 500) / 250.0f;
|
||||
|
||||
if(alpha > 1)
|
||||
alpha = 1.f - (alpha - 1.f);
|
||||
|
||||
fill.alpha *= alpha;
|
||||
}
|
||||
|
||||
dglDrawRectFill(yesProgressRect, fill);
|
||||
}
|
||||
|
||||
// draw the "No" progress
|
||||
noWidth = (S32)((F32)mBounds.extent.x * mNoProgress);
|
||||
|
||||
fill.set(255, 0, 0, 255);
|
||||
|
||||
if(noWidth > 0)
|
||||
{
|
||||
noProgressRect.point.y += 10;
|
||||
noProgressRect.point.x = ctrlRect.point.x + (S32)((F32)mBounds.extent.x * mYesProgress);
|
||||
noProgressRect.extent.y -= 20;
|
||||
noProgressRect.extent.x = noWidth;
|
||||
|
||||
if(mNoProgress >= ( 1 - mPassHash ))
|
||||
{
|
||||
S32 time = (S32)Platform::getVirtualMilliseconds();
|
||||
F32 alpha = F32(time % 500) / 250.0f;
|
||||
|
||||
if(alpha > 1)
|
||||
alpha = 1.f - (alpha - 1.f);
|
||||
|
||||
fill.alpha *= alpha;
|
||||
}
|
||||
|
||||
dglDrawRectFill(noProgressRect, fill);
|
||||
}
|
||||
}
|
||||
|
||||
// console functions
|
||||
////////////////////////////////////////////////////////////////
|
||||
static const char* cGetQuorumValue(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
F32 quorum = ctrl->getQuorumValue();
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%f", quorum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char* cGetPassValue(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
F32 hash = ctrl->getPassValue();
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%f", hash);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char* cGetYesValue(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
F32 yesValue = ctrl->getYesValue();
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%f", yesValue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char* cGetNoValue(SimObject *obj, S32, const char **)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
F32 noValue = ctrl->getNoValue();
|
||||
char * ret = Con::getReturnBuffer(64);
|
||||
dSprintf(ret, 64, "%f", noValue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cSetQuorumValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
ctrl->setQuorumValue(dAtof(argv[2]));
|
||||
}
|
||||
|
||||
static void cSetPassValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
ctrl->setPassValue(dAtof(argv[2]));
|
||||
}
|
||||
|
||||
static void cSetYesValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
ctrl->setYesValue(dAtof(argv[2]));
|
||||
}
|
||||
|
||||
static void cSetNoValue(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
GuiVoteCtrl *ctrl = static_cast<GuiVoteCtrl*>(obj);
|
||||
|
||||
ctrl->setNoValue(dAtof(argv[2]));
|
||||
}
|
||||
|
||||
void GuiVoteCtrl::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
Con::addCommand("GuiVoteCtrl", "setQuorumValue", cSetQuorumValue, "ctrl.setQuorumValue(value)", 3, 3);
|
||||
Con::addCommand("GuiVoteCtrl", "setPassValue", cSetPassValue, "ctrl.setPassValue(value)", 3, 3);
|
||||
Con::addCommand("GuiVoteCtrl", "setYesValue", cSetYesValue, "ctrl.setYesValue(value)", 3, 3);
|
||||
Con::addCommand("GuiVoteCtrl", "setNoValue", cSetNoValue, "ctrl.setNoValue(value)", 3, 3);
|
||||
Con::addCommand("GuiVoteCtrl", "getQuorumValue", cGetQuorumValue, "ctrl.getQuorumValue()", 2, 2);
|
||||
Con::addCommand("GuiVoteCtrl", "getPassValue", cGetPassValue, "ctrl.getPassValue()", 2, 2);
|
||||
Con::addCommand("GuiVoteCtrl", "getYesValue", cGetYesValue, "ctrl.getYesValue()", 2, 2);
|
||||
Con::addCommand("GuiVoteCtrl", "getNoValue", cGetNoValue, "ctrl.getNoValue()", 2, 2);
|
||||
}
|
||||
72
gui/guiVoteCtrl.h
Normal file
72
gui/guiVoteCtrl.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIVOTECTRL_H_
|
||||
#define _GUIVOTECTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "GUI/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiVoteCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
F32 mNoProgress;
|
||||
F32 mYesProgress;
|
||||
F32 mQuorum;
|
||||
F32 mPassHash;
|
||||
|
||||
public:
|
||||
//creation methods
|
||||
DECLARE_CONOBJECT(GuiVoteCtrl);
|
||||
GuiVoteCtrl();
|
||||
|
||||
//console related methods
|
||||
static void consoleInit();
|
||||
virtual const char *getScriptValue();
|
||||
virtual void setScriptValue(const char *value);
|
||||
|
||||
void onPreRender();
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
|
||||
public:
|
||||
void setPassValue(F32 value);
|
||||
void setQuorumValue(F32 value);
|
||||
void setYesValue(F32 value);
|
||||
void setNoValue(F32 value);
|
||||
|
||||
F32 getPassValue();
|
||||
F32 getQuorumValue();
|
||||
F32 getYesValue();
|
||||
F32 getNoValue();
|
||||
|
||||
};
|
||||
|
||||
inline F32 GuiVoteCtrl::getQuorumValue()
|
||||
{
|
||||
return mQuorum;
|
||||
}
|
||||
|
||||
inline F32 GuiVoteCtrl::getPassValue()
|
||||
{
|
||||
return mPassHash;
|
||||
}
|
||||
|
||||
inline F32 GuiVoteCtrl::getYesValue()
|
||||
{
|
||||
return mYesProgress;
|
||||
}
|
||||
|
||||
inline F32 GuiVoteCtrl::getNoValue()
|
||||
{
|
||||
return mNoProgress;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
582
gui/guiWindowCtrl.cc
Normal file
582
gui/guiWindowCtrl.cc
Normal file
|
|
@ -0,0 +1,582 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "GUI/guiCanvas.h"
|
||||
#include "GUI/guiWindowCtrl.h"
|
||||
|
||||
GuiWindowCtrl::GuiWindowCtrl(void)
|
||||
{
|
||||
mResizeWidth = true;
|
||||
mResizeHeight = true;
|
||||
mCanMove = true;
|
||||
mCanClose = true;
|
||||
mCanMinimize = true;
|
||||
mCanMaximize = true;
|
||||
mTitleHeight = 20;
|
||||
mResizeRightWidth = 10;
|
||||
mResizeBottomHeight = 10;
|
||||
|
||||
mCloseCommand = StringTable->insert("");
|
||||
|
||||
mMinimized = false;
|
||||
mMaximized = false;
|
||||
mMouseMovingWin = false;
|
||||
mMouseResizeWidth = false;
|
||||
mMouseResizeHeight = false;
|
||||
mBounds.extent.set(100, 200);
|
||||
mMinSize.set(50, 50);
|
||||
mMinimizeIndex = -1;
|
||||
mTabIndex = -1;
|
||||
|
||||
RectI closeRect(80, 2, 16, 16);
|
||||
mCloseButton = closeRect;
|
||||
closeRect.point.x -= 18;
|
||||
mMaximizeButton = closeRect;
|
||||
closeRect.point.x -= 18;
|
||||
mMinimizeButton = closeRect;
|
||||
|
||||
//other defaults
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("resizeWidth", TypeBool, Offset(mResizeWidth, GuiWindowCtrl));
|
||||
addField("resizeHeight", TypeBool, Offset(mResizeHeight, GuiWindowCtrl));
|
||||
addField("canMove", TypeBool, Offset(mCanMove, GuiWindowCtrl));
|
||||
addField("canClose", TypeBool, Offset(mCanClose, GuiWindowCtrl));
|
||||
addField("canMinimize", TypeBool, Offset(mCanMinimize, GuiWindowCtrl));
|
||||
addField("canMaximize", TypeBool, Offset(mCanMaximize, GuiWindowCtrl));
|
||||
addField("minSize", TypePoint2I, Offset(mMinSize, GuiWindowCtrl));
|
||||
addField("closeCommand", TypeString, Offset(mCloseCommand, GuiWindowCtrl));
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::consoleInit()
|
||||
{
|
||||
}
|
||||
|
||||
bool GuiWindowCtrl::isMinimized(S32 &index)
|
||||
{
|
||||
index = mMinimizeIndex;
|
||||
return mMinimized && mVisible;
|
||||
}
|
||||
|
||||
bool GuiWindowCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
//get the texture for the close, minimize, and maximize buttons
|
||||
mTextureHandle = mProfile->mTextureHandle;
|
||||
bool result = createBitmapArray(mTextureHandle.getBitmap(), mBitmapBounds, BmpStates, BmpCount);
|
||||
AssertFatal(result, "Failed to create the bitmap array");
|
||||
|
||||
mTitleHeight = mBitmapBounds[BmpStates * BmpClose].extent.y + 6;
|
||||
S32 buttonWidth = mBitmapBounds[BmpStates * BmpClose].extent.x;
|
||||
mResizeRightWidth = mTitleHeight / 2;
|
||||
mResizeBottomHeight = mTitleHeight / 2;
|
||||
|
||||
//set the button coords
|
||||
RectI closeRect(mBounds.extent.x - buttonWidth - 3, 2, mTitleHeight - 6, buttonWidth);
|
||||
mCloseButton = closeRect;
|
||||
|
||||
closeRect.point.x -= buttonWidth + 2;
|
||||
mMaximizeButton = closeRect;
|
||||
|
||||
closeRect.point.x -= buttonWidth + 2;
|
||||
mMinimizeButton = closeRect;
|
||||
|
||||
//set the tab index
|
||||
mTabIndex = -1;
|
||||
GuiControl *parent = getParent();
|
||||
if (parent && mFirstResponder)
|
||||
{
|
||||
mTabIndex = 0;
|
||||
|
||||
//count the number of windows preceeding this one
|
||||
iterator i;
|
||||
for (i = parent->begin(); i != parent->end(); i++)
|
||||
{
|
||||
GuiWindowCtrl *ctrl = dynamic_cast<GuiWindowCtrl *>(*i);
|
||||
if (ctrl)
|
||||
{
|
||||
if (ctrl == this) break;
|
||||
else if (ctrl->mFirstResponder) mTabIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GuiControl* GuiWindowCtrl::findHitControl(const Point2I &pt, S32 initialLayer)
|
||||
{
|
||||
if (! mMinimized)
|
||||
return Parent::findHitControl(pt, initialLayer);
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
|
||||
{
|
||||
Parent::resize(newPosition, newExtent);
|
||||
|
||||
//set the button coords
|
||||
S32 buttonWidth = mBitmapBounds[BmpStates * BmpClose].extent.x;
|
||||
RectI closeRect(mBounds.extent.x - buttonWidth - 3, 2, mTitleHeight - 6, buttonWidth);
|
||||
mCloseButton = closeRect;
|
||||
|
||||
closeRect.point.x -= buttonWidth + 2;
|
||||
mMaximizeButton = closeRect;
|
||||
|
||||
closeRect.point.x -= buttonWidth + 2;
|
||||
mMinimizeButton = closeRect;
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onMouseDown(const GuiEvent &event)
|
||||
{
|
||||
setUpdate();
|
||||
|
||||
mOrigBounds = mBounds;
|
||||
mPressClose = false;
|
||||
mPressMaximize = false;
|
||||
mPressMinimize = false;
|
||||
|
||||
mMouseDownPosition = event.mousePoint;
|
||||
Point2I localPoint = globalToLocalCoord(event.mousePoint);
|
||||
|
||||
//select this window - move it to the front, and set the first responder
|
||||
selectWindow();
|
||||
|
||||
//if we clicked within the title bar
|
||||
if (localPoint.y < mTitleHeight)
|
||||
{
|
||||
//if we clicked on the close button
|
||||
if (mCloseButton.pointInRect(localPoint))
|
||||
{
|
||||
mPressClose = mCanClose;
|
||||
}
|
||||
else if (mMaximizeButton.pointInRect(localPoint))
|
||||
{
|
||||
mPressMaximize = mCanMaximize;
|
||||
}
|
||||
else if (mMinimizeButton.pointInRect(localPoint))
|
||||
{
|
||||
mPressMinimize = mCanMinimize;
|
||||
}
|
||||
|
||||
//else we clicked within the title
|
||||
else
|
||||
{
|
||||
mMouseMovingWin = mCanMove;
|
||||
mMouseResizeWidth = false;
|
||||
mMouseResizeHeight = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mMouseMovingWin = false;
|
||||
|
||||
//see if we clicked on the right edge
|
||||
if (localPoint.x > mBounds.extent.x - mResizeRightWidth)
|
||||
{
|
||||
mMouseResizeWidth = true;
|
||||
}
|
||||
|
||||
//see if we clicked on the bottom edge (as well)
|
||||
if (localPoint.y > mBounds.extent.y - mResizeBottomHeight)
|
||||
{
|
||||
mMouseResizeHeight = true;
|
||||
}
|
||||
}
|
||||
if (mMouseMovingWin || mMouseResizeWidth || mMouseResizeHeight ||
|
||||
mPressClose || mPressMaximize || mPressMinimize)
|
||||
{
|
||||
mouseLock();
|
||||
}
|
||||
else
|
||||
{
|
||||
GuiControl *ctrl = findHitControl(event.mousePoint);
|
||||
if (ctrl && ctrl != this)
|
||||
{
|
||||
ctrl->onMouseDown(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
GuiControl *parent = getParent();
|
||||
GuiCanvas *root = getRoot();
|
||||
if (! root) return;
|
||||
|
||||
Point2I deltaMousePosition = event.mousePoint - mMouseDownPosition;
|
||||
|
||||
Point2I newPosition = mBounds.point;
|
||||
Point2I newExtent = mBounds.extent;
|
||||
bool update = false;
|
||||
if (mMouseMovingWin && parent)
|
||||
{
|
||||
newPosition.x = getMax(0, getMin(parent->mBounds.extent.x - mBounds.extent.x, mOrigBounds.point.x + deltaMousePosition.x));
|
||||
newPosition.y = getMax(0, getMin(parent->mBounds.extent.y - mBounds.extent.y, mOrigBounds.point.y + deltaMousePosition.y));
|
||||
update = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mMouseResizeWidth && parent)
|
||||
{
|
||||
newExtent.x = getMax(0, getMax(mMinSize.x, getMin(parent->mBounds.extent.x, mOrigBounds.extent.x + deltaMousePosition.x)));
|
||||
update = true;
|
||||
}
|
||||
if (mMouseResizeHeight && parent)
|
||||
{
|
||||
newExtent.y = getMax(0, getMax(mMinSize.y, getMin(parent->mBounds.extent.y, mOrigBounds.extent.y + deltaMousePosition.y)));
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
if (update)
|
||||
{
|
||||
Point2I pos = parent->localToGlobalCoord(mBounds.point);
|
||||
root->addUpdateRegion(pos, mBounds.extent);
|
||||
resize(newPosition, newExtent);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onMouseUp(const GuiEvent &event)
|
||||
{
|
||||
event;
|
||||
mouseUnlock();
|
||||
|
||||
mMouseMovingWin = false;
|
||||
mMouseResizeWidth = false;
|
||||
mMouseResizeHeight = false;
|
||||
|
||||
GuiControl *parent = getParent();
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
//see if we take an action
|
||||
Point2I localPoint = globalToLocalCoord(event.mousePoint);
|
||||
if (mPressClose && mCloseButton.pointInRect(localPoint))
|
||||
{
|
||||
Con::evaluate(mCloseCommand);
|
||||
}
|
||||
else if (mPressMaximize)
|
||||
{
|
||||
if (mMaximized)
|
||||
{
|
||||
//resize to the previous position and extent, bounded by the parent
|
||||
resize(Point2I(getMax(0, getMin(parent->mBounds.extent.x - mStandardBounds.extent.x, mStandardBounds.point.x)),
|
||||
getMax(0, getMin(parent->mBounds.extent.y - mStandardBounds.extent.y, mStandardBounds.point.y))),
|
||||
mStandardBounds.extent);
|
||||
//set the flag
|
||||
mMaximized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//only save the position if we're not minimized
|
||||
if (! mMinimized)
|
||||
{
|
||||
mStandardBounds = mBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMinimized = false;
|
||||
}
|
||||
|
||||
//resize to fit the parent
|
||||
resize(Point2I(0, 0), parent->mBounds.extent);
|
||||
|
||||
//set the flag
|
||||
mMaximized = true;
|
||||
}
|
||||
}
|
||||
else if (mPressMinimize)
|
||||
{
|
||||
if (mMinimized)
|
||||
{
|
||||
//resize to the previous position and extent, bounded by the parent
|
||||
resize(Point2I(getMax(0, getMin(parent->mBounds.extent.x - mStandardBounds.extent.x, mStandardBounds.point.x)),
|
||||
getMax(0, getMin(parent->mBounds.extent.y - mStandardBounds.extent.y, mStandardBounds.point.y))),
|
||||
mStandardBounds.extent);
|
||||
//set the flag
|
||||
mMinimized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent->mBounds.extent.x < 100 || parent->mBounds.extent.y < mTitleHeight + 3)
|
||||
return;
|
||||
|
||||
//only save the position if we're not maximized
|
||||
if (! mMaximized)
|
||||
{
|
||||
mStandardBounds = mBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMaximized = false;
|
||||
}
|
||||
|
||||
//first find the lowest unused minimized index up to 32 minimized windows
|
||||
U32 indexMask = 0;
|
||||
iterator i;
|
||||
S32 count = 0;
|
||||
for (i = parent->begin(); i != parent->end() && count < 32; i++)
|
||||
{
|
||||
count++;
|
||||
S32 index;
|
||||
GuiWindowCtrl *ctrl = dynamic_cast<GuiWindowCtrl *>(*i);
|
||||
if (ctrl && ctrl->isMinimized(index))
|
||||
{
|
||||
indexMask |= (1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
//now find the first unused bit
|
||||
for (count = 0; count < 32; count++)
|
||||
{
|
||||
if (! (indexMask & (1 << count))) break;
|
||||
}
|
||||
|
||||
//if we have more than 32 minimized windows, use the first position
|
||||
count = getMax(0, count);
|
||||
|
||||
//this algorithm assumes all window have the same title height, and will minimize to 98 pix
|
||||
Point2I newExtent(98, mTitleHeight);
|
||||
|
||||
//first, how many can fit across
|
||||
S32 numAcross = getMax(1, (parent->mBounds.extent.x / newExtent.x + 2));
|
||||
|
||||
//find the new "mini position"
|
||||
Point2I newPosition;
|
||||
newPosition.x = (count % numAcross) * (newExtent.x + 2) + 2;
|
||||
newPosition.y = parent->mBounds.extent.y - (((count / numAcross) + 1) * (newExtent.y + 2)) - 2;
|
||||
|
||||
//find the minimized position and extent
|
||||
resize(newPosition, newExtent);
|
||||
|
||||
//set the index so other windows will not try to minimize to the same location
|
||||
mMinimizeIndex = count;
|
||||
|
||||
//set the flag
|
||||
mMinimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GuiControl *GuiWindowCtrl::findNextTabable(GuiControl *curResponder, bool firstCall)
|
||||
{
|
||||
//set the global if this is the first call (directly from the canvas)
|
||||
if (firstCall)
|
||||
{
|
||||
GuiControl::gCurResponder = 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 *GuiWindowCtrl::findPrevTabable(GuiControl *curResponder, bool firstCall)
|
||||
{
|
||||
if (firstCall)
|
||||
{
|
||||
GuiControl::gPrevResponder = 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 GuiWindowCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if this control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake)) return true;
|
||||
|
||||
if ((event.keyCode == KEY_TAB) && (event.modifier & SI_CTRL))
|
||||
{
|
||||
//find the next sibling window, and select it
|
||||
GuiControl *parent = getParent();
|
||||
if (parent)
|
||||
{
|
||||
GuiWindowCtrl *firstWindow = NULL;
|
||||
iterator i;
|
||||
for (i = parent->begin(); i != parent->end(); i++)
|
||||
{
|
||||
GuiWindowCtrl *ctrl = dynamic_cast<GuiWindowCtrl *>(*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 GuiWindowCtrl::selectWindow(void)
|
||||
{
|
||||
//first make sure this window is the front most of its siblings
|
||||
GuiControl *parent = getParent();
|
||||
if (parent)
|
||||
{
|
||||
parent->bringObjectToFront(this);
|
||||
}
|
||||
|
||||
//also set the first responder to be the one within this window
|
||||
setFirstResponder(mFirstResponder);
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::drawWinRect(const RectI &myRect)
|
||||
{
|
||||
Point2I bl = myRect.point;
|
||||
Point2I tr;
|
||||
tr.x = myRect.point.x + myRect.extent.x - 1;
|
||||
tr.y = myRect.point.y + myRect.extent.y - 1;
|
||||
dglDrawRectFill(myRect, mProfile->mFillColor);
|
||||
dglDrawLine(Point2I(bl.x + 1, tr.y), Point2I(bl.x + 1, bl.y), ColorI(255, 255, 255));
|
||||
dglDrawLine(Point2I(bl.x, tr.y + 1), Point2I(tr.x, tr.y + 1), ColorI(255, 255, 255));
|
||||
dglDrawRect(myRect, ColorI(0, 0, 0));
|
||||
}
|
||||
|
||||
void GuiWindowCtrl::onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder)
|
||||
{
|
||||
//draw the outline
|
||||
RectI winRect;
|
||||
winRect.point = offset;
|
||||
winRect.extent = mBounds.extent;
|
||||
|
||||
if (mProfile->mOpaque)
|
||||
{
|
||||
drawWinRect(winRect);
|
||||
|
||||
//title bar
|
||||
ColorI titleColor = (! firstResponder || ControlIsChild(firstResponder)) ?
|
||||
mProfile->mFillColorHL : mProfile->mFillColorNA;
|
||||
RectI titleBarRect = winRect;
|
||||
titleBarRect.extent.y = mTitleHeight;
|
||||
|
||||
dglDrawRectFill(titleBarRect, titleColor);
|
||||
}
|
||||
|
||||
//outline the window
|
||||
if (mProfile->mBorder)
|
||||
dglDrawRect(winRect, mProfile->mBorderColor);
|
||||
|
||||
//draw the title
|
||||
dglSetBitmapModulation(mProfile->mFontColor);
|
||||
S32 fontHeight = mFont->getHeight();
|
||||
dglDrawText(mFont, Point2I(offset.x + 4, offset.y + ((mTitleHeight - fontHeight) / 2)), mText);
|
||||
|
||||
GuiCanvas *root = getRoot();
|
||||
AssertFatal(root, "Unable to get the root Canvas.");
|
||||
Point2I localPoint = globalToLocalCoord(root->getCursorPos());
|
||||
|
||||
//draw the close button
|
||||
Point2I tempUL;
|
||||
Point2I tempLR;
|
||||
S32 bmp = BmpStates * BmpClose;
|
||||
if (! mCanClose)
|
||||
bmp += BmpDisabled;
|
||||
else if (mCloseButton.pointInRect(localPoint) && root->mouseButtonDown())
|
||||
bmp += BmpHilite;
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, offset + mCloseButton.point, mBitmapBounds[bmp]);
|
||||
|
||||
//draw the maximize button
|
||||
if (mMaximized)
|
||||
bmp = BmpStates * BmpNormal;
|
||||
else
|
||||
bmp = BmpStates * BmpMaximize;
|
||||
if (! mCanMaximize)
|
||||
bmp += BmpDisabled;
|
||||
else if (mMaximizeButton.pointInRect(localPoint) && root->mouseButtonDown())
|
||||
bmp += BmpHilite;
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, offset + mMaximizeButton.point, mBitmapBounds[bmp]);
|
||||
|
||||
//draw the minimize button
|
||||
if (mMinimized)
|
||||
bmp = BmpStates * BmpNormal;
|
||||
else
|
||||
bmp = BmpStates * BmpMinimize;
|
||||
if (! mCanMinimize)
|
||||
bmp += BmpDisabled;
|
||||
else if (mMinimizeButton.pointInRect(localPoint) && root->mouseButtonDown())
|
||||
bmp += BmpHilite;
|
||||
dglClearBitmapModulation();
|
||||
dglDrawBitmapSR(mTextureHandle, offset + mMinimizeButton.point, mBitmapBounds[bmp]);
|
||||
|
||||
if (! mMinimized)
|
||||
{
|
||||
//render the children
|
||||
renderChildControls(offset, updateRect, firstResponder);
|
||||
}
|
||||
}
|
||||
109
gui/guiWindowCtrl.h
Normal file
109
gui/guiWindowCtrl.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIWINDOWCTRL_H_
|
||||
#define _GUIWINDOWCTRL_H_
|
||||
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "GUI/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
class GuiWindowCtrl : public GuiTextCtrl
|
||||
{
|
||||
private:
|
||||
typedef GuiTextCtrl Parent;
|
||||
|
||||
bool mResizeWidth;
|
||||
bool mResizeHeight;
|
||||
bool mCanMove;
|
||||
bool mCanClose;
|
||||
bool mCanMinimize;
|
||||
bool mCanMaximize;
|
||||
bool mPressClose;
|
||||
bool mPressMinimize;
|
||||
bool mPressMaximize;
|
||||
Point2I mMinSize;
|
||||
|
||||
StringTableEntry mCloseCommand;
|
||||
|
||||
S32 mTitleHeight;
|
||||
S32 mResizeRightWidth;
|
||||
S32 mResizeBottomHeight;
|
||||
|
||||
bool mMouseMovingWin;
|
||||
bool mMouseResizeWidth;
|
||||
bool mMouseResizeHeight;
|
||||
bool mMinimized;
|
||||
bool mMaximized;
|
||||
|
||||
Point2I mMouseDownPosition;
|
||||
RectI mOrigBounds;
|
||||
RectI mStandardBounds;
|
||||
|
||||
RectI mCloseButton;
|
||||
RectI mMinimizeButton;
|
||||
RectI mMaximizeButton;
|
||||
S32 mMinimizeIndex;
|
||||
S32 mTabIndex;
|
||||
|
||||
protected:
|
||||
enum BitmapIndices
|
||||
{
|
||||
BmpClose,
|
||||
BmpMaximize,
|
||||
BmpNormal,
|
||||
BmpMinimize,
|
||||
|
||||
BmpCount
|
||||
};
|
||||
|
||||
enum BitmapStates
|
||||
{
|
||||
BmpDefault = 0,
|
||||
BmpHilite,
|
||||
BmpDisabled,
|
||||
|
||||
BmpStates
|
||||
};
|
||||
RectI mBitmapBounds[BmpStates * BmpCount]; //bmp is [3*n], bmpHL is [3*n + 1], bmpNA is [3*n + 2]
|
||||
TextureHandle mTextureHandle;
|
||||
|
||||
|
||||
void drawWinRect(const RectI &myRect);
|
||||
|
||||
public:
|
||||
GuiWindowCtrl();
|
||||
DECLARE_CONOBJECT(GuiWindowCtrl);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
bool onWake();
|
||||
|
||||
bool isMinimized(S32 &index);
|
||||
|
||||
void setFont(S32 fntTag);
|
||||
|
||||
GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1);
|
||||
void resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
|
||||
void onMouseDown(const GuiEvent &event);
|
||||
void onMouseDragged(const GuiEvent &event);
|
||||
void onMouseUp(const GuiEvent &event);
|
||||
|
||||
//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);
|
||||
|
||||
S32 getTabIndex(void) { return mTabIndex; }
|
||||
void selectWindow(void);
|
||||
|
||||
void onRender(Point2I offset, const RectI &updateRect, GuiControl *firstResponder);
|
||||
};
|
||||
|
||||
#endif //_GUI_WINDOW_CTRL_H
|
||||
408
gui/messageVector.cc
Normal file
408
gui/messageVector.cc
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "GUI/messageVector.h"
|
||||
#include "Core/fileObject.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(MessageVector);
|
||||
|
||||
//-------------------------------------- Console functions
|
||||
namespace {
|
||||
|
||||
void cMVClear(SimObject *obj, S32, const char **)
|
||||
{
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
pMV->clear();
|
||||
}
|
||||
|
||||
void cMVPushBackLine(SimObject* obj, S32 argc, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
U32 tag = 0;
|
||||
if (argc == 4)
|
||||
tag = dAtoi(argv[3]);
|
||||
|
||||
pMV->pushBackLine(argv[2], tag);
|
||||
}
|
||||
|
||||
bool cMVPopBackLine(SimObject* obj, S32, const char**)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
if (pMV->getNumLines() == 0) {
|
||||
Con::errorf(ConsoleLogEntry::General, "MessageVector::popBackLine(): underflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
pMV->popBackLine();
|
||||
return true;
|
||||
}
|
||||
|
||||
void cMVPushFrontLine(SimObject* obj, S32 argc, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
U32 tag = 0;
|
||||
if (argc == 4)
|
||||
tag = dAtoi(argv[3]);
|
||||
|
||||
pMV->pushFrontLine(argv[2], tag);
|
||||
}
|
||||
|
||||
bool cMVPopFrontLine(SimObject* obj, S32, const char**)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
if (pMV->getNumLines() == 0) {
|
||||
Con::errorf(ConsoleLogEntry::General, "MessageVector::popFrontLine(): underflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
pMV->popFrontLine();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cMVInsertLine(SimObject* obj, S32 argc, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
U32 pos = U32(dAtoi(argv[2]));
|
||||
if (pos > pMV->getNumLines())
|
||||
return false;
|
||||
|
||||
S32 tag = 0;
|
||||
if (argc == 5)
|
||||
tag = dAtoi(argv[4]);
|
||||
|
||||
pMV->insertLine(pos, argv[3], tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cMVDeleteLine(SimObject* obj, S32, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
U32 pos = U32(dAtoi(argv[2]));
|
||||
if (pos >= pMV->getNumLines())
|
||||
return false;
|
||||
|
||||
pMV->deleteLine(pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cMVDump(SimObject* obj, S32 argc, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
if ( argc == 4 )
|
||||
pMV->dump( argv[2], argv[3] );
|
||||
else
|
||||
pMV->dump( argv[2] );
|
||||
}
|
||||
|
||||
S32 cMVGetNumLines(SimObject* obj, S32, const char**)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
return pMV->getNumLines();
|
||||
}
|
||||
|
||||
const char *cMVGetLineTextByTag(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
U32 tag = dAtoi(argv[2]);
|
||||
|
||||
for(U32 i = 0; i < pMV->getNumLines(); i++)
|
||||
if(pMV->getLine(i).messageTag == tag)
|
||||
return pMV->getLine(i).message;
|
||||
return "";
|
||||
}
|
||||
|
||||
S32 cMVGetLineIndexByTag(SimObject *obj, S32, const char **argv)
|
||||
{
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
U32 tag = dAtoi(argv[2]);
|
||||
|
||||
for(U32 i = 0; i < pMV->getNumLines(); i++)
|
||||
if(pMV->getLine(i).messageTag == tag)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* cMVGetLineText(SimObject* obj, S32, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
U32 pos = U32(dAtoi(argv[2]));
|
||||
if (pos >= pMV->getNumLines()) {
|
||||
Con::errorf(ConsoleLogEntry::General, "MessageVector::getLineText(con): out of bounds line");
|
||||
return "";
|
||||
}
|
||||
|
||||
return pMV->getLine(pos).message;
|
||||
}
|
||||
|
||||
S32 cMVGetLineTag(SimObject* obj, S32, const char** argv)
|
||||
{
|
||||
AssertFatal(dynamic_cast<MessageVector*>(obj) != NULL, "Error, how did a non-MessageVector get here?");
|
||||
MessageVector* pMV = static_cast<MessageVector*>(obj);
|
||||
|
||||
U32 pos = U32(dAtoi(argv[2]));
|
||||
if (pos >= pMV->getNumLines()) {
|
||||
Con::errorf(ConsoleLogEntry::General, "MessageVector::getLineTag(con): out of bounds line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pMV->getLine(pos).messageTag;
|
||||
}
|
||||
|
||||
} // namespace {}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
MessageVector::MessageVector()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mMessageLines);
|
||||
VECTOR_SET_ASSOCIATION(mSpectators);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
MessageVector::~MessageVector()
|
||||
{
|
||||
for (U32 i = 0; i < mMessageLines.size(); i++) {
|
||||
char* pDelete = const_cast<char*>(mMessageLines[i].message);
|
||||
delete [] pDelete;
|
||||
mMessageLines[i].message = 0;
|
||||
mMessageLines[i].messageTag = 0xFFFFFFFF;
|
||||
}
|
||||
mMessageLines.clear();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::consoleInit()
|
||||
{
|
||||
Con::addCommand("MessageVector", "pushBackLine", cMVPushBackLine, "[MessageVector].pushBackLine(\"Message\"[, Tag=0])", 3, 4);
|
||||
Con::addCommand("MessageVector", "popBackLine", cMVPopBackLine, "[MessageVector].popBackLine()", 2, 2);
|
||||
Con::addCommand("MessageVector", "pushFrontLine", cMVPushFrontLine, "[MessageVector].pushFrontLine(\"Message\"[, Tag=0])", 3, 4);
|
||||
Con::addCommand("MessageVector", "popFrontLine", cMVPopFrontLine, "[MessageVector].popFrontLine()", 2, 2);
|
||||
|
||||
Con::addCommand("MessageVector", "insertLine", cMVInsertLine, "[MessageVector].insertLine(InsertPos, \"Message\"[, Tag=0])", 4, 5);
|
||||
Con::addCommand("MessageVector", "deleteLine", cMVDeleteLine, "[MessageVector].deleteLine(DeletePos)", 3, 3);
|
||||
Con::addCommand("MessageVector", "clear", cMVClear, "[MessageVector].clear()", 2, 2);
|
||||
|
||||
Con::addCommand("MessageVector", "dump", cMVDump, "[MessageVector].dump(filename{, header})", 3, 4);
|
||||
|
||||
Con::addCommand("MessageVector", "getNumLines", cMVGetNumLines, "[MessageVector].getNumLines()", 2, 2);
|
||||
Con::addCommand("MessageVector", "getLineText", cMVGetLineText, "[MessageVector].getLineText(Line)", 3, 3);
|
||||
Con::addCommand("MessageVector", "getLineTag", cMVGetLineTag, "[MessageVector].getLineTag(Line)", 3, 3);
|
||||
Con::addCommand("MessageVector", "getLineTextByTag", cMVGetLineTextByTag, "[MessageVector].getLineTextByTag(Tag)", 3, 3);
|
||||
Con::addCommand("MessageVector", "getLineIndexByTag", cMVGetLineIndexByTag, "[MessageVector].getLineIndexByTag(Tag)", 3, 3);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool MessageVector::onAdd()
|
||||
{
|
||||
return Parent::onAdd();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::onRemove()
|
||||
{
|
||||
// Delete all the lines from the observers, and then forcibly detatch ourselves
|
||||
//
|
||||
for (S32 i = mMessageLines.size() - 1; i >= 0; i--)
|
||||
spectatorMessage(LineDeleted, i);
|
||||
spectatorMessage(VectorDeletion, 0);
|
||||
mSpectators.clear();
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::pushBackLine(const char* newMessage, const S32 newMessageTag)
|
||||
{
|
||||
insertLine(mMessageLines.size(), newMessage, newMessageTag);
|
||||
}
|
||||
|
||||
|
||||
void MessageVector::popBackLine()
|
||||
{
|
||||
AssertFatal(mMessageLines.size() != 0, "MessageVector::popBackLine: nothing to pop!");
|
||||
if (mMessageLines.size() == 0)
|
||||
return;
|
||||
|
||||
deleteLine(mMessageLines.size() - 1);
|
||||
}
|
||||
|
||||
void MessageVector::clear()
|
||||
{
|
||||
while(mMessageLines.size())
|
||||
deleteLine(mMessageLines.size() - 1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::pushFrontLine(const char* newMessage, const S32 newMessageTag)
|
||||
{
|
||||
insertLine(0, newMessage, newMessageTag);
|
||||
}
|
||||
|
||||
|
||||
void MessageVector::popFrontLine()
|
||||
{
|
||||
AssertFatal(mMessageLines.size() != 0, "MessageVector::popBackLine: nothing to pop!");
|
||||
if (mMessageLines.size() == 0)
|
||||
return;
|
||||
|
||||
deleteLine(0);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::insertLine(const U32 position,
|
||||
const char* newMessage,
|
||||
const S32 newMessageTag)
|
||||
{
|
||||
AssertFatal(position >= 0 && position <= mMessageLines.size(), "MessageVector::insertLine: out of range position!");
|
||||
AssertFatal(newMessage != NULL, "Error, no message to insert!");
|
||||
|
||||
U32 len = dStrlen(newMessage) + 1;
|
||||
char* copy = new char[len];
|
||||
dStrcpy(copy, newMessage);
|
||||
|
||||
mMessageLines.insert(position);
|
||||
mMessageLines[position].message = copy;
|
||||
mMessageLines[position].messageTag = newMessageTag;
|
||||
|
||||
// Notify of insert
|
||||
spectatorMessage(LineInserted, position);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::deleteLine(const U32 position)
|
||||
{
|
||||
AssertFatal(position >= 0 && position < mMessageLines.size(), "MessageVector::deleteLine: out of range position!");
|
||||
|
||||
char* pDelete = const_cast<char*>(mMessageLines[position].message);
|
||||
delete [] pDelete;
|
||||
mMessageLines[position].message = NULL;
|
||||
mMessageLines[position].messageTag = 0xFFFFFFFF;
|
||||
|
||||
mMessageLines.erase(position);
|
||||
|
||||
// Notify of delete
|
||||
spectatorMessage(LineDeleted, position);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool MessageVector::dump( const char* filename, const char* header )
|
||||
{
|
||||
Con::printf( "Dumping message vector %s to %s...", getName(), filename );
|
||||
FileObject file;
|
||||
if ( !file.openForWrite( filename ) )
|
||||
return( false );
|
||||
|
||||
// If passed a header line, write it out first:
|
||||
if ( header )
|
||||
file.writeLine( (const U8*) header );
|
||||
|
||||
// First write out the record count:
|
||||
char* lineBuf = (char*) dMalloc( 10 );
|
||||
dSprintf( lineBuf, 10, "%d", mMessageLines.size() );
|
||||
file.writeLine( (const U8*) lineBuf );
|
||||
|
||||
// Write all of the lines of the message vector:
|
||||
U32 len;
|
||||
for ( U32 i = 0; i < mMessageLines.size(); i++ )
|
||||
{
|
||||
len = ( dStrlen( mMessageLines[i].message ) * 2 ) + 10;
|
||||
lineBuf = (char*) dRealloc( lineBuf, len );
|
||||
dSprintf( lineBuf, len, "%d ", mMessageLines[i].messageTag );
|
||||
expandEscape( lineBuf + dStrlen( lineBuf ), mMessageLines[i].message );
|
||||
file.writeLine( (const U8*) lineBuf );
|
||||
}
|
||||
|
||||
file.close();
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MessageVector::registerSpectator(SpectatorCallback callBack, U32 spectatorKey)
|
||||
{
|
||||
AssertFatal(callBack != NULL, "Error, must have a callback!");
|
||||
|
||||
// First, make sure that this hasn't been registered already...
|
||||
U32 i;
|
||||
for (i = 0; i < mSpectators.size(); i++) {
|
||||
AssertFatal(mSpectators[i].key != spectatorKey, "Error, spectator key already registered!");
|
||||
if (mSpectators[i].key == spectatorKey)
|
||||
return;
|
||||
}
|
||||
|
||||
mSpectators.increment();
|
||||
mSpectators.last().callback = callBack;
|
||||
mSpectators.last().key = spectatorKey;
|
||||
|
||||
// Need to message this spectator of all the lines currently inserted...
|
||||
for (i = 0; i < mMessageLines.size(); i++) {
|
||||
(*mSpectators.last().callback)(mSpectators.last().key,
|
||||
LineInserted, i);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageVector::unregisterSpectator(U32 spectatorKey)
|
||||
{
|
||||
for (U32 i = 0; i < mSpectators.size(); i++) {
|
||||
if (mSpectators[i].key == spectatorKey) {
|
||||
// Need to message this spectator of all the lines currently inserted...
|
||||
for (S32 j = mMessageLines.size() - 1; j >= 0 ; j--) {
|
||||
(*mSpectators[i].callback)(mSpectators[i].key,
|
||||
LineDeleted, j);
|
||||
}
|
||||
|
||||
mSpectators.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(false, "MessageVector::unregisterSpectator: tried to unregister a spectator that isn't subscribed!");
|
||||
Con::errorf(ConsoleLogEntry::General,
|
||||
"MessageVector::unregisterSpectator: tried to unregister a spectator that isn't subscribed!");
|
||||
}
|
||||
|
||||
void MessageVector::spectatorMessage(MessageCode code, const U32 arg)
|
||||
{
|
||||
for (U32 i = 0; i < mSpectators.size(); i++) {
|
||||
(*mSpectators[i].callback)(mSpectators[i].key,
|
||||
code, arg);
|
||||
}
|
||||
}
|
||||
|
||||
108
gui/messageVector.h
Normal file
108
gui/messageVector.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MESSAGEVECTOR_H_
|
||||
#define _MESSAGEVECTOR_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
|
||||
class MessageVector : public SimObject
|
||||
{
|
||||
typedef SimObject Parent;
|
||||
|
||||
//-------------------------------------- Public interface...
|
||||
public:
|
||||
MessageVector();
|
||||
~MessageVector();
|
||||
|
||||
public:
|
||||
struct MessageLine {
|
||||
char* message;
|
||||
S32 messageTag;
|
||||
};
|
||||
|
||||
|
||||
// Spectator registration...
|
||||
public:
|
||||
enum MessageCode {
|
||||
LineInserted = 0,
|
||||
LineDeleted = 1,
|
||||
|
||||
VectorDeletion = 2
|
||||
};
|
||||
|
||||
typedef void (*SpectatorCallback)(const U32 spectatorKey,
|
||||
const MessageCode code,
|
||||
const U32 argument);
|
||||
|
||||
void registerSpectator(SpectatorCallback, U32 spectatorKey);
|
||||
void unregisterSpectator(U32 spectatorKey);
|
||||
|
||||
// Query functions
|
||||
public:
|
||||
U32 getNumLines() const;
|
||||
const MessageLine& getLine(const U32 line) const;
|
||||
|
||||
// Mutators
|
||||
public:
|
||||
void pushBackLine(const char*, const S32);
|
||||
void popBackLine();
|
||||
void pushFrontLine(const char*, const S32);
|
||||
void popFrontLine();
|
||||
void clear();
|
||||
|
||||
virtual void insertLine(const U32 position, const char*, const S32);
|
||||
virtual void deleteLine(const U32);
|
||||
|
||||
bool dump( const char* filename, const char* header = NULL );
|
||||
|
||||
|
||||
//-------------------------------------- Internal interface
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
private:
|
||||
struct SpectatorRef {
|
||||
SpectatorCallback callback;
|
||||
U32 key;
|
||||
};
|
||||
|
||||
Vector<MessageLine> mMessageLines;
|
||||
|
||||
Vector<SpectatorRef> mSpectators;
|
||||
void spectatorMessage(MessageCode, const U32 arg);
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(MessageVector);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline U32 MessageVector::getNumLines() const
|
||||
{
|
||||
return mMessageLines.size();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline const MessageVector::MessageLine& MessageVector::getLine(const U32 line) const
|
||||
{
|
||||
AssertFatal(line < mMessageLines.size(), "MessageVector::getLine: out of bounds line index");
|
||||
return mMessageLines[line];
|
||||
}
|
||||
|
||||
#endif // _H_GUICHATVECTOR_
|
||||
Loading…
Add table
Add a link
Reference in a new issue