Game Development Community

A simple MMORPG for Torque 1.4

by CodingChris · in Torque Game Engine · 06/16/2006 (8:15 am) · 22 replies

I've read Dreamer's "Advanced MMORPG" In milestone 3 when I click Start Mission or Join Server Torque freezed. Dreamer said "It's a Torque 1.4 bug" He says there is a version for Torque 1.4 on mydreamrpg.com, but I cannot find this tutorial. This there another one, maybe not from Dreamer?
Page «Previous 1 2
#1
06/16/2006 (8:30 am)
The tutorials aren't supported any more and were never meant for TGE 1.4 to begin with. They CAN all be ported over as I've done it, but it's a long tedious task. Although they were great tutorials, 99% of them didn't work without modifications beyond what the tutorial stated.

There is now an MMO Kit that you can purchase at www.mydreamrpg.com which is in active development and gives you a ton of MMO related features.
#2
06/19/2006 (6:36 am)
Dreamer told me about a free tutorial at www.mydreamrpg.com
#3
06/20/2006 (10:58 pm)
Free? He sell his kit for 100$ as i know ^^

A few Teams work/will try to build a free Kit for Torque, but actually is unfortunately no one avaliable. :(
#4
06/21/2006 (9:58 am)
Is there a fix for this bug? Dreamer said it is. There must be a fix for this or why haven't you this problem?
#5
06/21/2006 (10:14 am)
The problem with the password field is a known bug in TGE 1.4
Since this is a private forum I will share with you my guiTextEditCtrl.cc file which contains the relevant fixes as well as a few others.
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiMLTextCtrl.h"
#include "gui/controls/guiTextEditCtrl.h"
#include "gui/core/guiDefaultControlRender.h"
#include "core/frameAllocator.h"

IMPLEMENT_CONOBJECT(GuiTextEditCtrl);

U32 GuiTextEditCtrl::smNumAwake = 0;

GuiTextEditCtrl::GuiTextEditCtrl()
{
   mInsertOn = true;
   mBlockStart = 0;
   mBlockEnd = 0;
   mCursorPos = 0;
   mCursorOn = false;
   mNumFramesElapsed = 0;

   mDragHit = false;
   mTabComplete = false;
   mScrollDir = 0;

   mUndoBlockStart = 0;
   mUndoBlockEnd = 0;
   mUndoCursorPos = 0;
   mPasswordText = false;

   mSinkAllKeyEvents = false;

   mActive = true;

   mTextOffsetReset = true;

   mHistoryDirty = false;
   mHistorySize = 0;
   mHistoryLast = -1;
   mHistoryIndex = 0;
   mHistoryBuf = NULL;

   mValidateCommand = StringTable->insert("");
   mEscapeCommand = StringTable->insert( "" );
   mPasswordMask = StringTable->insert( "*" );
   mDeniedSound = dynamic_cast<AudioProfile*>( Sim::findObject( "InputDeniedSound" ) );

   mEditCursor = NULL;
}

GuiTextEditCtrl::~GuiTextEditCtrl()
{
   //delete the history buffer if it exists
   if (mHistoryBuf)
   {
      for (S32 i = 0; i < mHistorySize; i++)
         delete [] mHistoryBuf[i];

      delete [] mHistoryBuf;
   }
}

void GuiTextEditCtrl::initPersistFields()
{
   Parent::initPersistFields();

   addField("validate",          TypeString,    Offset(mValidateCommand,   GuiTextEditCtrl));
   addField("escapeCommand",     TypeString,    Offset(mEscapeCommand,     GuiTextEditCtrl));
   addField("historySize",       TypeS32,       Offset(mHistorySize,       GuiTextEditCtrl));
   addField("password",          TypeBool,      Offset(mPasswordText,      GuiTextEditCtrl));     
   addField("tabComplete",       TypeBool,      Offset(mTabComplete,       GuiTextEditCtrl));     
   addField("deniedSound",       TypeAudioProfilePtr, Offset(mDeniedSound, GuiTextEditCtrl));
   addField("sinkAllKeyEvents",  TypeBool,      Offset(mSinkAllKeyEvents,  GuiTextEditCtrl));
   addField("password",          TypeBool,      Offset(mPasswordText,      GuiTextEditCtrl));
   addField("passwordMask",      TypeString,    Offset(mPasswordMask,      GuiTextEditCtrl)); 
}
Continued in next post
#6
06/21/2006 (10:16 am)
bool GuiTextEditCtrl::onAdd()
{
   if ( ! Parent::onAdd() )
      return false;

   //create the history buffer
   if ( mHistorySize > 0 )
   {
      mHistoryBuf = new UTF8*[mHistorySize];
      for ( S32 i = 0; i < mHistorySize; i++ )
      {
         mHistoryBuf[i] = new UTF8[GuiTextCtrl::MAX_STRING_LENGTH + 1];
         mHistoryBuf[i][0] = '[[4fc501f607efb]]';
      }
   }

   setText(mText);

   return true;
}

void GuiTextEditCtrl::onStaticModified(const char* slotName)
{
   if(!dStricmp(slotName, "text"))
      setText(mText);
}

bool GuiTextEditCtrl::onWake()
{
   if (! Parent::onWake())
      return false;

   // If this is the first awake text edit control, enable keyboard translation
   if (smNumAwake == 0)
      Platform::enableKeyboardTranslation();
   ++smNumAwake;

   return true;
}

void GuiTextEditCtrl::onSleep()
{
   Parent::onSleep();

   // If this is the last awake text edit control, disable keyboard translation
   --smNumAwake;
   if (smNumAwake == 0)
      Platform::disableKeyboardTranslation();
}

void GuiTextEditCtrl::execConsoleCallback()
{
   // Execute the console command!
   if ( mConsoleCommand[0] )
   {
      char buf[16];
      dSprintf( buf, sizeof( buf ), "%d", getId() );
      Con::setVariable( "$ThisControl", buf );
      Con::evaluate( mConsoleCommand, false );
   }

   // Update the console variable:
   UTF8 buffer[1024];
   mTextBuffer.get(buffer, 1024);

   if ( mConsoleVariable[0] )
      Con::setVariable( mConsoleVariable, (char*)buffer );
}

void GuiTextEditCtrl::updateHistory( StringBuffer *inTxt, bool moveIndex )
{
   FrameTemp<UTF8> textString(inTxt->length()*3 + 1);
   inTxt->get(textString, inTxt->length()*3 + 1);

   UTF8 *txt = textString;

   if(!txt)
      return;

   if(!mHistorySize)
      return;

   // see if it's already in
   if(mHistoryLast == -1 || dStrcmp((const UTF8*)txt, (const UTF8*)mHistoryBuf[mHistoryLast]))
   {
      if(mHistoryLast == mHistorySize-1) // we're at the history limit... shuffle the pointers around:
      {
         UTF8 *first = mHistoryBuf[0];
         for(U32 i = 0; i < mHistorySize - 1; i++)
            mHistoryBuf[i] = mHistoryBuf[i+1];
         mHistoryBuf[mHistorySize-1] = first;
         if(mHistoryIndex > 0)
            mHistoryIndex--;
      }
      else
         mHistoryLast++;

      inTxt->get(mHistoryBuf[mHistoryLast], GuiTextCtrl::MAX_STRING_LENGTH);
      mHistoryBuf[mHistoryLast][GuiTextCtrl::MAX_STRING_LENGTH] = '[[4fc501f607efb]]';
   }

   if(moveIndex)
      mHistoryIndex = mHistoryLast + 1;
}

void GuiTextEditCtrl::getText( char *dest )
{
   if ( dest )
      mTextBuffer.get((UTF8*)dest, GuiTextCtrl::MAX_STRING_LENGTH+1);
}  
 
void GuiTextEditCtrl::setText( const char *txt )
{
	
	if(txt && txt[0] != 0){
		
		Parent::setText( txt );
		mTextBuffer.set( txt );
	}
	else
		mTextBuffer.set( "" );

   mCursorPos = mTextBuffer.length();
}

void GuiTextEditCtrl::reallySetCursorPos( const S32 newPos )
{
   S32 charCount = mTextBuffer.length();
   S32 realPos = newPos > charCount ? charCount : newPos < 0 ? 0 : newPos;
   if ( realPos != mCursorPos )
   {
      mCursorPos = realPos;
      setUpdate();
   }
}

S32 GuiTextEditCtrl::setCursorPos( const Point2I &offset )
{
   Point2I ctrlOffset = localToGlobalCoord( Point2I( 0, 0 ) );
   S32 charCount = mTextBuffer.length();
   S32 charLength = 0;
   S32 curX;

   curX = offset.x - ctrlOffset.x;
   setUpdate();

   //if the cursor is too far to the left
   if ( curX < 0 )
      return -1;

   //if the cursor is too far to the right
   if ( curX >= ctrlOffset.x + mBounds.extent.x )
      return -2;

   curX = offset.x - mTextOffset.x;
   S32 count=0;
   if(mTextBuffer.length())
   {
     for(count=0; count<mTextBuffer.length(); count++)
      {
         //bank060104 "*" password textselect mod
         // Apply password masking char size
         if(mPasswordText)
            charLength += mFont->getCharXIncrement( mPasswordMask[0] );
         else
            // Or else just count the actual size.
            charLength += mFont->getCharXIncrement( mTextBuffer.getChar(count) );

         if ( charLength > curX )
            break;
      }
   }

   return count;
}

void GuiTextEditCtrl::onMouseDown( const GuiEvent &event )
{
   mDragHit = false;

   //undo any block function
   mBlockStart = 0;
   mBlockEnd = 0;

   //find out where the cursor should be
   S32 pos = setCursorPos( event.mousePoint );

   // if the position is to the left
   if ( pos == -1 )
      mCursorPos = 0;
   else if ( pos == -2 ) //else if the position is to the right
      mCursorPos = mTextBuffer.length();
   else //else set the mCursorPos
      mCursorPos = pos;

   //save the mouseDragPos
   mMouseDragStart = mCursorPos;

   // lock the mouse
   mouseLock();

   //set the drag var
   mDragHit = true;

   //let the parent get the event
   setFirstResponder();
}
Continued in next post
#7
06/21/2006 (10:18 am)
void GuiTextEditCtrl::onMouseDragged( const GuiEvent &event )
{
   S32 pos = setCursorPos( event.mousePoint );

   // if the position is to the left
   if ( pos == -1 )
      mScrollDir = -1;
   else if ( pos == -2 ) // the position is to the right
      mScrollDir = 1;
   else // set the new cursor position
   {
      mScrollDir = 0;
      mCursorPos = pos;
   }

   // update the block:
   mBlockStart = getMin( mCursorPos, mMouseDragStart );
   mBlockEnd = getMax( mCursorPos, mMouseDragStart );
   if ( mBlockStart < 0 )
      mBlockStart = 0;

   if ( mBlockStart == mBlockEnd )
      mBlockStart = mBlockEnd = 0;

   //let the parent get the event
   Parent::onMouseDragged(event);
}

void GuiTextEditCtrl::onMouseUp(const GuiEvent &event)
{
   event;
   mDragHit = false;
   mScrollDir = 0;
   mouseUnlock();
}

void GuiTextEditCtrl::saveUndoState()
{
   //save the current state
   mUndoText.set(&mTextBuffer);
   mUndoBlockStart = mBlockStart;
   mUndoBlockEnd   = mBlockEnd;
   mUndoCursorPos  = mCursorPos;
}
Continued in next post
#8
06/21/2006 (10:20 am)
Bool GuiTextEditCtrl::onKeyDown(const GuiEvent &event)
{
   S32 stringLen = mTextBuffer.length();
   setUpdate();

   // Ugly, but now I'm cool like MarkF.
   if(event.keyCode == KEY_BACKSPACE)
      goto dealWithBackspace;

   if (event.modifier & SI_SHIFT)
    {
        switch (event.keyCode)
        {
            case KEY_TAB:
               if ( mTabComplete )
               {
                  Con::executef( this, 2, "onTabComplete", "1" );
                  return( true );
               }

            case KEY_HOME:
               mBlockStart = 0;
               mBlockEnd = mCursorPos;
               mCursorPos = 0;
               return true;

            case KEY_END:
                mBlockStart = mCursorPos;
                mBlockEnd = stringLen;
                mCursorPos = stringLen;
                return true;

            case KEY_LEFT:
                if ((mCursorPos > 0) & (stringLen > 0))
                {
                    //if we already have a selected block
                    if (mCursorPos == mBlockEnd)
                    {
                        mCursorPos--;
                        mBlockEnd--;
                        if (mBlockEnd == mBlockStart)
                        {
                            mBlockStart = 0;
                            mBlockEnd = 0;
                        }
                    }
                    else {
                        mCursorPos--;
                        mBlockStart = mCursorPos;

                        if (mBlockEnd == 0)
                        {
                            mBlockEnd = mCursorPos + 1;
                        }
                    }
                }
                return true;

            case KEY_RIGHT:
                if (mCursorPos < stringLen)
                {
                    if ((mCursorPos == mBlockStart) && (mBlockEnd > 0))
                    {
                        mCursorPos++;
                        mBlockStart++;
                        if (mBlockStart == mBlockEnd)
                        {
                            mBlockStart = 0;
                            mBlockEnd = 0;
                        }
                    }
                    else
                    {
                        if (mBlockEnd == 0)
                        {
                            mBlockStart = mCursorPos;
                            mBlockEnd = mCursorPos;
                        }
                        mCursorPos++;
                        mBlockEnd++;
                    }
                }
                return true;
        }
    }
   else if (event.modifier & SI_CTRL)
   {
      switch(event.keyCode)
      {
         // Added UNIX emacs key bindings - just a little hack here...

         // BJGTODO: Add vi bindings.

         // Ctrl-B - move one character back
         case KEY_B:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_LEFT;
            return(onKeyDown(new_event));
         }

         // Ctrl-F - move one character forward
         case KEY_F:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_RIGHT;
            return(onKeyDown(new_event));
         }

         // Ctrl-A - move to the beginning of the line
         case KEY_A:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_HOME;
            return(onKeyDown(new_event));
         }

         // Ctrl-E - move to the end of the line
         case KEY_E:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_END;
            return(onKeyDown(new_event));
         }

         // Ctrl-P - move backward in history
         case KEY_P:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_UP;
            return(onKeyDown(new_event));
         }

         // Ctrl-N - move forward in history
         case KEY_N:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_DOWN;
            return(onKeyDown(new_event));
         }

         // Ctrl-D - delete under cursor
         case KEY_D:
         { GuiEvent new_event;
            new_event.modifier = 0;
            new_event.keyCode = KEY_DELETE;
            return(onKeyDown(new_event));
         }

         case KEY_U:
         { GuiEvent new_event;
            new_event.modifier = SI_CTRL;
            new_event.keyCode = KEY_DELETE;
            return(onKeyDown(new_event));
         }

         // End added UNIX emacs key bindings

         case KEY_C:
         case KEY_X:
            // Don't copy/cut password field!
            if(mPasswordText)
               return true;

            UTF8 buf[GuiTextCtrl::MAX_STRING_LENGTH + 1];
            if (mBlockEnd > 0)
            {
               //save the current state
               saveUndoState();

               //copy the text to the clipboard
               StringBuffer tmp = mTextBuffer.substring(mBlockStart, mBlockEnd - mBlockStart);
               FrameTemp<UTF8> clipBuff((mBlockEnd-mBlockStart) * 3 + 1);
               tmp.get(clipBuff, (mBlockEnd-mBlockStart) * 3 + 1);

               Platform::setClipboard((char*)(UTF8*)clipBuff);

               //if we pressed ctrl-x, we need to cut the selected text from the control...
               if (event.keyCode == KEY_X)
               {
                  mTextBuffer.cut(mBlockStart, mBlockEnd - mBlockStart);
                  mCursorPos = mBlockStart;
               }

               mBlockStart = 0;
               mBlockEnd = 0;
            }

            return true;
