Torque 2D/Getting Started/ObjectSelection3Tutorial

From TDN

This page is a Work In Progress.

Torque 2D Tutorial – Object Selection 3: Debug Info

by: Matthew "King BoB" Langley
edited by: Spider

This tutorial will cover
the following:


  • Debug Message Display Techniques
  • Creating a GUI to Track Debug Info
  • Torque GUI controls: GuiPopUpMenuCtrl, GuiScrollCtrl, GuiMessageVectorCtrl, MessageVectors


This tutorial is the third in a three part series on object selection and movement using the mouse. We've actually already covered both the simple and complex methods of object selection and movement... in this final installation, we're going to create a nice GUI to display all the debug information that we've been putting into our code.

Note: This tutorial was written using the early release version of T2D, which has a default white background. To make your screenshots match those shown, open the SDK\games\T2D\data\gui\mainScreenGui.gui file and find/replace the text “logoblack” with “logowhite”.

Note: Any time you do a tutorial or experiment with Torque 2D, it’s a good idea to copy your entire Torque2D directory and modify only the copy. That way your original files remain intact.


Parts 1 and 2 revisited...


This tutorial assumes that you've done parts 1 and 2 already. However, in case you haven't, this section will explain how to set everything up as if you had, but will skip all the explanations. If you did go through the first two parts, you can skip over this whole section and move directly to the section called Creating the Debug GUI.

Create a file called "exec.cs" in the SDK/games/T2D/gameScripts folder (all our scripts will be here) and put this in it:

exec("./complexMouse.cs");

Put this statement into your game.cs file, right below the other exec statements:
exec("./exec.cs");

Scroll down a little and after these lines:
        // ************************************************************************
        //
        // Add your custom code here...
        //
        // ************************************************************************

add this:
initMouse();
complexMouse();

Finally, create a file called “complexMouse.cs” and paste this into it:
function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                echo("Mouse Moving");

        //store the mouse position
        $mouseObj::pos = %worldPos;

        //reset stopped to false so it checks
        $mouseObj::stopped = false;
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                echo("Mouse Dragging");

        //store the mouse position
        $mouseObj::pos = %worldPos;

        //reset stopped to false so it checks
        $mouseObj::stopped = false;
}

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                echo("Mouse Down");

        //check to see if we have an object already selected, 
        //if so we don't want to do anything expect set it to false so it doesn't follow anymore
        if(%this.objectSelected)
        {
                if($debugMsg::mouse::selection)
                        echo("unselecting");

                if($mouseObj::isObjMounted)
                {       
                        if(isObject($mouseObj::objMounted))
                        {
                                if($debugMsg::mouse::selection)
                                        echo("dismounting object");

                                $mouseObj::objMounted.dismount();
                                $mouseObj::isObjMounted = false;
                        }
                }

                %this.objectSelected = false;
        } else
        {
                //lets get a list of all the objects at the clicked point in the t2dScene
                %objList = t2dScene.pickPoint(%worldPos);
                //lets get a count of how many objects in the list
                %objCount = getWordCount(%objList);
        
                //we will start looping through the list
                for(%i=0;%i<%objCount;%i++)
                {
                        //grabing the entry corresponding to the loop
                        %obj = getWord(%objList, %i);
                
                        //if we find an object in the list that "isSelectable = true"
        
                        if(%obj.isSelectable)
                        {
                                //we toggle a value so we know we found an object that "isSelectable"
                                %selected = true;
                                //we kick out of the loop
                                %i = %objCount;
                        }       
                }
        
                //if we found an "isSelectable" object
                if(%selected)
                {
                        //we then store that object as the selectedObj
                        %this.selectedObj = %obj;
                
                        if($debugMsg::mouse::selection)
                                echo("You have selected:" SPC %obj SPC "with the name:" SPC %obj.objectName);

                        %this.objectSelected = true;

                        if($debugMsg::mouse::selection) 
                                echo("echo attempting to mount:" SPC %obj SPC " to mouse obj:" 
                                         SPC $mouseObj::object);
                                
                        %obj.mount($mouseObj::object, $mouseObj::mount::offset, 
                                             $mouseObj::mount::force, $mouseObj::mount::trackRotation);
                        $mouseObj::isObjMounted = true;
                        $mouseObj::objMounted = %obj;

                }
        }
}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                echo("Mouse Up");
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                echo("Mouse Entered... Knew it would come crawling back");
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                echo("Mouse Left... Go Get It!");
}

