Sequential Parameters

From Derivative
Jump to navigation Jump to search


The Basics[edit]

Sequential Parameters are sets of parameters (sequence blocks) that can be dynamically repeated multiple times. For example, the Add SOP lets you create multiple points by clicking the + button in the parameter dialog.

( See "Creating Custom Sequential Parameters" at the end of this page to create your own sequential blocks. )

All parameter sequences start with a sequence header parameter with a + and - button, followed by one or more "blocks" of parameters. The image below shows the parameter dialog for Add SOP's Points page. The sequence header has the label "Point", and is followed by two sequence blocks, each block containing a Position and a Weight parameter.

Seqpars.png

The parameters in sequence blocks are named in the form:

<sequence name><sequence index><parameter name>
  • sequence name: the sequence name, which is also the name of the sequence's header parameter
  • block index: the zero-based index of the block in the sequence
  • parameter name: the descriptive name of the parameter

In the example below, the sequence parameters are expanded to show their Python names. The sequence name is "point".

Expanded seq.png

You can add and remove sequential parameter blocks in multiple ways. The + and - buttons in the header add and remove sequence blocks respectively. You can also choose Insert Block or Remove Block in the RMB menu after right-clicking on a block parameter's name in the parameter dialog. Lastly, you can use Python (see Python section below)

Sequence Helpers for Parameter Expressions[edit]

In a parameter expression, you can use:

  • me.curSeq to access the sequence of the parameter currently being evaluated.
  • me.curSeq.numBlocks to access the number of blocks in the sequence of the parameter currently being evaluated. len(me.curSeq) works too.
  • me.curBlock to access the sequence block of the parameter currently being evaluated.
  • With that you can refer to any other parameter in the block, for example, me.curBlock.par.posz, not needing to specify the sequence name or block number.

Below are some examples:

CurBlock.png

See what else you can use here: Sequence Class, SequenceBlock Class, SequenceCollection Class.


Working with Sequential Parameters in Python[edit]

There are a number of utility classes, members, and methods that allow you to work with sequential parameters in Python. This section will give an overview of these features, but for detailed documentation please refer to: Sequence Class, SequenceBlock Class, SequenceCollection Class

Sequence Objects[edit]

Sequence objects are the main interface for interacting with parameter sequences in Python. They can be accessed via the sequence member of any parameter in a sequence or via the sequence name and seq member of operators.

mySequence = op('/add1').par.point0posx.sequence	# get the sequence object
sameSequence = op('/add1').seq.point				# another way to get the sequence object

Every sequence has a unique sequence name. This name is used to identify the sequence and to prefix the names of all block parameters. It is also the name of the sequence header parameter. You can find the sequence name by hovering over the sequence header's label or by looking at the block parameter names. It is also stored in the sequence object's name member.

Sequence Blocks[edit]

Sequence blocks are the blocks of parameters that are repeated in parameter sequences. The blocks in a sequence can be accessed and controlled using through the Sequence object. The following examples use the point sequence shown in the ADD SOP images above.

seq = op('/add1').seq.point				# get the sequence object with the name "vec"
alsoSeq = op('/add1').seq['point']		# you can also use bracket notation
allBlocks = seq.blocks					# list of all sequence blocks
count = len(seq)						# number of sequence blocks
firstBlock = seq[0]						# first block in the sequence
print(firstBlock.index)					# print the parameter block's index within the sequence. 0 in this case

You can also use the sequece object to control the number of blocks in the sequence:

seq.numBlocks = 4						# set the number of blocks to 4
seq.insertBlock(2)						# insert a block at position 2
seq.destroyBlock(0)						# destroy the first block

Sequence blocks provide easy access to the parameters within the block, using the familiar par and parGroup collection classes. Note that when accessing parameters from a sequence block, you use their base names (no sequence prefix) instead of their full names. The examples below illustrate this, again using the Add SOP images above:

seq = op('/add1').seq.point				# get the sequence object with the name "vec"
block = seq[1]							# second block in the sequence

block.par.weight = 3					# access the block's "weight" parameter. Its actual name is "point1weight"
block.par['weight'] = 4					# you can also use bracket notation
block.parGroup.pos = [1,1,1]			# access the block's "pos" parameter group.

Parameters in Sequence Blocks[edit]

Three ways to get a parameter in a sequence.

op('add1').par.point1posx                # normal 
op('add1').seq.point[1].par.point1posx   # by block index 
op('add1').seq.point[1].par.posx         # simplest, by block index

There are a number of ways to iterate through a given parameter in each block:

seq = op('add1').seq.point

# print the value of all weight parameters

# using Sequence.blocks
for block in seq.blocks:
	print(block.par.weight)
	
# using Sequence[blockIndex]
for index in range(len(seq)):
	print(seq[index].par.weight.eval())
	
# using Sequence.blockPars:
for weightPar in seq.blockPars.weight:
	print(weightPar.eval())

Sequence Helper Members in Parameters and ParGroups[edit]

There are a few helper members to work with sequences, built directly into parameters and parGroups:

# parameter helpers
par = op('/add1').par.point0weight	
print(par.sequence)						# prints the sequence object. Will be None if the parameter is not in a sequence

# parGroup helpers
parGroup = op('/add1').parGroup.point1pos		
print(parGroup.sequence)				# prints the sequence object. Will be None if the parGroup is not in a sequence
print(parGroup.sequenceIndex)			# prints the index of the parGroup's sequence block within the sequence. 1 in this case
print(parGroup.blockIndex)				# prints the index of the parGroup within its block. 0 in this case (it is the first par in the block)


Creating Custom Sequential Parameters[edit]

You can create custom sequential parameters on your components using the Component Editor. You can create a sequence in two ways:

Method One[edit]

  1. Create a Sequence parameter, which creates the sequence header
  2. Create the block parameters you want below the Sequence parameter
  3. Change the Sequence parameter's numBlocks to the number of block parameters you created

Method Two[edit]

  1. Create the block parameters you want
  2. Select the block parameters
  3. Right-click on one of the selected parameters and choose Create Sequence

Adding and Removing Parameters from the Sequence[edit]

There are a few ways to add or remove parameters from a sequence:

  • Drag them into or out of the sequence.
  • Select them in the parameter list and choose Add To Sequence or Remove From Sequence in the RMB menu.
  • Change the numBlocks member of the Sequence header parameter.

Referring to Another Block[edit]

Referring to another block in your sequence, where blocks may be re-ordered, deleted or inserted requires something invariant in blocks. For example, me.curSeq[3] will become me.curSeq[2] if you delete any of the prior blocks 0, 1 or 2.

However if you create a parameter in a block called Blockid, then when you create a new block, its value is automatically set to a unique number. Say a parameter called .Blockid in a block has been set to 7. To get that block any time in the future, you can write me.curSeq.id(7) and you will always get the same block. And to get to a parameter of that block, you write me.curSeq.id(7).par.Speed, for example.

If you make the original parameter of the block Read-only, then any newly-created Blockid parameters will be read-only, which is preferable as you don't want anyone accidentally changing it.