Forum Thread Not Found, Sorry.

Game Development Community

Fatal - String stack popped too much in script exec - LOGGED

by Nathan Bowhay - ESAL · in Torque 3D Professional · 02/15/2011 (6:09 pm) · 4 replies

I ran into this bug when messing around with script callbacks. It is sort of in depth to create, but I will try and write out all the code to hopefully reproduce.

I also have a question about what happened. So first I go a message popup that said "String stack popped too much in script exec" I then got one that said something like if you want to debug click ok if you don't want this message to show again click cancel. Both options don't seem to break in script or in engine (after attaching to process). And then I get:
Error: DebugBreak occurred
in the console. Is there any special set up? What is suppose to happen?

Anyway here is the code
First we need an engine change to get the mouse position relative to the main torque window.
On line 300 in guiCanvas.h add:
virtual Point2I getLocalCursorPos();

next on line 408 in guiCanvas.cpp add:
//nbowhay - created this so that we could have a relative position
Point2I GuiCanvas::getLocalCursorPos()
{
   Point2I p( 0, 0 );
   
   if( mPlatformWindow )
   {
      mPlatformWindow->getCursorPosition( p );

	  //compensating for window edges
	  p -= mPlatformWindow->getPosition();
	  p -= Point2I(8, 25);
   }
      
   return p;
}
and on line 2189 add:
DefineEngineMethod( GuiCanvas, getLocalCursorPos, Point2I, (),,
				   "@brief Get the current position of the cursor (in local space).nn"
				   "@param param Descriptionnn"
				   "@tsexamplen"
				   "%cursorPos = Canvas.getLocalCursorPos();n"
				   "@endtsexamplenn"
				   "@return Local coordinates of mouse cursor, in format "X Y"")
{
	return object->getLocalCursorPos();
}

The rest is all in script.
Add a gui file in art/gui called TestWindowGui.gui:
//--- OBJECT WRITE BEGIN ---
%guiContent = new GuiControl(TestWindowGui) {
   position = "0 0";
   extent = "1024 768";
   minExtent = "8 2";
   horizSizing = "right";
   vertSizing = "bottom";
   profile = "GuiDefaultProfile";
   visible = "1";
   active = "1";
   tooltipProfile = "GuiToolTipProfile";
   hovertime = "1000";
   isContainer = "1";
   canSave = "1";
   canSaveDynamicFields = "1";
      guidesVertical = "995 998 1013";

   new GuiWindowCtrl(TestWindow) {
      text = "New Window";
      resizeWidth = "1";
      resizeHeight = "1";
      canMove = "1";
      canClose = "1";
      canMinimize = "1";
      canMaximize = "1";
      canCollapse = "0";
      edgeSnap = "1";
      margin = "0 0 0 0";
      padding = "0 0 0 0";
      anchorTop = "1";
      anchorBottom = "0";
      anchorLeft = "1";
      anchorRight = "0";
      position = "90 73";
      extent = "600 302";
      minExtent = "8 2";
      horizSizing = "right";
      vertSizing = "bottom";
      profile = "GuiWindowProfile";
      visible = "1";
      active = "1";
      tooltipProfile = "GuiToolTipProfile";
      hovertime = "1000";
      isContainer = "1";
      canSave = "1";
      canSaveDynamicFields = "0";

      new GuiStackControl(TestStackGroup) {
         stackingType = "Vertical";
         horizStacking = "Left to Right";
         vertStacking = "Top to Bottom";
         padding = "0";
         dynamicSize = "1";
         dynamicNonStackExtent = "0";
         dynamicPos = "0";
         changeChildSizeToFit = "1";
         changeChildPosition = "1";
         position = "0 26";
         extent = "600 160";
         minExtent = "16 16";
         horizSizing = "width";
         vertSizing = "height";
         profile = "GuiDefaultProfile";
         visible = "1";
         active = "1";
         tooltipProfile = "GuiToolTipProfile";
         hovertime = "1000";
         isContainer = "1";
         canSave = "1";
         canSaveDynamicFields = "0";

         new GuiMouseEventCtrl() {
            lockMouse = "0";
            position = "0 0";
            extent = "600 40";
            minExtent = "8 2";
            horizSizing = "right";
            vertSizing = "bottom";
            profile = "GuiDefaultProfile";
            visible = "1";
            active = "1";
            tooltipProfile = "GuiToolTipProfile";
            hovertime = "1000";
            isContainer = "1";
            internalName = "Track1";
            class = "TestTrackClass";
            canSave = "1";
            canSaveDynamicFields = "0";

            new GuiButtonCtrl() {
               text = "Test";
               groupNum = "-1";
               buttonType = "PushButton";
               useMouseEvents = "1";
               position = "0 0";
               extent = "100 40";
               minExtent = "40 40";
               horizSizing = "right";
               vertSizing = "bottom";
               profile = "GuiButtonProfile";
               visible = "1";
               active = "1";
               tooltipProfile = "GuiToolTipProfile";
               hovertime = "1000";
               isContainer = "0";
               class = "TestButtonClass";
               canSave = "1";
               canSaveDynamicFields = "0";
            };
         };
         new GuiMouseEventCtrl() {
            lockMouse = "0";
            position = "0 40";
            extent = "600 40";
            minExtent = "8 2";
            horizSizing = "right";
            vertSizing = "bottom";
            profile = "GuiDefaultProfile";
            visible = "1";
            active = "1";
            tooltipProfile = "GuiToolTipProfile";
            hovertime = "1000";
            isContainer = "1";
            internalName = "Track2";
            class = "TestTrackClass";
            canSave = "1";
            canSaveDynamicFields = "0";
         };
         new GuiMouseEventCtrl() {
            lockMouse = "0";
            position = "0 80";
            extent = "600 40";
            minExtent = "8 2";
            horizSizing = "right";
            vertSizing = "bottom";
            profile = "GuiDefaultProfile";
            visible = "1";
            active = "1";
            tooltipProfile = "GuiToolTipProfile";
            hovertime = "1000";
            isContainer = "1";
            internalName = "Track3";
            class = "TestTrackClass";
            canSave = "1";
            canSaveDynamicFields = "0";
         };
         new GuiMouseEventCtrl() {
            lockMouse = "0";
            position = "0 120";
            extent = "600 40";
            minExtent = "8 2";
            horizSizing = "right";
            vertSizing = "bottom";
            profile = "GuiDefaultProfile";
            visible = "1";
            active = "1";
            tooltipProfile = "GuiToolTipProfile";
            hovertime = "1000";
            isContainer = "1";
            internalName = "Track4";
            class = "TestTrackClass";
            canSave = "1";
            canSaveDynamicFields = "0";
         };
      };
   };
};
//--- OBJECT WRITE END ---
add a script file in scripts/gui called TestWindowGui.cs:
function TestTrackClass::isInTrack(%this, %y)
{
   %pos = %this.getPosition();
   %extent = %this.getExtent();
   %yMin = getWord(%pos, 1);
   %yMax = %yMin + getWord(%extent, 1);
   if(%y >= %yMin && %y <= %yMax)
      return true;
      
   return false;
}

