setting ICEAttribute.DataArray in JScript

141 views
Skip to first unread message

Eugen Sares

unread,
Oct 23, 2012, 1:40:13 PM10/23/12
to soft...@listproc.autodesk.com
Hi, short question:
how do I set/write the ICEAttribute.DataArray from JScript? Can't find a
code example.
It is a safe array, that much I found out.

attr.DataArray = [23,44,50]; is not working.
// WARNING : 3392 - Invalid offset specified while extracting data from
this attribute...

Thanks,
Eugen

Sam Cuttriss

unread,
Oct 23, 2012, 2:02:47 PM10/23/12
to soft...@listproc.autodesk.com
this is in the help somewhere, damned if i can find it again.
its python, but will print info about the a selections attributes:
hopefully that helps.


from win32com.client import constants
xsi = Application
#xsi.CreatePrim("Cone", "MeshSurface", "", "")
attrs = xsi.Selection(0).ActivePrimitive.Geometry.ICEAttributes;
for attr in attrs:
if attr.IsDefined == True :
xsi.LogMessage( "*******************************************************************" )
xsi.LogMessage( "Name: " + attr.Name )
xsi.LogMessage( "DataType: " + str(attr.DataType) )
xsi.LogMessage( "StructType: " + str(attr.StructureType) )
xsi.LogMessage( "ContextType: " + str(attr.ContextType) )
xsi.LogMessage( "IsDefined: " + str(attr.IsDefined) )
xsi.LogMessage( "IsConstant: " + str(attr.IsConstant) )
xsi.LogMessage( "Readonly: " + str(attr.IsReadonly) )
xsi.LogMessage( "AttributeCategory: " + str(attr.AttributeCategory) )
xsi.LogMessage( "Element count: " + str(attr.ElementCount) )
dataType = attr.DataType;
data = attr.DataArray;
#print data.NestedObjects()
for i,elem in enumerate(data):
if dataType == constants.siICENodeDataFloat:
xsi.LogMessage( "float: " + str(elem) )
elif dataType == constants.siICENodeDataLong: 
xsi.LogMessage( "long: " + str(elem) )
elif dataType == constants.siICENodeDataBool: 
xsi.LogMessage( "bool: " + str(elem) )
elif dataType == constants.siICENodeDataVector3: 
xsi.LogMessage( "Vector3: " + str(elem.X) + ":" + str(elem.Y) + ":" + str(elem.Z) + ": index" + str(i) )
elif dataType == constants.siICENodeDataQuaternion: 
xsi.LogMessage( "Quaternion: " + str(elem.W) + ":" + str(elem.X) + ":" + str(elem.Y) + ":" + str(elem.Z) )
elif dataType == constants.siICENodeDataRotation: 
xsi.LogMessage( "Rotation: " + str(elem.RotX) + ":" + str(elem.RotY) + ":" + str(elem.RotZ) )
elif dataType == constants.siICENodeDataMatrix33: 
xsi.LogMessage( "Matrix33:" );
xsi.LogMessage( str(elem.Value(0,0)) + ":" + str(elem.Value(0,1)) + ":" + str(elem.Value(0,2)) )
xsi.LogMessage( str(elem.Value(1,0)) + ":" + str(elem.Value(1,1)) + ":" + str(elem.Value(1,2)) )
xsi.LogMessage( str(elem.Value(2,0)) + ":" + str(elem.Value(2,1)) + ":" + str(elem.Value(2,2)) )
elif dataType == constants.siICENodeDataMatrix44: 
xsi.LogMessage( "Matrix44:" );
xsi.LogMessage( str(elem.Value(0,0)) + ":" + str(elem.Value(0,1)) + ":" + str(elem.Value(0,2)) + ":" + str(elem.Value(0,3)))
xsi.LogMessage( str(elem.Value(1,0)) + ":" + str(elem.Value(1,1)) + ":" + str(elem.Value(1,2)) + ":" + str(elem.Value(1,3)))
xsi.LogMessage( str(elem.Value(2,0)) + ":" + str(elem.Value(2,1)) + ":" + str(elem.Value(2,2)) + ":" + str(elem.Value(2,3)))
xsi.LogMessage( str(elem.Value(3,0)) + ":" + str(elem.Value(3,1)) + ":" + str(elem.Value(3,2)) + ":" + str(elem.Value(3,3)))
elif dataType == constants.siICENodeDataColor4: 
xsi.LogMessage( "Color:" );
xsi.LogMessage( str(elem.Red) + ":" + str(elem.Green) + ":" + str(elem.Blue) + ":" + str(elem.Alpha) )
elif dataType == constants.siICENodeDataString: 
xsi.LogMessage( "String: " + elem );

