Dependency Class

From TouchDesigner 099 Wiki

A Dependency object is a value that automatically causes any expression referencing it to update when the dependency value has changed. These objects eliminate the need to manually force cook operators referencing values in Extensions or Storage for example.

For information about dependencies in mutable objects (lists, dicts, sets), see Deeply Dependable Collections.


Members

val The value associated with this object. Referencing this value in an expression will cause the operator to become dependent on its value. Setting this value will cause those operators to be recooked as necessary.
peekVal (Read Only) This returns the same value as .val but does not create a dependency on the value.
notify (Read Only) A list of custom python objects that can be added to. When the Dependency object is modified, it calls .modified(Dep) on each item on the list.
ops (Read Only) A list of operators currently dependent on the object.
listAttributes (Read Only) A list of list attributes currently dependent on the object.


Methods

modified()

This call is needed when changing not the value itself, but a subcomponent. For example, if Dependency.val is a dictionary, setting any of the members will not notify the dependent operators. A call to modified is necessary.


Miscellaneous

__getstate__()dict

Returns a dictionary with persistent data about the object suitable for pickling and deep copies.

__setstate__(dict)

Reads the dictionary to update persistent details about the object, suitable for unpickling and deep copies.


Usage

Consider the following module, used as an extension in a component called comp1 for example

class MyClass:
    def __init__(self):
        self.Scale = 5

Any expressions that reference Scale will not update when Scale is manually changed. For example, if either of these expressions was in the value field of a Constant CHOP, it would not be updated if the Scale value was updated.

Example:

# using a non-promoted extension
op('comp1').ext.MyClass.Scale
 
# using a promoted extension
op('comp1').Scale

If you need your references to dynamically update, you can create a Dependency. Start by defining a tdu.Dependency as below:

class MyClass:
    def __init__(self):
        self.Scale = tdu.Dependency(5)

Now there is a cook dependency created between the Scale value, and the Operator referencing it. There are two ways to reference the value. The first is similar to how we were referencing the value previous:

# using a non-promoted extension
op('comp1').ext.MyClass.Scale
 
# using a promoted extension
op('comp1').Scale

and the other method is to explicitly call the Scale's val:

# use for non-promoted extension
op('comp1').ext.MyClass.Scale.val
 
# use for a promoted extension
op('comp1').Scale.val

Note the .val is often not required, as the Dependency object will cast itself to its underlying value in most cases.

To update this value, you must reference the member's val. A Dependency value is a type in and of itself and writing the expression below would actually overwrite the Dependency value with a regular interger and remove the cook dependency from the references:

# wrong way to update dependency of a promoted extension
op('comp1').Scale = 5

What you should do instead is assign the value to the val of the Dependency as below:

# correct way to update dependency of a promoted extension
op('comp1').Scale.val = 5

Using this method will update the value of Scale while keeping the Dependency intact.

If Scale were a dictionary or list, instead of an integer, float or string, changes to items in the dictionary, would need to be followed by .modified() as in the example below:

Scale.modified()