<chapter id="ParametersChapter"><title>Effect Parameters</title>
  <section id="ParametersIntro">
    <title>Introduction</title>
    <para>
      Nearly all plug-ins have some sort of parameters that control their behaviour, the radius
      of a circle drawer, the frequencies to filter out of an audio signal, the colour of a lens flare 
      and so on.
    </para>
    <para>
      Seeing as hosts already provide for the general management of their own native parameters (eg: persistence, 
      interface, animation etc...), it would make no sense to force plug-ins to do this all themselves. 
    </para>
    <para>
      The OFX Parameters Suite is the means by which  parameters are defined and used by the 
      plug-in but maintained by the host. It is defined in the ofxParam.h header file.
    </para>
    <para>
      Note that the entire state of the plugin is encoded in the value of its parameter set. If you need to persist some sort of private data,
      you must do so by setting param values in the effects. The <link linkend="kOfxActionSyncPrivateData">Sync Private Data Action</link> is
      an action that tells you when to flush any values that need persisting out to the effects param set. You can reconstruct your private
      data during the <link linkEnd="kOfxActionCreateInstance">Create Instance Action</link>.
    </para>
  </section>
  
  <section id="ParametersDefining">
    <title>Defining Parameters</title>
    <para>
      A plugin needs to define it's parameters during a describe action. It does this with the <link linkend='OfxParameterSuiteV1_paramDefine'><code>OfxParameterSuiteV1::paramDefine</code></link> function, which returns a handle to a parameter <emphasis>description</emphasis>. Parameters cannot currently be defined outside of the plugins describe actions.
    </para>
    <para>
      Parameters are uniquely labelled within a plugin with an ASCII null terminated C-string. This name is not necassarily meant to be end-user readable, various properties are provided to set the user visible labels on the param.
    </para>
    <para>
      All parameters hold properties, though the exact set of properties on a parameter is dependant on the type of the parameter. 
    </para>
    <para>
      A parameter's handle comes in two slightly different flavours. The handle returned inside a plugin's describe action is not an actual instance of a parameter, it is there for the purpose description only. You can only set properties on that handle (eg: label, min/max value, default ...), you cannot get values from it or set values in it. The parameters defined in the describe action will common to all instances of a plugin.
    </para>
    <para>
      The handle returned by <link linkend='OfxParameterSuiteV1_paramGetHandle'><code>OfxParameterSuiteV1::paramGetHandle</code></link> outside of a describe action will be a working instance of a parameter, you can still set (some) properties of the parameter, and all the get/set value functions are now useable.
    </para>
  </section>
  
  <section id="ParametersTypes"><title>Parameter Types</title>
    <para>
      There are seventeen types of parameter. These are 
      <itemizedlist>
	<listitem>integers, 1, 2 and 3 dimensional</listitem>
	<listitem>doubles, 1, 2 and 3 dimensional</listitem>
	<listitem>colour, RGB and RGB + Alpha</listitem>
	<listitem>booleans</listitem>
	<listitem>choice </listitem>
	<listitem>string</listitem>
	<listitem>custom</listitem>
	<listitem>push button</listitem>
	<listitem>group</listitem>
	<listitem>page</listitem>
	<listitem>parametric</listitem>
      </itemizedlist>
    </para>
    
    
    <section id='ParametersMultiDimensional'><title>Multidimensional Parameters</title>
      <para>
	Some parameter types are multi dimensional, these are...
	<itemizedlist>
	  <listitem><code>kOfxParamTypeDouble2D</code>    - 2 doubles</listitem>
	  <listitem><code>kOfxParamTypeInteger2D</code>   - int X 2</listitem>
	  <listitem><code>kOfxParamTypeDouble3D</code>    - double X 3</listitem>
	  <listitem><code>kOfxParamTypeInteger3D</code>   - int X 3</listitem>
	  <listitem><code>kOfxParamTypeRGB</code>         - double X 3</listitem>
	  <listitem><code>kOfxParamTypeRGBA</code>        - double X 4</listitem>
	  <listitem><code>kOfxParamTypeParametric</code>  - variable dimension</listitem>
	</itemizedlist>
      </para>
      <para>
	These parameters are treated in an atomic manner, so that all dimensions are set/retrieved simultaneously. This applies to keyframes as well.
      </para>
      <para>
	The non colour parameters have an implicit 'X', 'Y' and 'Z' dimension, and any interface should display them with such labels.
      </para>
    </section>
    
    <section id='ParametersInteger'><title>Integer Parameters</title>
      <para>
	These are typed by <code>kOfxParamTypeInteger</code>, <code>kOfxParamTypeInteger2D</code> and <code>kOfxParamTypeInteger3D</code>.
      </para>
      <para>
	Integer parameters are of 1, 2 and 3D varieties and contain integer values, between INT_MIN and INT_MAX. 
      </para>
    </section>
    
    <section id='ParametersDouble'><title>Double Parameters</title>
      
      <para>
	These are typed by <code>kOfxParamTypeDouble</code>, <code>kOfxParamTypeDouble2D</code> and <code>kOfxParamTypeDouble3D</code>.
      </para>
      <para>
	Double parameters are of 1, 2 and 3D varieties and contain double precision floating point values. 
      </para>
    </section>
    <section id='ParametersColour'><title>Colour Parameters</title>
      <para>
	These are typed by <code>kOfxParamTypeRGB</code> and <code>kOfxParamTypeRGBA</code>.
      </para>
      <para>
	Colour parameters are 3 or 4 dimensional double precision floating point parameters. They are displayed using the host's appropriate interface for a colour. Values are always normalised in the range [0 .. 1], with 0 being the nominal black point and 1 being the white point.
      </para>
    </section>
    
    <section id='kOfxParamTypeBoolean'><title>Boolean Parameters</title>
      
      <para>
	This is typed by <code>kOfxParamTypeBoolean</code>.
      </para>
      <para>
	Boolean parameters are integer values that can have only one of two values, 0 or 1. 
      </para>
    </section>
    
    <section id='ParametersChoice'><title>Choice Parameters</title>
      
      <para>
	This is typed by <code>kOfxParamTypeChoice</code>.
      </para>
      <para>
	Choice parameters are integer values from 0 to N-1, which correspond to N labeled options. 
      </para>
      <para>
	Choice parameters have their individual options set via the <link linkend='kOfxParamPropChoiceOption'><code>kOfxParamPropChoiceOption</code></link> property, for example
      </para>
      <blockquote><programlisting>gPropHost->propSetString(myChoiceParam, kOfxParamPropChoiceOption, 0, "1st Choice");
