Initial commit

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

View File

@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "gui/utility/guiBubbleTextCtrl.h"
#include "gui/core/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((char*)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;
}

View File

@ -0,0 +1,37 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIBUBBLETEXTCTRL_H_
#define _GUIBUBBLETEXTCTRL_H_
#ifndef _GUITEXTCTRL_H_
#include "gui/controls/guiTextCtrl.h"
#endif
#ifndef _GUIMLTEXTCTRL_H_
#include "gui/controls/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_ */

View File

@ -0,0 +1,92 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "gui/utility/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, 4, "onInputEvent", deviceString, actionString, "1" );
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, 4, "onInputEvent", "keyboard", keyString, "0" );
return( true );
}
}
return( false );
}

View File

@ -0,0 +1,30 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIINPUTCTRL_H_
#define _GUIINPUTCTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/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

View File

@ -0,0 +1,95 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "gui/utility/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::initPersistFields()
{
Parent::initPersistFields();
addField("lockMouse", TypeBool, Offset(mLockMouse, GuiMouseEventCtrl));
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::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);
}

View File

@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _GUIMOUSEEVENTCTRL_H_
#define _GUIMOUSEEVENTCTRL_H_
#ifndef _GUICONTROL_H_
#include "gui/core/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 initPersistFields();
DECLARE_CONOBJECT(GuiMouseEventCtrl);
};
#endif

View File

@ -0,0 +1,144 @@
//------------------------------------------------------------------------------
// Gui Vector Field Render control
//------------------------------------------------------------------------------
#include "gui/utility/guiTransitionCtrl.h"
#include "gui/core/guiCanvas.h"
#include "dgl/dgl.h"
#include "util/safeDelete.h"
IMPLEMENT_CONOBJECT( GuiVectorFieldCtrl );
//------------------------------------------------------------------------------
// A init function for vector field to provide some distortion
void FN_CDECL testInitFn( const int x, const int y, const Point2I &resolution,
const F32 maxX, const F32 maxY, Point2F *outVec )
{
outVec->x *= mCos( ( x + y - resolution.x ) / 50.f * M_PI );
outVec->y *= mCos( ( x + y ) / 100.f * M_PI );
}
void FN_CDECL spiralInitFn( const int x, const int y, const Point2I &resolution,
const F32 maxX, const F32 maxY, Point2F *outVec )
{
outVec->x -= 0.5f;
outVec->y -= 0.5f;
F32 d = mSqrt( ( x - resolution.x /2.f ) * ( x - resolution.x / 2.f ) +
( y - resolution.y / 2.f ) * ( y - resolution.y / 2.f ) );
F32 c = mCos( d * M_PI / 64.f );
F32 s = mSin( (d) * M_PI / 64.f );
outVec->x = c * outVec->x - s * outVec->y;
outVec->y = s * outVec->x + c * outVec->y;
outVec->x += 0.5f;
outVec->y += 0.5f;
/*outVec->x += 1.f / resolution.x;
outVec->y += 1.f / resolution.y;*/
}
//------------------------------------------------------------------------------
GuiVectorFieldCtrl::GuiVectorFieldCtrl()
{
// Just clear things out, don't allocate.
// SimObjects may not do anything significant in their constructor.
mVectorField = NULL;
mTestTexture = NULL;
}
//------------------------------------------------------------------------------
GuiVectorFieldCtrl::~GuiVectorFieldCtrl()
{
// duplicate with onRemove, just in case we're somehow deleted w/out remove
SAFE_DELETE( mVectorField );
SAFE_DELETE( mTestTexture );
}
//------------------------------------------------------------------------------
bool GuiVectorFieldCtrl::onAdd()
{
if(!Parent::onAdd())
return false;
mVectorField = new VectorField(Point2I(16,21));
mTestTexture = new TextureHandle("common/TestMap", BitmapTexture);
mFeedbackTexture.setUpdateRect(mBounds);
mClearColor.set(1.0f, 0.0f, 0.0f, 1.0f);
return true;
}
//------------------------------------------------------------------------------
void GuiVectorFieldCtrl::onRemove()
{
SAFE_DELETE( mVectorField );
SAFE_DELETE( mTestTexture );
Parent::onRemove();
}
//------------------------------------------------------------------------------
void GuiVectorFieldCtrl::onRender( Point2I offset, const RectI &updateRect )
{
RectI ctrlRect( offset, mBounds.extent );
glDisable(GL_LIGHTING);
//glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
//glBindTexture(GL_TEXTURE_2D, mTestTexture->getGLName() );
//glBindTexture(GL_TEXTURE_2D, mFeedbackTexture.getTextureHandle().getGLName() );
// CTE = 0x812F
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (F32 *)&mClearColor );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// Blend stuff
glBlendEquationEXT( GL_FUNC_ADD_EXT );
glBlendColorEXT( 0.1f, 0.1f, 0.1f, 0.f );
glBlendFunc( GL_CONSTANT_COLOR_EXT, GL_ONE );
// Render the current field
//mVectorField->renderField( true );
//dglDrawRectFill( ctrlRect, mClearColor );
glColor4ub( 0, 128, 0, 255 );
glRecti( (S32)ctrlRect.point.x, (S32)ctrlRect.point.y,
(S32)ctrlRect.point.x + ctrlRect.extent.x,
(S32)ctrlRect.point.y + ctrlRect.extent.y );
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
//mVectorField->visualizeField();
}
//------------------------------------------------------------------------------
void GuiVectorFieldCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
{
Parent::resize( newPosition, newExtent );
mFeedbackTexture.setUpdateRect( RectI( newPosition, newExtent ) );
TextureObject *obj = (TextureObject *)*mTestTexture;
//TextureObject *obj = (TextureObject *)mFeedbackTexture.getTextureHandle();
F32 maxX = F32(obj->bitmapWidth) / F32(obj->texWidth);
F32 maxY = F32(obj->bitmapHeight) / F32(obj->texHeight);
mVectorField->initVectorField( maxX, maxY, VectorField::Flip_None, &spiralInitFn );
}
//------------------------------------------------------------------------------
void GuiVectorFieldCtrl::processTick()
{
mFeedbackTexture.updateAtEndOfFrame();
}