function initMouse()
{
        $mouseObj::object = new t2dSceneObject() { scenegraph = t2dScene; };
        $mouseObj::object.setSize("1 1");
      $mouseObj::object.setLayer(31);
        $mouseObj::follow = true;
        $mouseObj::speed::max = 250;
        $mouseObj::speed::default = 250;
        $mouseObj::mount::force = 0;
        $mouseObj::mount::offset = "0 0";
        $mouseObj::mount::trackRotation = true;
}

function t2dScene::onUpdateScene(%this)
{
        if(($mouseObj::follow) && (!$mouseObj::stopped))
                mouseObjCheck();        
}

function mouseObjCheck()
{

        // Get the position of the Mouse itself
        %x = getWord($mouseObj::pos, 0);
        %y = getWord($mouseObj::pos, 1);
                
        // Get the Position of the mounted scene object
        %objPos = $mouseObj::object.getPosition();
        %objX = getWord(%objPos, 0);
        %objY = getWord(%objPos, 1);

        // calculate the distance between the two (for speed calculations)
        %dist = distBetween(%objPos, $mouseObj::pos);
        
        // Set values for easy configuration
        // set speed = distance * 20, that way it slows when approach - no bobbing around
        %speed = %dist * 20;

        // limit speed if we want to
        if(%speed > $mouseObj::speed::max)
                %speed = $mouseObj::speed::default;

        %space = 0.25;
        
        if((%objX > (%x - %space)) && (%objX < (%x + %space)) && 
            (%objY > (%y - %space)) && (%objY < (%y + %space)))
        {
                if($debugMsg::mouse::object)
                        echo("object at mouse position, halting");

                $mouseObj::object.setLinearVelocityPolar(0,0);
                $mouseObj::stopped = true;
        } else
        {
                if($debugMsg::mouse::object)
                        echo("object seeking mouse at " @ angleBetween(%objPos, $mouseObj::pos));
        
                //set the polar velocity towards the mouse      
                $mouseObj::object.setLinearVelocityPolar(angleBetween(%objPos, $mouseObj::pos),%speed); 
        }        

}

function angleBetween(%playerPos, %mousePos)
{
        // Seperate Mouse Position
        %mxpos = getWord(%mousePos,0);
        %mypos = getWord(%mousePos,1);

        // Seperate Player Position
        %px = getWord(%playerPos,0);
        %py = getWord(%playerPos,1);

        // Calculate Angle from player to mouse (convert to degrees).
        %angle = mRadToDeg( mAtan( %mxpos-%px, %py-%mypos ) );

        return %angle;
}

function distBetween(%loc1, %loc2)
{       
        %x1 = getWord(%loc1, 0);
        %y1 = getWord(%loc1, 1);

        %x2 = getWord(%loc2, 0);
        %y2 = getWord(%loc2, 1);

        %xd = %x2 - %x1;
        %yd = %y2 - %y1;
        
        return mSqrt((mPow(%xd,2)) + (mPow(%yd,2)));
}

function complexMouse()
{
        $test = new t2dStaticSprite() { sceneGraph = t2dScene; };
        $test.setImageMap( tileMapImageMap );
        $test.setSize( "5 5" );
        $test.setPosition( "0 0" );
        $test.isSelectable = true;
        $test.objectName = "test box";
}

You should be all caught up now. If you fire up T2D you should be able to click the box in the middle of the screen and move it, then click again to drop it.