gPropHost->propSetString(myChoiceParam, kOfxParamPropChoiceOption, 1, "2nd Choice");
gPropHost->propSetString(myChoiceParam, kOfxParamPropChoiceOption, 2, "3nd Choice");
...
gPropHost->propSetString(myChoiceParam, kOfxParamPropChoiceOption, n, "nth Choice");</programlisting></blockquote>

      <para>
	It is an error to have gaps in the choices after the describe action has returned.
      </para>
    </section>
    
    <section id='kOfxParamTypeString'><title>String Parameters</title>
      <para>
	This is typed by <code>kOfxParamTypeString</code>.
      </para>
      <para>
	String parameters contain null terminated <code>char *</code> UTF8 C strings. They can be of several different variants, which is controlled by the <link linkend='kOfxParamPropStringMode'><code>kOfxParamPropStringMode</code></link> property, these are 
      </para>
      
      <para>
	<itemizedlist>
	  <listitem><code>kOfxParamStringIsSingleLine</code> - single line string</listitem>
	  <listitem><code>kOfxParamStringIsMultiLine</code>  - multi line string</listitem>
	  <listitem><code>kOfxParamStringIsFilePath</code>   - single line string interpretted as a file path on the computer
	  this should have appropriate file browser UIs available</listitem>
	  <listitem><code>kOfxParamStringIsDirectoryPath</code> - similar to the above, but refers to a directory rather than a file</listitem>
	  <listitem><code>kOfxParamStringIsLabel</code>      - string behaves as a pseudo parameter and acts as a label on the interface in this case the string is not editable by the user</listitem>
	</itemizedlist>
      </para>
    </section>
    <section id='kOfxParamTypeGroup'><title>Group Parameters</title>
      <para>
	This is typed by <code>kOfxParamTypeGroup</code>.
      </para>
      <para>
	Group parameters allow all parameters to be arranged in a tree hierarchy. They have no value, they are purely a grouping element.
      </para>
      <para>
	All parameters have a <link linkend='kOfxParamPropParent'><code>kOfxParamPropParent</code></link> property, which is a string property naming the group parameter which is its parent. 
      </para>
      <para>
	The empty string "" is used to label the root of the parameter hierarchy, which is the default parent for all parameters.
      </para>
      <para>
	Parameters inside a group are ordered by their order of addition to that group, which implies parameters in the root group are added in order of definition.
      </para>
      <para>
	Any host based hierarchical GUI should use this hierarchy to order parameters (eg: animation sheets).
      </para>
    </section>
    
    <section id='kOfxParamTypePage'><title>Page Parameters</title>
      
      <para>
	This is typed by <code>kOfxParamTypePage</code>.
      </para>
      
      <para>
  Page parameters are covered in detail in their own <link linkend="ParametersInterfacesPagedLayouts">section.</link>.
      </para>
    </section>
    
    <section id='kOfxParamTypeCustom'><title>Custom Parameters</title>
      
      <para>
	This is typed by <code>kOfxParamTypeCustom</code>.
      </para>
      
      <para>
	Custom parameters contain null terminated char * C strings, and may animate. They are designed to provide plugins with a way of storing data that is too complicated or impossible to store in a set of ordinary parameters. 
      </para>
      
      <para>
	If a custom parameter animates, it must set its <link linkend='kOfxParamPropCustomInterpCallbackV1'><code>kOfxParamPropCustomInterpCallbackV1</code></link> property, which points to a OfxCustomParamInterpFuncV1 function. This function is used to interpolate keyframes in custom params.
      </para>
      
      <para>
	Custom parameters have no interface by default. However,
      </para>
      <itemizedlist>
	<listitem>if they animate, the host's animation sheet/editor should present a keyframe/curve representation to allow positioning of keys and control of interpolation. The 'normal' (ie: paged or hierarchical) interface should not show any gui.</listitem>g
	<listitem>if the custom param sets its <link linkend='kOfxParamPropInteractV1'><code>kOfxParamPropInteractV1</code></link> property, this should be used by the host in any normal (ie: paged or hierarchical) interface for the parameter.</listitem>
      </itemizedlist>
      
      <para>
	Custom parameters are mandatory, as they are simply ASCII C strings. However, animation of custom parameters an support for an in editor interact is optional.
      </para>
    </section>
    
    <section id='kOfxParamTypePushButton'><title>Push Button Parameters</title>
      
      <para>
	This is typed by <code>kOfxParamTypePushButton</code>.
      </para>
      <para>
	Push button parameters have no value, they are there so a plugin can detect if they have been pressed and perform some action. If pressed, a <link linkend='kOfxActionInstanceChanged'><code>kOfxActionInstanceChanged</code></link> action will be issued on the parameter with a <link linkend='kOfxPropChangeReason'><code>kOfxPropChangeReason</code></link> of <code>kOfxChangeUserEdited</code>.
      </para>
    </section>
  </section>
  
  <section id="ParametersAnimation"><title>Animation</title>
    <para>
      By default the following parameter types animate...
      <itemizedlist>
	<listitem><code>kOfxParamTypeInteger</code></listitem>
	<listitem><code>kOfxParamTypeInteger2D</code></listitem>
	<listitem><code>kOfxParamTypeInteger3D</code></listitem>
	<listitem><code>kOfxParamTypeDouble</code></listitem>
	<listitem><code>kOfxParamTypeDouble2D</code></listitem>
	<listitem><code>kOfxParamTypeDouble3D</code></listitem>
	<listitem><code>kOfxParamTypeRGBA</code></listitem>
	<listitem><code>kOfxParamTypeRGB</code></listitem>
      </itemizedlist>
    </para>
    <para>
      The following types cannot animate...
      <itemizedlist>
	<listitem><code>kOfxParamTypeGroup</code></listitem>
	<listitem><code>kOfxParamTypePage</code></listitem>
	<listitem><code>kOfxParamTypePushButton</code></listitem>
      </itemizedlist>
    </para>
    
    <para>
      The following may animate, depending on the host. Properties exist on the host to check this. If the host does support animation on them, then they do _not_ animate by default. They are...
      <itemizedlist>
	<listitem><code>kOfxParamTypeCustom</code></listitem>
	<listitem><code>kOfxParamTypeString</code></listitem>
	<listitem><code>kOfxParamTypeBoolean</code></listitem>
	<listitem><code>kOfxParamTypeChoice</code></listitem>
      </itemizedlist>
    </para>
    <para>
      By default the <link linkend='OfxParameterSuiteV1_paramGetValue'><code>OfxParameterSuiteV1::paramGetValue</code></link> will get the 'current' value of the parameter. To access values in a potentially animating parameter, use the <link linkend='OfxParameterSuiteV1_paramGetValueAtTime'><code>OfxParameterSuiteV1::paramGetValueAtTime</code></link> function.
    </para>
    <para>
      Keys can be manipulated in a parameter using a variety of functions, these are...
      <itemizedlist>
	<listitem><link linkend='OfxParameterSuiteV1_paramSetValueAtTime'><code>OfxParameterSuiteV1::paramSetValueAtTime</code></link></listitem>
	<listitem><link linkend='OfxParameterSuiteV1_paramGetNumKeys'><code>OfxParameterSuiteV1::paramGetNumKeys</code></link></listitem>
	<listitem><link linkend='OfxParameterSuiteV1_paramGetKeyTime'><code>OfxParameterSuiteV1::paramGetKeyTime</code></link></listitem>
	<listitem><link linkend='OfxParameterSuiteV1_paramGetKeyIndex'><code>OfxParameterSuiteV1::paramGetKeyIndex</code></link></listitem>
	<listitem><link linkend='OfxParameterSuiteV1_paramDeleteKey'><code>OfxParameterSuiteV1::paramDeleteKey</code></link></listitem>
	<listitem><link linkend='OfxParameterSuiteV1_paramDeleteAllKeys'><code>OfxParameterSuiteV1::paramDeleteAllKeys</code></link></listitem>
      </itemizedlist>
    </para>
    
  </section>
  
  <section id="ParametersInterfaces"><title>Parameter Interfaces</title>
    
    <para>
      Parameters will be presented to the user in some form of interface. Typically on most host systems, this comes in three varieties...
      <itemizedlist>
	<listitem>a paged layout, with parameters spread over multiple controls pages (eg: the FLAME control pages)</listitem>
	<listitem>a hierarchical layout, with parameters presented in a grouped tree (eg: the After Effects 'effects' window)</listitem>
	<listitem>an animation sheet, showing animation curves and key frames. Typically this is hierarchical.</listitem>
      </itemizedlist>
    </para>
    <para>
      Most systems have an animation sheet and present one of either the paged or the hierarchical layouts. 
    </para>
    <para>
      Because a hierarchy of controls is explicitly set during plugin definition, the case of the animation sheet and hierarchial GUIs are taken care of explicitly.
    </para>
    <section id='ParametersInterfacesPagedLayouts'><title>Paged Parameter Editors</title>
      
      <para>
	A paged layout of controls is difficult to standardise, as the size of the page and controls, how the controls are positioned on the page, how many controls appear on a page etc... depend very much upon the host implementation. A paged layout is ideally best described in the .XML resource supplied by the plugin, however a fallback page layout can be specified in OFX via the <code>kOfxParamTypePage</code> parameter type.
      </para>
      <para>
	Several host properties are associated with paged layouts, these are...
	<itemizedlist>
	  <listitem><link linkend='kOfxParamHostPropMaxPages'><code>kOfxParamHostPropMaxPages</code></link> - the maximum number of pages you may use, 0 implies an unpaged layout</listitem>
	  <listitem><link linkend='kOfxParamHostPropPageRowColumnCount'><code>kOfxParamHostPropPageRowColumnCount</code></link> - the number of rows and columns for parameters in the paged layout.</listitem>
	</itemizedlist>
      </para>
      
      <para>
	Each page parameter represents a page of controls. The controls in that page are set by the plugin using the <link linkend='kOfxParamPropPageChild'><code>kOfxParamPropPageChild</code></link> multi-dimensional string. For example...
      </para>
      <blockquote><programlisting>OfxParamHandle  page;
