XBox:Framework:Widgets

From MadoxLabs

Template:Downloads:XBox

Edit Downloads:XBox (http://madox.ca/mediawiki2/index.php?title=Template:Downloads:XBox&action=edit)

Added Container and Label widgets to the UI today.

The current UI object hierarchy is as follows:

  • Placeable - an object that has a location and size. This is both componants and widgets
  • ComponantLink - this is a placeholder for a UI skin componant. It defines the place on the screen that the sprite goes.
  • Widget - A basic object that is composed of any number of componantlinks. Widgets can be active/inactive and have a fg/bg color
  • ParentWidget - This is a widget that can be composed of both ComponantLinks and other widgets.

A Container is simply a parentwidget that has specially defined componants to make it look like a window. In C++ a container is the only object that supports free floating child widgets that can be dragged around. It can also be resized. Both of these are not so relavent in XBox.

A Label is a special widget that uses text componants as its componant links. It supports colors and wrapping. The label's text must come from a DataWrapper that was published via the Library. Fonts are implemented as a skin with each letter in the font defined as a componant. An example is:

Componant MyFont_?   348 63 16 47
Componant MyFont_@   8 118 27 47
Componant MyFont_A   43 118 20 47
Componant MyFont_B   71 118 18 47
Componant MyFont_C   97 118 19 47
Componant MyFont_D   124 118 20 47 
Componant MyFont_E   152 118 18 47

Each componant is prefixed with the font name. Each font is fixed size since they are defined by the related texture.

Entering in all those componant is a giant pain, so I modified the XNA tff2bmp tool to generate skin files for use with MxLTools.

Update 2010-10-10

The UI library is fully completed. It is features fully skinnable widgets that are definable with a script. Available widgets include buttons, sliders, scrollbars, tab controls and dropdowns.

Since the XBox doesn't have a keyboard or mouse, I also added the idea of having a focus that the players move around. The widget being focused on receives the commands from the controller. The UI can also define commands using a sequence of key or button strokes. When the command is stroked, an event is fired.

Here is some excerpts from the documentation, which has more information:


The User Interface component is made up of a number of elements that are 
used to draw a 2d interactive set of widgets. 
- Widgets respond to controller inputs and display a graphic from a skin. 
Widgets can also provide a commandConfig to the player interacting with it. 
- Skins are stored in the mxSkinManager. Some skins can get their image from
a live rendering.
- The UI graphic is created by mxUISurface, which also hold the widgets in 
the current UI.
- mxUIManager drives the mxUISurface and handles the linkage between the 
UI and the Players.
The mxUIManager manages the player focuses. The UI can display distinct focus
elements for each Player, or have all players share a focus. When a certain
widget gains focus, the player(s) with the focus can gain extra command configs
that are only valid within that widget. Widgets can also provide command 
configs to all players, regardless of focus, as long as they are visible.
Typically, the result of generating a UI texture via mxUISurface is used as a 
fullscreen overlay with transparency.
Theoretically, the result of generating a UI texture via mxUISurface can itself
be used as a live texture for use in other UIs, or used as a texture in the core
engine to display UIs on oblique surfaces in game. In the latter case, we still
need a system that projects screen clicks to a click on the in game surface.

mxSkin.cs

   mxSkin gets auto-created using Content.Load() and the builtin content
   parsers. mxSkin contains a texture and a set of named rectangle areas.
   Widgets access graphic data from the skin using the names to get that
   portion of the image.
   
   mxSkin can also represent an animated texture, containing an array of 
   frames of aniamtions. The skin itself can only contain a single componant
   the size of a frame of animation. The skin manager will blt frames as needed
   from the skin and make the current frame available in the baked texture.
   
   If a skin is getting its image from a live render instead of a texture,
   mxLiveSkin is used instead. It is meant to be derived from and overloaded
   to do any dynamic rendering is needed. It contains a surface to render to
   and a Render() call. Render() should set refresh to false if the call 
   did not actually create a new rendering. This lets the skin manager optimize
   performance.

mxSkinManager.cs

   mxSkinManager is the repository of all mxSkin objects and handles giving
   out the rectangle regions. It is a singleton object. The skin manager takes
   all active mxSkins and bakes them into a single texture that contains all
   the skins. The various rectangle regions are converted into mxComponants.
   Theoretically, the result of the baking could be multiple textures, but
   currently a single texture is the result.
   
   For animated and live skins, the new frames are copied to the baked texture 
   everytime a new frame is available.
   
   mxComponant holds the baked-skin id, rectangle and name for the region. A
   componant can also be set to stretch to fill a space, or tile. The default 
   is to tile. Live skin componants will default to stretch.

BinSorter.cs

   This is used by the Skin Manager to take the collection of active skins and
   arrange them together so that the total area they take up is as small as 
   possible. This arrangement is then used to create the baked texture and the
   skin textures are blted onto the baked texture. 
       

mxLayout.cs

   This file contains classes that are used to position UI elements relative to
   each other. Anything that is able to be placed on screen uses the class
   mxLayoutDef. This defines that layout position of the element. mxLayoutDef
   contains the object and the positions of the topleft and bottomright corners. 
   
   Corners are defined by mxCorner. Each corner can be positioned relative to 
   another element or placed absolutely. The X and Y locations are set using 
   values from mxPlace. Not all mxPlace values are valid for all corner X and Ys.
   
   Objects that contain other objects that get positioned should use or derive 
   from the mxLayout class. The Arrange() function will operate on all the 
   elements to be positioned and set their position in the UI using their Place()
   function.
   
   Corner definitions:
       TopLeft
         X 
           LeftOf     - this is adjacent to the relative's left side
           Fixed      - this is placed absolutely
           LeftAlign  - the left edge is aligned with the relative's left edge
           RightOf    - this is adjacent to the relative's right side
           RightAlign - the right edge is aligned with the relative's right edge
           Center     - this's center is equal to the relative's center
           CenterAlign - this's left edge is equal to the relative's center
         Y 
           Below       - this is adjacent to the relative's bottom side
           BottomAlign - the bottom edge is aligned with the relative's bottom edge
           Above       - this is adjacent to the relative's top side
           TopAlign    - the top edge is aligned with the relative's top edge
           Fixed       - this is placed absolutely
           Center      - this's center is equal to the relative's center
           CenterAlign - this's left edge is equal to the relative's center
       BottomRight
         X
           CenterAlign - this's width is aligned with the relative's center
           LeftAlign   - this's width is aligned with the relative's left edge
           RightAlign  - this's width is aligned with the relative's right edge
           Fixed       - this's width is placed absolutely
         Y           
           CenterAlign - this's height is aligned with the relative's center
           TopAlign    - this's height is aligned with the relative's top edge
           BottomAlign - this's height is aligned with the relative's bottom edge
           Fixed       - this's height is placed absolutely
   When placing objects relative to other objects, the arrangement will fail if the
   objects are processed in the wrong order. Always make sure objects being 
   referenced are processed before objects referencing them. Also, widgets will 
   process child widgets before processing skin componants.
   
   Sometimes multiple calls to Arrange() are needed if you can not get the objects
   in a good enough order for one call. 

mxUIManager.cs

   mxUIManager contains the mxUISurface and is the link between the game, the UI and the 
   mxPlayer objects. It also contains a list of all widgets, focus and shift objects. 
   The currently actuve focus definition is tracked, and the UI Manager is able to 
   publish strings for use in widgets, and provide widget ID numbers for auto-
   created child widgets.
   
   The main job of the UI manager is linking actions from Player objects to the
   widgets in the UI. This is done using the Focus and Shift objects. 
   
   The Focus is a definition of a visual element that the player can move around 
   in the UI. It represents the widget that the player is focused on. One of more 
   focuses can be active simultaneouly and multiple players and move a common focus
   around. A Focus can also provide certain CommandConfigs to the players the focus
   is assigned to. 
   
   The Shift is a definition of the paths that a Focus can move along. It is a chain
   of widgets linked together by direction. A focus can move from one widget to another
   as long as the widgets are linked by a direction. A Shift can restrict different
   players to different paths if needed.
   
   A Focus typically assigns a special CommandConfig to its players which grants them
   the commands to move up/down/left/right. The UI Manager handles these commands and
   drives the OnFocusIn() and OnFocusOut() events on widgets. When a widget gains or
   loses focus, it adds or removes the visual element of the focus from itself. 
   
   The UI Manager also handles any commands that are targetting a widget and forwards
   them on. Most widget commands are assumed to be targetting the currently focused
   widget, but some widgets can have global commands that do not need them to be
   focused on.
   
   There are also commands that hide/show widgets, assign/remove command configs and
   change the current Focus definition.

mxUISurface.cs

   mxUISurface contains the DirectX surface that the UI is being rendered to. It 
   creates the vertex and index buffers by examining the widgets, then renders
   the whole mess. 
   

mxFocus.cs

   This contains the classes that make up the mxFocus and mxShift collection of classes.
   These are described in the mxUIManager section above.
       

mxWidget.cs

   This file contains all the base classes that are used to represent UI elements.
   There are different base classes depending on the nature of the element that
   is needed.
   
   mxPlaceable is needed by any element that is able to be placed in the UI. This is 
   all of them. mxPlaceable is used exclusively by mxLayout to call Place() in order
   to position the element. mxPlaceable holds the rectangle that defines the 
   position.
   
   mxComponantLink is a type of mxPlaceable used to represent a certain mxComponant
   from the baked skin. If you want to place a non-interactive graphical element in 
   the UI, that is the job of mxComponantLink. It links a mxComponant to the UI. A 
   mxComponantLink can be set to stretch or tile to fill its position, and can also
   be skipped by the renderer if needed.
   
   mxWidget is the base class of all the more complex widgets. A widget is a UI element
   that is composed of many mxComponantLinks, which are positioned using a mxLayout.
   A mxWidget can be visible or not, has foreground and background colours, and has a
   cliprect. The cliprect is the area that is considered inside the widget where its
   componants are.
   
   An mxWidget will usually assign a new commandConfig to any players with focus on
   the widget. This is to add controls for button press, scrolling, opening dropdowns 
   etc
   
   mxParentWidget is a mxWidget that is able to have other mxWidgets placed inside it.
   mxParentWidget has a layout for child widgets as well as the mxComponantLink
   layout. It also has an offset to shift the child widgets so they can be scrolled.

mxLabel.cs

   mxLabel is a widget that displays a text string using a certain font. The mxLabel
   doesn't do a lot since it is the mxUISurface that does the text drawing. Note that 
   the size of the mxLabel can not be dependant on the size of the text string.
   
   Fonts are just ordinary skins that get baked with all the other skins. The texture
   and skin definition should contain all the characters needed to draw text. A font
   has a fixed style and pointsize. Font skin files can be created using the modified
   ttf2bmp tool. This tool will output the texture containing the desired letters as 
   well as the skin file containing the rectangles for each letter.
         

mxContainer.cs

   mxContainer is a mxParentWidget that has visible edges, like a window. It automatically
   defines a set of mxComponantLinks depending on the border setting. The components 
   used can be altered to get custom looking windows.

mxButton.cs

   mxButton is a mxParentWidget that acts as an image button or a text button. The
   componants used to draw the button are fully definable. The button can be set to
   be a checkbox, or can be a part of a radio button group. When pressed, the button
   can trigger an event. It also publishes its state.  

mxSlider.cs

   mxSlider is a horizontal slider widget that moves by increments between a minimum
   and maximum value. The Slider is skinnable like other widgets and publishes
   its current position.
    

mxTabControl.cs

   mxTabControl is a special control that manages a set of containers. Only one container can
   be visible at any one time. The tab control also has a set of title widgets, one for each 
   container. When a container is visible, the matching title widget is also visible. Finally,
   the tab control also contains two buttons that are used to move from container to 
   container, selecting the visible one.
        

mxScrollbar.cs

   mxScrollbar affects the offset of the container widget it is a child of. The UISurface uses 
   the parent's clip rect and offset to render the proper part of the container. The scrollbar
   is unaffected by the offset. THe scrollbar's docsize must be set to the height of the
   container's content, not the height of the visible area on the container.
   
   mxScrollbar publishes the thumb position in pixels.
        

mxDropdown.cs

   mxDropdown allows for multiple choice from a published array of values. It has a skinnable button
   that opens and closes a scrollable container of choices.
Personal tools
Toolbox