| Home Page | Recent Changes | Preferences

Automated Component

The new internal management system for GUIMultiComponents enables you to automatically create variables of the desired type, without casting. It also handles initialization, tab order, and render weight for each automated component. It involves two new specifiers: one for classes - instanced, and one for properties - automated.

var automated GUIButton FantasticButton;

defaultproperties
{
    Begin Object Class=GUIButton Name=FantaticButtonTemplate
        OnClick=InternalOnClick
        WinWidth=0.06
        WinHeight=0.04
        bBoundToParent=True
        bScaleToParent=True
    End Object
    FantasticButton = FantasticButtonTemplate
}

Automated is a new variable modifier that tells the native code to automatically create instances of a subobject definition. By declaring a variable automated, all assignment and initialization will be taken care of natively. The auto-initialization is kicked off in GUIMultiComponent.InitComponent(). GUIMultiComponent.InitComponent() calls InitializeControls(), a native function which iterates through the class's properties. For any automated properties, it copies the default properties from a subobject definition into the associated variable. Similar to spawn, it always returns an object of the specified type, without need for casting.

GUIMultiComponent defines two arrays of GUIComponents - Controls and Components. The controls array contains all GUIComponents defined and initialized for that page. When using automated controls, the controls array will be sorted natively by RenderWeight, a property of GUIComponent. The native rendering code will draw Controls[0] first, proceeding through the array until it reaches the end. The components array contains all controls on the page that are tab stops. Components are generally controls on the page that can accept input, such as buttons, edit boxes, and tabs. The components array is sorted by TabOrder, a property of GUIComponent. Both arrays are managed automatically for automated components, but GUIMultiComponent provides methods for also manually managing the Components array.

GUIMultiComponent Methods and Properties:

var     array<GUIComponent>     Controls;                                              // An Array of Components that make up this Control
var     array<GUIComponent>     Components;                                            // An Array of Controls that can be tabbed to
var     GUIComponent            FocusedControl;                                        // Which component inside this one has focus
var     bool                    PropagateVisibility;                                   // Propgate changes to visibility to my Controls array
var     bool                    bOldStyleMenus;                                        // Set natively if Controls array members are defined in default properties

delegate OnCreateComponent(GUIComponent NewComponent, GUIComponent Sender);            // Hook to access components before they're initialized 
function native InitializeControls();                                                  // Initialize automated components
event GUIComponent AddComponent(string ComponentClass, optional bool SkipRemap)        // Create and add a new component, optionally skipping TabOrder remapping
event GUIComponent InsertComponent(GUIComponent NewComp, int Index, optional bool SkipRemap)
event GUIComponent AppendComponent(GUIComponent NewComp, optional bool SkipRemap)      // Append an existing component
event bool RemoveComponent(GUIComponent Comp, optional bool SkipRemap)                 // Remove a component from the Components array
event int FindComponentIndex(GUIComponent Who)                                         // Find the Components array index of a GUIComponent
event RemapComponents()                                                                // Remap the Components - resort based on TabOrder
event Free()                                                                           // The control is no longer needed, perform any cleanup here.

The two systems (current system and new system) cannot be mixed. InitializeControls() checks if there are any existing members defined for the Controls array in the class's default properties, and if so, simply returns. If you want to use automated components on your menus, you'll need to update everything :)

UT2004 will come with a completely new GUI which uses the automated system, as well as the original, which will use the current system.

AutoPositioning

// Auto-positioning - accounts for bBoundToParent & bScaleToParent
native final function AutoPosition(
        array<GUIComponent> Components,
        float LeftBound, float UpperBound, float RightBound, float LowerBound,
        float LeftPad, float UpperPad, float RightPad, float LowerPad
        );
 

GUIComponent.AutoPosition() is a native function that will automatically position an array of GUIComponents within the bounds passed to the function. It takes nine parameters. The first parameter is an array of GUIComponents that will be positioned. The next four parameters define the bounds of the area that you wish the components to be positions within, while the last four parameters specify the amount of padding to add to each side. These parameters must be actual screen values, not scaled values (For example, pass in the value of ActualTop(), not WinTop).

AutoPosition() first applies the padding values, then divides the length of the passed-in array by the difference between the lower bound and the upper bound to find the component offset. It adjusts each of the array member's WinWidth, WinLeft values based on the values passed into the function, and adjust each array member's WinTop value based on component offset. It does NOT modify the WinHeight value of the components. If the total number of components multiplied by the offset value would be greater than the bounded area, AutoPosition() writes an error to the log, and returns. AutoPosition() accounts for the bBoundToParent and bScaleToParent values, and internally adjusts the ratios of the components accordingly.

Multiple instancing

One of the largest benefits of using AutoPosition() to position your components is that you can very easily take advantage of multiple instancing. Multiple instancing is where you have one templated subobject definition, but assign multiple variables to it.

    Begin Object class=GUIImage Name=HUDPreviewImage
        ImageStyle=ISTY_Scaled
        ImageColor=(R=255,G=255,B=255,A=255)
        WinHeight=0.5
        RenderWeight=0.51
    End Object
    i_HUDTop=HUDPreviewImage
    i_HUDTopRight=HUDPreviewImage
    i_HUDTopLeft=HUDPreviewImage
    i_HUDMiddleRight=HUDPreviewImage
    i_HUDMiddleLeft=HUDPreviewImage
    i_HUDMiddleRight=HUDPreviewImage
    i_HUDBottomLeft=HUDPreviewImage
    i_HUDBottomRight=HUDPreviewImage
    i_HUDBottom=HUDPreviewImage

You can then pass these components to AutoPosition() as an array, and they will be automatically positioned for you. If you need to make changes to the original template image, you'd only need to make this change in one place. Likewise, if you wanted to add additional components, or remove components, you'd need only to add/remove the assignments in default properties. No more resizing dozens of components in design mode every time you change one option! :)

Overriding automated subobject definitions

The finer art of 'default vs. instanced'


Mychaeel: That's a very neat set of new features you're describing here. :-) It's just a bit of a pity that it's specific to the GUI classes and not made so generic that all classes could benefit from it – by allowing the "automated" keyword in any class, introducing an "InitObject" event in Object and defining a native "InitObjects" function in Object instead of InitComponents in GUIMultiComponent.

Evolution: Actually, 'automated' isn't specific to GUI subclasses. It can be used in any class, as long as the class is specified 'instanced'. The 'instanced' specifier is inherited, which is why all GUI classes are able to use 'automated' variables without the 'instanced' specifier (GUI itself is declared 'instanced'). However, the InitializeControls() doesn't have anything to do with automated components, per se. InitializeControls() does native management of the Controls array for automated variables in GUIMultiComponent subclasses, but auto-instancing doesn't require an InitializeControls() function at all. Any subobject definition can be automatically assigned to an 'automated' variable.

Mychaeel: Then I'm afraid I haven't understood yet what the "automated" specifier does at all, especially in contrast to how subobjects work in UT2003. Could you elaborate on that a bit, please?

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Image Uploads

Random Page

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

Mapping Topics

Mapping Lessons

UnrealEd Interface

Questions&Answers

Scripting Topics

Scripting Lessons

Making Mods

Class Tree

Questions&Answers

Modeling Topics

Questions&Answers

Log In