gHost->paramDefine(plugin, kOfxParamTypePage, "Main", &amp;page);
	  
propHost->propSetString(page, kOfxParamPropPageChild, 0, "size");      // add the size parameter to the top left of the page
propHost->propSetString(page, kOfxParamPropPageChild, 1, kOfxParamPageSkipRow); // skip a row
propHost->propSetString(page, kOfxParamPropPageChild, 2, "centre");    // add the centre parameter
propHost->propSetString(page, kOfxParamPropPageChild, 3, kOfxParamPageSkipColumn); // skip a column, we are now at the top of the next column
propHost->propSetString(page, kOfxParamPropPageChild, 4, "colour"); // add the colour parameter </programlisting></blockquote>

      <para>
	The host then places the parameters on that page in the order they were added, starting at the top left and going down columns, then across rows as they fill.
      </para>
      <para>
	Note that there are two pseudo parameters names used to help control layout, the <code>kOfxParamPageSkipRow</code> and <code>kOfxParamPageSkipColumn</code>. These will help control how parameters are added to a page, allowing vertical or horizontal slots to be skipped.
      </para>
      <para>
	A host sets the order of pages by using the instance's <link linkend='kOfxPluginPropParamPageOrder'><code>kOfxPluginPropParamPageOrder</code></link> property. Note that this property can vary from context to context, so you can exclude pages in contexts they are not useful in. For example...
      </para>