Matt Lind

unread,
Oct 23, 2012, 2:09:12 PM10/23/12
to soft...@listproc.autodesk.com
I ran into this problem a few years ago developing a tool. I don't remember how I resolved it, but try using the GridData object instead of reading/writing directly to a Jscript array.

GridData.Data = attr.DataArray;

You might have to define one or both dimensions of the GridData object before it will work.

Matt

Alan Fregtman

unread,
Oct 23, 2012, 2:21:10 PM10/23/12
to soft...@listproc.autodesk.com
Hi Eugen,

What version are you trying this in? AFAIK, writing ICE attributes is a new feature in the SDK of SI|2013...

http://download.autodesk.com/global/docs/softimage2013/en_us/sdkguide/files/GUID-177FE97B-99EB-4EF2-A33A-B17811915954.htm

New Methods (Object Model)

  • ICEAttribute.DataArray - Sets a 1D Array object containing the data defined by an attribute.

  • ICEAttribute.DataArray2D - Sets a 2D Array object containing the 2D data defined by an attribute.

  • Geometry.AddICEAttribute - Adds and returns a new attribute data on a geometry.

  • Geometry.RemoveICEAttribute - Removes a non-built-in attribute from a geometry if not required by an ICETree.

Eugen Sares

unread,
Oct 23, 2012, 2:30:16 PM10/23/12
to soft...@listproc.autodesk.com
Thanks, guys!
The Python example I found myself, but that does not help in JScript.

GridData must reside in a CustomProperty, right?
I would have to define one first... not very elegant.

Matt Lind

unread,
Oct 23, 2012, 2:56:11 PM10/23/12
to soft...@listproc.autodesk.com
No. Griddata can be made all by itself:


var oGridData = XSIFactory.CreateGridData();

oGridData.Rowcount = <n>;

oGridData.Data = attr.DataArray;

Stefan Kubicek

unread,
Oct 23, 2012, 2:57:32 PM10/23/12
to soft...@listproc.autodesk.com
Afaik you can create GridData on the fly without attaching it to a PPG:
XSIFactory.CreateGridData();

Search the SDk docs for "Using a Temporary GridData Object".
--
-------------------------------------------
Stefan Kubicek Co-founder
-------------------------------------------
keyvis digital imagery
Wehrgasse 9 - Grï¿œner Hof
1050 Vienna Austria
Phone: +43/699/12614231
--- www.keyvis.at ste...@keyvis.at ---
-- This email and its attachments are
--confidential and for the recipient only--

Francis Brissette

unread,
Oct 23, 2012, 3:54:10 PM10/23/12
to soft...@listproc.autodesk.com
>From what I observed, if your array is the right size, you will have this error shown.
The size of the array will depend on the siICENodeContextType associated with the ICEAttribute and the object containing this ICE Attribute.

--------------------------------------------------
NewScene("", "false")
CreatePrim("grid", "MeshSurface", "", "")
SetValue("grid.polymsh.geom.subdivu", 2, null);
SetValue("grid.polymsh.geom.subdivv", 2, null);

// Type = Vector3, Context = One element per polygon.
attr = Selection(0).ActivePrimitive.AddICEAttribute("MyVec3", siICENodeDataVector3, siICENodeStructureSingle, siICENodeContextComponent2D )
attr.DataArray = [
XSIMath.CreateVector3( 1.0, 0.0, 0.0 ),
XSIMath.CreateVector3( 0.0, 1.0, 0.0 ),
XSIMath.CreateVector3( 0.0, 0.0, 1.0 ),
XSIMath.CreateVector3( 0.0, 0.0, 0.0 ) ]
--------------------------------------------------

Francis

-----Original Message-----
From: softimag...@listproc.autodesk.com [mailto:softimag...@listproc.autodesk.com] On Behalf Of Stefan Kubicek
Sent: October 23, 2012 14:58
To: soft...@listproc.autodesk.com
Subject: Re: setting ICEAttribute.DataArray in JScript

