.. _ScenegraphAttr-porting-guide:

ScenegraphAttr Porting Guide
============================

Introduction
------------

In Katana 1, two classes were used for representing scene graph attributes:
``FnAttribute`` was used exclusively by C++ plug-ins, while ``ScenegraphAttr``
was used in both C++ and Python contexts.

In Katana 2, ``FnAttribute`` replaced ``ScenegraphAttr`` as the preferred class
for handling attribute data. ``ScenegraphAttr`` became a legacy emulation layer
on top of ``FnAttribute``.

In Katana 4.5, ``ScenegraphAttr`` is no longer available.
Porting to ``FnAttribute`` is mostly straightforward, however there are one or
two methods and functions that have moved, changed signature, or been removed
entirely. This guide details the differences between the two and offers
solutions for functionality that has been removed.

Classes
-------
Class names have changed slightly between the two modules, as detailed in the
following table. Note that the abstract base classes are not included, as they
cannot be instantiated directly.

+---------------------+---------------------+
| ``ScenegraphAttr``  | ``FnAttribute``     |
+=====================+=====================+
| ``GroupAttr``       | ``GroupAttribute``  |
+---------------------+---------------------+
| ``IntAttr``         | ``IntAttribute``    |
+---------------------+---------------------+
| ``FloatAttr``       | ``FloatAttribute``  |
+---------------------+---------------------+
| ``StringAttr``      | ``StringAttribute`` |
+---------------------+---------------------+
| ``NullAttr``        | ``NullAttribute``   |
+---------------------+---------------------+

Construction
------------
The “constructor” of ``ScenegraphAttr.Attr`` acted as a factory, allowing
instantiation of subclasses by passing an attribute type name string token as
the first argument. Uses of this pattern should be updated to construct objects
directly instead.

For example::

    attr = ScenegraphAttr.Attr('StringAttr', 'hello')

becomes::

    attr = FnAttribute.StringAttribute('hello')

Direct construction of ``GroupAttribute``\ s remains possible without using a
``GroupBuilder``, just as it was for ``GroupAttr``. However, the signature of
the constructor has changed.  Specifically, the ``groupInherit`` argument has
reversed position and is optional in the GroupAttribute constructor, defaulting
to ``True``.

For example::

    number = ScenegraphAttr.DoubleAttr(2)
    group = ScenegraphAttr.GroupAttr(True, {"anumber": number})

becomes::

    number = FnAttribute.DoubleAttribute(2)
    group = FnAttribute.GroupAttribute({"anumber": number}, True)

or::

    number = FnAttribute.DoubleAttribute(2)
    group = FnAttribute.GroupAttribute({"anumber": number})

Differences in Method Names
---------------------------
The following table lists the methods that have different names but are
otherwise functionally identical.

+------------------------+-----------------------------+
| ``ScenegraphAttr``     | ``FnAttribute``             |
+========================+=============================+
| ``childByIndex``       | ``getChildByIndex``         |
+------------------------+-----------------------------+
| ``childByName``        | ``getChildByName``          |
+------------------------+-----------------------------+
| ``getNumTimeSamples``  | ``getNumberOfTimeSamples``  |
+------------------------+-----------------------------+
| ``inheritChildren``    | ``getGroupInherit``         |
+------------------------+-----------------------------+

Replaced Methods
----------------
Several methods and functions that were available in ``ScenegraphAttr`` should
be updated to replacements in ``FnAttribute`` or other modules, as listed in
the following table.

+-----------------------------------------+-----------------------------------------------------------+
| ``ScenegraphAttr``                      | Replacement                                               |
+=========================================+===========================================================+
| ``ParseXML``                            | ``FnAttribute.Attribute.parseXML``                        |
+-----------------------------------------+-----------------------------------------------------------+
| ``getInterpSample``                     | ``FnAttribute.Util.ResampleAttrWithInterp``               |
+-----------------------------------------+-----------------------------------------------------------+
| ``getSamples(start, end)``              | ``FnAttribute.Util.RemoveTimeSamplesUnneededForShutter``  |
|                                         |                                                           |
| [NB: ``getSamples()`` with no arguments |                                                           |
| remains identical]                      |                                                           |
+-----------------------------------------+-----------------------------------------------------------+

Removed Methods
---------------

``childDict()`` and ``childNames()``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No direct equivalents of ``ScenegraphAttr.GroupAttr``'s ``childDict()`` and
``childNames()`` methods are available in ``FnAttribute.GroupAttribute``, but
their results can be trivially obtained via ``FnAttribute.GroupAttribute``'s
``childList()`` method, specifically ``dict(groupAttribute.childList())`` and
``dict(groupAttribute.childList()).keys()`` (or similar), respectively.

``childByNameAndDimension()``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No equivalent to ``ScenegraphAttr.GroupAttr``'s ``childByNameAndDimension()``
method is available in ``FnAttribute.GroupAttribute``. It was functionally
equivalent to::

    def childByNameAndDimension(groupAttribute, attrName, tupleSize,
                                numElements):
       child = groupAttribute.getChildByName(attrName)

       if isinstance(child, FnAttribute.DataAttribute):
           if (child.getTupleSize() == tupleSize
                   and child.getNumberOfTuples() == numElements):
               return child

       elif isinstance(child, FnAttribute.GroupAttribute):
           if tupleSize <= 0 or numElements <= 0:
               return child

       return None

``CalcTransformMatrix()``
^^^^^^^^^^^^^^^^^^^^^^^^^
``ScenegraphAttr`` contained a convenience function ``CalcTransformMatrix()``
for calculating the transform encoded in a given ``GroupAttribute``.  This
function returned the transform matrix as a 16-tuple of ``double`` s.  No
direct equivalent is available, but its result can be trivially obtained via
``PyFnGeolibServices.XFormUtil.CalcTransformMatrixAtTime()`` as::

    def CalcTransformMatrix(attr):
        xform, isAbs = \
            PyFnGeolibServices.XFormUtil.CalcTransformMatrixAtTime(attr, 0.0)
        return (xform.getData(), isAbs)

``Push<Transform>Attr()``
^^^^^^^^^^^^^^^^^^^^^^^^^
``ScenegraphAttr`` contained top-level utility functions for appending various
transform attributes to a ``GroupAttr`` object. These included
``PushMatrixAttr()``, ``PushOriginAttr()``, ``PushRotateAttr()``,
``PushScaleAttr()``, and ``PushTranslateAttr()``. Equivalent functions are
available in ``PyFnGeolibServices.XFormUtil``.