Creating The Debug GUI


Let's jump right into it... fire up T2D and hit "F10" to enter the GUI editor:

Image:T2D_tut_ObjSelection3_01.jpg

Click File>New Gui... in the menu. In GUI Name: put “DebugGui”. Change the Class to GuiWindowCtrl, and click Create. For the controls that follow, you don't have to worry about matching the placements precisely... those can be edited later on.

Image:T2D_tut_ObjSelection3_02.jpg

Click on New Control in the top left.

Image:T2D_tut_ObjSelection3_03.jpg

Scroll down and select GuiPopUpMenuCtrl.

Image:T2D_tut_ObjSelection3_04.jpg

Move and stretch the new control to about here.

Image:T2D_tut_ObjSelection3_05.jpg

Now click New Control, scroll down and select GuiScrollCtrl. Place it about here.

Image:T2D_tut_ObjSelection3_06.jpg

Finally, click New Control, scroll down and select GuiMessageVectorCtrl. Place it about here.

Image:T2D_tut_ObjSelection3_07.jpg


This is going to be the basis of our GUI window. Select File>Save GUI... from the menu. Change the Directory to T2D/gameScripts. Click Save.

Image:T2D_tut_ObjSelection3_08.jpg

Now exit T2D and open up the DebugGui.gui file (that you just created with the GUI editor) in the T2D/gameScripts folder. You should see this:
//--- OBJECT WRITE BEGIN ---
new GuiWindowCtrl(DebugGui) {
   profile = "GuiWindowProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "640 480";
   minExtent = "8 2";
   visible = "1";
   maxLength = "255";
   resizeWidth = "1";
   resizeHeight = "1";
   canMove = "1";
   canClose = "1";
   canMinimize = "1";
   canMaximize = "1";
   minSize = "50 50";

   new GuiPopUpMenuCtrl(DebugList) {
      profile = "GuiPopUpMenuProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "5 24";
      extent = "113 19";
      minExtent = "8 2";
      visible = "1";
      maxLength = "255";
      maxPopupHeight = "200";
   };
   new GuiScrollCtrl(DebugScroll) {
      profile = "GuiScrollProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "5 45";
      extent = "146 140";
      minExtent = "8 2";
      visible = "1";
      willFirstRespond = "1";
      hScrollBar = "alwaysOn";
      vScrollBar = "alwaysOn";
      constantThumbHeight = "0";
      childMargin = "0 0";
   };
   new GuiMessageVectorCtrl(DebugVector) {
      profile = "GuiDefaultProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "11 50";
      extent = "122 118";
      minExtent = "8 2";
      visible = "1";
      lineSpacing = "0";
      lineContinuedIndex = "10";
      matchColor = "0 0 255 255";
      maxColorIndex = "9";
   };
};
//--- OBJECT WRITE END ----------------------

Let's name some of these controls so we can utilize them in script. Change this line:

