|
1 | 1 | import Sofa.Core |
2 | 2 | import inspect |
3 | 3 |
|
| 4 | + |
4 | 5 | class Prefab(Sofa.Core.RawPrefab): |
5 | 6 | """ |
6 | | - The Prefab object is a Base class to create custom Prefab components for SOFA, implemented in python. |
7 | | - A Prefab can have parameters defined in the "properties" list (datafields under the group "Prefab's Properties"), that trigger its doReInit() function when modified. Parameters must be in a list of dictionaries containing the 3 required fields ("name", "type", "help") and one optional field ("default"). |
8 | | - When initializing a Prefab, if a prefab property name matches a keyword argument fed to the Prefab's initializer, the property will be added to the prefab as a SOFA data of the given type. |
| 7 | + Special Node to make reusable procedural objects in Sofa. |
| 8 | + --------------------------------------------------------- |
| 9 | +
|
| 10 | + Inherit from this class to create your own Prefab. What makes Prefab special is that they |
| 11 | + have a set of special data named prefabParameters. When any of prefabParameter is changed the prefab |
| 12 | + is completely recreated by calling the onParameterChanged method so the scene graph is always kept synchronized |
| 13 | + with the parameter's content. |
9 | 14 |
|
10 | | - Prefabs have protected keyword arguments: |
11 | | - - name: the name of the prefab instance |
12 | | - - parent and parents: can't be used together, they set the context of the prefab, thus allowing paths resolution for Prefab parameters whose arguments are passed as link paths (strings). parents (with an '-s') sets multi-node contexts |
13 | | - - All other protected keyword arguments in SOFA components |
| 15 | + To specify the prefabParameters, it is possible to provide in the class a list of dictionaries containing the 3 required fields ("name", "type", "help") |
| 16 | + and one optional field ("default"). |
| 17 | +
|
| 18 | + The same syntax can be used to also add prefab's data. |
14 | 19 |
|
15 | 20 | Example of use: |
16 | 21 | .. code-block:: python |
| 22 | +
|
17 | 23 | import Sofa.Core |
18 | 24 |
|
19 | 25 | class Foo(Sofa.Core.Prefab): |
20 | | - properties = [{ 'name': 'n', 'type': 'int', 'help': 'number of times this prefab prints 'message', 'default': '1'}, |
21 | | - {'name': 'message', 'type': 'string', 'help': 'message to display n times', 'default': 'Hello World!'}] |
| 26 | + prefabParameters = [{ 'name': 'n', 'type': 'int', 'help': 'number of repetition, 'default': 1}, |
| 27 | + {'name': 'message', 'type': 'string', 'help': 'message to display', 'default': ''}] |
| 28 | +
|
| 29 | + myAttribute = 0 |
22 | 30 |
|
23 | 31 | def __init__(self, *a, *k): |
24 | 32 | Sofa.Core.Prefab.__init__(self, *a, **k) |
25 | 33 |
|
26 | | - def doReInit(self): |
| 34 | + def init(self): |
| 35 | + myAttribute += 1 |
27 | 36 | for i in range(0, self.n.value): |
28 | 37 | print(self.message.value) |
29 | 38 |
|
30 | 39 | n = Sofa.Core.Node() |
31 | 40 | n.addChild(Foo(name="aFooPrefab", n=42, message="hello universe!")) |
| 41 | +
|
| 42 | + Prefab has protected the following additional keywords: |
| 43 | + - "name": the name of the prefab instance |
| 44 | + - "parent" and "parents": can't be used together, they set the context of the prefab, |
| 45 | + thus allowing paths resolution for Prefab parameters whose arguments are passed as link paths (strings). parents (with an '-s') sets multi-node contexts |
| 46 | +
|
| 47 | +
|
32 | 48 | """ |
33 | 49 | def __init__(self, *args, **kwargs): |
34 | 50 | Sofa.Core.RawPrefab.__init__(self, *args, **kwargs) |
@@ -71,14 +87,36 @@ def __init__(self, *args, **kwargs): |
71 | 87 | if "parent" in kwargs and "parents" in kwargs: |
72 | 88 | Sofa.Helper.msg_error(self, "Cannot use both 'parent' and 'parents' keywords on a prefab. Use 'parent' to set the context of your prefab, 'parents' in the case of a multi-parent prefab") |
73 | 89 |
|
74 | | - # Prefab parameters are defined in a list of dictionaries named "properties". |
| 90 | + # Prefab parameters are defined in a list of dictionaries named "prefabParameters". |
75 | 91 | # The dictionaries has 3 required fields (name, type, help) and an additional optional field "default" |
76 | 92 | docstring = "" |
| 93 | + |
| 94 | + if hasattr(self, "prefabParameters"): |
| 95 | + docstring += "Prefab's parameters:" |
| 96 | + for p in self.prefabParameters: |
| 97 | + self.addPrefabParameter(name=p['name'], |
| 98 | + type=p['type'], |
| 99 | + help=p['help'], |
| 100 | + default=kwargs.get(p['name'], p.get('default', None))) |
| 101 | + docstring += "\n:param " + p['name'] + ": " + p['help'] + ", defaults to " + str(p.get('default', '')) + '\n:type ' + p['name'] + ": " + p['type'] + "\n\n" |
| 102 | + |
| 103 | + if hasattr(self, "prefabData"): |
| 104 | + docstring += "Prefab's data:" |
| 105 | + for p in self.prefabData: |
| 106 | + self.addData(name=p['name'], type=p['type'], help=p['help'], |
| 107 | + value=kwargs.get(p['name'], p.get('default', None)), |
| 108 | + default=p['default'], |
| 109 | + group=p.get('group', 'Property')) |
| 110 | + docstring += "\n:param " + p['name'] + ": " + p['help'] + ", defaults to " + str(p.get('default', '')) + '\n:type ' + p['name'] + ": " + p['type'] + "\n\n" |
| 111 | + |
77 | 112 | if hasattr(self, "properties"): |
78 | | - docstring += "" |
| 113 | + Sofa.Helper.msg_deprecated(self, "'properties' has been replaced with 'prefabParameters'. Please update your code.") |
| 114 | + docstring += "Prefab's (properties):" |
79 | 115 | for p in self.properties: |
80 | 116 | self.addPrefabParameter(name=p['name'], type=p['type'], help=p['help'], default=kwargs.get(p['name'], p.get('default', None))) |
81 | 117 | docstring += "\n:param " + p['name'] + ": " + p['help'] + ", defaults to " + str(p.get('default', '')) + '\n:type ' + p['name'] + ": " + p['type'] + "\n\n" |
82 | 118 |
|
83 | 119 | self.addData("docstring", value=('' if self.__doc__ is None else self.__doc__) + docstring, type="string", group="Infos", help="Documentation of the prefab") |
| 120 | + |
| 121 | + # calls the init() method in the prefab, then do node init & traversal. |
84 | 122 | self.init() |
0 commit comments