Game Development Community

TGEA 1.7.0 Beta 2 Bug(s?) - GuiMLTextEditCtrl

by Kirk Longendyke · in Torque Game Engine Advanced · 03/31/2008 (6:42 pm) · 6 replies

Ok, this ones... um... *special*

First up, just to verrify that theres not an issue with the profile that's throwing things off, using the following def since there isn't one laying about in any demo, or backup that I can find be it on site, or in any codebase backups I've got laying about:

new GuiControlProfile (GuiMLTextEditProfile)
{
opaque = true;
fillColor = "255 255 255";
fillColorHL = "255 255 255";
border = 3;
borderThickness = 2;
borderColor = "0 0 0";
fontColor = "0 0 0";
fontColorHL = "0 0 0";
fontColorLink = "255 96 96";
fontColorLinkHL = "0 0 255";
textOffset = "0 2";
autoSizeWidth = false;
autoSizeHeight = true;
//tab = true;
canKeyFocus = true;
};

second off, as is perhapse obvious in the following pic:

img510.imageshack.us/img510/9623/wiredness1sk6.th.jpg

The extents for the drop-in methodology for the GuiMLTextEditCtrl become really, really fouled.

Third, the default maxChars = "-1"; entry does not allow any typing whatsoever.

Fourth, extending that to maxChars = "65535"; does allow the entry of carriage returns and backspace typing, however no other keypresses seem to register...

Now the really wierd part: one, count em 1, of the GuiMLTextEditCtrl s from the rescource:

www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3531

Just in case theres something I'm overlooking there that's actually allowing the entry of text, actually does somewhat function, in that the cursor position is aproximately 3 chars back behind where it actually enters data into the string vs where it visually displays it...

Honestly wish I could be more definative about this one, but after going over it for the last 2 days, I just can't put my finger on what all could be going wrong, though something tells me that the majority, if not all the above is somehow related...

#1
04/01/2008 (11:55 am)
Funny, TGE originally had this issue with 1.4. I reported it, as well as a fix for it. It was supposed to be added to the stack with the rest of the bugs/fixes... perhaps it didn't make it into a TGE->TSE/TGEA merge. Let me dig up the thread real quick...

Okay here it is: http://www.garagegames.com/mg/forums/result.thread.php?qt=34517

I used to post under "Jase" but have since changed my member name to "fireVein". So just do a quick page search for fireVein and you will come upon a post about GUIMLTextEditCtrl and some fixes are in that post... now I am not sure how much of it is relevent as TGE(TGEA more specifically for right now) has undergone A LOT of change since then. But surely something in that post should prove useful.

Hope it helps!
#2
04/01/2008 (1:39 pm)
Did, sorta. The code thats fix is based on looks to have been completely rewritten, however tracing the accociated functionality did lead me to:

//--------------------------------------------------------------------------
// Key events...
bool GuiMLTextEditCtrl::onKeyDown(const GuiEvent& event)
{
	setUpdate();

	Con::errorf("something pushed");
...

   if (event.ascii != 0)
   {
	Con::errorf("ascii key pressed");
}

resulting in feedback wich indicates the *editing* break at least resides between the two, as the ones wich doesn't allow charachter apending only gets to the first, while the one that is simply a bit offset gets through both... It's one step closer, at any rate...
#3
04/02/2008 (12:49 pm)
Research update:

//--------------------------------------------------------------------------
// Key events...
bool GuiMLTextEditCtrl::onKeyDown(const GuiEvent& event)
{
	if (!mActive)
	{
		Con::errorf("Not Active!");
		return Parent::onKeyDown(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;
				}
				Con::errorf("copy/cut pressed");
				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);
				}
				Con::errorf("paste pressed");
				return true;
			}
		}
   }
   else if ( event.modifier & SI_SHIFT )
   {
      switch ( event.keyCode )
      {
         case KEY_TAB:
			 Con::errorf("if ( event.modifier & SI_SHIFT ) pressed");
            return( Parent::onKeyDown( event ) );
      }
   }
   else if ( event.modifier == 0 )
   {
      switch (event.keyCode)
      {
         // Escape:
         case KEY_ESCAPE:
            if ( mEscapeCommand[0] )
            {
				Con::errorf("Escape pressed");
               Con::evaluate( mEscapeCommand );
               return( true );
            }
            return( Parent::onKeyDown( event ) );

         // Deletion
         case KEY_BACKSPACE:
         case KEY_DELETE:
			 Con::errorf("Deletion keyblock pressed");
            handleDeleteKeys(event);
            return true;

         // Cursor movement
         case KEY_LEFT:
         case KEY_RIGHT:
         case KEY_UP:
         case KEY_DOWN:
         case KEY_HOME:
         case KEY_END:
			 Con::errorf("Cursor movement keyblock pressed");
            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 );
			Con::errorf("TAB pressed");
            return true;

         case KEY_RETURN:
            // insert carriage return
            if (mSelectionActive == true)
            {
               mSelectionActive = false;
               deleteChars(mSelectionStart, mSelectionEnd);
               mCursorPosition = mSelectionStart;
            }
            insertChars( "\n", 1, mCursorPosition );
			Con::errorf("return pressed");
            return true;
      }
   }

   if (event.ascii != 0)
   {
	Con::errorf("ascii key pressed");
      // Normal ascii keypress.  Go ahead and add the chars...
      if (mSelectionActive == true)
      {
         mSelectionActive = false;
         deleteChars(mSelectionStart, mSelectionEnd);
         mCursorPosition = mSelectionStart;
      }

      UTF8 *outString = NULL;
      U32 outStringLen = 0;

#ifdef TORQUE_UNICODE

      UTF16 inData[2] = { event.ascii, 0 };
      StringBuffer inBuff(inData);

      FrameTemp<UTF8> outBuff(4);
      inBuff.getCopy8(outBuff, 4);

      outString = outBuff;
      outStringLen = dStrlen(outBuff);
#else
      char ascii = char(event.ascii);
      outString = &ascii;
      outStringLen = 1;
#endif

      insertChars(outString, outStringLen, mCursorPosition);
      mVertMoveAnchorValid = false;
      return true;
   }

   // Otherwise, let the parent have the event...

	Con::errorf("all other options failed  defaulting to Parent::onKeyDown(event)");
   return Parent::onKeyDown(event);
}

