Difference between revisions of "Dev:Action System"
(Make page more coherent) |
m |
||
(3 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | This page is a | + | {{Title|Action System}} |
− | + | The action system provides a good entry-point into Synfig because it functions as a stand-alone component that only interacts with Synfig's core data structure. This page is intended to provide a quick overview of the structure of the action system. | |
− | |||
− | + | ==Data Structures== | |
− | + | The action system interacts with the underlying data structure of a Synfig document. An action is most likely to affect the parameters of a given layer or object, which are described by the following classes. | |
− | + | ===Value (ValueBase)=== | |
+ | The ValueBase class can store values of any of the {{l|Dev:Types|13 Value Types}}, such as numbers, points, and colors. Before reading or setting any values, it is important to check the type of value being used (by calling value.get_type()). Getting the contents of the value as a C++ type also requires knowing what type is expected (e.g. value.get(Real())). | ||
− | + | ===ValueNode=== | |
+ | A {{l|ValueNode}} is a value can change with time. A "converted" or "animated" parameter is always a ValueNode. | ||
+ | Calling "value_node(time)" retrieves the value at that given time. | ||
+ | ===ValueDesc=== | ||
+ | Instances of this class describe a ''location'' where a ValueNode may be rather than that ValueNode itself. For example, they can refer to "the 'amount' parameter of layer x" or "the 5th point in the spline (bline)". That way, the ValueDesc continues to function even if the underlying value has been changed, exported, converted, etc. | ||
− | Actions typically receive ValueDescs to operate on | + | Actions typically receive ValueDescs to operate on, only retrieving their values when they are necessary for computations. |
==Properties of an Action== | ==Properties of an Action== | ||
− | The majority of actions are accessible by right-clicking on certain ducks, parameters, or layers. At that point, Synfig Studio automatically determines which actions can be called based on the data that is currently selected | + | The majority of actions are accessible by right-clicking on certain handle (ducks), parameters, or layers. At that point, Synfig Studio automatically determines which actions can be called based on the data that is currently selected. |
− | get_param_vocab() | + | The first step is for the action to provide a "Parameter Vocabulary" object that describes what types of parameters it needs in order to function. |
+ | |||
+ | ===get_param_vocab()=== | ||
Typical implementation: | Typical implementation: | ||
Line 33: | Line 39: | ||
However, the parameter types alone are not always sufficient to determine whether the action should be called. As such, checking a given parameter set is done by the action: | However, the parameter types alone are not always sufficient to determine whether the action should be called. As such, checking a given parameter set is done by the action: | ||
− | is_candidate(const ParamList &x) | + | ===is_candidate(const ParamList &x)=== |
Typical implementation: | Typical implementation: | ||
* The first step of any candidate check is to test whether the requirements of the ParamDesc are met. "if (!candidate_check(get_param_vocab(), x)) return false;" | * The first step of any candidate check is to test whether the requirements of the ParamDesc are met. "if (!candidate_check(get_param_vocab(), x)) return false;" | ||
* At this point, you know that all of your parameters are present and can begin testing for specific cases. (For example, the "activepointsetoff" action is only applicable when the activepoint is currently on) | * At this point, you know that all of your parameters are present and can begin testing for specific cases. (For example, the "activepointsetoff" action is only applicable when the activepoint is currently on) | ||
− | * If there are no tests to perform, | + | * If there are no tests to perform, return "true". |
− | Once the parameter list is checked, Synfig Studio will pass the actual parameters to the action. The action must then retrieve their values and store them internally. This internal storage allows for the action to be un-done and re-done multiple times. | + | Once the parameter list is checked, Synfig Studio will pass the actual parameters to the action. The action must then retrieve their values and store them internally. This internal storage allows for the action to be un-done and re-done multiple times. |
− | set_param(const synfig::String& name, const Action::Param ¶m) | + | ===set_param(const synfig::String& name, const Action::Param ¶m)=== |
Typical implementation: | Typical implementation: | ||
Line 50: | Line 56: | ||
The action needs to be able to check whether all of its parameters are set. While the parameter list is checked when the action is called as a result of a right-click menu, any actions called from other places (e.g. by other actions) manually set parameters and must check that the proper parameters are present. | The action needs to be able to check whether all of its parameters are set. While the parameter list is checked when the action is called as a result of a right-click menu, any actions called from other places (e.g. by other actions) manually set parameters and must check that the proper parameters are present. | ||
− | is_ready() | + | ===is_ready()=== |
Typical implementation: | Typical implementation: | ||
Line 56: | Line 62: | ||
* Check that the required parameters for CanvasSpecific actions are met "return Action::CanvasSpecific::is_ready();" | * Check that the required parameters for CanvasSpecific actions are met "return Action::CanvasSpecific::is_ready();" | ||
+ | ===get_param(const synfig::String& name, Action::Param ¶m)=== | ||
+ | |||
+ | Typical implementation: | ||
+ | * Set the value of the parameter from the action point of vue | ||
+ | The action is used in action like renameValueNode / renameLayer ... all case when a previous value was present. | ||
+ | To use get_param you will need Action::set_value_provided() property during the parameter description in {{l|Dev:Action_System#get_param_vocab()|get_param_vocab()}} implemenation. | ||
==Types of actions== | ==Types of actions== | ||
Line 62: | Line 74: | ||
There are two major types of actions. | There are two major types of actions. | ||
+ | ===Undoable actions=== | ||
The first are standard undoable actions | The first are standard undoable actions | ||
*These inherit from [http://download.tuxfamily.org/synfig/api/synfig-studio/classsynfigapp_1_1Action_1_1Undoable.html Undoable] and [http://download.tuxfamily.org/synfig/api/synfig-studio/classsynfigapp_1_1Action_1_1CanvasSpecific.html CanvasSpecific] | *These inherit from [http://download.tuxfamily.org/synfig/api/synfig-studio/classsynfigapp_1_1Action_1_1Undoable.html Undoable] and [http://download.tuxfamily.org/synfig/api/synfig-studio/classsynfigapp_1_1Action_1_1CanvasSpecific.html CanvasSpecific] | ||
*It is necessary to implement perform() and undo() | *It is necessary to implement perform() and undo() | ||
+ | ===Super-actions=== | ||
The second are Super-actions which can only call other actions. Since undoing a Super-action is simply undoing all of its sub-actions, these do not require an undo method. | The second are Super-actions which can only call other actions. Since undoing a Super-action is simply undoing all of its sub-actions, these do not require an undo method. | ||
*Inherit from [http://download.tuxfamily.org/synfig/api/synfig-studio/classsynfigapp_1_1Action_1_1Super.html Super] | *Inherit from [http://download.tuxfamily.org/synfig/api/synfig-studio/classsynfigapp_1_1Action_1_1Super.html Super] | ||
− | |||
*perform() and undo() are inherited from Super and should not be overridden. | *perform() and undo() are inherited from Super and should not be overridden. | ||
+ | *Instead, one should implement the prepare() method, which creates sub-actions | ||
− | + | To add sub-actions: | |
− | * First create the action of the needed type "Action::Handle action(Action::create("ValueDescSet"));" or "ValueDescConnect::create()" (TODO: Style review here) | + | * First create the action of the needed type e.g. "Action::Handle action(Action::create("ValueDescSet"));" or "ValueDescConnect::create()" (TODO: Style review here) |
− | * Set | + | * Set its parameters: |
− | **The canvas, canvas interface, and current time are usually | + | **The canvas, canvas interface, and current time of the current action are usually passed on to children |
***action->set_param("canvas",get_canvas()); | ***action->set_param("canvas",get_canvas()); | ||
***action->set_param("canvas_interface",get_canvas_interface()); | ***action->set_param("canvas_interface",get_canvas_interface()); | ||
Line 82: | Line 96: | ||
***action->set_param("value_desc",reference_value_desc); | ***action->set_param("value_desc",reference_value_desc); | ||
***action->set_param("new_value",value); | ***action->set_param("new_value",value); | ||
+ | * Add it to the action stack | ||
+ | ** "add_action(action)" |
Latest revision as of 17:55, 16 March 2017
The action system provides a good entry-point into Synfig because it functions as a stand-alone component that only interacts with Synfig's core data structure. This page is intended to provide a quick overview of the structure of the action system.
Data Structures
The action system interacts with the underlying data structure of a Synfig document. An action is most likely to affect the parameters of a given layer or object, which are described by the following classes.
Value (ValueBase)
The ValueBase class can store values of any of the 13 Value Types, such as numbers, points, and colors. Before reading or setting any values, it is important to check the type of value being used (by calling value.get_type()). Getting the contents of the value as a C++ type also requires knowing what type is expected (e.g. value.get(Real())).
ValueNode
A ValueNode is a value can change with time. A "converted" or "animated" parameter is always a ValueNode.
Calling "value_node(time)" retrieves the value at that given time.
ValueDesc
Instances of this class describe a location where a ValueNode may be rather than that ValueNode itself. For example, they can refer to "the 'amount' parameter of layer x" or "the 5th point in the spline (bline)". That way, the ValueDesc continues to function even if the underlying value has been changed, exported, converted, etc.
Actions typically receive ValueDescs to operate on, only retrieving their values when they are necessary for computations.
Properties of an Action
The majority of actions are accessible by right-clicking on certain handle (ducks), parameters, or layers. At that point, Synfig Studio automatically determines which actions can be called based on the data that is currently selected.
The first step is for the action to provide a "Parameter Vocabulary" object that describes what types of parameters it needs in order to function.
get_param_vocab()
Typical implementation:
- Get the param vocab from the parent action. In most cases, it will be "ParamVocab ret(Action::CanvasSpecific::get_param_vocab());"
- Create a parameter description for each of the parameters your action needs(see ParamDesc)
- ParamDesc("new_value",Param::TYPE_VALUE)
- Set the parameter options e.g. "ParamDesc(...).set_local_name(_("ValueBase"))"
- The set actions all return the object, so you should chain them: ParamDesc(...).set_local_name(...).set_supports_multiple(...)
- Once the parameters are set, add them to the Parameter Vocabulary e.g. "ret.push_back(ParamDesc("new_value",Param::TYPE_VALUE).set_local_name(_("ValueBase")));"
However, the parameter types alone are not always sufficient to determine whether the action should be called. As such, checking a given parameter set is done by the action:
is_candidate(const ParamList &x)
Typical implementation:
- The first step of any candidate check is to test whether the requirements of the ParamDesc are met. "if (!candidate_check(get_param_vocab(), x)) return false;"
- At this point, you know that all of your parameters are present and can begin testing for specific cases. (For example, the "activepointsetoff" action is only applicable when the activepoint is currently on)
- If there are no tests to perform, return "true".
Once the parameter list is checked, Synfig Studio will pass the actual parameters to the action. The action must then retrieve their values and store them internally. This internal storage allows for the action to be un-done and re-done multiple times.
set_param(const synfig::String& name, const Action::Param ¶m)
Typical implementation:
- Retrieve value of the parameter and store it in an internal variable
The action needs to be able to check whether all of its parameters are set. While the parameter list is checked when the action is called as a result of a right-click menu, any actions called from other places (e.g. by other actions) manually set parameters and must check that the proper parameters are present.
is_ready()
Typical implementation:
- Return false if your custom parameters are unset
- Check that the required parameters for CanvasSpecific actions are met "return Action::CanvasSpecific::is_ready();"
get_param(const synfig::String& name, Action::Param ¶m)
Typical implementation:
- Set the value of the parameter from the action point of vue
The action is used in action like renameValueNode / renameLayer ... all case when a previous value was present. To use get_param you will need Action::set_value_provided() property during the parameter description in get_param_vocab() implemenation.
Types of actions
There are two major types of actions.
Undoable actions
The first are standard undoable actions
- These inherit from Undoable and CanvasSpecific
- It is necessary to implement perform() and undo()
Super-actions
The second are Super-actions which can only call other actions. Since undoing a Super-action is simply undoing all of its sub-actions, these do not require an undo method.
- Inherit from Super
- perform() and undo() are inherited from Super and should not be overridden.
- Instead, one should implement the prepare() method, which creates sub-actions
To add sub-actions:
- First create the action of the needed type e.g. "Action::Handle action(Action::create("ValueDescSet"));" or "ValueDescConnect::create()" (TODO: Style review here)
- Set its parameters:
- The canvas, canvas interface, and current time of the current action are usually passed on to children
- action->set_param("canvas",get_canvas());
- action->set_param("canvas_interface",get_canvas_interface());
- action->set_param("time",time);
- Other parameters will vary from action to action. For ValueDescSet they might be:
- action->set_param("value_desc",reference_value_desc);
- action->set_param("new_value",value);
- The canvas, canvas interface, and current time of the current action are usually passed on to children
- Add it to the action stack
- "add_action(action)"