Continued in next post
#9
06/21/2006 (10:22 am)
case KEY_V:
         {
            UTF8 buf[GuiTextCtrl::MAX_STRING_LENGTH + 1];

            //first, make sure there's something in the clipboard to copy...
            const char *temp = (const char*)Platform::getClipboard();
            UTF8 *clipBuf = (UTF8*)GuiMLTextCtrl::stripControlChars(temp);
            if (dStrlen(clipBuf) <= 0)
               return true;

            //save the current state
            saveUndoState();

            //delete anything hilited
            if (mBlockEnd > 0)
            {
               mTextBuffer.cut(mBlockStart, mBlockEnd - mBlockStart);
               mCursorPos = mBlockStart;
               mBlockStart = 0;
               mBlockEnd = 0;
            }

            StringBuffer tmp(clipBuf);
            S32 pasteLen = tmp.length();
            if ((stringLen + pasteLen) > mMaxStrLen)
            {
               pasteLen = mMaxStrLen - stringLen;

               // Trim down to be pasteLen long.
               tmp.cut(pasteLen, tmp.length() - pasteLen);
            }


            if (mCursorPos == stringLen)
            {
               mTextBuffer.append(tmp);
            }
            else
            {
               mTextBuffer.insert(mCursorPos, tmp);
            }
            mCursorPos += tmp.length();

            return true;
         }

         case KEY_Z:
            if (! mDragHit)
            {
                StringBuffer tempBuffer;
                S32 tempBlockStart;
                S32 tempBlockEnd;
                S32 tempCursorPos;

                //save the current
                tempBuffer.set(&mTextBuffer);
                tempBlockStart = mBlockStart;
                tempBlockEnd   = mBlockEnd;
                tempCursorPos  = mCursorPos;

                //restore the prev
                mTextBuffer.set(&mUndoText);
                mBlockStart = mUndoBlockStart;
                mBlockEnd   = mUndoBlockEnd;
                mCursorPos  = mUndoCursorPos;

                //update the undo
                mUndoText.set(&tempBuffer);
                mUndoBlockStart = tempBlockStart;
                mUndoBlockEnd   = tempBlockEnd;
                mUndoCursorPos  = tempCursorPos;

                return true;
             }

         case KEY_DELETE:
         case KEY_BACKSPACE:
            //save the current state
            saveUndoState();

            //delete everything in the field
            mTextBuffer.set("");
            mCursorPos  = 0;
            mBlockStart = 0;
            mBlockEnd  = 0;

            execConsoleCallback();

            return true;
      }
   }
   else
   {
      switch(event.keyCode)
      {
         case KEY_ESCAPE:
            if ( mEscapeCommand[0] )
            {
               Con::evaluate( mEscapeCommand );
               return( true );
            }
            return( Parent::onKeyDown( event ) );

         case KEY_RETURN:
         case KEY_NUMPADENTER:
            //first validate
            if (mProfile->mReturnTab)
            {
               onLoseFirstResponder();
            }

            updateHistory(&mTextBuffer, true);
            mHistoryDirty = false;

            //next exec the alt console command
            if ( mAltConsoleCommand[0] )
            {
               char buf[16];
               dSprintf( buf, sizeof( buf ), "%d", getId() );
               Con::setVariable( "$ThisControl", buf );
               Con::evaluate( mAltConsoleCommand, false );
            }

            if (mProfile->mReturnTab)
            {
               GuiCanvas *root = getRoot();
               if (root)
               {
                  root->tabNext();
                  return true;
               }
            }
            return true;

         case KEY_UP:
         {
            if(mHistoryDirty)
            {
               updateHistory(&mTextBuffer, false);
               mHistoryDirty = false;
            }

            mHistoryIndex--;
            
            if(mHistoryIndex >= 0 && mHistoryIndex <= mHistoryLast)
               setText((char*)mHistoryBuf[mHistoryIndex]);
            else if(mHistoryIndex < 0)
               mHistoryIndex = 0;
            
            return true;
         }

         case KEY_DOWN:
            if(mHistoryDirty)
            {
               updateHistory(&mTextBuffer, false);
               mHistoryDirty = false;
            }
            mHistoryIndex++;
            if(mHistoryIndex > mHistoryLast)
            {
               mHistoryIndex = mHistoryLast + 1;
               setText("");
            }
            else
               setText((char*)mHistoryBuf[mHistoryIndex]);
            return true;

         case KEY_LEFT:
            mBlockStart = 0;
            mBlockEnd = 0;
            if (mCursorPos > 0)
            {
                mCursorPos--;
            }
            return true;

         case KEY_RIGHT:
            mBlockStart = 0;
            mBlockEnd = 0;
            if (mCursorPos < stringLen)
            {
                mCursorPos++;
            }
            return true;

         case KEY_BACKSPACE:
dealWithBackspace:
            //save the current state
            saveUndoState();

            if (mBlockEnd > 0)
            {
               mTextBuffer.cut(mBlockStart, mBlockEnd-mBlockStart);
               mCursorPos  = mBlockStart;
               mBlockStart = 0;
               mBlockEnd   = 0;
               mHistoryDirty = true;

               // Execute the console command!
               execConsoleCallback();

            }
            else if (mCursorPos > 0)
            {
               mTextBuffer.cut(mCursorPos-1, 1);
               mCursorPos--;
               mHistoryDirty = true;

               // Execute the console command!
               execConsoleCallback();
            }
            return true;

         case KEY_DELETE:
            //save the current state
            saveUndoState();

            if (mBlockEnd > 0)
            {
               mHistoryDirty = true;
               mTextBuffer.cut(mBlockStart, mBlockEnd-mBlockStart);

               mCursorPos = mBlockStart;
               mBlockStart = 0;
               mBlockEnd = 0;

               // Execute the console command!
               execConsoleCallback();
            }
            else if (mCursorPos < stringLen)
            {
               mHistoryDirty = true;
               mTextBuffer.cut(mCursorPos, 1);

               // Execute the console command!
               execConsoleCallback();
            }
            return true;

         case KEY_INSERT:
            mInsertOn = !mInsertOn;
            return true;

         case KEY_HOME:
            mBlockStart = 0;
            mBlockEnd   = 0;
            mCursorPos  = 0;
            return true;

         case KEY_END:
            mBlockStart = 0;
            mBlockEnd   = 0;
            mCursorPos  = stringLen;
            return true;

         }
   }