Wehrgasse 9 - Grüner Hof
winmail.dat

Eugen Sares

unread,
Mar 11, 2013, 11:44:54 AM3/11/13
to soft...@listproc.autodesk.com
Sorry, got interrupted... ;q
Thanks, Francis, that works (2013 SP1 )!

What still gives me troubles is setting the MaterialID attribute (exists
on every polymesh by default), which is what I actually need.
I cannot write to it. Reading works, though. Could you guys please have
a look?

This works:
<JScript>
NewScene("", "false");
var oObj = CreatePrim("grid", "MeshSurface", "", "");
SetValue("grid.polymsh.geom.subdivu", 2, null);
SetValue("grid.polymsh.geom.subdivv", 2, null);
var oICEAttr = oObj.ActivePrimitive.AddICEAttribute("MyAttr",
siICENodeDataLong, siICENodeStructureSingle, siICENodeContextComponent2D );
oICEAttr.DataArray = [0,1,2,3];

var oProp = oObj.AddProperty("AttributeDisplay");
SetValue(oObj.Name + ".AttributeDisplay.attrname", "MyAttr", null);
</JScript>



Whereas this throws a warning:
<JScript>
NewScene("", "false");
var oObj = CreatePrim("grid", "MeshSurface", "", "");
SetValue("grid.polymsh.geom.subdivu", 2, null);
SetValue("grid.polymsh.geom.subdivv", 2, null);
var oICEAttr = oObj.ActivePrimitive.GetICEAttributeFromName("MaterialID");
oICEAttr.DataArray = [0,1,2,3]; // WARNING : 3403 - The data is not set
on this ICEAttribute: MaterialID

var oProp = oObj.AddProperty("AttributeDisplay");
SetValue(oObj.Name + ".AttributeDisplay.attrname", "MyLong", null);
</JScript>


The attribute "MyAttr" has exactly the same "format" as MaterialID, so
what's the difference?

Using a GridData object does not help.

<JScript>
NewScene("", "false");
var oObj = CreatePrim("grid", "MeshSurface", "", "");
SetValue("grid.polymsh.geom.subdivu", 2, null);
SetValue("grid.polymsh.geom.subdivv", 2, null);
var oICEAttr = oObj.ActivePrimitive.GetICEAttributeFromName("MaterialID");
var oGridData = XSIFactory.CreateGridData();
oGridData.RowCount = 1;
oGridData.ColumnCount = 4;
oGridData.SetRowValues(0, [0,1,2,3]);
oICEAttr.DataArray = oGridData.Data;

var oProp = oObj.AddProperty("AttributeDisplay");
SetValue(oObj.Name + ".AttributeDisplay.attrname", "MyLong", null);
</JScript>


Am I missing something, or is this a bug?
Thanks!
Eugen

Stephen Blair

unread,
Mar 11, 2013, 12:15:55 PM3/11/13
to soft...@listproc.autodesk.com
MaterialID isn't defined. Seems that you cannot set MaterialID.DataArray
unless IsDefined is True

Eugen Sares

unread,
Mar 11, 2013, 12:25:49 PM3/11/13
to soft...@listproc.autodesk.com
Thanks, Steven!
IsDefined is read-only, by the looks.
So how do I write to it to define it (outside of ICE), when it cannot be
written until it's defined??

Stephen Blair

unread,
Mar 11, 2013, 1:46:57 PM3/11/13
to soft...@listproc.autodesk.com
I don't think it is possible.

MaterialID becomes undefined/uninitialized pretty quick...
http://screencast.com/t/HeNPz4qgwlh

Eugen Sares

unread,
Mar 12, 2013, 5:18:08 AM3/12/13
to soft...@listproc.autodesk.com
Ok... I'm trying this workaround:
- Create custom ICEAttributes instead of the factory ones via scripting,
with exactly the same type.
- Create a simple ICE graph that reads from the custom attributes and
writes to the factory attr via scripting.

I've managed to write the "MaterialID" this way, but with "Materials" I
have the problem that I cannot create an equal string array custom
attribute:

<JScript>
var oObj = CreatePrim("grid", "MeshSurface", "", "");
oICEAttrMats = oObj.ActivePrimitive.AddICEAttribute("MyString",
siICENodeDataString, siICENodeStructureArray, siICENodeContextSingleton);
oICEAttrMats.DataArray = ["a", "b", "c", "d"];
</JScript>
// WARNING : 3392 - Invalid offset specified while extracting data from
this attribute: <Attribute: MyString>

The DataType, StructType and ContextType of that string array attribute
is exactly the same as the factory "Materials" attribute.
(I checked in XSI_SAMPLES\ICE\Modelling_Materials.scn)

What's wrong now?
Thanks,
Eugen

Stephen Blair

unread,
Mar 12, 2013, 7:29:30 AM3/12/13
to soft...@listproc.autodesk.com
Last time I tried, I gave up on JScript (it seemed impossible) and got
something to work in Python.

si = Application
from win32com.client import constants as C #
win32com.client.constants

oObj = si.Selection(0)
oICEAttrMats = oObj.ActivePrimitive.AddICEAttribute("MyString",
C.siICENodeDataString, C.siICENodeStructureArray,
C.siICENodeContextSingleton)
oICEAttrMats.DataArray2D = ["a", "b", "c", "d"]

x = oICEAttrMats.DataArray2D
print x
print len(x)
print len(x[0])
print len(x[0][0])

for d in x[0][0]:
print d


# (((u'a', u'b', u'c', u'd'),),)
# 1
# 1
# 4
# a
# b
# c
# d

Ho Chung Nguyen

unread,
Mar 24, 2013, 11:42:52 PM3/24/13
to soft...@listproc.autodesk.com
- In Jscript, the array needs to be converted to safearray before you can set it on ICE attribute data. Check out the code below for the conversion.
- As a workaround for setting MaterialID, you can store the data in a custom attribute, then use ICE to read from it and set MaterialID

function getSafeArray(jsArr) {
var dict = new ActiveXObject("Scripting.Dictionary");
for (var i = 0; i < jsArr.length; i++)
dict.add(i, jsArr[i]);
return dict.Items();
}

//to a safe array
var safearr = getSafeArray([1,2,1,2,1,2]);

//back to a js array
//var jsArr = new VBArray(safearr).toArray();

cube = Dictionary.GetObject("cube")

attr = cube.ActivePrimitive.Geometry.AddICEAttribute("CustomMaterialID", siICENodeDataType.siICENodeDataLong, siICENodeStructureType.siICENodeStructureSingle, siICENodeContextType.siICENodeContextComponent2D)
attr.DataArray = safearr

-----Original Message-----
From: softimag...@listproc.autodesk.com [mailto:softimag...@listproc.autodesk.com] On Behalf Of Stephen Blair
Sent: Tuesday, March 12, 2013 7:29 PM
To: soft...@listproc.autodesk.com
Subject: Re: setting ICEAttribute.DataArray in JScript

winmail.dat

Eugen Sares

unread,
Mar 25, 2013, 4:29:57 AM3/25/13
to soft...@listproc.autodesk.com
Thanks, Ho Chung!
Writing to the MaterialID attribute works (array of integers), but not
to Materials (array of strings).
Workaround would be to create an ICE array via scripting, I got that
working already, but still I wonder why the problem is.
Could you please check this code?


NewScene("", "false");
var oObj = CreatePrim("grid", "MeshSurface", "", "");
SetValue(oObj + ".polymsh.geom.subdivu", 2, null);
SetValue(oObj + ".polymsh.geom.subdivv", 2, null);

oIA = oObj.ActivePrimitive.Geometry.AddICEAttribute("CustomMaterials",
siICENodeDataType.siICENodeDataString,
siICENodeStructureType.siICENodeStructureArray,
siICENodeContextType.siICENodeContextSingleton);
var aData = ["Mat0", "Mat1", "Mat2", "Mat3"];
//oIA.DataArray = aData; // WARNING : 3392 - Invalid offset specified
var saData = getSafeArray(aData);
oIA.DataArray = saData; // WARNING : 3392 - Invalid offset specified