View File

@ -0,0 +1,48 @@
//------------------------------------------------------------------------------
// Gui Transition Control
//------------------------------------------------------------------------------
#ifndef _GUI_VECTORFIELDCTRL_H_
#define _GUI_VECTORFIELDCTRL_H_
#include "gui/shiny/guiTickCtrl.h"
#include "dgl/gVectorField.h"
#include "dgl/gDynamicTexture.h"
class GuiVectorFieldCtrl : public GuiTickCtrl
{
typedef GuiTickCtrl Parent;
private:
VectorField *mVectorField;
DynamicTexture mFeedbackTexture;
ColorF mClearColor;
TextureHandle *mTestTexture;
protected:
// No interpolation on this
virtual void interpolateTick( F32 delta ) {};
// Don't care if time passes
virtual void advanceTime( F32 timeDelta ) {};
// I do care about this
virtual void processTick();
// do allocation and init of members here.
virtual bool onAdd(void);
// do deallocation of members here.
virtual void onRemove(void);
public:
GuiVectorFieldCtrl();
~GuiVectorFieldCtrl();
virtual void resize( const Point2I &newPosition, const Point2I &newExtent );
virtual void onRender( Point2I offset, const RectI &updateRect );
DECLARE_CONOBJECT( GuiVectorFieldCtrl );
};
#endif

View File

