Results 1 to 9 of 9
  1. #1
    The Sacrifice
    Join Date
    Jul 2010
    Posts
    288

    Default Documentation for making list after february version

    So I have been following the examples in the documentation to make a list-menu: http://udn.epicgames.com/Three/Mobil...icalGuide.html
    After fixing (or at least got rid of) nearly 100 syntax errors due to the changes in unrealscript made in the february version, it still won't work. Are there any plans to update the documentation?
    It's basicly the changes made to the touch functions that is confusing me. I just added the nessescary parameters needed to get rid of the syntax errors, but I do not really use or do know how to use them. I guess I have to, since nothing happens on touch.

    Scaleform is not an option for us at the momment.
    Last edited by TheBuilder; 06-22-2012 at 11:11 PM.

  2. #2
    Technical Writer - UDN
    Join Date
    Aug 2006
    Posts
    3,928
    Gamer IDs

    Gamertag: ffejnosliw

    Default

    Yeah, the example was pretty dated. I'm not sure if or when we will have time to update it. I removed it for nowadays it does t cause issues for people in the future. Hopefully we will be able to get to it at some point.

  3. #3
    The Sacrifice
    Join Date
    Jul 2010
    Posts
    288

    Default

    Crap, I should have taken backup before you removed it (At least it lead me to the right directions)

    I regret making this thread...
    Last edited by TheBuilder; 06-23-2012 at 03:27 PM.

  4. #4
    Technical Writer - UDN
    Join Date
    Aug 2006
    Posts
    3,928
    Gamer IDs

    Gamertag: ffejnosliw

    Default

    I'll post it here for you. I just didn't want more people to find it in the docs and expect it to just work.

    Outdate List example:


    Custom Input Menu Example

    Making a menu and controls that go beyond the basic buttons, images, and labels can be done with a little creativity. This example will demonstrate creating custom controls that handle input themselves, instead of leaving all input handling up to the scene, including a scrolling list as well as a combobox and a new button and label. These controls will all extend from a new base control class that implements a custom interface which allows them to easily be passed input from the scene, which will itself be a new custom scene class.

    Basic Touchable Controls

    The custom touchable controls rely on the scene to pass all input events on to its controls. In turn, each control either handles the input itself, passes it on to any children controls, or a combination of the two.

    Before we jump into implementing the new controls, you may be wondering, "Why would I want the controls to handle input?" This is a good question, and it really comes down to the kind of functionality you need from your menu scenes and controls. In this case, we will be creating complex controls that are essentially containers for other sub-controls. In such a case, it is very beneficial for the controls to be able to determine whether they have been touched and react to the input accordingly. A crucial factor is the ability for a button to notify its parent when it has been clicked and allow the parent to perform a specific action based on that. If this were not possible, all of the logic for doing complex interactions between controls would have to be located in the scene itself, which would drastically limit the usefulness of creating complex controls like lists. You would essentially be re-implementing the entire list logic every time you wanted to use a list.

    Code:
    ITouchable Interface
    The first step to creating the new touchable controls involves creating the interface that will be implemented by any custom control which wants to be given input. This interface is extremely simple, declaring a single function.

    Code:
    Interface ITouchable;
    
    function OnTouch(EZoneTouchEvent Type, float X, float Y);
    The OnTouch function here mimics the OnSceneTouch() function from the MobileMenuScene class, allowing that function to simply pass on the touch input data to any control which implements this ITouchable interface.

    Scene Classes

    We have to pull a little trickery off to get full access to generic touch events. A new base scene class with no width or height is created to handle passing the input on to the actual scene through a new delegate. The actual scene class opens a new base scene as a helper scene when it is opened and assigns its OnSceneTouch() function to the base scene's delegate. It then takes the input from the OnSceneTouch() function and passes it on to any touchable controls. All scenes which use touchable controls will then extend from this class and automatically have the functionality for handling those controls ready to go.

    Input Handling

    The general idea behind passing the input is the scene class will receive notification of all touch input events through its OnSceneTouch() function. Inside this function, the list of all controls belonging to the scene, the MenuObjects array, will be iterated casting each item in the array to the ITouchable interface. If the cast succeeds, the control is touchable and the input is passed to that control using the OnTouch() function inherited from the interface. In addition, some basic swipe detection is performed here so that any control can quickly query the owner scene to see if the input is a swipe or a tap, without being required to re-implement this functionality in each control where it is needed.

    List Handling

    The base scene class also references a new control class, the UDNMobileMenuList. This class does not exist yet, but once created it will be used to display scrolling lists of items. Any visible list will always be fullscreen and needs to be overlaid on top of any other controls within the scene. Because the controls are all rendered in order and there is no way to know which controls might want to display lists at some point, the only way to guarantee this is to let the scene handle the rendering of any list and have any control using a list assign their list to the scene when necessary.

    Helper Scene Class

    Code:
    class UDNMobileMenuBase extends MobileMenuScene;
    
    
    /**
     * Delegate fired when generic touch occurs (outside the scene)
     */
    delegate bool OnInputTouch(EZoneTouchEvent EventType, float TouchX, float TouchY);
    
    /**
     * Called when touch input occurs
     */
    function bool OnSceneTouch(EZoneTouchEvent EventType, float TouchX, float TouchY)
    {
       OnInputTouch(EventType, TouchX, TouchY);
       
       return true;   
    }
    
    defaultproperties
    {
    }
    Real Scene Class

    Code:
    class UDNMobileMenuScene extends MobileMenuScene;
    
    /** Cached location of the initial touch event */
    var Vector StartTouchLocation;
    
    /** Current location of the last touch update event */
    var Vector CurrentTouchLocation;
    
    /** TRUE if the current touch is a swipe */
    var bool bSwipe;
    
    /** Minimum distance a touch must move to be a swipe. Less than this, it is a tap. */
    var float SwipeTolerance;
    
    /** Used to allow combo boxes to display their lists overlaid over all controls */
    var instanced UDNMobileMenuList List;
    
    var UDNMobileMenuBase HelperScene;
    
    
    function Opened(string Mode)
    {
       Super.Opened(Mode);
       
       //open new base scene - has no width or height so can get generic touch events
       HelperScene = UDNMobileMenuBase(InputOwner.OpenMenuScene(class'UDNMobileMenuBase'));
       
       //Assign our handler to the input delegate of the base scene
       HelperScene.OnInputTouch = OnSceneTouch;
    }
    
    function Closing()
    {
       //Cleanup - close the helper scene before closing this scene
       if(HelperScene != none)
       {
          InputOwner.CloseMenuScene(HelperScene);
       }
    
       Super.Closing();
    }
    
    function bool OnSceneTouch(EZoneTouchEvent EventType, float TouchX, float TouchY)
    {
       local MobileMenuObject Touchable;
       
       //initial touch event
       if(EventType == ZoneEvent_Touch)
       {
          //Clear swipe
          bSwipe = false;
          
          //Cache touch location
          StartTouchLocation.X = TouchX;
          StartTouchLocation.Y = TouchY;
       }
       //touch update event
       else if(EventType == ZoneEvent_Update)
       {      
          //Save current touch location
          CurrentTouchLocation.X = TouchX;
          CurrentTouchLocation.Y = TouchY;
          
          //See if this touch is a swipe
          CheckSwipe();
       }
    
       //if our list isn't displayed, pass input to touchable controls
       if(List == none || List.bIsHidden)
       {
          foreach MenuObjects(Touchable)
          {   
             if(ITouchable(Touchable) != none)
             {
                ITouchable(Touchable).OnTouch(EventType, TouchX, TouchY);
             }
          }   
       }
       //if the list is visible, pass touch input to it
       else if(List != none && !List.bIsHidden)
       {
          ITouchable(List).OnTouch(EventType, TouchX, TouchY);
       }
       
       //return true to acknowledge we handled the input
       return true;
    }
    
    function CheckSwipe()
    {
       //check if the touch moved enough to be a swipe
       if(VSize(StartTouchLocation - CurrentTouchLocation) > SwipeTolerance)
       {
          bSwipe = true;
       }   
    }
    
    function RenderScene(Canvas Canvas,float RenderDelta)
    {
       //Draw the list if it is visible
       if(List != none && !List.bIsHidden)
       {
          List.RenderObject(Canvas);
       }
       //Draw our controls if no list
       else
       {
          Super.RenderScene(canvas, RenderDelta);
       }
    }
    
    defaultproperties
    {
       SwipeTolerance = 5.0
    }
    Base Touchable Control Class

    The base touchable control class extends the base MobileMenuObject control class; implementing the new ITouchable interface and adding a couple helper functions for checking if the location of a touch is within its bounds and finding out if the current touch is a swipe from the owner scene. It also must define the OnTouch() function declared in the ITouchable interface. The base implementation of this function simply checks the input to see whether the control is being touch and sets the bIsTouched and bIsHighlighted variables accordingly.

    Code:
    class UDNMobileMenuObject extends MobileMenuObject
       implements(ITouchable) DependsOn(UDNMobileMenuBase);
    
       
    function OnTouch(EZoneTouchEvent Type, float X, float Y)
    {   
       if(bIsActive)
       {
          if(CheckBounds(X, Y))
          {
             if(Type == ZoneEvent_Touch)
             {
                bIsTouched = true;
                bIsHighlighted = true;
             }
             else if(Type == ZoneEvent_Untouch || Type == ZoneEvent_Cancelled)
             {
                bIsTouched = false;
                bIsHighlighted = false;
             }
          }
          else
          {
             bIsTouched = false;
             bIsHighlighted = false;
          }
       }
    }
    
    function bool CheckBounds(float X, float Y)
    {
       if(X >= Left && X <= Left + Width && Y >= Top && Y <= Top + Height)
       {
          return true;
       }
       
       return false;
    }
    
    function bool CheckSwipe()
    {
       return UDNMobileMenuScene(OwnerScene).bSwipe;
    }
    Custom Label

    The touchable label control is a modified version of the standard MobileMenuButton and MobileMenuLabel classes. The code for those classes was merged into the new class and then modified to add some additional rendering functionality, such as simple box and border background visual components and the ability to align the caption text.

    Code:
    class UDNMobileMenuLabel extends UDNMobileMenuObject;
       
    
    /** The 2 images that make up the label. [0] = the untouched, [1] = touched */
    var Texture2D Images[2];
    
    /** The UV Coordinates for the images. [0] = the untouched, [1] = touched */
    var UVCoords ImagesUVs[2];
    
    /** Holds the color override for the image */
    var LinearColor ImageColors[2];
    
    /** Localizable caption for the label */
    var string Caption;
    
    /** Holds the color for the caption */
    var LinearColor CaptionColors[2];
    
    /** Holds the font that will be used to draw the text */
    var font TextFont;
    
    /** If TRUE, center the text in the label. Otherwise, left align it. */
    var bool bCenterText;
    
    /** If TRUE, the label text will not wrap */
    var bool bClipText;
    
    /** Number of pixels to pad text when not centering text */
    var float TextPadding;
    
    /** Colors to use to draw the background of the label. Used if no texture is specified */
    var LinearColor BackgroundColors[2];
    
    /** Colors to use to draw the borders of the label. Used if no texture is specified. */
    var LinearColor BorderColors[2];
    
    /** Widths of the four borders. (Order: Top, Right, Bottom, Left) */
    var float BorderWidth[4];
    
    /** If TRUE, use DrawTileStretched() to draw the label image. Otherwise, use DrawTile(). */
    var bool bStretchBackground;
    
    
    /**
     * Initialize label - Setup image coords
     */
    function InitMenuObject(MobilePlayerInput PlayerInput, MobileMenuScene Scene, int ScreenWidth, int ScreenHeight)
    {
       local int i;
       
       Super.InitMenuObject(PlayerInput, Scene, ScreenWidth, ScreenHeight);
    
       //No custom coords, set to full size of image
       for (i=0;i<2;i++)
       {
          if (!ImagesUVs[i].bCustomCoords && Images[i] != none)
          {
             ImagesUVs[i].U = 0.0f;
             ImagesUVs[i].V = 0.0f;
             ImagesUVs[i].UL = Images[i].SizeX;
             ImagesUVs[i].VL = Images[i].SizeY;
          }
       }
    }
    
    
    /**
     * Render the widget
     */
    function RenderObject(canvas Canvas)
    {
       local int Idx;
       local LinearColor DrawColor;
    
       //Get image/color index based on if the label is being touched or highlighted
       Idx = (bIsTouched || bIsHighlighted) ? 1 : 0;
       
       //If there is an image set, draw it
       if(Images[Idx] != none)
       {   
          //Set up Canvas for drawing the background image
          Canvas.SetPos(OwnerScene.Left + Left - Canvas.OrgX, OwnerScene.Top + Top - Canvas.OrgY);
          Drawcolor = ImageColors[Idx];
          Drawcolor.A *= Opacity * OwnerScene.Opacity;
          
          //Draw background image stretched
          if(bStretchBackground)
          {
             Canvas.DrawTileStretched(Images[Idx], Width, Height,ImagesUVs[Idx].U, ImagesUVs[Idx].V, ImagesUVs[Idx].UL, ImagesUVs[Idx].VL, DrawColor, true, true);
          }
          //Draw background image scaled
          else
          {
             Canvas.DrawTile(Images[Idx], Width, Height,ImagesUVs[Idx].U, ImagesUVs[Idx].V, ImagesUVs[Idx].UL, ImagesUVs[Idx].VL, DrawColor, true);
          }
       }
       //No image set, draw simple rect background
       else
       {
          //Set up Canvas for drawing the background rect
          Canvas.SetPos(OwnerScene.Left + Left - Canvas.OrgX, OwnerScene.Top + Top - Canvas.OrgY);
          Canvas.DrawColor.R = byte(BackgroundColors[Idx].R * 255.0);
          Canvas.DrawColor.G = byte(BackgroundColors[Idx].G * 255.0);
          Canvas.DrawColor.B = byte(BackgroundColors[Idx].B * 255.0);
          Canvas.DrawColor.A = byte(BackgroundColors[Idx].A * 255.0);
          Canvas.DrawRect(Width, Height);
          
          //Draw border
          DrawBorder(Canvas);
       }
    
       //Draw caption text
       RenderCaption(Canvas);
    }
    
    /**
     * Draw the label's border
     *
     * @param Canvas - Canvas object used for drawing
     */
    function DrawBorder(Canvas Canvas)
    {
       local int Idx;
       
       Idx = (bIsTouched || bIsHighlighted) ? 1 : 0;
       
       //Draw top border
       if(BorderWidth[0] > 0)
       {
          Canvas.SetPos(Left - Canvas.OrgX, Top - Canvas.OrgY);
          Canvas.DrawColor.R = byte(BorderColors[Idx].R * 255.0);
          Canvas.DrawColor.G = byte(BorderColors[Idx].G * 255.0);
          Canvas.DrawColor.B = byte(BorderColors[Idx].B * 255.0);
          Canvas.DrawColor.A = byte(BorderColors[Idx].A * 255.0);
          Canvas.DrawRect(Width, BorderWidth[0]);
       }
       
       //Draw right border
       if(BorderWidth[1] > 0)
       {
          Canvas.SetPos(Left + Width - 1 - Canvas.OrgX, Top + Height - 1 - Canvas.OrgY);
          Canvas.DrawColor.R = byte(BorderColors[Idx].R * 255.0);
          Canvas.DrawColor.G = byte(BorderColors[Idx].G * 255.0);
          Canvas.DrawColor.B = byte(BorderColors[Idx].B * 255.0);
          Canvas.DrawColor.A = byte(BorderColors[Idx].A * 255.0);
          Canvas.DrawRect(BorderWidth[1], Height);
       }
       
       //Draw bottom border
       if(BorderWidth[2] > 0)
       {
          Canvas.SetPos(Left - Canvas.OrgX, Top + Height - 1 - Canvas.OrgY);
          Canvas.DrawColor.R = byte(BorderColors[Idx].R * 255.0);
          Canvas.DrawColor.G = byte(BorderColors[Idx].G * 255.0);
          Canvas.DrawColor.B = byte(BorderColors[Idx].B * 255.0);
          Canvas.DrawColor.A = byte(BorderColors[Idx].A * 255.0);
          Canvas.DrawRect(Width, BorderWidth[2]);
       }
       
       //Draw left border
       if(BorderWidth[3] > 0)
       {
          Canvas.SetPos(Left - Canvas.OrgX, Top - Canvas.OrgY);
          Canvas.DrawColor.R = byte(BorderColors[Idx].R * 255.0);
          Canvas.DrawColor.G = byte(BorderColors[Idx].G * 255.0);
          Canvas.DrawColor.B = byte(BorderColors[Idx].B * 255.0);
          Canvas.DrawColor.A = byte(BorderColors[Idx].A * 255.0);
          Canvas.DrawRect(BorderWidth[3], Height);
       }
    }
    
    /**
     * Draw the label's text
     *
     * @param Canvas - Canvas object used for drawing
     */
    function RenderCaption(canvas Canvas)
    {
       local float X,Y,UL,VL;
       local FontRenderInfo FRI;
       local int Idx;
       
       Idx = (bIsTouched || bIsHighlighted) ? 1 : 0;
    
       //Only draw if some text is set
       if (Caption != "")
       {
          Canvas.Font = TextFont;
          Canvas.TextSize(Caption,UL,VL);
    
          //Center text if necessary, left-align otherwise
          if(bCenterText)
          {
             X = Left + (Width / 2) - (UL/2);
             Y = Top + (Height /2) - (VL/2);
          }
          else
          {
             X = Left + 5;
             Y = Top + (Height /2) - (VL/2);
          }
    
          //Set up Canvas for drawing caption
          Canvas.SetPos(OwnerScene.Left + X - Canvas.OrgX, OwnerScene.Top + Y - Canvas.OrgY);
          Canvas.DrawColor.R = byte(CaptionColors[Idx].R * 255.0);
          Canvas.DrawColor.G = byte(CaptionColors[Idx].G * 255.0);
          Canvas.DrawColor.B = byte(CaptionColors[Idx].B * 255.0);
          Canvas.DrawColor.A = byte(CaptionColors[Idx].A * 255.0);
    
          //Draw text - clip if desired
          FRI.bClipText = bClipText;
          Canvas.DrawText(Caption, false, 1.0, 1.0, FRI);
       }
    }
    
    defaultproperties
    {
       ImageColors(0)=(r=1.0,g=1.0,b=1.0,a=1.0)
       ImageColors(1)=(r=0.5,g=0.5,b=0.5,a=1.0)
       CaptionColors(0)=(r=0.0,g=0.0,b=0.0,a=1.0)
       CaptionColors(1)=(r=1.0,g=1.0,b=1.0,a=1.0)
       
       bIsActive=false
       bCenterText=false
       bStretchBackground=true
       
       BorderWidth(0)=0
       BorderWidth(1)=0
       BorderWidth(2)=0
       BorderWidth(3)=0
    }
    Touchable Button

    The touchable button control is a simple extension of the UDNMobileMenuLabel class which overrides the OnTouch() function to add tap detection and call a new OnClick delegate to alert any listeners that the button has been "clicked".

    Code:
    class UDNMobileMenuButton extends UDNMobileMenuLabel;
       
    
    /** 
     * Delegate called when the button receives a tap 
     */
    delegate OnClick(UDNMobileMenuObject Sender, float X, float Y);
    
    /**
     * Implementation of the OnTouch() member of the ITouchable interface.
     * Called when the parent receives a touch event.
     *
     * @param Type - type of touch event
     * @param X - Horizontal location of touch event
     * @param Y - Vertical location of touch event
     */
    function OnTouch(EZoneTouchEvent Type, float X, float Y)
    {
       Super.OnTouch(Type, X, Y);
       
       //touch ending within the button bounds, fire OnClick delegate to alert listeners of a tap
       if(Type == ZoneEvent_Untouch && CheckBounds(X, Y))
       {
          OnClick(self, X, Y);
       }
    }
    
    defaultproperties
    {
       bIsActive=true
       bCenterText=true
    }
    Last edited by ffejnosliw; 06-23-2012 at 04:06 PM.

  5. #5
    Technical Writer - UDN
    Join Date
    Aug 2006
    Posts
    3,928
    Gamer IDs

    Gamertag: ffejnosliw

    Default

    Scrolling List

    The scrolling list class attempts to create a new control which behaves similar to the standard list controls found in iOS interfaces. It is a list of items, each one a UDNMobileMenuButton, which can be scrolled up or down using touch input. Swiping will cause the list to continue to move for a bit after the touch ends exhibiting an "inertial" scrolling behavior. These lists must always be fullscreen because of the limitations of clipping text, i.e. it can only be clipped by the extents of the viewport.

    Code:
    class UDNMobileMenuList extends UDNMobileMenuObject;
       
    /** text to display as the title of the list. */
    var string Title;   
    
    /** Color to use for drawing the title text */
    var Color CaptionColor;
    
    /** If TRUE, center the caption text. otherwise, left align it */
    var bool bCenterText;
       
    /** Color to use for filling the list background */
    var Color BackgroundColor;
    
    /** Color to use for the list border */
    var Color BorderColor;
    
    /** Colors to use for drawing the background of the list items. [0] is for non-selected items. [1] is for the selected item. */
    var LinearColor ItemBackgroundColors[2];
    
    /** Colors to use for drawing the border of the list items. [0] is for non-selected items. [1] is for the selected item. */
    var LinearColor ItemBorderColors[2];
    
    /** Colors to use for drawing the text of list items. [0] is for non-selected items. [1] is for the selected item. */
    var LinearColor ItemCaptionColors[2];
    
    /** Font to use for drawing list item text. */
    var Font ItemFont;
    
    /** Reference to the Cancel button used to close the list */
    var instanced UDNMobileMenuButton Cancel;
    
    /** If TRUE, the list be be cancelable (i.e., the Cancel button will be displayed) */
    var bool bHasCancel;
    
    /** The list of items belonging to the menu */
    var instanced array<UDNMobileMenuButton> Items;
    
    /** Index of the currently selected item */
    var int SelectedIndex;
    
    /** Height of each item cell in the list */
    var float ItemHeight;
    
    /** Height of the title bar */
    var float TitleBarHeight;
    
    /** Color of the title bar */
    var Color TitleBarColor;
    
    /** TRUE when the list is being controlled, i.e. when the user is actively scrolling the list. */
    var bool bActive;
    
    /** Holds the cached location of the last touch event for the list */
    var vector LastTouchLocation;
    
    /** The amount to scroll the list while active. (This is the delta between touch updates. It keeps the list in sync with the user's finger.) */
    var float ScrollAmount;
    
    /** The amount to scroll the list when inactive. (This is how much stored velocity the list has from a swipe.) */
    var float ScrollInertia;
    
    /** Holds the cached time of the last render update. */
    var float LastRenderTime;
    
    /** Multiplier for the touch movement used to control the ScrollInertia. */
    var float SwipeFactor;
    
    /** Multiplier for the speed at which the list snaps back when scrolled past its bounds. */
    var float SnapFactor;
    
    /** Distance past the list's bounds it can be actively scrolled. */
    var float ScrollLimit;
    
    
    /****************************************
    * Init and Rendering Functions
    ****************************************/
    
    /**
     * Initialize the list
     */
    function InitMenuObject(MobilePlayerInput PlayerInput, MobileMenuScene Scene, int ScreenWidth, int ScreenHeight)
    {   
       Super.InitMenuObject(PlayerInput, Scene, ScreenWidth, ScreenHeight);
       
       //Force list to the size of the device's screen since text can't be easily clipped by the list's bounds 
       Left = 0;
       Top = 0;
       Width = ScreenWidth;
       Height = ScreenHeight;
       
       //initialize the Cancel button (the menu system has no built-in handling for controls within controls)
       Cancel.InitMenuObject(PlayerInput, Scene, ScreenWidth, ScreenHeight);
       
       //Position the Cancel button vertically centered on the right of the title bar
       Cancel.Top = Top + ((TitleBarHeight - Cancel.Height) / 2);
       Cancel.Left = Left + Width - Cancel.Width - 1;
       
       //Grab click events from the button
       Cancel.OnClick = HandleCancel;
    }
    
    /**
     * Draw the list
     */
    function RenderObject(canvas Canvas)
    {
       local int i;
       local float DeltaTime;
       local float ScrollDelta;
       
       Canvas.SetPos(Left, Top);
       
       //Draw the list's background
       Canvas.DrawColor = BackgroundColor;
       Canvas.DrawRect(Width, Height);
       
       //Calculate the render delta to use for passively scrolling the list
       if(LastRenderTime != 0)
       {
          DeltaTime = InputOwner.Outer.WorldInfo.RealTimeSeconds - LastRenderTime;
       }
       lastRenderTime = InputOwner.Outer.WorldInfo.RealTimeSeconds;   
       
       if(Items.Length > 0)
       {
          //Calculate scroll delta for this render pass and snap the list back if outside the list bounds
          if(Items[0].Top > Top + TitleBarHeight)
          {
             ScrollInertia = Top + TitleBarHeight - Items[0].Top;
             ScrollDelta = ScrollInertia * DeltaTime * SnapFactor;
          }
          else if(Items[Items.Length - 1].Top + ItemHeight < Top + Height)
          {
             ScrollInertia = (Top + Height) - (Items[Items.Length - 1].Top + ItemHeight);
             ScrollDelta = ScrollInertia * DeltaTime * SnapFactor;
          }
          else
          {      
             ScrollDelta = ScrollInertia * DeltaTime;
          }
          
          //render each list item
          for(i=0; i < Items.Length; i++)
          {
             //force item size here in case orientation changes
             Items[i].Left = left;
             Items[i].Top += bActive ? ScrollAmount : ScrollDelta;
             Items[i].Width = Width;
             Items[i].Height = ItemHeight;
             
             //Only render item if part of it is visible
             if(Items[i].Top + ItemHeight > Top && Items[i].Top < Top + Height)
             {
                Items[i].RenderObject(Canvas);
             }
          }
       }
       
       if(bActive)
       {
          //Zero out active scroll if active
          ScrollAmount = 0;
       }
       else
       {
          //decrement scroll inertia if passive
          ScrollInertia -= ScrollDelta;
       }
       
       //Draw title bar - we draw after the list items so they are clipped by it
       Canvas.SetPos(Left, Top);   
       Canvas.DrawColor = TitleBarColor;
       Canvas.DrawRect(Width, TitleBarHeight);
       
       //Draw title
       RenderTitle(Canvas);
       
       //Draw list border
       Canvas.SetPos(Left, Top + TitleBarHeight);   
       Canvas.DrawColor = BorderColor;
       Canvas.DrawBox(Width, Height - TitleBarHeight);
       
       //Drawn Cancel button if desired
       if(bHasCancel)
       {
          Cancel.RenderObject(Canvas);
       }
    }
    
    /**
     * Draw the list's title text
     */
    function RenderTitle(canvas Canvas)
    {
       local float X,Y,UL,VL;
       local FontRenderInfo FRI;
    
       //don't bother if there is no title
       if (Title != "")
       {
          //set font (we're just borrowing the scene font. Could add custom font)
          Canvas.Font = OwnerScene.SceneCaptionFont;
          Canvas.TextSize(Title,UL,VL);
    
          //Calculate position - Centered or Left-aligned
          if(bCenterText)
          {
             X = Left + (Width / 2) - (UL/2);
             Y = Top + (Height /2) - (VL/2);
          }
          else
          {
             X = Left + (TitleBarHeight /2) - (VL/2);
             Y = Top + (TitleBarHeight /2) - (VL/2);
          }
    
          //Draw title text clipped (Could add ability to shorten if it won't fit, i.e. use ...)
          Canvas.SetPos(OwnerScene.Left + X - Canvas.OrgX, OwnerScene.Top + Y - Canvas.OrgY);
          Canvas.DrawColor = CaptionColor;
          FRI.bClipText = true;
          Canvas.DrawText(Title, false, 1.0, 1.0, FRI);
       }
    }
    
    /****************************************
    * Item Management Functions
    ****************************************/
    
    /**
     * Add a new item to the list
     *
     * @param item - the value of the new item to add
     */
    function AddItem(string item)
    {
       local UDNMobileMenuButton NewItem;
       local Vector2D ViewportSize;
       
       //Create a new item (a button)
       NewItem = new(Outer) class'UDNMobileMenuButton';
       
       if(NewItem != none)
       {
          //initialize the new item
          LocalPlayer(InputOwner.Outer.Player).ViewportClient.GetViewportSize(ViewportSize);
          NewItem.InitMenuObject(InputOwner, OwnerScene, ViewportSize.X, ViewportSize.Y);
          
          //Set new item properties
          NewItem.Caption = item;
          NewItem.CaptionColors[0] = ItemCaptionColors[0];
          NewItem.CaptionColors[1] = ItemCaptionColors[1];
          NewItem.TextFont = ItemFont;
          NewItem.Left = Left;
          NewItem.BackgroundColors[0] = ItemBackgroundColors[0];
          NewItem.BackgroundColors[1] = ItemBackgroundColors[1];
          NewItem.BorderColors[0] = ItemBorderColors[0];
          NewItem.BorderColors[1] = ItemBorderColors[1];
          NewItem.Top = Top + TitleBarHeight + (Items.Length * ItemHeight);
          NewItem.OnClick = OnSelect;
          NewItem.bCenterText = false;
          NewItem.BorderWidth[2] = 1;
          
          //If this is to be the selected item, highlight it
          if(Items.Length == SelectedIndex)
          {
             NewItem.bIsHighlighted = true;
          }
          
          //Add the item to the list
          Items.AddItem(NewItem);
       }
    }
    
    /**
     * Remove a value from the list
     * 
     * @param Idx - the index of the item to remove
     */
    function RemoveItem(int Idx)
    {
       local int i;
       
       //remove the item from the list
       Items.Remove(Idx, 1);
       
       //shift subsequent items up
       for(i=Idx; i < Items.Length; i++)
       {
          Items[i].Top -= ItemHeight;
       }
       
       //If we removed the selected item, reset selection to first item
       if(SelectedIndex == Idx)
       {
          SelectedIndex = 0;
          if(Items.Length > 0)
          {
             Items[0].bIsHighlighted = true;
          }
       }
    }
    
    /**
     * Get the value of the list.
     *
     * Returns the caption of the selected item
     */
    function string GetValue()
    {
       //must have items to access selected index
       if(Items.Length > 0)
       {
          //return the caption (value) of the selected item
          return Items[SelectedIndex].Caption;
       }
       else
       {
          //no items - return empty string
          return "";
       }
    }
    
    /****************************************
    * Input Functions
    ****************************************/
       
    /**
     * Delegate fired when an item is selected in the list
     */
    delegate OnChange(int Idx, string Item, float X, float Y);
    
    /**
     * Delegate fired when the list is canceled
     */
    delegate OnCancel();
    
    /**
     * Implementation of the ITouchable interface
     */
    function OnTouch(EZoneTouchEvent Type, float X, float Y)
    {
       local UDNMobileMenuButton Label;
       local float ActualY;
       
       Super.OnTouch(Type, X, Y);
       
       //Initial touch event
       if(Type == ZoneEvent_Touch)
       {
          //Ignore if touch is outside list or in title bar
          if(CheckBounds(X, Y) && Y > Top + TitleBarHeight)
          {
             //set list active - user is controlling it
             bActive = true;
             
             //Cache touch location
             LastTouchLocation.X = X;
             LastTouchLocation.Y = y;
             
             //reset scroll values
             ScrollAmount = 0;
             ScrollInertia = 0;
          }
       }
       //Touch in progress
       else if(Type == ZoneEvent_Update || Type == ZoneEvent_Stationary)
       {
          //Ignore if the list is not active - touch must have started outside the list
          if(bActive)
          {
             /************************************************************
             *   We only update scrolling if:
             *
             *    * There are enough items to require scrolling
             *    * The list is not scrolled outside the bounds already
             *    
             ************************************************************/
             if(   (Items.Length * ItemHeight > Height) && 
                ((Items[0].Top - (Top + TitleBarHeight) < ScrollLimit) || (Y < LastTouchLocation.Y)) && 
                (((Top + Height) - (Items[Items.Length - 1].Top + ItemHeight) < ScrollLimit) || (Y > LastTouchLocation.Y)))
             {
                //Actual inertia is scaled by device scaling and custom swipe factor to get used inertia
                ActualY = (Y - LastTouchLocation.Y) * class'MobileMenuScene'.static.GetGlobalScaleY() * SwipeFactor;
                
                //Reset scroll inertia if the movement is negligible. Otherwise, increment it with new delta.
                if(Abs(ActualY) < UDNMobileMenuScene(OwnerScene).SwipeTolerance)
                {
                   ScrollInertia = 0;
                }
                else
                {
                   ScrollInertia += ActualY;
                }
                
                //Calculate movement delta for active scrolling and increment
                ActualY = (Y - LastTouchLocation.Y);
                ScrollAmount += ActualY;
             }
             
             //Update cached touch location
             LastTouchLocation.X = X;
             LastTouchLocation.Y = y;
          }
       }
       //touch ending because user lifted finger
       else if(Type == ZoneEvent_Untouch)
       {
          //not a swipe and within the list
          if(!CheckSwipe() && CheckBounds(X, Y))
          {   
             //not in title bar - must be a tap on an item
             if(Y > Top + TitleBarHeight)
             {
                //pass tap on to all items
                foreach Items(Label)
                {
                   Label.OnTouch(Type, X, Y);
                }
             }
             //tap on title bar
             else
             {
                //if list can be canceled, let the Cancel button handle the tap
                if(bHasCancel)
                {
                   Cancel.OnTouch(Type, X, Y);
                }
             }
          }
          
          //update scroll inertia one last time before going passive
          if(bActive)
          {
             ActualY = (Y - LastTouchLocation.Y) * class'MobileMenuScene'.static.GetGlobalScaleY() * SwipeFactor;
             ScrollInertia += ActualY;
             
             //set list passive
             bActive = false;
          }
       } 
       //touch ending prematurely
       else if(Type == ZoneEvent_Cancelled)
       {      
          //set passive
          bActive = false;
          
          //zero out all scroll values
          ScrollAmount = 0;
          ScrollInertia = 0;
       }
    }
    
    /**
     * Selects a new item in the list. 
     * Assigned to the OnClick() of each item in the list.
     */
    function OnSelect(UDNMobileMenuObject Sender, float X, float Y)
    {
       local UDNMobileMenuButton Label;
       local int i;
       
       i = 0;
       
       if(UDNMobileMenuButton(Sender) != none)
       {
          //iterate items to find item matching sender
          foreach Items(Label)
          {
             //found the matching item
             if(Label == UDNMobileMenuButton(Sender))
             {
                //Set new selected index
                SelectedIndex = i;
                
                //Highlight the selected item
                Sender.bIsHighlighted = true;
                
                //Call OnChange delegate to alert anyone listening
                OnChange(i, Label.Caption, X, Y);
                
                //break out of the iterator since we're done here
                break;
             }
             
             i++;
          }
       }
       
       //set passive
       bActive = false;
       
       //zero out all scroll values
       ScrollAmount = 0;
       ScrollInertia = 0;
    }
    
    /**
     * Cancels the list. 
     * Assigned to the OnClick() of the Cancel button.
     */
    function HandleCancel(UDNMobileMenuObject Sender, float X, float Y)
    {
       //Call the OnCancel delegate to alert anyone listening
       OnCancel();
       
       //set passive
       bActive = false;
       
       //zero out all scroll values
       ScrollAmount = 0;
       ScrollInertia = 0;
    }
    
    defaultproperties
    {
       CaptionColor=(R=255,G=255,B=255,A=255)
       BackgroundColor=(R=64,G=64,B=64,A=255)
       BorderColor=(R=64,G=64,B=64,A=255)
       ItemBackgroundColors(0)=(R=0.5,G=0.5,B=0.5,A=1.0)
       ItemBackgroundColors(1)=(R=0.75,G=0.75,B=0.75,A=1.0)
       ItemBorderColors(0)=(R=0.25,G=0.25,B=0.25,A=1.0)
       ItemBorderColors(1)=(R=1.0,G=1.0,B=1.0,A=1.0)
       ItemCaptionColors(0)=(R=1.0,G=1.0,B=1.0,A=1.0)
       ItemCaptionColors(1)=(R=1.0,G=1.0,B=1.0,A=1.0)
       ItemFont=Font'EngineFonts.SmallFont'
       
       ItemHeight=48
       SwipeFactor=5
       SnapFactor=5
       ScrollLimit=20
       
       TitleBarHeight=32
       TitleBarColor=(R=96,G=96,B=96,A=255)
       
       Begin Object class=UDNMobileMenuButton name=CancelButton
          Tag="Cancel"
          Width=64
          Height=32
          Caption="Cancel"
          TextFont=Font'EngineFonts.SmallFont'
          CaptionColors(0)=(r=1.0,g=1.0,b=1.0,a=1.0)
          CaptionColors(1)=(r=0.0,g=0.0,b=0.0,a=1.0)
          Images(0)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
          Images(1)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
          ImagesUVs(0)=(bCustomCoords=true,U=0,V=896,UL=256,VL=128)
          ImagesUVs(1)=(bCustomCoords=true,U=0,V=896,UL=256,VL=128)
       End Object
       Cancel=CancelButton
    }
    ComboBox

    The combobox control provides a simple way to have settings in a menu whose value can be selected from a list of options. The main visual component of a combobox is a touchable button that toggles open a scrolling list control when tapped. The list displays all the options for the combobox and when one is selected, the list closes, setting the value of the combobox to the new selected option.

    Note: The options for the combobox currently require hard coding when the combobox is created. This can easily be changed to work as a per-object-config property or some other method of populating the list of available options.


    Code:
    class UDNMobileMenuComboBox extends UDNMobileMenuObject;
    
    
    /** The button that visually represents the combo box */
    var instanced UDNMobileMenuButton Label;
    
    /** The list used to select new values for the combo box */
    var instanced UDNMobileMenulist list;
    
    /** The title of the combo box - used to set the title of the list as well */
    var string Title;
    
    /** If TRUE, show the title. Otherwise show the current value. */
    var bool bShowTitle;
    
    /** The list of values used to populate the list */
    var array<string> Items;
    
    /** The index of the value to initialize the combo box to */
    var int InitialSelectedIndex;
    
    /** TRUE when the list is open for selecting a new value */
    var bool bIsOpen;
    
    
    /****************************************
    * Init and Render Functions
    ****************************************/
    
    /**
     * Initializes the combo box
     */
    function InitMenuObject(MobilePlayerInput PlayerInput, MobileMenuScene Scene, int ScreenWidth, int ScreenHeight)
    {
       local string item;
       
       Super.InitMenuObject(PlayerInput, Scene, ScreenWidth, ScreenHeight);
       
       //initialize label and list
       Label.InitMenuObject(PlayerInput, Scene, ScreenWidth, ScreenHeight);
       List.InitMenuObject(PlayerInput, Scene, ScreenWidth, ScreenHeight);
       
       //Set position and size of label
       Label.Left = Left;
       Label.Width = Width;
       Label.Top = Top;
       Label.height = height;
       
       //initialize label caption
       Label.Caption = Items[InitialSelectedIndex];
       
       //Set up delegates
       Label.OnClick = OnClick;
       List.OnChange = OnSelect;
       List.OnCancel = OnCancel;   
       
       //initialize list
       List.bHasCancel = true;
       List.SelectedIndex = InitialSelectedIndex;
       List.Title = Title;
       
       //Add item values as items to the list
       foreach Items(item)
       {
          List.AddItem(item);
       }
    }
    
    /**
     * Draw the combo box
     */
    function RenderObject(canvas Canvas)
    {      
       //don't render anything if open - the list belonging to the owner scene handles rendering
       if(!bIsOpen)
       {
          //Update label text
          if(bShowTitle)
          {
             Label.Caption = Title;
          }
          else
          {
             Label.Caption = GetValue();
          }
          
          //Draw the label
          Label.RenderObject(Canvas);
       }
    }
    
    /****************************************
    * List Management Functions
    ****************************************/
    
    /**
     * Add an item to the combo box's options
     *
     * @param item - the value of the item to add
     */
    function AddItem(string Item)
    {
       //Add the value to out internal list
       Items.Additem(Item);
       
       //Add the value as a new item in the actual list
       List.Additem(Item);
    }
    
    /**
     * Removes an value from the combo box's options
     *
     * @param Idx - index of the item to remove
     */
    function RemoveItem(int Idx)
    {
       //remove the item from our internal list
       Items.Remove(Idx, 1);
       
       //Remove the value from the actual list
       List.RemoveItem(Idx);
    }
    
    /**
     * Toggle whether the list is open or closed
     */
    function ToggleList()
    {
       //toggle open value
       bIsOpen = !bIsOpen;
       
       //update the owner scene's list
       if(bIsOpen)
       {   
          //set our list as the active list and make sure it is visible
          UDNMobileMenuScene(OwnerScene).List = List;
          List.bIsHidden = false;
       }
       else
       {
          //Null out the scene's list reference and make our list invisible
          UDNMobileMenuScene(OwnerScene).List = none;
          List.bIsHidden = true;
       }
    }
    
    /**
     * Returns the value of the combo box (via it's list)
     */
    function string GetValue()
    {
       //let list handle getting the value
       return List.GetValue();
    }
    
    /****************************************
    * Input Functions
    ****************************************/
    
    /**
     * Delegate fired when an item is selected
     */
    delegate OnChange(int Idx, string Item, float X, float Y);
    
    /**
     * Implementation of the OnTouch() of the ITouchable interface
     */
    function OnTouch(EZoneTouchEvent Type, float X, float Y)
    {
       Super.OnTouch(Type, X, Y);
       
       //the list is open, pass input to the list
       if(bIsOpen)
       {
          List.OnTouch(Type, X, Y);
       }
       //the list is closed
       else
       {   
          //we got a tap, toggle the list open
          if(!CheckSwipe())
          {
             Label.OnTouch(Type, X, Y);
          }
       }
    }
    
    function OnClick(UDNMobileMenuObject Sender, float X, float Y)
    {
       ToggleList();
    }
    
    /**
     * Called when an item is selected
     * Assigned to the OnChange() of the list
     */
    function OnSelect(int Idx, string item, float X, float Y)
    {
       //close the list
       ToggleList();
       
       //fire off our OnChange delegate to anyone listening
       OnChange(Idx, Item, X, Y);
       
       //let the owner scene know we got a tap
       OwnerScene.OnTouch(self, X, Y, false);
    }
    
    /**
     * Cancels selection, closing the list
     */
    function OnCancel()
    {
       //Selection was canceled, close the list
       ToggleList();
    }
    
    defaultproperties
    {   
       Begin Object class=UDNMobileMenuButton name=Label0
          Tag="Combo_LabelItem"
          bCenterText=false
          TextFont=Font'EngineFonts.SmallFont'
          CaptionColors(0)=(R=0.125,G=0.125,B=0.125,A=1.0)
          CaptionColors(1)=(R=0.125,G=0.125,B=0.125,A=1.0)
          Images(0)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
          Images(1)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
          ImagesUVs(0)=(bCustomCoords=true,U=0,V=768,UL=1024,VL=128)
          ImagesUVs(1)=(bCustomCoords=true,U=0,V=768,UL=1024,VL=128)
       End Object
       Label=Label0
       
       Begin Object class=UDNMobileMenuList name=List0
          Tag="Combo_ItemsList"
       End Object
       List=List0
    }
    Example Menu Scene - Putting It All Together

    The final step is to create a sample menu using these new controls. It should extend from the base UDNMobileMenuScene class so that it can accept input from the helper scene and pass it to touchable controls. This example has two comboboxes and a label. Changing the value of either combobox updates the label with its new value. Also, one of the comboboxes always displays its "name", while the other shows its current value.

    Code:
    class UDNMobileMenuExample extends UDNMobileMenuScene;
    
    /**
     * Handle basic taps from controls
     */
    event OnTouch(MobileMenuObject Sender,float TouchX, float TouchY, bool bCancel)
    {
       //Combobox 1 changed, set label to its value
       if(Sender.Tag == "Combo1")
       {
          UDNMobileMenuLabel(FindMenuObject("Title")).Caption = UDNMobileMenuComboBox(FindMenuObject("Combo1")).GetValue();
       }
       //Combobox 2 changed, set label to its value
       else if(Sender.Tag == "Combo2")
       {
          UDNMobileMenuLabel(FindMenuObject("Title")).Caption = UDNMobileMenuComboBox(FindMenuObject("Combo2")).GetValue();
       }
    }
    
    defaultproperties
    {
       //Create a combobox
       Begin Object class=UDNMobileMenuComboBox name=Combo0
          Tag="Combo1"
          Title="Setting One"
          Height=32
          Width=256
          Top=20
          Left=20
          Items(0)="Item 0"
          Items(1)="Item 1"
          Items(2)="Item 2"
          Items(3)="Item 3"
          Items(4)="Item 4"
          Items(5)="Item 5"
          InitialSelectedIndex=3
          bShowTitle=true
       End Object
       MenuObjects.Add(Combo0)
       
       //Create a combobox
       Begin Object class=UDNMobileMenuComboBox name=Combo1
          Tag="Combo2"
          Title="Setting Two"
          Height=32
          Width=256
          Top=60
          Left=20
          Items(0)="Object 0"
          Items(1)="Object 1"
          Items(2)="Object 2"
          Items(3)="Object 3"
          Items(4)="Object 4"
          Items(5)="Object 5"
          Items(6)="Object 6"
          Items(7)="Object 7"
          Items(8)="Object 8"
          Items(9)="Object 9"
          Items(10)="Object 10"
          Items(11)="Object 11"
          Items(12)="Object 12"
          Items(13)="Object 13"
          Items(14)="Object 14"
          Items(15)="Object 15"
          InitialSelectedIndex=9
       End Object
       MenuObjects.Add(Combo1)
       
       //Create a label
       Begin Object class=UDNMobileMenuLabel name=Label0
          Tag="Title"
          Height=32
          Width=160
          Left=296
          Top=20
          TextFont=Font'EngineFonts.SmallFont'
          CaptionColors(0)=(R=1.0,G=1.0,B=1.0,A=1.0)
          CaptionColors(1)=(R=1.0,G=1.0,B=1.0,A=1.0)
          Images(0)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
          Images(1)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
          ImagesUVs(0)=(bCustomCoords=true,U=576,V=384,UL=192,VL=192)
          ImagesUVs(1)=(bCustomCoords=true,U=576,V=384,UL=192,VL=192)
       End Object
       MenuObjects.Add(Label0)
    }

  6. #6
    The Sacrifice
    Join Date
    Jul 2010
    Posts
    288

    Default

    Thank you

    I will just mess with it untill I get it to work.

    By the way, if anyone here at the forum know what and how I should change it, I would appreciate getting some help
    Last edited by TheBuilder; 06-23-2012 at 05:16 PM.

  7. #7
    The Sacrifice
    Join Date
    Jul 2010
    Posts
    288

    Default

    I think I got it working, wasn't that hard really. The reason I didn't get it to work was because I messed up elsewhere.

    As long as people know how the touch functions have changed and adapt to it, the documentation above will still work well.

  8. #8
    The Sacrifice
    Join Date
    Feb 2010
    Posts
    371
    Gamer IDs

    Gamertag: TGB Murat

    Default

    I tested above codes. Did not work it. Already have more than 100 error message. I fixed all of them. I could not work menu list on mobile. I will learn unity. Good bye.

  9. #9
    The Sacrifice
    Join Date
    Jul 2010
    Posts
    288

    Default

    Remember that scareform also is an option. Once you know how to use scaleform, it's much easier than this code.


 

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Copyright ©2009-2011 Epic Games, Inc. All Rights Reserved.
Digital Point modules: Sphinx-based search vBulletin skin by CompletevB.com.