Continued in next post
#10
06/21/2006 (10:23 am)
switch ( event.keyCode )
   {
      case KEY_TAB:
         if ( mTabComplete )
         {
            Con::executef( this, 2, "onTabComplete", "0" );
            return( true );
         }
      case KEY_UP:
      case KEY_DOWN:
      case KEY_ESCAPE:
         return Parent::onKeyDown( event );
   }

   if ( mFont->isValidChar( event.ascii ) )
   {
      // Get the character ready to add to a UTF8 string.
      UTF16 conv[2] = { event.ascii, 0 };
      StringBuffer convertedChar(conv);

#if 0
      {
         UTF8 pony[10];
         convertedChar.get(pony, 10);
         Con::printf("Got key '%s' (0x%x)", pony, event.ascii );
      }
#endif

      //see if it's a number field
      if ( mProfile->mNumbersOnly )
      {
         if (event.ascii == '-')
         {
            //a minus sign only exists at the beginning, and only a single minus sign
            if ( mCursorPos != 0 )
            {
               playDeniedSound();
               return true;
            }

            if ( mInsertOn && ( mTextBuffer.getChar(0) == '-' ) ) 
            {
               playDeniedSound();
               return true;
            }
         }
         // BJTODO: This is probably not unicode safe.
         else if ( event.ascii < '0' || event.ascii > '9' )
         {
            playDeniedSound();
            return true;
         }
      }

      //save the current state
      saveUndoState();

      //delete anything highlighted
      if ( mBlockEnd > 0 )
      {
         mTextBuffer.cut(mBlockStart, mBlockEnd-mBlockStart);
         mCursorPos  = mBlockStart;
         mBlockStart = 0;
         mBlockEnd   = 0;
      }

      if ( ( mInsertOn && ( stringLen < mMaxStrLen ) ) ||
          ( !mInsertOn && ( mCursorPos < mMaxStrLen ) ) )
      {
         if ( mCursorPos == stringLen )
         {
            mTextBuffer.append(convertedChar);
            mCursorPos++;
         }
         else
         {
            if ( mInsertOn )
            {
               mTextBuffer.insert(mCursorPos, convertedChar);
               mCursorPos++;
            }
            else
            {
               mTextBuffer.cut(mCursorPos, 1);
               mTextBuffer.insert(mCursorPos, convertedChar);
               mCursorPos++;
            }
         }
      }
      else
         playDeniedSound();

      //reset the history index
      mHistoryDirty = true;

      //execute the console command if it exists
      execConsoleCallback();

      return true;
   }

   //not handled - pass the event to it's parent

   // Or eat it if that's appropriate.
   if (mSinkAllKeyEvents)
      return true;

   return Parent::onKeyDown( event );
}
Continued in next post
#11
06/21/2006 (10:24 am)
void GuiTextEditCtrl::setFirstResponder()
{
   Parent::setFirstResponder();
   
   Platform::enableKeyboardTranslation();
}

