You.i Engine
Layout

Detailed Description

A layout system used to arrange the children of views.

The layout system augments views with the ability to position and size their children according to a set of rules. The layout system is used by assigning an instance of a CYILayout to a CYISceneView. Configuration is set on each layout instance. Children of the view can be assigned an instance of CYILayoutConfig to specify per-child layout configuration. Some of the layout classes provided by You.i Engine include:

Layout

A layout refers to an instance of the CYILayout class. More specifically, to an instance of a subclass of CYILayout (since CYILayout is abstract). The layout is then assigned to an instance of CYISceneView, which then takes ownership of the layout instance. That view is then said to be 'having a layout', or to 'have a layout assigned to it'. Children of the view are said to be 'laid out'. Any child of the view (including instances of CYISceneNode) can be laid out.

Layouts can also be assigned to views through After Effects. To do so, the properties panel is used to select a layout type for a given composition. The properties panel lists all built-in layout types in a dropdown. Specifying a user-defined layout is done by selecting the 'Custom Layout' option, and entering a layout class name in the text field underneath. For details on writing custom layouts, see CYILayout.

Note
Because views can contain other views, views that have a layout can contain views with that also have a layout. This allows layouts to be nested.

Layout Configuration

The layout system supports two levels of configuration: configuration on the layout instance itself, and configuration on the children of the view which has a layout assigned to it.

Layout Instance Configuration

Layout instance configuration is performed directly on layout instances. The configuration can be applied to layout instances prior to assigning it to a view, or after the layout has been assigned to a view.