<blockquote><programlisting>OfxStatus describeInContext(OfxImageEffectHandle plugin)
{
...
    // order our pages of controls
    propHost->propSetString(paramSetProp, kOfxPluginPropParamPageOrder, 0, "Main");
    propHost->propSetString(paramSetProp, kOfxPluginPropParamPageOrder, 1, "Sampling");
    propHost->propSetString(paramSetProp, kOfxPluginPropParamPageOrder, 2, "Colour Correction");
    if(isGeneralContext)
       propHost->propSetString(paramSetProp, kOfxPluginPropParamPageOrder, 3, "Dance! Dance! Dance!");
...
} </programlisting></blockquote>

      &note;
      <para>
	<itemizedlist>
	  <listitem>parameters <emphasis>can</emphasis> be placed on more than a single page (this is often useful),</listitem>
	  <listitem>group parameters cannot be added to a page,</listitem>
	  <listitem>page parameters cannot be added to a page or group.</listitem>
	</itemizedlist>
      </para>
    </section>
    
    <section id='ParametersInterfacesUndoRedo'><title>Parameter Undo/Redo</title>
      
      <para>
	Hosts usually retain an undo/redo stack, so users can undo changes they make to a parameter. Often undos and redos are grouped together into an undo/redo block, where multiple parameters are dealt with as a single undo/redo event. Plugins need to be able to deal with this cleanly. 
      </para>
      
      <para>
	Parameters can be excluded from being undone/redone if they set the <link linkend='kOfxParamPropCanUndo'><code>kOfxParamPropCanUndo</code></link> property to 0.
      </para>
      
      <para>      If the plugin changes parameters' values by calling the get and set value functions, they will ordinarily be put on the undo stack, one event per parameter that is changed. If the plugin wants to group sets of parameter changes into a single undo block and label that block, it should use the <link linkend='OfxParameterSuiteV1_paramEditBegin'><code>OfxParameterSuiteV1::paramEditBegin</code></link> and <link linkend='OfxParameterSuiteV1_paramEditEnd'><code>OfxParameterSuiteV1::paramEditEnd</code></link> functions.
      </para>
      
      <para>
	An example would be a 'preset' choice parameter in a sky simulation whose job is to set other parameters to values that achieve certain looks, eg "Dusk", "Midday", "Stormy", "Night" etc... This parameter has a value change callback which looks for  <code>kOfxParamEventUserEdited</code> then sets other parameters, sky colour, cloud density, sun position etc.... It also resets itself to the first choice, which says "Example Skys...". 
      </para>
      
      <para>
	Rather than have many undo events appear on the undo stack for each individual parameter change, the effect groups them via the paramEditBegin/paramEditEnd and gets a single undo event. The 'preset' parameter would also not want to be undoable as it such an event is redunant. Note that as the 'preset' has been changed it will be sent another instance changed action, however it will have a reason of <code>kOfxChangePluginEdited</code>, which it ignores and so stops an infinite loop occuring.
      </para>
    </section>
  </section>
  <section id='ParametersXML'><title>XML Resource Specification for Parameters</title>
    <para>
      Parameters can have various properties overriden via a seperate XML based resource file. 
    </para>
  </section>
  
  <section id="ParametersPersistence"><title>Parameter Persistence </title>
    
    <para>
      All parameters flagged with the <link linkend='kOfxParamPropPersistent'><code>kOfxParamPropPersistent</code></link> property will persist when an effect is saved. How the effect is saved is completely up to the host, it may be in a file, a data base, where ever. We call a saved set of parameters a <emphasis>setup</emphasis>. A host will need to save the major version number of the plugin, as well as the plugin's unique identifier, in any setup.
    </para>
    <para>
      When an host loads a set up it should do so in the following manner...
      <orderedlist>
	<listitem> examines the setup for the major version number.</listitem>
	<listitem> find a matching plugin with that major version number, if multiple minor versions exist, the plugin with the largest minor version should be used.</listitem>
	<listitem> creates an instance of that plugin with its set of parameters.</listitem>
	<listitem> sets all those parameters to the defaults specified by the plugin.</listitem>
	<listitem> examines the setup for any persistent parameters, then sets the instance's parameters to any found in it.</listitem>
	<listitem> calls create instance on the plugin.</listitem>
      </orderedlist>
    </para>
    <para>
      It is <emphasis>not</emphasis> an error for a parameter to exist in the plugin but not the setup, and vice versa. This allows a plugin developer to modify parameter sets between point releases, generally by adding new params. The developer should be sure that the default values of any new parameters yield the same behaviour as before they were added, otherwise it would be a breach of the 'major version means compatibility' rule.
    </para>
  </section>
  
  <section id="ParameterPropertiesVariantTypes"><title>Parameter Properties Whose Type Vary</title>
    <para>
      Some properties type depends on the kind of the parameter, eg: <link linkend='kOfxParamPropDefault'><code>kOfxParamPropDefault</code></link> is an int for a integer parameter but a double X 2 for a <code>kOfxParamTypeDouble2D</code> parameter.
    </para>
    <para>
      The variant property types are as follows....
      <itemizedlist>
	<listitem><code>kOfxParamTypeInteger</code>    - int X 1</listitem>
	<listitem><code>kOfxParamTypeDouble</code>     - double X 1</listitem>
	<listitem><code>kOfxParamTypeBoolean</code>    - int X 1</listitem>
	<listitem><code>kOfxParamTypeChoice</code>     - int X 1</listitem>
	<listitem><code>kOfxParamTypeRGBA</code>       - double X 4 (normalised to 0..1 range)</listitem>
	<listitem><code>kOfxParamTypeRGB</code>        - double X 3 (normalised to 0..1 range)</listitem>
	<listitem><code>kOfxParamTypeDouble2D</code>   - double X 2</listitem>
	<listitem><code>kOfxParamTypeInteger2D</code>  - int X 2</listitem>
	<listitem><code>kOfxParamTypeDouble3D</code>   - double X 3</listitem>
	<listitem><code>kOfxParamTypeInteger3D</code>  - int X 3</listitem>
	<listitem><code>kOfxParamTypeString</code>     - char * X 1</listitem>
	<listitem><code>kOfxParamTypeCustom</code>     - char * X 1</listitem>
	<listitem><code>kOfxParamTypePushButton</code> - none</listitem>
      </itemizedlist>
    </para>
  </section>
  
  <section id="ParameterPropertiesDoubleTypes"><title>Types of Double Parameters</title>
    
    <para>
      Double parameters can be used to represent a variety of data, by flagging what a double parameter is representing, a plug-in allows a host to represent to the user a more appropriate interface than a raw numerical value. Double parameters have the <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> property, which gives some meaning to the value. This can be one of...
      <itemizedlist>
	<listitem><code>kOfxParamDoubleTypePlain</code> - parameter has no special interpretation,</listitem>
	<listitem><code>kOfxParamDoubleTypeAngle</code> - parameter is to be interpretted as an angle,</listitem>
	<listitem><code>kOfxParamDoubleTypeScale</code> - parameter is to be interpretted as a scale factor,</listitem>
	<listitem><code>kOfxParamDoubleTypeTime</code>  - parameter represents a time value (1D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeAbsoluteTime</code>  - parameter represents an absolute time value (1D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeX</code> - size in the X dimension, in canonical coords (1D double only),</listitem>
	<listitem><code>kOfxParamDoubleTypeXAbsolute</code> - positing in the X axis, in canonical coords (1D double only)</listitem>
	<listitem><code>kOfxParamDoubleTypeY</code> - size in the Y dimension, in canonical coords (1D double only),</listitem>
	<listitem><code>kOfxParamDoubleTypeYAbsolute</code> - positing in the Y axis, in canonical coords (1D double only)</listitem>
	<listitem><code>kOfxParamDoubleTypeXY</code> - 2D size, in canonical coords (2D double only),</listitem>
	<listitem><code>kOfxParamDoubleTypeXYAbsolute</code> - 2D position, in canonical coords. (2D double only)</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedX</code> - normalised size with respect to the project's X dimension (1D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedXAbsolute</code> - normalised absolute position on the X axis (1D only)</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedY</code> - normalised size wrt to the project's Y dimension(1D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedYAbsolute</code> - normalised absolute position on the Y axis (1D only)</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedXY</code> - normalised to the project's X and Y size (2D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedXYAbsolute</code> - normalised to the projects X and Y size, and is an absolute position on the image plane.</listitem>
      </itemizedlist>
    </para>
  
  <section id='kOfxParamDoubleTypePlain'><title>Plain Double Parameters </title>
    
    <para>
      Double parameters with their <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> property set to <code>kOfxParamDoubleTypePlain</code> are uninterpretted. The values represented to the user are what is reported back to the effect when values are retrieved. 1, 2 and 3D parameters can be flagged as <code>kOfxParamDoubleTypePlain</code>, which is the default.
    </para>
    
    <para>
      For example a physical simulation plugin might have a 'mass' double parameter, which is in kilograms, which should be displayed and used as a raw value.
    </para>
  </section>
  <section id='kOfxParamDoubleTypeAngle'><title>Angle Double Parameters </title>
    
    <para>
      Double parameters with their <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> property set to <code>kOfxParamDoubleTypeAngle</code> are interpretted as angles. The host could use some fancy angle widget in it's interface, representing degrees, angles mils whatever. However, the values returned to a plugin are always in degrees. Applicable to 1, 2 and 3D parameters.
    </para>
    
    <para>
      For example a plugin that rotates an image in 3D would declare a 3D double parameter and flag that as an angle parameter and use the values as Euler angles for the rotation.
    </para>
    
  </section>
  <section id='kOfxParamDoubleTypeScale'><title>Scale Double Parameters </title>
    
    <para>
      Double parameters with their <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> property set to <code>kOfxParamDoubleTypeScale</code> are interpretted as scale factors. The host can represent these as 1..100 percentages, 0..1 scale factors, fractions or whatever is appropriate for its interface. However, the plugin sees these as a straight scale factor, in the 0..1 range. Applicable to 1, 2 and 3D parameters.
    </para>
    <para>
      For example a plugin that scales the size of an image would declare a 'image scale' parameter and use the raw value of that to scale the image.
    </para>
  </section>
  <section id='kOfxParamDoubleTypeTime'><title>Time Double Parameters </title>
    
    <para>
      Double parameters with their <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> property set to <code>kOfxParamDoubleTypeTime</code> are interpretted as a time. The host can represent these as frames, seconds, milliseconds, millenia or whatever it feels is appropriate. However, a visual effect plugin sees such values in 'frames'. Applicable only to 1D double parameters. It is an error to set this on any other type of double parameter.
    </para>
    <para>
      For example a plugin that does motion blur would have a 'shutter time' parameter and flags that as a time parameter. The value returned would be used as the length of the shutter, in frames.</para>
  </section>
  <section id='kOfxParamDoubleTypeAbsoluteTime'><title>Absolute Time Double Parameters </title>
    
    <para>
      Double parameters with their <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> property set to <code>kOfxParamDoubleTypeAbsoluteTime</code> are interpretted as an absolute time from the begining of the effect. The host can represent these as frames, seconds, milliseconds, millenia or whatever it feels is appropriate. However, a plugin sees such values in 'frames' from the beginning of a clip. Applicable only to 1D double parameters. It is an error to set this on any other type of double parameter.
    </para>
    
    <para>
      For example a plugin that stabalises all the images in a clip to a specific frame would have a 'reference frame' parameter and declare that as an absolute time parameter and use its value to fetch a frame to stablise against.
    </para>
  </section>
  
  <section id='ParameterPropertiesDoubleTypesSpatial'><title>Spatial Parameters</title>
    <para> Parameters that can represent a size or position are essential. To that end there are several values of the <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> that say it should be interpretted as a size or position, in either one or two dimensions.</para>

    <para>The original OFX API only specifed <link linkend='ParameterPropertiesDoubleTypesNormalised'>normalised</link> parameters, this proved to be somewhat more of a problem than expected. With the 1.2 version of the API, <link linkend='ParameterPropertiesDoubleTypesStrictlySpatial'>spatial</link> parameters were introduced. Ideally these should be used and the normalised parameter types should be deprecated.</para>

  <para>Plugins can check <link linkend="kOfxPropAPIVersion">kOfxPropAPIVersion</link> to see if these new parameter types are supported, in hosts with version 1.2 or greater they will be.</para>
    <para>
      See the section on <link linkend="CoordinateSystems">coordinate systems</link> to understand some of the terms being discussed.
    </para>

    <section id='ParameterPropertiesDoubleTypesStrictlySpatial'><title>Spatial Double Parameters</title>
    
    <para>
      These parameter types represent a size or position in one or two dimensions in <link linkend="CanonicalCoordinates">Canonical Coordinate</link>. The host 
      and plug-in get and set values in this coordinate system. Scaling to  <link linkend='PixelCoordinates'>Pixel Coordinate</link> is the reponsibility of the effect.
    </para>

    <para>
      The default value of a spatial parameter can be set in either a normalised coordinate system or the canonical coordinate system. This is controlled by the <link linkend="kOfxParamPropDefaultCoordinateSystem">kOfxParamPropDefaultCoordinateSystem</link> on the parameter descriptor.
    </para>
    
    <para>
      Parameters can choose to be spatial in several ways...
      <itemizedlist>
	<listitem><code>kOfxParamDoubleTypeX</code> - size in the X dimension, in canonical coords (1D double only),</listitem>
	<listitem><code>kOfxParamDoubleTypeXAbsolute</code> - positing in the X axis, in canonical coords (1D double only)</listitem>
	<listitem><code>kOfxParamDoubleTypeY</code> - size in the Y dimension, in canonical coords (1D double only),</listitem>
	<listitem><code>kOfxParamDoubleTypeYAbsolute</code> - positing in the Y axis, in canonical coords (1D double only)</listitem>
	<listitem><code>kOfxParamDoubleTypeXY</code> - 2D size, in canonical coords (2D double only),</listitem>
	<listitem><code>kOfxParamDoubleTypeXYAbsolute</code> - 2D position, in canonical coords. (2D double only).</listitem>
      </itemizedlist>
    </para>
  </section>

  <section id='ParameterPropertiesDoubleTypesNormalised'><title>Spatial Normalised Double Parameters</title>
    <para>Ideally, normalised parameters should be deprecated and no longer used if <link linkend="ParameterPropertiesDoubleTypesSpatial">spatial</link> parameters are available.</para>

    <para>
      There are several values of the <link linkend='kOfxParamPropDoubleType'><code>kOfxParamPropDoubleType</code></link> that say it should be interpretted as a size or position. These are expressed  and proportional to the current project's size. This will allow the parameter to scale cleanly with project size changes and to be represented to the user in an appropriate range.
    </para>
    <para>
      For example, the sensible X range of a visual effect plugin is the project's width, say 768 pixels
      for a PAL D1 definition video project. The user sees the parameter as 0..768, the effect sees it as 0..1. So if
      the plug-in wanted to set the default value of an effect to be the centre of the image, it would flag a 2D 
      parameter as normalised and set the defaults to be 0.5. The user would see this in the centre of the
      image, no matter the resolution of the project in question. The plugin would retrieve the parameter as 0..1 and scale
      it up to the project size to size to use.
    </para>
    
    <para>
      Parameters can choose to be normalised in several ways...
      <itemizedlist>
	<listitem><code>kOfxParamDoubleTypeNormalisedX</code> - normalised size wrt to the project's X dimension (1D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedXAbsolute</code> - normalised absolute position on the X axis (1D only)</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedY</code> - normalised size wrt to the project's Y dimension(1D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedYAbsolute</code> - normalised absolute position on the Y axis (1D only)</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedXY</code> - normalised to the project's X and Y size (2D only),</listitem>
	<listitem><code>kOfxParamDoubleTypeNormalisedXYAbsolute</code> - normalised to the projects X and Y size, and is an absolute position on the image plane.</listitem>
      </itemizedlist>
    </para>
    <para>
      See the section on <link linkend="CoordinateSystems">coordinate systems</link> on how to scale between normalised, cannonical and pixel coordinates.
    </para>
  </section>
  
  </section>
  
  <section id='ParameterPropertiesDoubleTypesDefaultsAndAll'><title>Double Parameters Defaults, Increments, Mins and Maxs</title>
    
    <para>
      In all cases double parameters' defaults, minimums and maximums are specified in the same space as the parameter, as is the increment in all cases but normalised parameters.
    </para>
    
    <para>
      Normalised parameters specify thier increments in cannonical coordinates, rather than in normalised coordinates. So an increment of '1' means 1 pixel, not '1 project width', otherwise sliders would be a bit wild.
    </para>
  </section>
  </section>

  <section id="ParametersParametric">
    <title>Parametric Parameters</title>
  <section id="ParametersParametricIntro">
    <title>Introduction</title>
    <para>Parametric params are new for 1.2 and are optinally supported by host applications. They are specified via the
          <code>kOfxParamTypeParametric</code> identifier passed into 
          <link linkend='OfxParameterSuiteV1_paramDefine'><code>OfxParameterSuiteV1::paramDefine</code></link>.
    </para>
    <para>
       These parameters are somewhat more complex than normal parameters and require their own set of functions to manage and manipulate them. 
       The new <link linkend="OfxParametricParameterSuiteV1">OfxParametricParameterSuiteV1</link> is there to do that.</para>
    <para>
       All the defines and suite definitions for parameteric parameters are defined in the file <code>ofxParametricParam.h</code></para>
    <para> 
       Parametric parameters are in effect 'functions' a plug-in can ask a host to arbitrarily evaluate for some value 'x'. A classic use
       case would be for constructing look-up tables, a plug-in would ask the host to evaluate one at multiple values from 0 to 1 and use that to fill an array.
    </para>
    <para>
       A host would probably represent this to a user as a cubic curve in a standard curve editor interface, or possibly through scripting. 
       The user would then use this to define the 'shape' of the parameter.
    </para>
    <para>
      The evaluation of such params is not the same as animation, they are returning values based on some arbitrary argument 
      orthogonal to time, so to evaluate such a param, you need to pass a parametric position and time.
    </para>
    <para>
      Often, you would want such a parametric parameter to be multi-dimensional, for example, a colour look-up table might want 
      three values, one for red, green and blue. Rather than declare three separate parametric parameters, so a parametric parameter can be multi-dimensional.
    </para>
    <para>
       Due to the nature of the underlying data, you <emphasis>cannot</emphasis> call certain functions in the ordinary parameter suite when manipulating a parametric parameter. 
       All functions in the standard parameter suite are valid when called on a parametric parameter, with the exception of the following....
      <itemizedlist>
	      <listitem><link linkEnd="OfxParameterSuiteV1_paramGetValue">OfxParameterSuiteV1::paramGetValue</link></listitem>
	      <listitem><link linkEnd="OfxParameterSuiteV1_paramGetValueAtTime">OfxParameterSuiteV1::paramGetValueAtTime</link></listitem>
	      <listitem><link linkEnd="OfxParameterSuiteV1_paramGetDerivative">OfxParameterSuiteV1::paramGetDerivative</link></listitem>
	      <listitem><link linkEnd="OfxParameterSuiteV1_paramGetIntegral">OfxParameterSuiteV1::paramGetIntegral</link></listitem>
	      <listitem><link linkEnd="OfxParameterSuiteV1_paramSetValue">OfxParameterSuiteV1::paramSetValue</link></listitem>
	      <listitem><link linkEnd="OfxParameterSuiteV1_paramSetValueAtTime">OfxParameterSuiteV1::paramSetValueAtTime</link></listitem>
      </itemizedlist>        
    </para>
  </section>
  <section>
    <title>Defining Parametric Parameters</title>
    Parametric parameters are defined using the standard parameter suite function 
   <link linkend='OfxParameterSuiteV1_paramDefine'><code>OfxParameterSuiteV1::paramDefine</code></link>. 
   The descriptor returned by this call have several non standard parameter properties available. These are
      <itemizedlist>
	      <listitem><link linkEnd="kOfxParamPropParametricDimension">kOfxParamPropParametricDimension</link> - the dimension of the parametric parameter,</listitem>
	      <listitem><link linkEnd="kOfxParamPropParametricUIColour">kOfxParamPropParametricUIColour</link> - the colour of the curves of a parametric parameter in any user interface</listitem>
	      <listitem><link linkEnd="kOfxParamPropParametricInteractBackground">kOfxParamPropParametricInteractBackground</link> - a pointer to an interact entry point, which will be used to draw a background under any user interface,</listitem>
	      <listitem><link linkEnd="kOfxParamPropParametricRange">kOfxParamPropParametricRange</link> - the min and max value that the parameter will be evaluated over.</listitem>
      </itemizedlist>
  </section>

  <section>
    <title>Animating Parametric Parameters</title>
    Animation is an optional host feature for parametric parameters. Hosts flag whether they support this feature by setting the host descriptor property <link linkEnd="kOfxParamHostPropSupportsParametricAnimation">kOfxParamHostPropSupportsParametricAnimation</link>. 
  </section>

  <section>
    <title>Getting and Setting Values on a Parametric Parameters</title>
    <para>
      Seeing as we need to pass in the parametric position and dimenstion to evaluate, parametric parameters need a new evaluation mechanism.
      They do this with the <link linkEnd="OfxParametricParameterSuiteV1_parametricParamGetValue">OfxParametricParameterSuiteV1::parametricParamGetValue</link>
      function. This function returns the value of the parameter at the given time, for the given dimension, adt the given parametric position,.</para>
    <para>
      Parametric parameters are effectively interfaces to some sort of host based curve library. To get/set/delete points in the curve that
      represents a parameter, the new suite has several functions available to manipulate control points of the underlying curve.
    </para>
    <para>
      To set the default value of a parametric parameter to anything but the identity, you use the control point setting functions in the new suite to 
      set up a curve on the <emphasis>descriptor</emphasis> returned by <link linkend='OfxParameterSuiteV1_paramDefine'><code>OfxParameterSuiteV1::paramDefine</code></link>.
      Any instances later created, will have that curve as a default.
    </para>
  </section>

  <section>
    <title>Example</title>
    <para>This simple example defines a colour lookup table, defines a default, and show how to evaluate the curve</para>
<blockquote><programlisting>// describe our parameter in 
static OfxStatus
describeInContext( OfxImageEffectHandle  effect,  OfxPropertySetHandle inArgs)
{
  ....
  // define it
  OfxPropertySetHandle props;
  gParamHost->paramDefine(paramSet, kOfxParamTypeParametric, "lookupTable", &amp; props);

  // set standard names and labeles
  gPropHost->propSetString(props, kOfxParamPropHint, 0, "Colour lookup table");
  gPropHost->propSetString(props, kOfxParamPropScriptName, 0, "lookupTable");
  gPropHost->propSetString(props, kOfxPropLabel, 0, "Lookup Table");

  // define it as three dimensional
  gPropHost->propSetInt(props, kOfxParamPropParametricDimension, 0, 3);

  // label our dimensions are r/g/b
  gPropHost->propSetString(props, kOfxParamPropDimensionLabel, 0, "red");
  gPropHost->propSetString(props, kOfxParamPropDimensionLabel, 1, "green");
  gPropHost->propSetString(props, kOfxParamPropDimensionLabel, 2, "blue");

  // set the UI colour for each dimension
  for(int component = 0; component &lt; 3; ++component) {
     gPropHost->propSetDouble(props, kOfxParamPropParametricUIColour, component * 3 + 0, component % 3 == 0 ? 1 : 0);
     gPropHost->propSetDouble(props, kOfxParamPropParametricUIColour, component * 3 + 1, component % 3 == 1 ? 1 : 0);
     gPropHost->propSetDouble(props, kOfxParamPropParametricUIColour, component * 3 + 2, component % 3 == 2 ? 1 : 0);
  }

  // set the min/max parametric range to 0..1
  gPropHost->propSetDouble(props, kOfxParamPropParametricRange, 0, 0.0);
  gPropHost->propSetDouble(props, kOfxParamPropParametricRange, 1, 1.0);
 
  // set a default curve, this example sets an invert 
  OfxParamHandle descriptor;
  gParamHost->paramGetHandle(paramSet, "lookupTable", &amp;descriptor, NULL);
  for(int component = 0; component &lt; 3; ++component) {
    // add a control point at 0, value is 1
    gParametricParamHost->parametricParamAddControlPoint(descriptor,
                                                          component, // curve to set 
                                                          0.0,   // time, ignored in this case, as we are not adding a ket
                                                          0.0,   // parametric position, zero
                                                          1.0,   // value to be, 1
                                                          false);   // don't add a key
    // add a control point at 1, value is 0
    gParametricParamHost->parametricParamAddControlPoint(descriptor, component, 0.0, 1.0, 0.0, false);
  }
 
  ...
}

void render8Bits(double currentFrame, otherStuff...)
{
   ...

   // make three luts from our curves   
   unsigned char lut[3][256];

  OfxParamHandle param;
  gParamHost->paramGetHandle(paramSet, "lookupTable", &amp;param, NULL);
  for(int component = 0; component &lt; 3; ++component) {
    for(int position = 0; position &lt; 256; ++position) {
      // position to evaluate the param at
      float parametricPos = float(position)/255.0f;
       
      // evaluate the parametric param
      float value;
      gParametricParamHost->parametricParamGetValue(param, component, currentFrame, parametricPos, &amp;value);
      value = value * 255;
      value = clamp(value, 0, 255);

      // set that in the lut
      lut[dimension][position] = (unsigned char)value;
    }
  }
  ...
}

</programlisting></blockquote>
   </section>
 </section>

  <section id="SettingParams">
    <title>Setting Parameters</title>
    <para>
       Plugins are free to set parameters in limited set of circumstances, typically relating to user interaction. You can only set parameters in the 
       following actions passed to the plug-in's <link linkEnd="mainEntryPoint">main entry</link> function...
      <itemizedlist>
	      <listitem>The <link linkEnd="kOfxActionCreateInstance">Create Instance Action</link></listitem>
	      <listitem>The <link linkend="kOfxActionBeginInstanceChanged">Begin Instance Changed Action</link></listitem>
	      <listitem>The <link linkend="kOfxActionInstanceChanged">Instance Changed Action</link></listitem>
	      <listitem>The <link linkend="kOfxActionEndInstanceChanged">End Instance Changed Action</link></listitem>
	      <listitem>The <link linkend="kOfxActionSyncPrivateData">Sync Private Data Action</link></listitem>
      </itemizedlist>
    </para>
        
    <para>
       Plugins can also set parameter values during the following actions passed to any of its  <link linkEnd="CustomInteracts">interacts</link>
       main entry function...
      <itemizedlist>
	     <listitem><link linkend="kOfxInteractActionPenDown">The Pen Down Action</link></listitem>
	     <listitem><link linkend="kOfxInteractActionPenMotion">The Pen Motion Action</link></listitem>
	     <listitem><link linkend="kOfxInteractActionPenUp">The Pen Up Action</link></listitem>
	     <listitem><link linkend="kOfxInteractActionKeyDown">The Key Down Action</link></listitem>
     	 <listitem><link linkend="kOfxInteractActionKeyRepeat">The Key Repeat Action</link></listitem>
       <listitem><link linkend="kOfxInteractActionKeyUp">The Key Up Action</link></listitem>
       <listitem><link linkend="kOfxInteractActionLoseFocus">The Lose Focus Action</link></listitem>
      </itemizedlist>
    </para>
  </section>

</chapter>