@ -0,0 +1,360 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "gui/utility/messageVector.h"
#include "core/fileObject.h"
IMPLEMENT_CONOBJECT(MessageVector);
//-------------------------------------- Console functions
ConsoleMethod( MessageVector, clear, void, 2, 2, "Clear the message vector.")
{
object->clear();
}
ConsoleMethod( MessageVector, pushBackLine, void, 4, 4, "(string msg, int tag=0)"
"Push a line onto the back of the list.")
{
U32 tag = 0;
if (argc == 4)
tag = dAtoi(argv[3]);
object->pushBackLine(argv[2], tag);
}
ConsoleMethod( MessageVector, popBackLine, bool, 2, 2, "()"
"Pop a line from the back of the list; destroys the line.")
{
if (object->getNumLines() == 0) {
Con::errorf(ConsoleLogEntry::General, "MessageVector::popBackLine(): underflow");
return false;
}
object->popBackLine();
return true;
}
ConsoleMethod( MessageVector, pushFrontLine, void, 3, 4, "(string msg, int tag=0)"
"Push a line onto the front of the vector.")
{
U32 tag = 0;
if (argc == 4)
tag = dAtoi(argv[3]);
object->pushFrontLine(argv[2], tag);
}
ConsoleMethod( MessageVector, popFrontLine, bool, 2, 2,
"Pop a line from the front of the vector, destroying the line.")
{
if (object->getNumLines() == 0) {
Con::errorf(ConsoleLogEntry::General, "MessageVector::popFrontLine(): underflow");
return false;
}
object->popFrontLine();
return true;
}
ConsoleMethod( MessageVector, insertLine, bool, 4, 5, "(int insertPos, string msg, int tag=0)"
"Insert a new line into the vector at the specified position.")
{
U32 pos = U32(dAtoi(argv[2]));
if (pos > object->getNumLines())
return false;
S32 tag = 0;
if (argc == 5)
tag = dAtoi(argv[4]);
object->insertLine(pos, argv[3], tag);
return true;
}
ConsoleMethod( MessageVector, deleteLine, bool, 3, 3, "(int deletePos)"
"Delete the line at the specified position.")
{
U32 pos = U32(dAtoi(argv[2]));
if (pos >= object->getNumLines())
return false;
object->deleteLine(pos);
return true;
}
ConsoleMethod( MessageVector, dump, void, 3, 4, "(string filename, string header=NULL)"
"Dump the message vector to a file, optionally prefixing a header.")
{
if ( argc == 4 )
object->dump( argv[2], argv[3] );
else
object->dump( argv[2] );
}
ConsoleMethod( MessageVector, getNumLines, S32, 2, 2, "Get the number of lines in the vector.")
{
return object->getNumLines();
}
ConsoleMethod( MessageVector, getLineTextByTag, const char*, 3, 3, "(int tag)"
"Scan through the lines in the vector, returning the first line that has a matching tag.")
{
U32 tag = dAtoi(argv[2]);
for(U32 i = 0; i < object->getNumLines(); i++)
if(object->getLine(i).messageTag == tag)
return object->getLine(i).message;
return "";
}
ConsoleMethod( MessageVector, getLineIndexByTag, S32, 3, 3, "(int tag)"
"Scan through the vector, returning the line number of the first line that matches the specified tag; else returns -1 if no match was found.")
{
U32 tag = dAtoi(argv[2]);
for(U32 i = 0; i < object->getNumLines(); i++)
if(object->getLine(i).messageTag == tag)
return i;
return -1;
}
ConsoleMethod( MessageVector, getLineText, const char*, 3, 3, "(int line)"
"Get the text at a specified line.")
{
U32 pos = U32(dAtoi(argv[2]));
if (pos >= object->getNumLines()) {
Con::errorf(ConsoleLogEntry::General, "MessageVector::getLineText(con): out of bounds line");
return "";
}
return object->getLine(pos).message;
}
ConsoleMethod( MessageVector, getLineTag, S32, 3, 3, "(int line)"
"Get the tag of a specified line.")
{
U32 pos = U32(dAtoi(argv[2]));
if (pos >= object->getNumLines()) {
Con::errorf(ConsoleLogEntry::General, "MessageVector::getLineTag(con): out of bounds line");
return 0;
}
return object->getLine(pos).messageTag;
}
//--------------------------------------------------------------------------
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();
}
//--------------------------------------------------------------------------
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, void *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(void * 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);
}
}

View File

@ -0,0 +1,110 @@
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, 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
/// Store a list of chat messages.
///
/// This is responsible for managing messages which appear in the chat HUD.
///
/// @see GuiMessageVectorCtrl for more details on how this is used.
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)(void * spectatorKey,
const MessageCode code,
const U32 argument);
void registerSpectator(SpectatorCallback, void * spectatorKey);
void unregisterSpectator(void *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;
void * key;
};
Vector<MessageLine> mMessageLines;
Vector<SpectatorRef> mSpectators;
void spectatorMessage(MessageCode, const U32 arg);
public:
DECLARE_CONOBJECT(MessageVector);
static void initPersistFields();
};
//--------------------------------------------------------------------------
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_