Defining SceneGraph components

Structure XML component files with name, extends, and child elements

A Roku SceneGraph application consists of one or more SceneGraph
components. These SceneGraph components are defined in XML files, which
consist of a required <component> XML element, that contains the
other possible XML elements to fully define the component. The Roku
SceneGraph application can then create an object instance of any defined
SceneGraph component as needed.

<component> XML element

The component XML files consist of a
<component> XML element, which contains
the other XML elements that can further define the component. The
<component> element has two required attributes:

  • name
    A unique name for the component
  • extends
    The name of the built-in node class, or extended component, that the
    component extends

All components in a SceneGraph application are defined by extending the
component from a built-in node class or extended component, and setting
the field values of the nodes included in the component, which may be
built-in node classes or extended components. When you extend a
component, the extended component includes all of the previously
declared or defined characteristics of the original component, plus the
new characteristics you declare and define for the new component.

<interface> XML Element

Roku SceneGraph components allow (but do not enforce), encapsulation of
internal component behavior, by providing an
<interface> XML element. The <interface> element can contain several <field> elements,
which define custom fields for the components. These custom fields can
be written and read by the application in the same way as the fields of
the built-in node classes. This allows the application to set a field
value to control the component operation, and read a field value to get
the results of the component operation, without writing and reading the
internal fields of the component.

<script> XML Element

Component behavior is controlled using
BrightScript in a
<script> XML element. The <script>
element provides two methods of including BrightScript code in the
component:

  • directly, using a CDATA element section
  • by reference, using the uri attribute of the <script>
    element to specify the location of the BrightScript code to be
    included

<children> XML Element

You can create the component SceneGraph nodes entirely in BrightScript
in the <script> element. But Roku SceneGraph also supplies a
<children> XML element to allow nodes to
be defined in XML markup. These SceneGraph nodes are then created
automatically when the component is created (see Component
Initialization Order
for
important details on this process).

Defining SceneGraph nodes in the <children> element is
particularly useful when the component will have a relatively fixed
number and types of nodes, rather than a number of different node types
that may be created (and removed) dynamically as part of component
operation. Field values of the nodes declared and defined in the
<children> element can still be set dynamically in the
<script> element, by first using the
ifSGNodeDict findNode() method to find the object reference.

There are some limitations in defining node field values in the
<children> element. You cannot use expressions and otherwise
manipulate variables and object references in the XML markup to set
field values. You are restricted to fixed values that can be expressed
only as strings assigned to the field. And you should not start or stop
or otherwise control the operation of certain nodes, such as media
playback or animation nodes, by setting the values of those types of
fields in the XML markup definition of the node in the <children>
element. Rather you should find the object reference using the
ifSGNodeDict findNode() method in the <script> element,
then set those fields there, as part of your scripting to control
component behavior.

Node Definition Examples

A typical XML file will include one or more SceneGraph node elements
inside the <component> element. These nodes are instantiated when
the XML is parsed, and added as children of the XML
<component> element top-level node.

Nodes are defined using an XML element that matches the node type.
Field values of the node are specified as attributes of the node
element. The following example shows how to define a
<Poster> node, and set its id, uri and translation
fields.

Defining a Node in XML

<Poster
  id="myPoster"
  uri="pkg:/images/myPoster.jpg"
  translation="[ 200, 100 ]" />

Nodes can include children by simply including them in the body of a
node XML element. The follow example shows how to declare a Poster
node that includes a Label draw on top of
it.

Adding a Child Node in XML

<Poster
  id="myPoster"
  uri="pkg:/images/myPoster.jpg"
  translation="[ 200, 100 ]">
  <Label
    id="FirstName"
    text="John" />
</Poster>

By default, if a node includes one or more node elements in the body of
its XML definition, the nodes defined in the body are added as children
of the node. In a few cases, nodes defined in the body of another node
serve a special purpose, and should not be added as children. In that
case, the nodes defined in the body should have an XML role attribute
specified to indicate which field of the parent node should be set to
their value. For example, a <Label> node could have a
<Font> node defined in its body. If you specify the role
attribute as font for the <Font> node, it causes the
parent <Label> node font field to be set to the
<Font> node.

Defining the role Attribute of a Node

<Label text="John Doe">
  <Font
    id="TypewriterFont"
    role="font"
    uri="pkg:/fonts/BohemianTypewriter.ttf"
    size="36" />
</Label>

An instance of a node can be used in more than place in the scene, using
a field attribute value that begins with dictionary:. For example, if
the <Label> node is defined as above in an XML file, another
<Label> node can be defined that uses the same <Font> node
as
follows:

Using dictionary to Set an Attribute Value

<Label
  text="John Doe"
  font="dictionary:TypewriterFont" />

Extending Built-In Node Classes

Roku SceneGraph includes a wide variety of node classes that are built
into the SceneGraph API. These built-in node classes are described
in the SceneGraph XML
Reference
.

But Roku SceneGraph allows you to extend these built-in node classes
with your own custom node classes, with unique fields, appearance,
behaviors, and interfaces. The key to writing SceneGraph applications is
to define your own custom node classes, then create and use them as
needed for your application.

For example, the starting point of any SceneGraph application is a
custom node class extended from one of the built-in Scene node
classes, such as Scene or
OverhangPanelSetScene. These
Scene node classes are abstract node classes, you must extend
them in order to use them. So every SceneGraph application must
include an XML component file in the following format:

<?xml version="1.0" encoding="utf-8" ?>
<component name="MyApplicationScene" extends="Scene">
  customized_scene_definitions
</component>

The built-in abstract Scene node is extended by setting the name
and extends attributes of the
<component> XML element. After this
custom extended Scene node is defined in an XML component file in
the pkg:/components directory, you can then start the application by
creating the custom Scene node component in the pkg:/source
/main.brs file using the Scene node component name as the
CreateScene() argument for a BrightScript roSGScreen object:

scene = screen.CreateScene("MyApplicationScene")

Likewise, you define custom components for your entire application that
are created and added to your SceneGraph node tree as needed. For
example, you could add a custom scrollable row list component to your
application by extending the built-in
RowList node class component in an XML
component file:

<?xml version="1.0" encoding="utf-8" ?>
<component name="MyCustomRowList" extends="RowList">
  customized_rowlist_definitions
</component>

Once this XML component file is created, you can now add the custom row
list component to your Scene component, or any other SceneGraph
component in your application. For example, the following adds the
custom row list to the application Scene component using the
createChild() function using BrightScript in a
<script> element:

<?xml version="1.0" encoding="utf-8" ?>
<component name="MyApplicationScene" extends="Scene">
  <script type="text/brightscript">
    <![CDATA[
      sub init()
        rowlist = m.top.createChild("MyCustomRowList")
      end sub
    ]]>
  </script>
</component>

Or you can add the custom component using XML markup in the
<children> element of the XML component
file:

<?xml version="1.0" encoding="utf-8" ?>
<component name="MyApplicationScene" extends="Scene">
  <children>
    <MyCustomRowList />
  </children>
</component>

In either case, you have added your custom component to the SceneGraph
node tree as a child node of the Scene node, by specifying the component
name from your custom XML component file.


Did this page help you?