To work around this limitation, I use a (truly painful) trick.
Here's a "simplified" explaination:
- NOTE - So far this thing has proven to be safe (but slow). Please note
that any mistakes done in the implementation of the technique might crash
xsi.
- NOTE - Use this workaround at your own risk. Remember to debug for memory
leaks and implement some serious error handling routines.
a) Create a polygonmesh cube, delete all it's polygons and create a single
0-area triangle.
b) Add a complete cluster and a texture projection.
c) Freeze the object.
d) Split your operator in three operators: (1) one "main" operator that does
the calculations and returns a parameter value containing <number of
triangles-1>, (2) another operator that sets the geometry, (3) another
operator that sets the UVs.
e) Apply operators to the polygon mesh in the following order:
- "main" operator,
- an "ExtrudeComponentAxis" operator (with the "Duplicate Polygons"
parameter set to true),
- "geometry" operator,
- "uv" operator.
The "main" operator will write its output value into the "subdivs" parameter
of the "ExtrudeComponentAxis" operator, forcing xsi to refresh the number of
cluster elements based on the number of duplicated triangles (custom
operators can't do that, but xsi operators can).
After the "ExtrudeComponentAxis" operator has updated cluster elements, you
overwrite the geometry with your custom "geometry" operator, and then fill
the cluster property with the "uv" operator.
All these operators will have the polygonmesh connected as input, and
because of this they will be evaluated in the correct order.
The "uv" operator also needs the cluster as input as well as the cluster
property.
At this point you need the 3 operators to ble able to exchange informations
and do the calculations only once (instead of 3 times) when their input
connections change.
To do this, you'll need to have the 3 custom operators inside a single DLL,
and build a linked list of customoperator instance pointers, mapped against
customoperator instance UniqueNames.
This linked list needs to be inside the DLL global space, so everything
inside the DLL can access it.
Each element of the linked list will contain (1) a pointer to an xsi
operator instance, (2) a CString variable and (3) a pointer to the next
element in the list.
Everytime the "main" operator is instanced in the scene (Init), you'll add
an entry in this map, set the entry's customoperator pointer to the current
"main" customoperator pointer and set its CString variable to the UniqueName
of the "main" customoperator instance.