Results 1 to 7 of 7
  1. #1

    Default Scaleform 4/AS3 - Toggleable Mouse Cursor

    This tutorial will walk you through the steps needed to create a toggleable mouse cursor that remembers the position it was last in.

    UPDATE: The March 2012 UDK includes a new function SetMouse() which allows you to set the Unreal/Windows mouse position. This new function means a DLL Bind is no longer required. The tutorial will explain further.

    IMPORTANT: If you are using a UDK version prior to March 2012, you will need a DLL file. I have precompiled the file, and it (as well as all the files used in this tutorial) can be downloaded from this link: http://forums.epicgames.com/threads/...-Sandbox-Files



    Flash Setup

    The very first thing we need to do is to add a mouse cursor to our Flash HUD file.

    • Create (or import) a mouse cursor graphic on the stage.
    • Now, right click on it and choose Convert to Symbol.
    • Choose Movie Clip as the type and name it mCursor.
    • Set the registration point to top left, then press OK to create the new symbol.
    • Give the movie clip on stage an instance name of mCursor as well.
    • Now, right click on the movie clip instance and choose Convert to Symbol once more.
    • Again choose Movie Clip as the type and name it MouseCursorContainer this time.
    • Now, double click MouseCursorContainer to enter its timeline.
    • Add a new layer and label it 'actions'.
    • On frame 1 of this layer, add the following ActionScript 3 code:


    ActionScript 3.0

    Code:
    Mouse.hide();
    
    var mCursor:MovieClip;
    mCursor.mouseEnabled = false;
    mCursor.tabEnabled = false;
    
    function handleMouseMove( e:MouseEvent ):void 
    {
        mCursor.x = e.stageX;
        mCursor.y = e.stageY;
    }
    
    stage.addEventListener( MouseEvent.MOUSE_MOVE, handleMouseMove, false, 0, true );
    
    stop();
    • Delete this movie clip from the stage. (Don't worry, the mouse still exists in the library.)
    • Now, right click the MouseCursorContainer in the library, and choose Properties.
    • In the Symbol Properties window, check Export for ActionScript and Export in frame 1.
    • The Class name should match the Symbol Name (MouseCursorContainer).
    • Press OK.
    • Save and Publish the file.
    • Import/reimport into UDK.




    UnrealScript Setup

    To begin, we need to tell Unreal that the Left Shift key on the keyboard will be used to toggle our mouse cursor on/off.

    DefaultInput.ini
    Code:
    .Bindings=(Name="LeftShift",Command="ToggleMouseCursor true | Onrelease ToggleMouseCursor false")


    Next, we need to add the function that Left Shift executes in our HUD Wrapper class:

    UnrealScript - HudWrapper Class (extends UTHUDBase)

    Code:
    exec function ToggleMouseCursor(bool showCursor)
    {
        HudMovie.ToggleMouseCursor(showCursor);
    }


    Next, we need to create the mouse and allow for toggling it on/off:

    UnrealScript - HUD Class (extends GFxMoviePlayer)

    First, we declare our variables:

    Code:
    var GFxObject 		RootMC;
    var GFxMouse            MyMouse;

    Next, we instantiate the mouse, and tell the movie to ignore Left Shift key presses, so that they can be intercepted by Unreal instead:

    Code:
    function Init(optional LocalPlayer player)
    {	
        super.Init(player);
    
        Start();
        Advance(0);
    	
        // Creates the mouse cursor.
        MyMouse = new class'GFxMouse';
        MyMouse.RegisterHud(self);
        MyMouse.SetTimingMode(TM_Real);
        MyMouse.Init();
    
        // This key will be used to toggle the mouse cursor on/off.
        AddFocusIgnoreKey('LeftShift');
    }
    After this, we provide the toggle function to enable/disable the cursor:

    Code:
    // Toggles mouse cursor on/off
    function ToggleMouseCursor(bool showCursor)
    {	
        if (showCursor)
        {
    	MyMouse.ToggleMouse(true);
        }
        else
        {
    	MyMouse.ToggleMouse(false);
        }
    	
        // When showCursor is true, the movie should capture all input, including mouse input; otherwise, it should not capture input or mouse input.
        self.bCaptureInput = showCursor;
        self.bIgnoreMouseInput = !showCursor;	
    }
    And, of course, we need our default properties to set the initial values to ignore mouse input and capture not capture input:

    Code:
    defaultproperties
    {		
        bIgnoreMouseInput = true
        bCaptureInput = false;
    }


    Now, we need to create the mouse class (GFxMouse.uc). It should have the MousePosition.dll bound to it:

    UnrealScript - Mouse Class (extends GFxMoviePlayer)

    First, declare the class -

    Pre-March 2012 UDK

    Code:
    class GFxMouse extends GFxMoviePlayer
    	DLLBind(MousePosition);
    March 2012 UDK

    Code:
    class GFxMouse extends GFxMoviePlayer;
    Next, we define the variables we need in GFxMouse:

    Code:
    var SFAS3Hud					SFHud;
    	
    // Standard Flash Objects
    var GFxObject 					MouseContainerMC, MouseCursorMC;
    	
    var Vector2D 					lastMousePOS;
    This next line of code is Pre-March 2012 UDK ONLY

    After that, we need to do a DLL import statement to let the class know about the SetMousePosition() function inside the DLL MousePosition:

    Code:
    // DLL import declaration, for setting the position of the mouse - the DLL is here: /Binaries/Win32/UserCode/MousePosition.dll
    dllimport final function SetMousePosition(int newX, int newY);

    Then we need our initialization function:

    Code:
    function Init(optional LocalPlayer player)
    {
        local float x0, y0, x1, y1;
    	
        super.Init(player);
    	
        // Get the HUD's viewport size and set the mouse's initial position to the center of the screen.
        SFHud.GetVisibleFrameRect(x0, y0, x1, y1);
        lastMousePOS.X = (x1-x0)/2;
        lastMousePOS.Y = (y1-y0)/2;
    }
    And next, we need a function that allows us to cache a reference to the HUD

    Code:
    // This function gives us a reference to the HUD which created the mouse.
    function RegisterHud(SFAS3Hud hud)
    {
        SFHud = hud;
    }
    Next comes our function to toggle the mouse cursor on/off:

    Code:
    // Attachs the mouse cursor container movie clip to the stage/root.
    function ToggleMouse(bool enableMouse)
    {	
        if (enableMouse)
        {
    	// Attaches the mouse container movie clip to the stage/root of the HUD and caches a reference to it.
    	MouseContainerMC = SFHud.GetVariableObject("root").AttachMovie("MouseCursorContainer", "MouseConatinerMC"); // argument1 = Flash AS3 class name; argument2 = new instance name
    		
    	// Caches a reference to the actual mouse cursor movie clip, which is inside the mouse container movie clip.
    	MouseCursorMC = MouseContainerMC.GetObject("mCursor");
    	
            // Pre-March 2012 UDK CODE ONLY
    
    	// Ensures that the Unreal/Windows mouse is set to the last known Flash mouse position.
            // This is a function from the MousePosition.DLL, which moves the windows mouse to the location specified.
    	SetMousePosition(lastMousePOS.X,lastMousePOS.Y);
    
            // March 2012 UDK CODE ONLY
    
            // Ensures that the Unreal/Windows mouse is set to the last known Flash mouse position.
            GetGameViewportClient().SetMouse(lastMousePOS.X,lastMousePOS.Y);
    
            // Use the rest of this code for both versions of UDK
    			
    	// Sets the position of the Flash mouse cursor movie clip to match the Unreal/Windows mouse position.
    	MouseCursorMC.SetPosition(lastMousePOS.X,lastMousePOS.Y);
    			
    	// Ensures the mouse cursor is drawn on top of all other movie clips.
    	MouseContainerMC.SetBool("topmostLevel", true);
        }
        else
        {
    	// Saves the mouse cursor's last known position on the screen before removing it.
    	lastMousePOS.X = MouseCursorMC.GetFloat("x");
    	lastMousePOS.Y = MouseCursorMC.GetFloat("y");
    		
    	// Removes the Flash mouse container movie clip using a custom class 'GFxDisplayObject'.		
    	GFxDisplayObject(MouseContainerMC.GetObject("parent",class'GFxDisplayObject')).RemoveChild(MouseContainerMC);
        }
    }


    Last of all, we need a new class that will remove a movie clip from the stage.:

    UnrealScript - Class to remove a movie clip (extends GFxObject)

    Code:
    class GFxDisplayObject extends GFxObject;
    
    function RemoveChild(GFxObject childObject)
    {
        ActionScriptVoid("removeChild");
    }
    Last edited by Matt Doyle; 04-13-2012 at 02:50 PM.

  2. #2
    Skaarj
    Join Date
    May 2012
    Location
    Barcelona
    Posts
    27

    Default

    Uhmm, for some reason my editor isn't recognizing the Scaleform Hud variable 'SFAS3Hud'.

    Console error:
    Error 1 Unrecognized type 'SFAS3Hud'

    Thank you in advance

  3. #3
    MSgt. Shooter Person
    Join Date
    Sep 2009
    Posts
    147

    Default

    Thanks for this tutorial, very useful.

    I have one question though. I have set the movie's scaling mode to EXACT_FIT, and when the movie is rescaled in game, the mouse cursor rescales as well. However I wanted the mouse cursor's size to be fixed. How can this be done?

    Note: I didn't simply set the movie's scaling mode to NO_SCALE because I want the rest of the HUD to rescale with game window size; only the cursor movie clip should have a fixed size. Or can the cursor and HUD be in different movies?
    --

  4. #4
    MSgt. Shooter Person
    Join Date
    Sep 2009
    Posts
    147

    Default

    Quote Originally Posted by cgascons View Post
    Uhmm, for some reason my editor isn't recognizing the Scaleform Hud variable 'SFAS3Hud'.

    Console error:
    Error 1 Unrecognized type 'SFAS3Hud'

    Thank you in advance
    Replace SFAS3Hud with your GFxMovie class (it should extend GFxMoviePlayer).
    --

  5. #5

    Default

    There's only one scale mode for the each movie that you can set. For what you're looking for you have two options, either simply create an individual movie for the cursor alone, and play it on top of the Hud movie, or my recommendation, after you set the scaling mode, manually rescale the mouse cursor to keep it's aspect ratio (or even exact dimensions) the same for every resolution.

  6. #6
    MSgt. Shooter Person
    Join Date
    Sep 2009
    Posts
    147

    Default

    Hmm, I've run into another problem. I added some buttons (from CLIK_Components_AS3.fla), and they work fine in Flash's Scaleform Launcher, but in UDK, when I hover over the buttons, they flicker very quickly and I am unable to click them. I ran out of ideas, what could be wrong?

    Some experiments:

    1) if I do not attach the MouseCursorContainer (i.e. if I comment the line MouseContainerMC = SFHud.GetVariableObject("root").AttachMovie("Mouse CursorContainer", "MouseConatinerMC"); ), it works fine, but then the mouse cursor doesn't shows up.
    2) if I remove the mouse cursor bitmap from the movieclip "mCursor", the buttons also work in UDK, but of course mouse cursor won't show up.
    3) if I add a 0 (zero) as the third parameter to AttachMovie() (that would be Depth), the buttons work, but the mouse cursor is rendered behind the Container movie clip (where the buttons reside).

    My Flash setup is: mCursor movieclip with the graphics, MouseCursorContainer containing mCursor and the code, and all my HUD (including the buttons) inside a "Container" movieclip.

    Edit: got this fixed by separating the mouse cursor and HUD files. That is, I now have a Mouse.swf that contains only the mouse graphic (loaded and initialized by GFxMouse.uc), and another HUD.swf that contains my HUD/menus.
    Last edited by Pinheiro; 10-30-2013 at 02:57 PM.
    --

  7. #7

    Default

    Matt,

    This is a great tutorial thanks. With it's help today I developed a fully working level map with plenty of cool features. I did discover that it can be done far simpler than shown in your tutorial, if you are willing to make some compromises. Just in case anyone is looking for a simpler, quick and dirty version here are the details:

    (1) Use a permanent mouse cursor in the flash movie

    It probably wastes resources, but if you have a movieclip on the stage in your flash swf already to use as a mouse cursor then it isn't necessary to create it dynamically or remove it after use. Just hide and show it by passing a boolean to its visible property.

    (2) Use your Custom GFxMovie Class rather than a Separate Class for your Mouse

    You can just include a few extra functions in your custom GFxMovie class to setup the mouse. It takes only a few lines of code. Once you've changed the bCaptureInput and bIgnoreMouseInput on the GFxMovie flash takes care of all the functionality in the menu/map. This is great since all the functions are in the swf rather than scattered through several unrealscripts. Below is an example based on my Custom GFxMovie, but nothing is written in stone here...there are many different ways to write these functions.

    Code:
    class MyGameGFxHUD extends GFxMoviePlayer;
    
    	//Declare a variable for the mouse
    	var GFxObject myMouse;
    
    	//Declare a variable for my map which is contained in a movieClip on the stage
    	var GFxObject myMap;
    
    
    DefaultProperties
    {
    	
    	//The path to your swf asset
    	MovieInfo=SwfMovie'UIMyGame.UI_MyGame'
    	//Defaults to HUD not receiving mouse or key input
    	bDisplayWithHudOff=false
    	bIgnoreMouseInput=true
    	bCaptureInput=false
    	bAutoPlay=true
    }
    
    
    function Init( optional LocalPlayer LocPlay )
    {
            //This init function is called from PostBeginPlay() in the HUDWrapper (this extends UTHUDBase)
    	
    
    	//Gets all the other intialization stuff we need.
    	super.Init (LocPlay);
    
    	//Starts the GFx Movie that's attached to this script (IE: our HUD). 
            Start(); 
            //Advances the frame to the first one.
    	Advance(0.f);
    
    	//Get the path to the mouse in the SWF and set it to hidden
    	myMouse = GetVariableObject("root.mvMouse");
    	myMouse.SetBool("visible", false);
    
    	//Start off with my map hidden
    	myMap = GetVariableObject("root.mvMap");
    	myMap.SetBool("visible", false);
    
    	//Ensure unrealscript still has access to M key so it can toggle the Map
    	AddFocusIgnoreKey('M');
    
    }
    
    
    function initMouse()
    {
        local float x0, y0, x1, y1;
        local vector2D lastMousePOS;
    	
        //Show the mouse pointer
        myMouse.SetBool("visible",true);
    
        // Get the HUD's viewport size and set the mouse's initial position to the center of the screen.
        GetVisibleFrameRect(x0, y0, x1, y1);
        lastMousePOS.X = (x1-x0)/2;
        lastMousePOS.Y = (y1-y0)/2;
        GetGameViewportClient().SetMouse(lastMousePOS.X,lastMousePOS.Y);
    
        //Notice I am not worried about saving the mouse position
        
    }
    
    
    function toggleMap()
    {
    	//This is called from a exec function in my custom game controller bound to the M key
    	//It toggles the map and the mouse
    
    	if (myMap.GetBool("visible")==true){
    		myMap.SetBool("visible",false);
    		toggleMouse();
    	} else {
    		myMap.SetBool("visible",true);
    		toggleMouse();
    	}
    			
    }
    
    
    function toggleMouse(){
    	
    	//This is called from toggleMap
    
    	if (myMouse.GetBool("visible")==true){
    
    		//Hide the mouse pointer
    		myMouse.SetBool("visible",false);
    	
    		//Set the movie so it isn't the focus of input
    		bCaptureInput = false;
    		bIgnoreMouseInput = true;
    
    	} else {
    
    		//Setup the mouse (show it and initialise position)
    		initMouse();
    
    		//Set the movie so it receives all input, allowing the flash movie to control functions
    		bCaptureInput = true;
    		bIgnoreMouseInput = false;
    	}
    }
    That is pretty much it. The only issues I had to overcome were with right mouse click functions, which were caused in flash by CLICK events overriding RIGHT_MOUSE_DOWN. I solved these by using MOUSE_DOWN instead and determining whether the primary mouse button was pressed using event.buttonDown (true if primary button).

    In my application I pass information back to unrealscript simply by checking a few variables set in flash once I pass control back to unrealscript by hiding my map. Real simple.

    I must say I am loving Scaleform.


    -------------------------------------
    Medusa Pro - A rock model creator for UDK.
    Forester Pro - An easy tree and plant creator for UDK.


 

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.