Game Development Community

Make GuiSpriteCtrl respond to touch/mouse? [solved]

by Joe Williams · in Torque 2D Beginner · 05/05/2013 (8:04 am) · 4 replies

I want to use my own art for touch controls for my game. I have a sprite control appearing in the game properly, but it isn't responding to the touch at all. Any ideas? Here is the relevant code.

iOSGameUI.gui.taml file:
<GuiSpriteCtrl
    Name="iOSGameUI"
    Profile="GuiDirectionalUI"
    HorizSizing="relative"
    VertSizing="relative"
    Position="200 200"
    Extent="171 171"
    MinExtent="60 60"
    Visible="1"
    Active="1"
    useMouseEvents="1"
    class="moveCircle"
    Image="@asset=CFD:DirectionalUI"/>

Game create function:
function CFD::create( %this )
{
    // Activate the package.
    activatePackage( CFDPackage );
   
    exec("./gui/guiProfiles.cs");
    
    //allow objects to interact with inputs
    SandboxWindow.UseObjectInputEvents = true;
    
    CFD.add( TamlRead("./gui/iOSGameUI.gui.taml") );
    SandboxWindow.add(iOSGameUI);
    iOSGameUI.onTouchUp( 0, "0 0" );
}

Touch callbacks:
function moveCircle::onTouchDown( %this, %touchID, %worldPosition )
{
   echo( "Move Circle Touched!" );
   %this.myTouchID = %touchID;
   %angleMod = mFloor( ( Vector2AngleToPoint ( %this.getPosition(), %worldPosition ) + 22.5 ) / 45 ) % 8;
   
   %this.setImageFrame( %angleMod );
}

function moveCircle::onTouchUp( %this, %touchID, %worldPosition )
{  
   %this.setImageFrame( 8 );
}

When the game starts, the frame is set to 8, so I know the control class is set properly and that it's responding to function calls. It just isn't responding to the mouse or touch at all. What am I missing?

I should mention that the GuiDirectionalUI profile is just a blank profile in guiProfiles.cs. I'm not sure if I need anything in there or not.

(Given my track record, I'll figure this out shortly after posting this.)

Update: The new SceneWindow.addInputListener( %obj ) function solved this for me. So any scene object, it appears, can be added as a listener so that the input callbacks will work with it. One thing to note is that Gui controls don't use positioning the same way, though. So comparing a Gui control's position against the %worldPosition parameter of an input callback won't work.

Further update: There is a 100 pixel difference (at 800 x 600) between where the Gui control is and where the window recognizes touch to be. Also, adding something as an input listener means it will respond any time the screen/window is touched/clicked, not just when the control is touched/clicked. All of this means the following:
1. Get the window coordinates based on world position, like this (using Sandbox as example): %windowCoords = SandboxWindow.getWindowPoint( %worldPosition )
2. Subtract 100 to the window point coordinates like this: %windowCoords = %windowCoords.x - 100 SPC %windowCoords.y - 100
3. Limit your control's callback based on the %windowCoords being within its bounds with something like this:
function guiControl::inRange( %this, %windowCoords ) //assumes %windowCoords already adjusted - 100
{
   %xMax = %this.getPosition().x + %this.getExtent().x / 2;
   %xMin = %this.getPosition().x - %this.getExtent().x / 2;
   %yMax = %this.getPosition().y + %this.getExtent().y / 2;
   %yMin = %this.getPosition().y - %this.getExtent().y / 2;
   
   if( %windowCoords.x < %xMax && %windowCoords.x > %xMin && %windowCoords.y < %ymax && %windowCoords.y > %yMax )
   {
      return true;
   {

   return false;
}

function guiControl::onTouchDown( %this, %touchID, %worldPostiion )
{
   %windowCoords = SandboxWindow.getWindowPoint( %worldPosition );
   %windowCoords = %windowCoords.x - 100 SPC %windowCoords.y - 100;
   if( %this.inRange( %windowCoords )
   {
      //touch response code here
   }
}

#1
05/05/2013 (8:37 am)
Is there a gui above it? If that's not it, how about trying makeFirstResponder() (no clue what it does).
#2
05/05/2013 (8:55 am)
Thanks for the suggestion. There isn't anything above the control in the TAML file or in the scene, and I think makeFirstResponder is just a way to ensure that the control is the first to act when clicked/touched. That isn't a problem with my current setup.
#3
05/05/2013 (11:10 am)
Except for the SceneWindow, GuiControls do not respond to onTouchDown, they respond to onMouseDown.

function My_GUI_Control::onMouseDown(%this, %modifier, %worldPos, %mouseClicks)
{
}

%modifier will list all modifier keys being held down (Shift, ctrl, etc.)

%worldPos is the position of the mouse click

%mouseclicks determines how many clicks occured so you can easily detect double-clicks with this.

I can't test iOS functionality as I don't have an iDevice but I've looked at the code and don't see anything that seems to contradict my theory.
#4
05/05/2013 (11:16 am)
That doesn't seem to work, either. I changed the touchdown code to this

function moveCircle::onMouseDown( %this, %modifier, %worldPos, %mouseClicks )  
{  
   echo( "Move Circle Touched!" );  
   //%this.myTouchID = %touchID;  
   %angleMod = mFloor( ( Vector2AngleToPoint ( %this.getPosition(), %worldPos ) + 22.5 ) / 45 ) % 8;  
     
   %this.setImageFrame( %angleMod );  
}

but it still doesn't respond.

Anyone have any other ideas? I could modify the touch functions of the scene window, but I'd prefer to keep this as simple and intuitive as possible.