Announcement

Collapse
No announcement yet.

Making Sense of GFxUDKFrontEnd

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Making Sense of GFxUDKFrontEnd

    This is a step by step, high level explanation of how GFxUDKFrontEnd loads and displays each view of the menu which ships with UDK.

    [Tested Working as of: July 2012 UDK] You may download a simplified version of the UDK Front End files --> HERE <--

    This simplified version illustrates the code & assets needed for pushing & popping 2 views (Main Menu & Options) to a viewstack, using a menu manager. It contains custom files & assets (not covered below, but similar in execution).

    NOTE: If you download and use the simplified version above, add the following two lines to [Engine.PackagesToForceCookPerMap] in DefaultEngine.ini.


    Code:
    .Map=SF-FrontEnd
    .Package=SFSandbox



    Files Involved

    Unreal Script Files Involved
    • The Menu Manager - \Development\Src\UTGame\GFxUDKFrontEnd.uc
    • The Views - \Development\Src\UTGame\GFxUDKFrontEnd_MainMenu.uc , *_Multiplayer.uc, *_Settings.uc, etc.
    • Base class for Views - Development\Src\UTGame\GFxUDKFrontEnd_Screen.uc
    • Base View class - \Development\Src\UTGame\GFxUDKFrontEnd_View.uc


    Flash Files Involved
    • The Manager - \UDKGame\Flash\UDKFrontEnd\udk_manager.fla
    • The Views - \UDKGame\Flash\UDKFrontEnd\udk_main_menu.fla, *_multiplayer.fla, *_settings.fla, etc.
    • All graphical assets pulled from this file - \UDKGame\Flash\UDKFrontEnd\udk_assets.fla


    ActionScript Files Involved
    • The Views - \UDKGame\Flash\ActionScript\com\scaleform\udk\view s\MainMenuView.as, MultiplayerView.as, SettingsView.as, etc.
    • The Manager - \UDKGame\Flash\ActionScript\com\scaleform\udk\mana gers\MenuManager.as
    • Utlility for registering a document's class - \UDKGame\Flash\ActionScript\com\scaleform\udk\util s\UDKUtils.as


    Other Files

    • \UDKGame\Config\DefaultUI.ini
    • \UDKGame\Content\Maps\UT3\UDKFrontEndMap.udk
    • \UDKGame\Flash\UDKFonts\fonts_en.fla
    • \UDKGame\Flash\UDKFonts\gfxfontlib.fla





    Modifying and Reimporting the Front End Menu Files

    If you make changes to any of the Flash files of the front end menu system, be very careful to follow the procedure below to ensure they continue to work properly once reimported into UDK.
    1. First, Add this classpath to the ActionScript 2.0 Settings, directly above $(LocalData)/Classes and below the \Development\Flash\AS3\CLIK\ classpath: C:\UDK\UDK-2012-03\UDKGame\Flash\ActionScript\
    2. Publish/compile these files into SWF files in this order:
      \UDKGame\Flash\UDKFonts\fonts_en.fla
      \UDKGame\Flash\UDKFonts\gfxfontlib.fla

    3. Now, make your changes in the \UDKFrontEnd\udk_assets.fla file. For instance, to mofidy the main menu, make changes inside the main_menu movie clip found in the library panel of this file.
    4. Save and compile the file.
    5. Do the same for any other fla files you modified as well.
    6. Now, reimport everything into UDK by adding the following line to a batch file (.bat), and executing the file:

      Code:
      C:\UDK\UDK-2012-03\Binaries\Win64\UDK.exe gfximport
    7. Test your changes.





    The Menu Manager

    GFxUDKFrontEnd.uc is the master class (or manager) for the front end (menu). It extends GFxMoviePlayer, and makes use of the config file DefaultUI.ini. It is called in the startup level (UDKFrontEndMap) in Kismet via Open GFx Movie. The Movie loaded there is: UDKFrontEnd.udk_manager (package name.swf name), and the Movie Player Class is set to GFxUDKFrontEnd. Take Focus, Capture Input, and Display With Hud Off are all checked.


    * GFxUDKFrontEnd’s SWF is also defined in the defaultproperties of GFxUDKFrontEnd.uc as: UDKFrontEnd.udk_manager
    * On frame 1 of the actions layer, udk_manager.FLA/SWF is given the document class of: com.scaleform.udk.managers.MenuManager (MenuManager.as)
    a. MenuManager.as initializes the _viewStack array & provides several functions for tweening (animating) the viewstack.
    b. On the 'canvas' layer, udk_manager.FLA contains the empty movieClip: manager which is of type: manager. This movieClip will be used to hold the views.


    GFxUDKFrontEnd.uc Variables

    ViewInfo data structure
    a. ViewName, SwfName, and DependantViews
    b. These values will be populated by data in DefaultUI.ini

    ViewData[] array of type ViewInfo
    a. +ViewData lines defined in DefaultUI.ini


    GFxUDKFrontEnd.uc Function Execution

    1. Start() is executed
    a. Calls ConfigFrontEnd()
    2. ConfigFrontEnd() is executed
    a. “_root” of udk_manager.fla is cached in RootMC
    b. “manager” movie clip from udk_manager.fla is cached in ManagerMC
    3. Start() calls LoadViews()
    4. LoadViews() is executed
    a. Calls LoadView() passing each element (each view) of the ViewData[] array
    5. LoadView() is executed
    a. A new empty movieclip is created inside ManagerMC with the name: SomeViewNameContainer (example: MainMenuContainer, MultiplayerContainer, HostGameContainer, etc.)
    i. And this new movieclip is referenced by ViewContainer
    b. A new empty movie clip is then created inside the ViewContainer with the name: SomeViewName.
    i. This new movieclip is referenced by ViewLoader.
    c. We get the SWFName and store at element 0 of the args[] array of asvals as a string.
    d. We then invoke “loadMovie” (a standard Flash function in a GFxObject) on ViewLoader, passing it the SWFName via the args[] array.
    i. This loads the actual SWF file for that view into the ViewLoader movie clip as a new movie clip.
    ii. The SWF files sets their document class (example: com.scaleform.udk.views.MainMenuView (MainMenuView.as))
    iii. The SWFs contain an empty movie clip of type container with the instance name: “container”
    1. Inside “container” is another movie clip which is loaded via runtime sharing. “udk_main_menu.fla” for instance has the “main_menu” movie clip of type main_menu.
    a. These movie clips have been imported into the SWF via runtime sharing from udk_assets.swf
    b. UDK_assets.swf contains all the views in the library, and each view is setup to export for runtime sharing in the properties.
    iv. The newly loaded SWF fires off a CLIK WidgetInitialized event with the ActionScript: if (enableInitCallback && _global.CLIK_loadCallback) { _global.CLIK_loadCallback(this._name, targetPath(this), this); }
    e. Finally, we add the name of the view to the LoadedViews[] array.
    6. WidgetInitialized() is executed for each loaded view as they are loaded.
    a. Example: MainMenu
    i. MainMenuView is created of type GFxUDKFrontEnd_MainMenu
    ii. Calls ConfigureView()
    iii. ConfigureView() is executed.
    1. SetWidgetPathBinding() is called - this function sets it up so that all child widget's found in the view's path will send their initCallBack events to the view's WidgetInitialized() handler.
    a. This requires using SubWidgetBindings.Add instead of the usual WidgetBindings.Add in the default properties when binding a widget.
    iv. (MainMenuView ONLY) Calls ConfigureTargetView()
    7. ConfigureTargetView() is executed (for the first view only – main menu)
    a. This function first tests to see if the view is already on the stack or not.
    b. Calls OnViewActivated() (found in GFxUDKFrontEnd_View.uc)
    c. Calls OnTopMostView(), passing true.
    i. OnTopMostView() plays the open animation & sets the escape key delegate.
    d. Adds the view to the UnrealScript ViewStack[] array.
    e. Calls PushView().
    8. PushView() is executed.
    a. Fires off the ActionScript function pushStandardView() in MenuManager.as, passing it the new view.


    MenuManager.as Function Execution

    1. pushStandardView() is executed.
    a. Calls pushViewImpl()
    2. pushViewImpl() is executed.
    a. Tweens the new view into place.
    b. Pushes the new view onto the _vewStack[] array in AS.




    "Popping" a View


    When a view is "popped" off the viewstack, as when pressing BACK to go from the Multiplayer screen to the Main Menu, the essential functions used are:

    PopView()
    PopViewStub()

    1. Each Screen has a "Back" button. The Back button is bound in GFxUDKFrontEnd_Screen.uc in the defaultproperites:

      Code:
      defaultproperties
      {
      	// General
      	SubWidgetBindings.Add((WidgetName="list",WidgetClass=class'GFxClikWidget'))
      	SubWidgetBindings.Add((WidgetName="back",WidgetClass=class'GFxClikWidget'))
      
      	AcceptButtonImage="pc_enter_png"
      	CancelButtonImage="pc_esc_png"
      	AcceptButtonHelpText="SELECT"
      	CancelButtonHelpText="BACK"
      }
    2. In the WidgetInitialized() handler of GFxUDKFrontEnd_Screen.uc, the Back button is told to listen for 'CLIK_press' events, and to execute Select_Back() on press.:

      Code:
      case ('back'):   
                  BackBtn = GFxClikWidget(Widget.GetObject("btn", class'GFxClikWidget'));
                  BackBtn.SetString("label", "BACK");
                  BackBtn.AddEventListener('CLIK_press', Select_Back);
                  BackBtn.AddEventListener('CLIK_focusIn', FocusIn_BackButton);
                  bWasHandled = true;            
                  break;
    3. The event handler Select_Back() is found in GFxUDKFrontEnd_View. It fires off the function MoveBackImpl():

      Code:
      function Select_Back(GFxClikWidget.EventData ev)
      {
          MoveBackImpl();
      }
    4. MoveBackImpl() executes PopView() from the MenuManager (GFxUDKFrontEnd.uc)

      Code:
      function MoveBackImpl()
      {
          if (MenuManager != none)
          {
              PlayCloseAnimation();
              MenuManager.PopView();        
          }
      }
    5. PopView() removes the current view from the ViewStack[] array.

      Code:
      ViewStack.Remove(ViewStack.Length-1, 1);
    6. It then executes the OnTopMostView() function of the previous view (which is now the current view).

      Code:
       ViewStack[ViewStack.Length-1].OnTopMostView( false );
    7. Last of all, it executes the PopViewStub() function as its return value.
    8. PopViewStub() executes the popView() ActionScript function found in MenuManager.as
    9. popView() then executes popViewImpl() which tweens the movie out.

    #2
    Wow! This is an excellent explanation of the GFxUDKFrontEnd! Really taught me a lot. I appreciate your help to the community.

    But I'm having some issues I've been grinding at for hours to no avail. I have a main menu set up - not with a dynamic list or anything. Just three buttons for now "play" "credits" "quit". I'm using the GFxUDKFrontEnd style because my project will be expanding to support multiplayer stuff later on.




    Code:
    event bool WidgetInitialized(name WidgetName, name WidgetPath, GFxObject Widget)
    {
        local bool bWasHandled;
        bWasHandled = false;
    
        `log("Chroma_SFMenu_MainMenu: WidgetInitialized():: WidgetName: " @ WidgetName @ " : " @ WidgetPath @ " : " @ Widget);
        switch(WidgetName)
        {
            case ('button_play'): 
                if (PlayBtn == none)
                {
                    PlayBtn = GFxClikWidget(Widget);                      
    		PlayBtn.AddEventListener('CLIK_press', OnPlayButtonPress);
                    bWasHandled = true;
                }
                break;
            case ('button_credits'): 
                if (CreditsBtn == none)
                {
                    CreditsBtn = GFxClikWidget(Widget);                      
    		CreditsBtn.AddEventListener('CLIK_press', OnCreditsButtonPress);		
                    bWasHandled = true;
                }
                break;
    		case ('button_quit'): 
                if (QuitBtn == none)
                {
                    QuitBtn = GFxClikWidget(Widget);                                          
    		QuitBtn.AddEventListener('CLIK_press', OnQuitButtonPress);
                    bWasHandled = true;
                }
                break;
    		default:
                break;
        }
    	return true;
    	if (!bWasHandled)
    	{
    		bWasHandled = Super.WidgetInitialized(WidgetName, WidgetPath, Widget);    
    	}		
    	return bWasHandled;
    }
    
    defaultproperties
    {
    	WidgetBindings.Add((WidgetName="button_play",WidgetClass=class'GFxClikWidget'))
    	WidgetBindings.Add((WidgetName="button_credits",WidgetClass=class'GFxClikWidget'))
    	WidgetBindings.Add((WidgetName="button_quit",WidgetClass=class'GFxClikWidget'))
    	
    	AcceptButtonHelpText="SELECT"
    	CancelButtonHelpText="EXIT GAME"
    
    }
    my flash file has all the buttons set up from the AnimatedButton in the CLIK sample files. they're all named properly so they are set up as widgets

    the Frame1 action script mimics the same in the udk_main_menu.fla

    I've tried several things now, but still get this error message:

    Code:
    ScriptWarning: Accessed None 'PlayBtn'
    	Chroma_SFMenu_MainMenu MainMenu.TheWorld:PersistentLevel.Main_Sequence.Chroma_SFMenu_0.Chroma_SFMenu_MainMenu_0
    	Function Chroma.Chroma_SFMenu_MainMenu:WidgetInitialized:017C

    I get this for all 3 buttons.

    Any idea where I should look into? Thanks

    Comment


      #3
      That's very likely because of the way the FrontEnd view manager system is built. If you copied it, you probably have a line of code: SetWidgetPathBinding(InView, WidgetPath) in the ConfigureView() function. This line basically makes it so that all child widgets found in a view's path will be handled by that view's WidgetInitialized() handler. In that case however, you must not use WidgetBindings.Add to bind the widgets as you normally would, but must instead use: SubWidgetBindings.Add

      Code:
      defaultproperties
      {
      	SubWidgetBindings.Add((WidgetName="button_play",WidgetClass=class'GFxClikWidget'))
      	SubWidgetBindings.Add((WidgetName="button_credits",WidgetClass=class'GFxClikWidget'))
      	SubWidgetBindings.Add((WidgetName="button_quit",WidgetClass=class'GFxClikWidget'))
      	
      	AcceptButtonHelpText="SELECT"
      	CancelButtonHelpText="EXIT GAME"
      
      }

      Comment


        #4
        Aaaahhhhh!!! That was it! THANK YOU!! I just took a victory lap around my team's room.

        Comment


          #5
          Very usefull! Just want to say thank you Matt Doyle!

          Comment


            #6
            Matt this is really great. Thanks. I've been working on customizing the UDK frontend for a few months now and figured out most of what you have here. I still find it very confusing to be honest and very difficult to get help with because of the integration between both platforms. Flash guys will help with flash stuff, script guys with script but when the problem lies between the two systems good luck

            One question I have is, why all the going back and forth with actionscript for popping and pushing views? Could we handle more from script with attach and remove clips? I get the tween stuff, but the view handling not so sure of.

            Comment


              #7
              I recently reinstalled UDK and have been trying to take a more in depth look at the Menu Files but when I open them their is nothing in the Flash Files. When I play the file I get a message "Drag and drop SWF/GFX file here" anyone know why this is happening?

              Comment


                #8
                Couple questions:

                1. I never could get the widgetInitialized() function to fire until I explicitly set enableInitCallback to true, how does SFSandbox accomplish this without setting it first?

                2. What exactly does this do?
                Code:
                class com.scaleform.udk.utils.UDKUtils 
                {
                	public static function setDocumentClass(mc:MovieClip, cls:Object):Void {
                		registerClass(mc, cls);
                	}
                	
                	public static function registerClass(mc:MovieClip, cls:Object):Void {
                		mc.__proto__ = cls.prototype;
                		Function(cls).apply(mc, null);
                	}
                }
                I get the feeling that it answers my next question, but I'll ask it anyways.

                3. How does this function call:
                Code:
                /** Pushes a view onto MenuManager.as view stack. */
                function PushView(coerce LSFrontEnd_View targetView) 
                {   
                	`log("LSFrontEndGFx: PushView() executed");
                    ActionScriptVoid("pushStandardView"); 
                }
                end up calling MenuManager.as's pushStandardView function? Shouldn't it require a handle somewhere? or is this completely related to the above setDocumentClass thing?

                Currently my log shows that pushview is being executed, but that it's not being met on the other end in actionscript. I've been using the simple frontend source for most of this, but even looking at UDK's source I can't see the hook that lets the manager.swf call the actionscript function defined in MenuManager.as.

                Lastly, is there no AS3 source for any of unreals frontend stuff? I tried to recreate this in AS3 but ran into a problem trying to initialize the widgets. I'll have to look into this a bit more later, but AS3 was my preferred route and it was a bit demoralizing not being able to find the names and calls I needed anywhere.

                Comment


                  #9
                  setDocumentClass() is used to set the class (MenuManager.as) of the Manager Flash (Manager.fla) file, which basically injects the AS code into the Flash file. It is called inside the Flash file on frame 1.

                  Code:
                  UDKUtils.setDocumentClass(this, com.scaleformsandbox.udk.managers.MenuManager);
                  We can then use ActionScriptVoid() (which is a wrapper function) in UnrealScript to call the pushStandardView() function of MenuManager.as.

                  AS3 tutorials are limited at this time, as I just haven't had enough time to write them.

                  Comment


                    #10
                    Wow I feel dumb.
                    So the reason my call wasn't working is because I included the "com" folder in my classpath and not the "Actionscript" folder... com is within actionscript... etc. Ugh.

                    Thanks for the response Matt!

                    For any of you getting the error " setDocumentClass called on invalid object " Make DOUBLE SURE your classpath is set up for so the imports can find "com.*"

                    Comment


                      #11
                      Hey, I know this thread is a little old now, but I've recently downloaded the simplified version and gone through it thoroughly to understand it all. Once I was aware of all its parts, I went about renaming various parts e.g. all uc files are now of the pattern RG_FrontEnd & RG_FrontEnd_*
                      ActionScript packages are also changed to com.robotgameui.*.*
                      I believe I've made all appropriate changes across all files, however I have an issue when running it all on my custom MainMenu level.
                      If I use my own RG_FrontEnd (Inherited from GFxMoviePlayer) the level loads with no clear errors shown or logged except that the UI isn't visible at-all and the camera stays in First person mode, albeit unmovable, when it should be attaching to a camera. If I change the Movie Player to the standard GFxMoviePlayer and change the movie from the Manager to one of the Menus for e.g. the Main Menu, it proceeds to load fine, including camera attachment.

                      I can provide with any info / code necessary if anyone has any inklings where my problem may be, although It's 95% exactly the same as the download in the first post of this thread with the basic changes I outlined first.

                      Thanks in advance for any ideas / help.

                      Comment


                        #12
                        Could it be because you haven't associated your level's prefix with a gametype? This is done in DefaultGame.ini with something like:

                        +DefaultMapPrefixes=(Prefix="SF",bUsesCommonPackag e=FALSE,GameType="SFTutorial.SFTutorialGame")

                        Where SF = your map file's prefix (SF-MyMap for example), and SFTutorial.SFTutorialGame is the path to the UnrealScript source files in the Dev directory.

                        Comment


                          #13
                          Thanks for the reply Matt.

                          I tried that change, although It's made no difference, Still nothing running, I'm not sure that the movie is even loading for some reason as the FrontEnd.uc file should be making `log calls to output, I'm not seeing any of these.
                          I'm sure this is the most simple of stupid mistakes, but It's hard to pin down what it is.

                          Comment


                            #14
                            Hmm. Sounds like it's not even loading if it's not displaying log messages. Do you get any AccessedNone messages in the log?

                            Comment


                              #15
                              Ahha, after trawling through iterations of Change->Run->View logs, I think I found it.
                              I noticed it was logging the initial call from ConfigFrontEnd() but no more, then found it got into the LoadViews() function. From here I guessed perhaps there were no views to load and voila, it was a ridiculously simple / small change I had forgot.
                              While changing filenames and the rest to conform to my personal ways, I apparently forgot to update this line in the DefaultScaleformSandboxUI.ini (or equivalently named) file:

                              [SFTutorial.SFSandboxFrontEnd]
                              Changed to
                              [RobotGame.RG_FrontEnd]

                              It appears to be working, and logging correctly now

                              Thanks for the prompt help all the same Matt!

                              Comment

                              Working...
                              X