new GuiPopUpMenuCtrl() {

to:
new GuiPopUpMenuCtrl(DebugList) {

Change this line:
   new GuiScrollCtrl() {

to:
   new GuiScrollCtrl(DebugScroll) {

Change this line:
   new GuiMessageVectorCtrl() {

to:
   new GuiMessageVectorCtrl(DebugVector) {

Now that the controls have names, we can reference them in script. Moving on, we need to restructure this a bit... we want the GuiMessageVectorCtrl to be a child of the GuiScrollCtrl, so we delete the "};" that's right before
   new GuiMessageVectorCtrl(DebugVector) {

and then add one right before
//--- OBJECT WRITE END ---

like this:
   new GuiScrollCtrl(DebugScroll) {
      profile = "GuiScrollProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "5 45";
      extent = "146 140";
      minExtent = "8 2";
      visible = "1";
      willFirstRespond = "1";
      hScrollBar = "alwaysOn";
      vScrollBar = "alwaysOn";
      constantThumbHeight = "0";
      childMargin = "0 0";
  
   new GuiMessageVectorCtrl(DebugVector) {
      profile = "GuiDefaultProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "11 50";
      extent = "122 118";
      minExtent = "8 2";
      visible = "1";
      lineSpacing = "0";
      lineContinuedIndex = "10";
      matchColor = "0 0 255 255";
      maxColorIndex = "9";
   };
};
};

Let's look at a couple of the control types we're using here that you might not have seen before: guiPopUpMenuCtrl and guiMessageVectorCtrl.

A guiPopUpMenuCtrl is what it seems: a pop-up menu. To see an example of a pop-up menu, all you have to do is click on New Control.

A guiMessageVectorCtrl is basically a text display area. We can add lines of text to it, and clear it out when we need to. Games often use these to display multiple line messages during play. For example, the message HUD in Tribes / Tribes 2 is a guiMessageVectorCtrl. The text that is displayed is called a MessageVector, and we need to create that in script. Add this function to the end of the .gui file:
function DebugGui::onWake(%this)
{
        new MessageVector(DebugText){};
        DebugVector.attach(DebugText);
        DebugList.add(None,0);
        DebugList.add(callBacks,1);
        DebugList.add(selection,2);
        $debugCount = 2;
}

The onWake function is a nice built-in GUI callback function that runs whenever a GUI starts. Notice that it has one argument, %this, so that we can reference our GUI if we need to inside the function. The fist line in our onWake function, the “new MessageVector” line, creates the MessageVector mentioned above, and names it “DebugText”. The next few lines add entries into DebugList; these will be the choices that are available when the user clicks on that pop-up menu. Next, we specify a $debugCount of 2, which is how we'll know how many choices are available in our pop-up.

Before we start testing this, we need to make sure our GUI file is executed, so add this line to exec.cs:

exec("./DebugGui.gui");

We also need to add our debugGui to the main GUI when we start up, so add this to the complexMouse function in complexMouse.cs:

        mainscreengui.add(debuggui);

like this:
function complexMouse()
{
        $test = new t2dStaticSprite() { sceneGraph = t2dScene; };
        $test.setImageMap( tileMapImageMap );
        $test.setSize( "5 5" );
        $test.setPosition( "0 0" );
        $test.isSelectable = true;
        $test.objectName = "test box";

        mainScreenGui.add(DebugGui);
}

Save your script files and fire up T2D and you should see something like this:
Image:T2D_tut_ObjSelection3_09.jpg Now click the pop-up button like this. You should be able to select the options we included, though presently it doesn't do anything. So, let's make it do something...

Close T2D down and add this function at the end of debugGui.gui:
function DebugList::onSelect(%this, %id)
{
        debugText.clear();
        for(%i=1;%i<=$debugCount;%i++)
                eval("$debugMsg::mouse::" @ %this.getTextById(%i) @ " = false;");
        
        eval("$debugMsg::mouse::" @ %this.getTextById(%id) @ " = true;");                               
}

This function is attached to our pop-up DebugList. You've probably guessed that this callback function is called when we select something out of the list. It receives the id number of the selection (the 0,1, and 2 we specified) as an argument. Let's go through this function line by line...

debugText.clear()

This clears the text out of our MessageVector, which is important because we want to start with a clean slate when we make a selection.

for(%i=1;%i<=$debugCount;%i++)
        eval("$debugMsg::mouse::" @ %this.getTextById(%id) @ " = false;");       

This line starts at 1 and loops while less than or equal to $debugCount (the number of choices in the pop-up). The function %this.getTextById() returns the text of the list item by the id. The eval function, as you probably know by now, just takes a string and executes it, in this case setting a variable. Basically this loop sets all our debug message flags to false, like this:
Loop 1: $debugMsg::mouse::callBacks = false;
Loop 2: $debugMsg::mouse::selection = false;

        eval("$debugMsg::mouse::" @  %this.getTextById(%id); @ " = true;");                     

This final line will set whichever %id we have selected to true, so if we were to click on the "selected" option in the pop-up it would do this: “$debugMsg::mouse::selection = true;”. The effect of this line in combination with the if statement is that the debug messages corresponding to the %id that the user picks, and only those debug messages will be displayed.

Save the GUI file and open up complexMouse.cs. Our next task is setting up a helper function to transmit messages to our message vector.

function registerDebug(%debug)
{
        if(%debug !$= $lastDebug)
        {
                $lastDebug = %debug;
                DebugText.pushBackLine(%debug,0);
        }
}

This function gets passed a string. We then compare that string to the last string the function received and if it's different, we do this:
                $lastDebug = %debug;
                DebugText.pushBackLine(%debug,0);

This sets $lastDebug (for the next time we check) and then uses pushBackLine to add the string we received to our message vector (DebugText). The pushBackLine takes as arguments the string to be added and a special tag entry that we won't be using. Message vectors have many useful built-in commands including this one, pushBackLine, as well as pushFrontLine, clear, and even one called dump that outputs the contents to a file. All these can be found in the T2D documentation.

This function will update the message vector, so we'll need to change all our old echo calls to registerDebug calls. The quick and easy way to do this is to use whatever “Find and Replace” functionality your text editor has to replace “echo(“ with “registerDebug(“ throughout your complexMouse.cs file. After you do this, complexMouse.cs should look like this:
function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                registerDebug("Mouse Moving");

        //store the mouse position
        $mouseObj::pos = %worldPos;

        //reset stopped to false so it checks
        $mouseObj::stopped = false;
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                registerDebug("Mouse Dragging");

        //store the mouse position
        $mouseObj::pos = %worldPos;

        //reset stopped to false so it checks
        $mouseObj::stopped = false;
}
function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                registerDebug("Mouse Down");

        //check to see if we have an object already selected, 
        //if so we don't want to do anything expect set it to false so it doesn't follow anymore
        if(%this.objectSelected)
        {
                if($debugMsg::mouse::selection)
                        registerDebug("unselecting");

                if($mouseObj::isObjMounted)
                {       
                        if(isObject($mouseObj::objMounted))
                        {
                                if($debugMsg::mouse::selection)
                                        registerDebug("dismounting object");

                                $mouseObj::objMounted.dismount();
                                $mouseObj::isObjMounted = false;
                        }
                }

                %this.objectSelected = false;
        } else
        {
                //lets get a list of all the objects at the clicked point in the t2dScene
                %objList = t2dScene.pickPoint(%worldPos);
                //lets get a count of how many objects in the list
                %objCount = getWordCount(%objList);
        
                //we will start looping through the list
                for(%i=0;%i<%objCount;%i++)
                {
                        //grabing the entry corresponding to the loop
                        %obj = getWord(%objList, %i);
                
                        //if we find an object in the list that "isSelectable = true"
        
                        if(%obj.isSelectable)
                        {
                                //we toggle a value so we know we found an object that "isSelectable"
                                %selected = true;
                                //we kick out of the loop
                                %i = %objCount;
                        }       
                }

        
                //if we found an "isSelectable" object
                if(%selected)
                {
                        //we then store that object as the selectedObj
                        %this.selectedObj = %obj;
                
                        if($debugMsg::mouse::selection)
                                registerDebug("You have selected:" SPC %obj SPC "with the name:" 
                                                        SPC %obj.objectName);

                        %this.objectSelected = true;

                        if($debugMsg::mouse::selection) 
                                registerDebug("echo attempting to mount:" SPC %obj SPC " to mouse obj:" 
                                                         SPC $mouseObj::object);
                                
                        %obj.mount($mouseObj::object, $mouseObj::mount::offset, 
                                             $mouseObj::mount::force, $mouseObj::mount::trackRotation);
                        $mouseObj::isObjMounted = true;
                        $mouseObj::objMounted = %obj;

                }
        }

}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                registerDebug("Mouse Up");
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                registerDebug("Mouse Entered... Knew it would come crawling back");
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
        if($debugMsg::mouse::callBacks)
                registerDebug("Mouse Left... Go Get It!");
}

function initMouse()
{
        $mouseObj::object = new t2dSceneObject() { scenegraph = t2dScene; };
        $mouseObj::object.setSize("1 1");
        $mouseObj::object.setLayer(31);
        $mouseObj::follow = true;
        $mouseObj::speed::max = 250;
        $mouseObj::speed::default = 250;
        $mouseObj::mount::force = 0;
        $mouseObj::mount::offset = "0 0";
        $mouseObj::mount::trackRotation = true;
}

function t2dScene::onUpdateScene(%this)
{
        if(($mouseObj::follow) && (!$mouseObj::stopped))
                mouseObjCheck();        
}

function mouseObjCheck()
{

        // Get the position of the Mouse itself
        %x = getWord($mouseObj::pos, 0);
        %y = getWord($mouseObj::pos, 1);
                
        // Get the Position of the mounted scene object
        %objPos = $mouseObj::object.getPosition();
        %objX = getWord(%objPos, 0);
        %objY = getWord(%objPos, 1);

        // calculate the distance between the two (for speed calculations)
        %dist = distBetween(%objPos, $mouseObj::pos);
        
        // Set values for easy configuration
        // set speed = distance * 20, that way it slows when approach - no bobbing around
        %speed = %dist * 20;

        // limit speed if we want to
        if(%speed > $mouseObj::speed::max)
                %speed = $mouseObj::speed::default;

        %space = 0.25;
        
        if((%objX > (%x - %space)) && (%objX < (%x + %space)) && 
            (%objY > (%y - %space)) && (%objY < (%y + %space)))
        {
                if($debugMsg::mouse::object)
                        registerDebug("object at mouse position, halting");
                $mouseObj::object.setLinearVelocityPolar(0,0);
                $mouseObj::stopped = true;
        } else
        {
                if($debugMsg::mouse::object)
                        registerDebug("object seeking mouse at " @ angleBetween(%objPos, $mouseObj::pos));
        
                //set the polar velocity towards the mouse      
                $mouseObj::object.setLinearVelocityPolar(angleBetween(%objPos, $mouseObj::pos),%speed); 
        }        

}

function angleBetween(%playerPos, %mousePos)
{
        // Seperate Mouse Position
        %mxpos = getWord(%mousePos,0);
        %mypos = getWord(%mousePos,1);

        // Seperate Player Position
        %px = getWord(%playerPos,0);
        %py = getWord(%playerPos,1);

        // Calculate Angle from player to mouse (convert to degrees).
        %angle = mRadToDeg( mAtan( %mxpos-%px, %py-%mypos ) );

        return %angle;
}

function distBetween(%loc1, %loc2)
{       
        %x1 = getWord(%loc1, 0);
        %y1 = getWord(%loc1, 1);

        %x2 = getWord(%loc2, 0);
        %y2 = getWord(%loc2, 1);

        %xd = %x2 - %x1;
        %yd = %y2 - %y1;
        
        return mSqrt((mPow(%xd,2)) + (mPow(%yd,2)));
}

function complexMouse()
{
        $test = new t2dStaticSprite() { sceneGraph = t2dScene; };
        $test.setImageMap( tileMapImageMap );
        $test.setSize( "5 5" );
        $test.setPosition( "0 0" );
        $test.isSelectable = true;
        $test.objectName = "test box";

        mainScreenGui.add(DebugGui);
}

function registerDebug(%debug)
{
        if(%debug !$= $lastDebug)
        {
                $lastDebug = %debug;
                DebugText.pushBackLine(%debug,0);
        }
}

Another thing we need to fix up is before we test this is the GUI layout. If you remember from our last test, it takes up the whole screen. Can't really test debug messages for the demo if we can't see the demo, now can we? Go into the GUI file and change the position and extent:
new GuiWindowCtrl(DebugGui) {
   profile = "GuiWindowProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "0 0";
   extent = "640 480";

to:
new GuiWindowCtrl(DebugGui) {
   profile = "GuiWindowProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "400 0";
   extent = "150 200";

Alright! save the script and the GUI file and fire up T2D. You should see this:
Image:T2D_tut_ObjSelection3_10.jpg

Select callbacks from the pop-up in your GUI, then move the mouse around and do some clicking and dragging. You'll see the text update like this.

Image:T2D_tut_ObjSelection3_11.jpg

Now change the pop-up to selection (if that's not too confusing). Click on the box, drag it around and then click to unselect it. The messageVector clears and now displays only the selection messages. This is a pretty useful little thing we set up here.

Image:T2D_tut_ObjSelection3_12.jpg

Change the pop-up to none and give it a try. Sure enough... nothin'.

Image:T2D_tut_ObjSelection3_13.jpg
So that's it... we have a cool little debug GUI. The only other thing you might add is the following line to the GuiWindowCtrl:

text = "   Debug GUI";


Image:T2D_tut_ObjSelection3_14.jpg
The final product will look like this. The system we've created in this tutorial can be quite powerful for debugging, especially as you create more debug categories to be managed. It's also nice that the debug box can be moved and minimized.

Here's the complete DebugGui.gui file:
//--- OBJECT WRITE BEGIN ---
new GuiWindowCtrl(DebugGui) {
   profile = "GuiWindowProfile";
   horizSizing = "right";
   vertSizing = "bottom";
   position = "400 0";
   extent = "150 200";
   minExtent = "8 2";
   visible = "1";
   maxLength = "255";
   resizeWidth = "1";
   resizeHeight = "1";
   canMove = "1";
   canClose = "1";
   canMinimize = "1";
   canMinimize = "1";
   canMaximize = "1";
   minSize = "50 50";
   text = "    Debug GUI"; 

   new GuiPopUpMenuCtrl(DebugList) {
      profile = "GuiPopUpMenuProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "5 24";
      extent = "113 19";
      minExtent = "8 2";
      visible = "1";
      maxLength = "255";
      maxPopupHeight = "200";
   };
   new GuiScrollCtrl(DebugScroll) {
      profile = "GuiScrollProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "5 45";
      extent = "146 140";
      minExtent = "8 2";
      visible = "1";
      willFirstRespond = "1";
      hScrollBar = "alwaysOn";
      vScrollBar = "alwaysOn";
      constantThumbHeight = "0";
      childMargin = "0 0";
  
   new GuiMessageVectorCtrl(DebugVector) {
      profile = "GuiDefaultProfile";
      horizSizing = "right";
      vertSizing = "bottom";
      position = "11 50";
      extent = "122 118";
      minExtent = "8 2";
      visible = "1";
      lineSpacing = "0";
      lineContinuedIndex = "10";
      matchColor = "0 0 255 255";
      maxColorIndex = "9";
   };
};
};
//--- OBJECT WRITE END ---

function DebugGui::onWake(%this)
{
        %c = new MessageVector(DebugText){};
        DebugVector.attach(DebugText);
        DebugList.add(None,0);
        DebugList.add(callBacks,1);
        DebugList.add(selection,2);
        $debugCount = 2;
}

function DebugList::onSelect(%this, %id)
{
        debugText.clear();
        for(%i=1;%i<=$debugCount;%i++)
                eval("$debugMsg::mouse::" @ %this.getTextById(%i) @ " = false;");
        
        eval("$debugMsg::mouse::" @ %this.getTextById(%id) @ " = true;");                       
}

Well... nice work! That concludes this final part of the Object Selection tutorial. You've learned some good techniques for coding with the mouse, and some nice GUI/debugging techniques. If you need to find further information about anything we did here, you can find just about everything in the T2D documentation and forums.