C

QML: Preserving Attributes

TODO: Needs to be rewritten or removed.

Everyone wants presentations to take up as little memory at runtime as possible. The benefits of memory efficiency are numerous, especially on embedded hardware where cache coherency is king. In order to minimize the amount of memory used by a given presentation the Qt 3D Studio Runtime employs several sophisticated and aggressive optimizations.

One such optimization is the static analysis of a presentation performed by the runtime at startup. The runtime looks at each attribute on each element in the presentation and uses a simple heuristic to decide if a given attribute is `going to change at runtime'. The idea is that if an attribute is not going to change at runtime there is no point in storing it at all, anywhere. It will be set in the static scene and never need to be updated.

The heuristic that is used to make this determination is twofold. An attribute will be preserved (not optimized away) if it is either (1) animated, or (2) an attribute on a master element that is unlinked and changed per-slide.

A problem occurs when an attribute is optimized away and later a script tries to access or modify that attribute at runtime. When this happens this error message will be logged: setAttribute: Attribute "someAttribute" not found. The solution to this problem is to "reference" these attributes with the behavior that needs to change them to ensure they are not optimized away.

Note that not every attribute needs to be referenced for scripting. Custom attributes on behaviors are never optimized away (otherwise, why did you add them?) and some other attributes are also never optimized away, such as name for all elements, or attributes specified to Text objects (because the runtime bitmap font engine needs access to the values to accurately render the text).

References

To make the references modular, and to ensure they require no knowledge or intervention from an artist wanting to use a behavior, the references are stored as part of the behavior. These are placed inside a <Reference> element in the Artist Interface preamble at the top of a behavior. For example:

--[[
  <Property ... />
  <Property ... />
  <Handler  ... />
  <Event    ... />
  <Event    ... />
  <Event    ... />

  <Reference>
    parent.opacity
    parent.children.position
  </Reference>
--]]

-- The rest of the behavior code
function self:onInitialize()
  ...
end

Add reference strings to indicate which attributes this behavior needs at runtime to guarantee its proper execution. Each attribute reference string is made up of two parts:

  • the element or elements to preserve the attributes on,
  • followed by the attribute(s) to preserve.

The first part can start with a path, either relative or absolute. Scene.Layer.Cube specifies a path to a certain cube absolutely, while parent.Cube specifies a path to a sibling Cube (relative to the behavior). Alternatively, the first part can start with a square bracketed name, like {[}targetObject{]} where the name in square brackets is the name of a Object Reference type custom property on this behavior. Using the square bracket syntax is equivalent to typing an absolute path to an object, except the object can be chosen by the artist in the inspector palette.

The first part can optionally end with one of the two keywords, .children or .descendants. Specifying these will cause the specified attribute(s) to be preserved on either all of the children of the element pointed to by the specified path, or recursively preserve that attribute on all descendants. See the examples below for more details.

The second part of the attribute reference string is the name of a attribute. The Attribute Names page of this manual outlines the names of the different attributes. You can also use the suffixe .all to preserve all attributes on a certain object, though this is typically not recommended as it undermines the operation of the optimizer.

The second part of the attribute reference string can also use a square bracket syntax to reference a String type custom property on this behavior to specify (by name, as a string) which attribute to preserve. For example, if you had a String type custom property called targetProp, you could have an attribute reference string like Scene.Layer.Cube.{[}targetProp{]} which would preserve whatever property that was specified (by name) as the value of targetProp set in the inspector palette.

Explaining that all in words is a bit cumbersome, the following examples show many different attribute reference strings.

Reference Examples

# Preserve opacity on a certain cube

Scene.Layer.Cube.opacity

# Preserve opacity on the element the behavior is attached to

parent.opacity

# Preserve position on all the children of a certain group

Scene.Layer.Group.children.position

# Same as above, but specify the group with an object reference custom property

[targetGroup].children.position

# Keep opacity on siblings and their descendants

parent.descendants.opacity

# Preserves the property typed in by the artist in the Inspector palette

parent.[targetProp]

# Circumvent the optimizer (don't do this :)

Scene.descendants.all

Available under certain Qt licenses.
Find out more.