function TestStackGroup::getTrackFromPos(%this, %y)
{
   for(%i = 0; %i < %this.getCount(); %i++)
   {
      %track = %this.getObject(%i);
      
      if(%track.isInTrack(%y))
         return %track;
   }
   
   return "";
}

function TestButtonClass::onClick(%this)
{
   //Didn't click on the button if we dragging it
   if(%this.dragged !$= "" && %this.dragged)
   {
      %this.clickPos = "";
      %this.dragged = "";
      %this.editSection = "";
      TestWindow.draggingButton = "";
      
      return;
   }
}

function TestButtonClass::onMouseDown(%this)
{
   //Get our mouse position on the button
   %mousePos = Canvas.getLocalCursorPos();
   %globalPos = %this.getGlobalPosition();
   %mouseX = getWord(%mousePos, 0) - getWord(%globalPos, 0);
   %mouseY = getWord(%mousePos, 1) - getWord(%globalPos, 1);
   %this.clickPos = %mouseX SPC %mouseY;
   
   %edgeSize = 4;
   %width = getWord(%this.getExtent(), 0);
   //Get the secion we are editing based on where they clicked
   if(%mouseX > %edgeSize && %mouseX < (%width - %edgeSize))
      %this.editSection = "middle";
   else if(%mouseX <= %edgeSize)
      %this.editSection = "start";
   else
      %this.editSection = "end";
      
   TestWindow.draggingButton = %this;
}

function TestTrackClass::onMouseEnter(%this, %modifier, %mousePoint, %mouseClickCount)
{
   //If dragging a button now
   %button = TestWindow.draggingButton;
   if(isObject(%button) && %button.dragged !$= "" && %button.dragged && %this.getId() != %button.getParent().getId())
   {
      //Let the button do all the work
      %button.onMouseDragged(%this);
   }
}

function TestButtonClass::onMouseDragged(%this, %newTrack)
{   
   %track = %this.getParent();
   %mousePos = Canvas.getLocalCursorPos();
   
   //Check if there is an open spot on the track we are over
   %globalPos = TestStackGroup.getGlobalPosition();
   %mouseY = getWord(%mousePos, 1) - getWord(%globalPos, 1);
   
   //Check if we passed in the track so we don't have to find it
   if(!isObject(%newTrack) || !%newTrack.isInTrack(%mouseY))
      %newTrack = TestStackGroup.getTrackFromPos(%mouseY);
   
   //If we are over a track that isn't the track we are in then try and move us
   if(%newTrack !$= "" && %newTrack.className $= "TestTrackClass" && %track.getId() != %newTrack.getId())
   {
      //Get our mouse position on the track
      %globalPos = %newTrack.getGlobalPosition();
      %mouseX = getWord(%mousePos, 0) - getWord(%globalPos, 0);
      
      //Calculate where the button will be
      %mouseX -= getWord(%this.clickPos, 0);
      %height = getWord(%newTrack.getExtent(), 1);
      %width = getWord(%this.getExtent(), 0);
      
      //Look if there is anything under our new spot
      %list = %newTrack.findHitControls(%mouseX, 0, %width, %height);
      %list = strreplace(%list, %newTrack.getId(), "");
      %count = getWordCount(%list);
      
      if(%count < 1)
      {
         %newTrack.add(%this);
      }
   }
   
   %this.dragged = true;
}

function TestButtonClass::onMouseUp(%this)
{
   TestWindow.draggingButton = "";
}
Lastly go to scripts/client/init.cs and on line 99 add:
exec("art/gui/TestWindowGui.gui");
and on line 107 add:
exec("scripts/gui/TestWindowGui.cs");

Now hit run, then F10, in the top left drop down go to "TestWindowGui" then hit F10 again. Now click on the button and drag it up and down. Try clicking and dragging and just clicking around. You should eventually get it to happen.

PS: I got the second prompt to actually break in c++ in a stock build after writing up this little tutorial on how to reproduce the but, not sure why it doesn't work in my build. If anyone has any idea let me know.

#1
02/23/2011 (12:07 pm)
I'll check this out. Thanks for the detailed information Nathan.
#2
03/16/2011 (7:37 am)
Greetings!

Logged as THREED-1485. Thanks!

- Dave
#3
10/19/2011 (8:44 pm)
Just ran into this myself in 1.1Final. Was the issue addressed?
#4
10/20/2011 (11:50 am)
This issue is still unresolved for Torque 3D 1.2.