Alternatively, layout instances can be configured in After Effects using the properties panel. To do so, select a composition (assigning it a layout if it doesn't have one already). The available layout configuration properties for the selected layout type will show up beneath the layout type.

Children Layout Configuration

Children of a view that have a layout can optionally be assigned a layout configuration object. This object gives additional information to the layout of the parent view about how this specific child should be laid out.

Warning
The type of layout configuration object must match the type of the layout of the parent view. For this reason, it is recommended to fetch the existing layout configuration object of a child in order to configure it. This should be done after the parent view has had its layout instance assigned. This will ensure that the layout configuration object fetched from the child will be of the proper type. If a layout configuration object of an incorrect type is assigned, a runtime crash can occur.

As with layout instance configuration, layout configuration for children of views that have a layout can be configured in After Effects using the properties panel. To do so, select a layer whose parent composition has a layout assigned. The available layout configuration options for the layer will be displayed in the properties panel.

Background And Layoutable

All children configuration objects provide the 'background' and 'layoutable' flags.

When the 'layoutable' flag is set to false, the position and size of the child is left alone. The child is left untouched even if its parent has a layout assigned.

The 'background' flag is used as a 'special case' to facilitate laying out elements. When set, the child's size is set such that its size is equal to its parent's size. This makes it easy to set a background to a view.

Size Constraints

Through children layout configuration objects, users can specify limits on the size of children of views with layouts. This allows the layout to grow and shrink the children as needed, and ensures that the children's sizes do not exceed configured limits. Constraints can be set independently on the width, height and depth. Users can set a preferred size (which defaults to the current size of the child if absent), a maximum size (which defaults to infinity), and a minimum size (which defaults to 0).

Children can also be configured to 'fill parent'. When this is set, the child will expand to fill all available space in the parent view. The available space is dictated by the parent view's layout, and considers the size of the view and the presence of other children with the 'fill parent' flag set. The exact manner in which this is done depends on the type of layout that is selected.

Finally, views (and children of views) can be configured to 'fit content'. When this is set, the view will shrink (or expand) such that its size matches its laid-out children. This can be used to make expanding containers. Note that the 'fit content' property can only be set on views that have a layout assigned. The views expand and contract from their origin. If the view should be aligned in a specific way in its parent, a layout should be assigned to the parent of the view.

Size and Measured Size

Each scene node has a size, accessible through the CYISceneNode::GetSize() function. The size of a scene node may be set when it is created (such as for CYIImageSceneNode), be set based on its content (such as for CYITextSceneNode), be set manually (through the CYISceneNode::SetSize() function), or be calculated automatically by the layout system (for views that have an assigned layout instance, or for their children). The reported size of a scene node represents how big it is in its parent's coordinate space.

Note
The size of a node is sometimes calculated automatically, either because its size depends on its content, or because its size is calculated by the layout system. When the size of a node is calculated automatically, it is typically set during the app's update phase. Therefore, the size returned by CYISceneNode::GetSize() may sometimes appear incorrect because the size has not yet been calculated. Therefore, calling CYISceneNode::GetSize() from the app may result in an incorrect size being returned (since the size may be calculated 'later').

The measured size of a scene node is calculated during the layout update phase, and is typically only of interest for users who wish to write their own custom layout class.

Layout Update Phase

Children of views that have a layout are automatically laid out during the update phase of the app. This is done only if the layout system determines that a change has been made that may change the positioning of children. For example, adding a child to a view that has a layout will trigger a re-layout in the update phase.

Note
Changing the configuration of a layout instance or changing the layout configuration of a child does not automatically trigger a re-layout. In these cases, the user is expected to call CYISceneNode::RequestLayout() on the view or on the child to indicate that a layout update is needed.

The layout update phase is divided in two phases: the measurement phase, and the apply measurements phase.

During the layout update phase, each scene node is measured. (For simplification, this description will assume that all nodes need to be re-laid out). Scene nodes, as well as views that don't have an assigned layout, use their own size as measurement. For example, an image scene node would report the image's size, a text scene node would report its own glyph box size (considering the text to render), and a scene view would report its default template dimensions. Measurement is recursive: when a scene node is measured, all of its descendents are also measured.

Views that have a layout are measured differently. The layout instance takes control of how the view is measured. Exactly how this is done depends on the specific layout type, but typically the layout measures each of the view's children in turn, and then computes a measured size for the view itself.

After all scene nodes have been measured, the measured sizes are applied. This process recursively traverses the scene tree, sets the size of all scene nodes to their measured size, and moves the children of views that have a layout to the position required by the layout instance.

Depth

While users typically only arrange scene nodes in 2D, the layout system is written to arrange children of views in 3D. This is the reason why the size reported by CYISceneNode::GetSize() is a glm::vec3. Certain layout configuration options, such as the gravity, can make use of a depth component to indicate how elements should be arranged on the z axis. There is also a layout class aimed specifically at arranging elements on depth: CYIShaftLayout. This layout arranges elements in a line along the z axis.

Note that when arranging children in 3D, it is important to ensure that the children have a correct depth component on their sizes. Also note that because depth is seldom used, support for it in the After Effects properties panel is limited.

Classes

class  CYIAnimatingLayout
 A layout that can animate its children's position and size. More...
 
class  CYIAnimatingLayoutConfig
 A class used to hold per-child layout configuration for CYIAnimatingLayout layouts. More...
 
class  CYIAnimatingLayoutState
 A class used to hold layout state for CYIAnimatingLayout layouts. More...
 
class  CYIAutoLayout
 A layout that assigns margins to children based on their initial position and size. More...
 
class  CYIAutoLinearLayout
 A linear layout that switches between horizontal and vertical orientations based on a configurable condition. More...
 
class  CYIColumnLayout
 
class  CYIGridLayout
 A layout that positions items in a grid. More...
 
class  CYIGridLayoutConfig
 A class used to hold per-child layout configuration for CYIGridLayout layouts. More...
 
class  CYILayout
 This class defines a layout that can be applied to a scene view. The layout class determines how objects should be laid out, and can apply that layout configuration. More...
 
class  CYILayoutConfig
 A class used to hold node-specific layout configuration (such as, for example, Margin). More...
 
class  CYILayoutState
 A class used to hold node-specific layout state. More...
 
class  CYILinearLayout
 A layout that positions all of its children in a row, a column, or a 'shaft'. More...
 
class  CYIRowLayout
 A CYILinearLayout that always uses a 'horizontal' orientation. More...
 
class  CYIScalingLayout
 A layout that scales its children to fill their container. More...
 
class  CYIShaftLayout
 A CYILinearLayout that always uses a 'shaft' (i.e. depth) orientation. More...
 
class  CYIStackLayout
 A layout that positions all of its children in a 'stack'. More...