void GuiTextEditCtrl::onLoseFirstResponder()
{
   Platform::disableKeyboardTranslation();

   //first, update the history
   updateHistory( &mTextBuffer, true );

   //execute the validate command
   if ( mValidateCommand[0] )
      Con::evaluate( mValidateCommand, false );

   // Redraw the control:
   setUpdate();
}


void GuiTextEditCtrl::parentResized(const Point2I &oldParentExtent, const Point2I &newParentExtent)
{
   Parent::parentResized( oldParentExtent, newParentExtent );
   mTextOffsetReset = true;
}

void GuiTextEditCtrl::onRender(Point2I offset, const RectI & /*updateRect*/)
{
   RectI ctrlRect( offset, mBounds.extent );

   //if opaque, fill the update rect with the fill color
   if ( mProfile->mOpaque )
      dglDrawRectFill( ctrlRect, mProfile->mFillColor );
   
   //if there's a border, draw the border
   if ( mProfile->mBorder )
      renderBorder( ctrlRect, mProfile );

   drawText( ctrlRect, isFirstResponder() );
   
}

void GuiTextEditCtrl::onPreRender()
{
   if ( isFirstResponder() )
   {
      U32 timeElapsed = Platform::getVirtualMilliseconds() - mTimeLastCursorFlipped;
      mNumFramesElapsed++;
      if ( ( timeElapsed > 500 ) && ( mNumFramesElapsed > 3 ) )
      {
         mCursorOn = !mCursorOn;
         mTimeLastCursorFlipped = Platform::getVirtualMilliseconds();
         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) mTextBuffer.length() ) )
            mCursorPos++;
      }
   }
}
Continued in Next Post
#12
06/21/2006 (10:25 am)
void GuiTextEditCtrl::drawText( const RectI &drawRect, bool isFocused )
{
   StringBuffer textBuffer;
   Point2I drawPoint = drawRect.point;
   Point2I paddingLeftTop, paddingRightBottom;

   // Just a little sanity.
   if(mCursorPos > mTextBuffer.length()) 
      mCursorPos = mTextBuffer.length();

// Apply password masking (make the masking char optional perhaps?)
   if(mPasswordText)
   {
     //fixed	
      for(U32 i = 0; i<mTextBuffer.length(); i++)
         textBuffer.append(StringBuffer(mPasswordMask));
   }
   else
   {
      // Or else just copy it over.
      textBuffer.set(&mTextBuffer);
   }

   paddingLeftTop.set(( mProfile->mTextOffset.x != 0 ? mProfile->mTextOffset.x : 3 ), mProfile->mTextOffset.y);
   paddingRightBottom = paddingLeftTop;

   // Center vertically:
   drawPoint.y += ( ( drawRect.extent.y - paddingLeftTop.y - paddingRightBottom.y - mFont->getHeight() ) / 2 ) + paddingLeftTop.y;

   // Align horizontally:
   
   S32 textWidth;
   {
      FrameTemp<UTF8> widthTemp(textBuffer.length()*3+1);
      textBuffer.get(widthTemp, textBuffer.length()*3+1);
      textWidth = mFont->getStrWidth( widthTemp );
   }

   if ( drawRect.extent.x - paddingLeftTop.x > textWidth )
   {
      switch( mProfile->mAlignment )
      {
      case GuiControlProfile::RightJustify:
         drawPoint.x += ( drawRect.extent.x - textWidth - paddingRightBottom.x );
         break;
      case GuiControlProfile::CenterJustify:
         drawPoint.x += ( ( drawRect.extent.x - textWidth ) / 2 );
         break;
      default:
      case GuiControlProfile::LeftJustify :
         drawPoint.x += paddingLeftTop.x;
         break;
      }
   }
   else
      drawPoint.x += paddingLeftTop.x;

   ColorI fontColor = mActive ? mProfile->mFontColor : mProfile->mFontColorNA;

   // now draw the text
   Point2I cursorStart, cursorEnd;
   mTextOffset.y = drawPoint.y;
   if ( mTextOffsetReset )
   {
      mTextOffset.x = drawPoint.x;
      mTextOffsetReset = false;
   }

   if ( drawRect.extent.x - paddingLeftTop.x > textWidth )
      mTextOffset.x = drawPoint.x;
   else
   {
      // Alignment affects large text
      if ( mProfile->mAlignment == GuiControlProfile::RightJustify
         || mProfile->mAlignment == GuiControlProfile::CenterJustify )
      {
         if ( mTextOffset.x + textWidth < (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x)
            mTextOffset.x = (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x - textWidth;
      }
   }

   // calculate the cursor
   if ( isFocused )
   {
      // Where in the string are we?
      //StringBuffer preCursor = mTextBuffer.substring(0, mCursorPos);
      StringBuffer preCursor = textBuffer.substring(0, mCursorPos);
      S32 cursorOffset=0, charWidth=0;
      //UTF16 tempChar = mTextBuffer.getChar(mCursorPos);
      UTF16 tempChar = textBuffer.getChar(mCursorPos);
      // Alright, we want to terminate things momentarily.
      if(mCursorPos > 0)
      {
         FrameTemp<UTF8> cursorTemp(preCursor.length()*3+1);
         preCursor.get(cursorTemp, preCursor.length()*3+1);
         cursorOffset = mFont->getStrWidth(cursorTemp);
      }
      else
         cursorOffset = 0;

      if ( tempChar )
         charWidth = mFont->getCharWidth( tempChar );
      else
         charWidth = paddingRightBottom.x;

      if( mTextOffset.x + cursorOffset + charWidth >= (drawRect.point.x + drawRect.extent.x) - paddingLeftTop.x )
      {
         // Cursor somewhere beyond the textcontrol,
         // skip forward roughly 25% of the total width (if possible)
         S32 skipForward = drawRect.extent.x / 4;

         if ( cursorOffset + skipForward > textWidth )
            mTextOffset.x = (drawRect.point.x + drawRect.extent.x) - paddingRightBottom.x - textWidth;
         else
            mTextOffset.x -= skipForward;
      }
      else if( mTextOffset.x + cursorOffset < drawRect.point.x + paddingLeftTop.x )
      {
         // Cursor somewhere before the textcontrol
         // skip backward roughly 25% of the total width (if possible)
         S32 skipBackward = drawRect.extent.x / 4;

         if ( cursorOffset - skipBackward < 0 )
            mTextOffset.x = drawRect.point.x + paddingLeftTop.x;
         else
            mTextOffset.x += skipBackward;
      }
      cursorStart.x = mTextOffset.x + cursorOffset;
      cursorEnd.x = cursorStart.x;

      S32 cursorHeight = mFont->getHeight();
      if ( cursorHeight < drawRect.extent.y )
      {
         cursorStart.y = drawPoint.y;
         cursorEnd.y = cursorStart.y + cursorHeight;
      }
      else
      {
         cursorStart.y = drawRect.point.y;
         cursorEnd.y = cursorStart.y + drawRect.extent.y;
      }
   }

   //draw the text
   if ( !isFocused )
      mBlockStart = mBlockEnd = 0;

   //also verify the block start/end
   if ((mBlockStart > textBuffer.length() || (mBlockEnd > textBuffer.length()) || (mBlockStart > mBlockEnd)))
      mBlockStart = mBlockEnd = 0;

   UTF16 temp;

   Point2I tempOffset = mTextOffset;

   //draw the portion before the highlight
   if ( mBlockStart > 0 )
   {
      StringBuffer preBuffer = textBuffer.substring(0, mBlockStart);
      FrameTemp<UTF8> preString(preBuffer.length()*3+1);
      preBuffer.get(preString, preBuffer.length()*3+1);

      dglSetBitmapModulation( fontColor );
      dglDrawText( mFont, tempOffset, preString, mProfile->mFontColors );
      tempOffset.x += mFont->getStrWidth( (const UTF8*)preString );
   }

   //draw the hilighted portion
   if ( mBlockEnd > 0 )
   {
      StringBuffer highlightBuff = textBuffer.substring(mBlockStart, mBlockEnd-mBlockStart);
      FrameTemp<UTF8> highlightTemp(highlightBuff.length()*3 + 1);
      highlightBuff.get(highlightTemp, highlightBuff.length()*3 + 1);

      S32 highlightWidth = mFont->getStrWidth( highlightTemp );

      dglDrawRectFill( Point2I( tempOffset.x, drawRect.point.y ),
         Point2I( tempOffset.x + highlightWidth, drawRect.point.y + drawRect.extent.y - 1),
         mProfile->mFillColorHL );

      dglSetBitmapModulation( mProfile->mFontColorHL );
      dglDrawText( mFont, tempOffset, highlightTemp, mProfile->mFontColors );
      tempOffset.x += highlightWidth;
   }

   //draw the portion after the highlite
   if(mBlockEnd < mTextBuffer.length())
   {
      //StringBuffer finalBuff = mTextBuffer.substring(mBlockEnd, mTextBuffer.length() - mBlockEnd);
     StringBuffer finalBuff = textBuffer.substring(mBlockEnd, mTextBuffer.length() - mBlockEnd);
      FrameTemp<UTF8> finalTemp(finalBuff.length()*3 + 1);
      finalBuff.get(finalTemp, finalBuff.length()*3 + 1);

      dglSetBitmapModulation( fontColor );
      dglDrawText( mFont, tempOffset, finalTemp, mProfile->mFontColors );
   }

   //draw the cursor
   if ( isFocused && mCursorOn )
      dglDrawLine( cursorStart, cursorEnd, mProfile->mCursorColor );
}
Continued in Next Post
#13
06/21/2006 (10:26 am)
bool GuiTextEditCtrl::hasText()
{
   return (mTextBuffer.length());
}

void GuiTextEditCtrl::playDeniedSound()
{
   if ( mDeniedSound )
   {
      AUDIOHANDLE handle = alxCreateSource( mDeniedSound );
      alxPlay( handle );
   }
}

bool GuiTextEditCtrl::initCursors()
{
   if ( mEditCursor == NULL )
   {
      SimObject *obj;
      obj = Sim::findObject("TextEditCursor");
      mEditCursor = dynamic_cast<GuiCursor*>(obj);

      return( mEditCursor != NULL );
   }
   else
      return(true);
}


void GuiTextEditCtrl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent)
{
   showCursor = true;

   if( initCursors() )
   {
      Point2I mousePos  = lastGuiEvent.mousePoint;
      RectI winRect   = mBounds;
      winRect.point = localToGlobalCoord( winRect.point );

      if( winRect.pointInRect( mousePos ) )
         cursor = mEditCursor;
      else
         cursor = NULL;
   }
}

const char *GuiTextEditCtrl::getScriptValue()
{
   FrameTemp<UTF8> temp(mTextBuffer.length() * 3 + 1);
   mTextBuffer.get(temp, mTextBuffer.length() * 3 + 1);
   return StringTable->insert((const char*)(UTF8*)temp);
}

void GuiTextEditCtrl::setScriptValue(const char *value)
{
   mTextBuffer.set(value);
   mCursorPos = mTextBuffer.length() - 1;
}

ConsoleMethod( GuiTextEditCtrl, getText, const char*, 2, 2, "textEditCtrl.getText()" )
{
   argc; argv;
   if( !object->hasText() )
      return StringTable->insert("");

   char *retBuffer = Con::getReturnBuffer( GuiTextEditCtrl::MAX_STRING_LENGTH );
   object->getText( retBuffer );

   return retBuffer;
}


ConsoleMethod( GuiTextEditCtrl, getCursorPos, S32, 2, 2, "textEditCtrl.getCursorPos()" )
{
   argc; argv;
   return( object->getCursorPos() );
}

ConsoleMethod( GuiTextEditCtrl, setCursorPos, void, 3, 3, "textEditCtrl.setCursorPos( newPos )" )
{
   argc;
   object->reallySetCursorPos( dAtoi( argv[2] ) );
}

That should fix the password fields problem.
And just so you get the information from the horses mouth so to speak. The original plan for the kit was to release the Advanced Tutorial series as a patch that would be free and then there would be a paid version with more features. However the community did not respond well to the idea so I rolled all of those new features into a single paid patch kit. The MMOKit is a selling product with literally hundreds of more features than you can get by doing the tutorials. However I do still have the tutorials, they are still free for members of the site. For some reason they don't seem to be posted at the moment, and I am looking into why (I think it may be an access control or permissions problem), anyways sorry about that.

Regards,
Dreamer
#14
06/25/2006 (4:59 am)
Thanks a lot.
#15
06/25/2006 (9:11 am)
Visual C++ 2005 Express makes error with this new code:

1>------ Build started: Project: Torque Demo, Configuration: Debug Win32 ------
1>Compiling...
1>guiTextEditCtrl.cc
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(335) : error C2143: syntax error : missing ';' before 'GuiTextEditCtrl::onKeyDown'
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(335) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(336) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(336) : error C2556: 'int GuiTextEditCtrl::onKeyDown(const GuiEvent &)' : overloaded function differs only by return type from 'bool GuiTextEditCtrl::onKeyDown(const GuiEvent &)'
1> c:\torque\sdk\engine\gui\controls\guitexteditctrl.h(100) : see declaration of 'GuiTextEditCtrl::onKeyDown'
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(336) : error C2371: 'GuiTextEditCtrl::onKeyDown' : redefinition; different basic types
1> c:\torque\sdk\engine\gui\controls\guitexteditctrl.h(100) : see declaration of 'GuiTextEditCtrl::onKeyDown'
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(433) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(441) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(449) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(457) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(465) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(473) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(481) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>c:\torque\sdk\engine\gui\controls\guitexteditctrl.cc(488) : error C2264: 'GuiTextEditCtrl::onKeyDown' : error in function definition or declaration; function not called
1>Creating browse information file...
1>Microsoft Browse Information Maintenance Utility Version 8.00.50727
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>Build log was saved at "file://c:\Torque\SDK\engine\out.VC8.DEBUG\BuildLog.htm"
1>Torque Demo - 13 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 6 up-to-date, 0 skipped ==========

Please help me!
Thanks!
#16
07/04/2006 (6:29 am)
Why don't somebody answer?
#17
07/15/2006 (6:19 am)
Maybe because it appears you're running into quite basic errors. Maybe you should get some programming experience, buy a couple of books and try write a few simple programs? Learn to walk before you run so to speak.
#18
07/16/2006 (11:08 pm)
@Inge Siebmanns: In the code above are a few errors. Havent check it completly, but "Bool GuiTextEditCtrl::onKeyDown(const GuiEvent &event)" schould be "bool GuiTextEditCtrl::onKeyDown(const GuiEvent &event)".

@Anders Jacobsen: Why so agressive? Learn to behave you, befor you post.
#19
07/17/2006 (7:23 am)
Now it all works in milestone 3, tanks a lot. (Now I will work on the others) I hope they work... If not I will post.
#20
07/17/2006 (7:30 am)
Ohh, there is an error/question: How create an Account???
Page «Previous 1 2