function getSafeArray(jsArr)
{
var dict = new ActiveXObject("Scripting.Dictionary");
for(var i = 0; i < jsArr.length; i++)

Stephen Blair

unread,
Mar 25, 2013, 10:11:54 AM3/25/13
to soft...@listproc.autodesk.com

Eugen Sares

unread,
Mar 25, 2013, 10:48:16 AM3/25/13
to soft...@listproc.autodesk.com
Doh... you have to "wrap" the string twice in a safe array and use
DataArray2D...
You thought of this at the dentist's? Normally pain's no good for the
brain...
Many thanks!!

Eugen Sares

unread,
Mar 25, 2013, 11:46:18 AM3/25/13
to soft...@listproc.autodesk.com
Ok, here's the complete JScript for creating MaterialIDs.
A lot of hoops to jump through for something seemingly simple...
For some obscure reason the viewport does not update with the shader
colors. You have to render to see the result.
Also, I don't know why string attribute "Materials" can only be set via
a helper attribute, whereas "MaterialID" can be set directly.



NewScene("", "false");
SetDisplayMode("Camera", "shaded");
var oObj = CreatePrim("grid", "MeshSurface", "", "");
SetValue(oObj + ".polymsh.geom.subdivu", 2, null);
SetValue(oObj + ".polymsh.geom.subdivv", 2, null);

var sLib = "Sources.Materials.DefaultLib.";
var oMat = SICreateMaterial("$XSI_DSPRESETS\\Shaders\\Material\\Phong",
"Mat0", null, null, false, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.red", 1.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.green", 0.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.blue", 0.0, null);
var oMat = SICreateMaterial("$XSI_DSPRESETS\\Shaders\\Material\\Phong",
"Mat1", null, null, false, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.red", 0.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.green", 1.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.blue", 0.0, null);
var oMat = SICreateMaterial("$XSI_DSPRESETS\\Shaders\\Material\\Phong",
"Mat2", null, null, false, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.red", 0.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.green", 0.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.blue", 1.0, null);
var oMat = SICreateMaterial("$XSI_DSPRESETS\\Shaders\\Material\\Phong",
"Mat3", null, null, false, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.red", 1.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.green", 1.0, null);
SetValue(sLib + oMat.Name + ".NestedShaders." + oMat.Name +
".diffuse.blue", 0.0, null);

var oIA = oObj.ActivePrimitive.AddICEAttribute("sMaterials",
siICENodeDataString, siICENodeStructureArray, siICENodeContextSingleton);

ApplyOp("ICETree", oObj, siNode, null, null, 0);
AddICECompoundNode("Set Data", oObj + ".polymsh.ICETree");
ConnectICENodes(oObj + ".polymsh.ICETree.port1", oObj +
".polymsh.ICETree.Set_Data.Execute");
SetValue(oObj + ".polymsh.ICETree.Set_Data.Reference", "self.Materials",
null);
AddICENode("$XSI_DSPRESETS\\ICENodes\\GetDataNode.Preset", oObj +
".polymsh.ICETree");
ConnectICENodes(oObj + ".polymsh.ICETree.Set_Data.Value", oObj +
".polymsh.ICETree.SceneReferenceNode.value");
SetValue(oObj + ".polymsh.ICETree.SceneReferenceNode.reference", oObj +
".sMaterials", null);

var aData = [sLib + "Mat0", sLib + "Mat1", sLib + "Mat2", sLib + "Mat3"];
var asData = getSafeArray(aData);
var asData1 = getSafeArray([asData]);
oIA.DataArray2D = asData1;

AddICECompoundNode("Set Data", oObj + ".polymsh.ICETree");
AddPortToICENode(oObj + ".polymsh.ICETree.port1",
siNodePortDataInsertionLocationAfter);
ConnectICENodes(oObj + ".polymsh.ICETree.port2",
"grid.polymsh.ICETree.Set_Data[1].Execute");
SetValue(oObj + ".polymsh.ICETree.Set_Data[1].Reference",
"self.MaterialID", null);

var oIA = oObj.ActivePrimitive.GetICEAttributeFromName("MaterialID");
var saData = getSafeArray([1,2,3,4]);
oIA.DataArray = saData;

Matt Lind

unread,
Mar 25, 2013, 1:32:39 PM3/25/13
to soft...@listproc.autodesk.com
That would be a bug.

Softimage is suspposed to handle the conversion from Jscript array to SafeArray as that's how it's handled in the rest of the application.


Matt
Reply all
Reply to author
Forward
0 new messages