result:
all other options failed defaulting to Parent::onKeyDown(event)


edit: updatage:

replacing that last spam with
Con::printf("Mousclicks? %i",event.mouseClickCount);

results in

Mousclicks? 1
Mousclicks? 2
Mousclicks? 4
Mousclicks? 15

ect where # stays static when pressing keys, and increments while reclicking. (meaning click once = Mousclicks? 1 x 10 when typing 10 letters, ect, clicking a bit more and more typing got us 5 Mousclicks? 4 ect ect.)

looks like theres one of the issues then...
#4
04/05/2008 (2:25 pm)
Right, well, while the primary not allowing editing 90% of the time has still got me wondering if I've lost a few braincells someplace, the cursor fix was relatively simplistic once i decided to change pace and look at the other aspects for a bit:


void GuiMLTextCtrl::getCursorPositionAndColor(Point2I &cursorTop, Point2I &cursorBottom, ColorI &color)
x += font->getStrNWidth(buff, mCursorPosition - awalk->textStart - 1);
to
x += font->getStrNWidth(buff, mCursorPosition - awalk->textStart);

puts that at the expected behavior, at least.
#5
04/06/2008 (2:47 pm)
[removed erroneous stacktracing research. didn't go far enough down to show anything relevant]

so lesee... passing in

AssertFatal(event.ascii,"Non-Acii Key propigated to onKEY down...");
   if (event.ascii != 0)
wich gives a resultant traceback of:
static void _keyboardEvent(Win32Window* window,UINT message, WPARAM wParam, WPARAM lParam)
   // Early out if keyboard translation is off and it's not a make event...
   if(!enableTranslation || !make)
      return;
for the first test, wich is the non-typing version
vs
AssertFatal(!event.ascii,"Acii Key propigated to onKEY down...");
   if (event.ascii != 0)
wich gives a resultant traceback of:
static void _keyboardEvent(Win32Window* window,UINT message, WPARAM wParam, WPARAM lParam)
   // Post chars, but filter them to not be control codes... this is a bit hacky.
   for(S32 i=0; i<charsRecvd; i++)
      if(chars[i] >= 32)
         window->charEvent.trigger(window->getDeviceId(),_ModifierKeys,chars[i]);
for the second test, wich the one that does work...

so... tried tossing in
windispatch.cpp
static void _keyboardEvent(Win32Window* window,UINT message, WPARAM wParam, WPARAM lParam)
{
...
   // Early out if keyboard translation is off [b]and[/b] it's not a make event...
   if(!enableTranslation && !make)
      return;
...
}

and that seems to have fixed that... anybody see any particular downside to that I'm just blanking on? After all, gotta be some reason the comment and code disagree, and it's got me a bit paro about side-effects, considering just how much of an overhaul the inputs seem to have gone under for the baseline stuff...

edit2: *sigh* so. right. aparently thats tied in to multiple charachter inputs...
#6
05/11/2008 (8:08 pm)
Began looking into this. Admittedly, I have a bit of a hard time following your steps but maybe that's just because it's time to wrap up.

Here's what I found:

- 'maxChars' of -1

That's fine. Means no limit on the number of characters.

- Does not receive input

You were pretty close there. It's because keyboard translation is not enabled. Simply add

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

   getRoot()->enableKeyboardTranslation();
   return true;
}

and it's fine.

- Wrong cursor positions

Yep, correct. Your fix and that thing above and everything's fine.