Object Hierarchy | 関連する C++クラス:UserDataMap
UserDataMap
v3.0
UserDataMap は、任意のクラスタに割り当てることができる Property です。UserDataMap により、ジオメトリの個々のコンポーネントに可変長のバイナリユーザデータを格納できます。このデータはシーンファイルの一部として保存され、オブジェクトモデルを使用することでプラグインからアクセスできます。
Softimage Plugin(パーシスタントエフェクトおよびイミディエイトエフェクトの双方)は、このプロパティを使い、個々の頂点、ポリゴン、エッジなどのオブジェクトのコンポーネントに関するデータを保存し、取得することができます。考え得るデータを具体的に挙げると、カスタムゲームストラクチャ、ローシミュレーションデータ、行列、コメント、イメージなどがあります。
UserDataMap には、バイナリデータ用に使用する用途とテンプレートデータ用に使用する用途の 2 通りがあります。バイナリ UserDataMap を使用すると、ユーザデータの構造は完全にプラグイン次第となります。これは C++ プラグインに適しています。ただし、以下の例が示すように、文字列を使うことによりスクリプトからこのデータにアクセスできます。テンプレート UserDataMap は、CustomProperty を使用してユーザデータの構造を厳密に定義します(UserDataMap.Template を参照)。テンプレートユーザデータはスクリプト、C++からのアクセスに加え UI からもインスペクトすることができます(InspectUserData を参照)。
UserDataMaps オブジェクトは、CreateUserDataMap または SceneItem.AddProperty を使用して作成できます。
UserDataMap は、クラスタの個々のコンポーネントに対して個別にデータを保存し、この点で CustomProperty オブジェクトや UserDataBlob オブジェクトとは異なります。たとえば、10 個のポリゴンを持つクラスタは、10 個の異なる UserDataItem オブジェクトを持ちます。UserDataItem オブジェクトを列挙する方法には、UserDataMap.Item を使用して UserDataMap に列挙する方法、VBScript の"for each"ループを作成する方法、および JScript の Enumerator オブジェクトを使用する方法があります。また、UserDataMap.ItemValue を使用して UserDataMap の内容に直接アクセスすることも可能です。
コンポーネント別のデータを保存する点で、UserDataMap は ClusterProperty に似ています。ただし、ClusterProperty は各コンポーネントにおいて常に倍精度の定数を保存し、UserDataMap は可変長データを使用できる点で異なります。
この User Data Map は、SAAPHIRE SAA_subelement* UserData 関数で使用できる User Data Map と同様の機能を提供します。たとえば、プロパティの名前(Name)は、SAA_subelementSetUserData などの関数の Tag 引数に対応します。
ユーザデータマップのプリセットを保存しておけば、別のオブジェクトにそのユーザデータを適用できます。最良の結果を得るためには、両クラスタのコンポーネント数を揃えるようにしてください。
'example giving an overview of accessing per-component 'user data on a cluster dim oObj, oCluster, oUDProp, i, oUserDataAtIndex2 set oObj = CreatePrim( "Sphere", "MeshSurface" ) SetValue oObj & ".polymsh.geom.subdivu", 1 SetValue oObj & ".polymsh.geom.subdivv", 1 'Create a cluster covering all edges on the geometry set oCluster = oObj.ActivePrimitive.Geometry.AddCluster( siEdgeCluster,"UserDataCls" ) set oUDProp = oCluster.AddProperty( "UserDataMap",,"UserDataExample" ) 'UserDataMap logmessage oUDProp.Type 'Assign user data to a particular index oUDProp.ItemValue(2) = "Some String Data" 'Another way to do the same thing is to use a UserDataItem object oUDProp.Item(3).Value = "String data for index 3" 'Erase the data we just placed at 3 oUDProp.ClearItem(3) 'Now look at all the user data in the property looking for non-empty content for i = 0 to oUDProp.Count if ( not oUDProp.IsEmpty(i) ) then logmessage "Found data with size " & oUDProp.ItemSize(i) & " at cluster index " & i end if next 'Output of this script is: 'INFO : "UserDataMap" 'INFO : "Found data with size 32 at cluster index 2" |
//example giving an overview of accessing per-component //user data on a cluster var oObj = CreatePrim( "Sphere", "MeshSurface" ) ; SetValue( oObj + ".polymsh.geom.subdivu", 1 ) ; SetValue( oObj + ".polymsh.geom.subdivv", 1 ) ; //Create a cluster covering all edges on the geometry var oCluster = oObj.ActivePrimitive.Geometry.AddCluster( siEdgeCluster, "UserDataCls" ) ; var oUDProp = oCluster.AddProperty( "UserDataMap",false,"UserDataExample" ) ; //UserDataMap logmessage( oUDProp.Type ) ; //Assign user data to a particular index oUDProp.ItemValue(2) = "Some String Data" //Or we can use a UserDataItem object as another way to set data oUDProp.Item(3).Value = "String data for index 3" //Erase the data we just placed at 3 oUDProp.ClearItem(3) //Now look at all the user data in the property looking for non-empty content for( var i = 0 ; i < oUDProp.Count ; i++ ) { if ( !oUDProp.IsEmpty(i) ) { logmessage( "Found data with size " + oUDProp.ItemSize(i) + " at cluster index " + i ) ; } } //Output of this script is: //INFO : "UserDataMap" //INFO : "Found data with size 32 at cluster index 2" |
'example demonstrating the how to display the entire contents 'of a binary user data map in the command history window. '(For an example showing how to show the contents of a templated user data map 'see the Info OM Netview page that is part of XSI Local\Tools) dim oObj, oCluster, oUDProp, i 'First set up a little demo scenario set oObj = CreatePrim( "Arc", "NurbsCurve" ) set oCluster = oObj.ActivePrimitive.Geometry.AddCluster( siVertexCluster,"PntCluster",Array(1,4,7,10,13,16) ) set oUDProp = oCluster.AddProperty( "UserDataMap",,"UserDataExample" ) 'Fill in the user data with the string version of the index for i = 0 to oUDProp.Count - 1 oUDProp.Item( i ).Value = CStr( i ) next SelectObj oUDProp 'Then dump out all the content that was added TraceSelectedUserDataMap 'Output of this script will look approximately like this: 'INFO : "User Data Map: arc.crvlist.cls.PntCluster.UserDataExample" 'INFO : "Size of User Data Map 6- Size of Cluster 6" 'INFO : "Property was created on little-endian computer" 'INFO : "Contents:" 'INFO : "Item 0 pnt(1): 0 " 'INFO : "Item 1 pnt(4): 1 " 'INFO : "Item 2 pnt(7): 2 " 'INFO : "Item 3 pnt(10): 3 " 'INFO : "Item 4 pnt(13): 4 " 'INFO : "Item 5 pnt(16): 5 " 'The number of components with user data could get huge so this constant 'constrains the size of the output to reasonable proportions const g_MapItemsDisplay = 256 const g_ShowEmptyItems = false sub TraceSelectedUserDataMap 'This example could easily to enhanced to loop through multiple selections 'but for the sake of simplicity it only looks at the first item if ( selection.Count > 0 ) then if ( typename( selection( 0 ) ) = "UserDataMap" ) then TraceUserDataMap( selection( 0 ) ) else logmessage "Please select a user data map and try again" end if else logmessage "Please select a user data map and try again" end if end sub sub TraceUserDataMap( in_oUDM ) dim i, oItem, cntCluster, byteString, j, str, val cntCluster = in_oUDM.Parent.Elements.Count Logmessage "User Data Map: " & in_oUDM.FullName Logmessage "Size of User Data Map " & in_oUDM.Count & "- Size of Cluster " & cntCluster Logmessage "Contents:" dim oCluster, oClusterElementsCollection, aElements set oCluster = in_oUDM.Parent set oClusterElementsCollection = oCluster.Elements aElements = oClusterElementsCollection.Array dim iElementInCluster, strItemDesc dim cntItems cntItems = in_oUDM.Count dim cntDisplayedItems cntDisplayedItems = 0 for i = 0 to ( cntItems - 1) if ( i < cntCluster ) then iElementInCluster = aElements(i) strItemDesc = "Item " & i & " " & oCluster.type & "(" & iElementInCluster & "): " else strItemDesc = "Item " & i & " " & oCluster.type & "(INVALID INDEX): " end if set oItem = in_oUDM.Item( i ) if ( not oItem.IsEmpty ) then 'We convert the contents into a byte by byte description 'because we don't know if this is a safe to display unicode string strItemDesc = strItemDesc & GetUserDataContentsString( oItem ) logmessage strItemDesc cntDisplayedItems = cntDisplayedItems + 1 if ( cntDisplayedItems = g_MapItemsDisplay ) then exit for end if elseif ( g_ShowEmptyItems ) then logmessage strItemDesc & " is empty" end if next end sub 'Produces a string representation of the user data function GetUserDataContentsString( in_UserDataItem ) dim strValue strValue = in_UserDataItem.Value dim j 'Also attempt to produce a string representation dim strAsString for j = 1 to Len( strValue ) val = Asc( Mid( strValue, j, 1 ) ) 'We only accept the basic ascii values - other content is 'not necessary safe to print. For supporting non-English 'characters, line breaks and tabs this logic would need 'to be more sophisticated if (( val < 127 ) AND ( val > 31 )) then strAsString = strAsString & Chr( val ) else 'we assume that there is binary content strAsString = strAsString & "." end if next GetUserDataContentsString = strAsString end function |
'example of how to access a templated UserDataMap from from scripting. 'In this example we create user data for an imaginary game on the vertices of 'a sphere. ' 'The user data template is designed to match an associated structure in the game engine, 'and consists of 5 parameters ("ImagePath", "AttachmentPoint", "FixedPoint", "ZetaFactor", 'and "Friction") ' 'This example creates the object and sets some example values on a few points. (A user could also 'add and edit these values from the user interface using the InspectUserData command) ' 'When you run this example this is the output in the log window: ' 'INFO : "User data on sphere.polymsh.cls.AllVertices.GameData" 'INFO : "pnt[12]: ZetaFactor:0.2 Friction:64 AttachmentPoint Image: image12.tif" 'INFO : "pnt[31]: ZetaFactor:0.9 Friction:12 AttachmentPoint FixedPoint Image: unknown" 'INFO : "pnt[44]: ZetaFactor:0.5 Friction:28 FixedPoint Image: image1.jpg" option explicit const g_ClusterName = "AllVertices" const g_UserDataMapName = "GameData" const g_TemplateName = "VertexInfoTemplate" newscene ,false dim oSphere, oUserDataMap set oSphere = ActiveSceneRoot.AddGeometry( "Sphere", "MeshSurface" ) 'Create templated user data map - currently it is has no user data set oUserDataMap = SetupObject( oSphere ) 'Set these user data values on vertex 44 call AddUserData( oUserDataMap , 44, "image1.jpg", false, true, 0.5, 28 ) 'Set different values on points 12 call AddUserData( oUserDataMap , 12, "background14.tif", true, false, 0.1, 39 ) 'Change our minds about point 12 call AddUserData( oUserDataMap , 12, "image12.tif", true, false, 0.2, 64 ) call AddUserData( oUserDataMap , 31, "unknown", true, true, 0.9, 12 ) call LogUserData( oUserDataMap ) 'On the given object create a UserDataMap for the game data function SetupObject( in_oObj ) dim oCluster, oPSet, oUserDataMap 'Test if we have already setup this object on error resume next set oUserDataMap = in_oObj.ActivePrimitive.Geometry._ Clusters( g_ClusterName ).Properties( g_UserDataMapName ) on error goto 0 if typename( oUserDataMap ) = "UserDataMap" then 'Our user data map already exists set SetupObject = oUserDataMap exit function end if set oCluster = in_oObj.ActivePrimitive.Geometry.AddCluster( siVertexCluster, g_ClusterName ) set oPSet = CreateTemplate( oCluster ) set oUserDataMap = oCluster.AddProperty( "UserDataMap",,g_UserDataMapName ) 'Associate the template with our user data map set oUserDataMap.Template = oPSet 'Return the newly created User Data Map set SetupObject = oUserDataMap end function 'This function creates the template that defines the format of the data inside our UserDataMap 'The new template is returned. 'Note: this function does not associate the template with any user data map, or set any values on 'the user data map. function CreateTemplate( in_oParentObject ) dim oPSet set oPSet = in_oParentObject.AddProperty( "Custom_parameter_list",, g_TemplateName ) oPSet.AddParameter "ImagePath", siString oPSet.AddParameter "AttachmentPoint", siBool, , , ,, , false oPSet.AddParameter "FixedPoint", siBool, , , ,, , false oPSet.AddParameter "ZetaFactor", siDouble, , , , , , 0.0, 0.0, 1.0 oPSet.AddParameter "Friction", siUByte, , , , , , 64, 0, 128 set CreateTemplate = oPSet end function 'Given specific game parameter values, this routine will save those values 'on the specified vertex of the UserDataMap sub AddUserData( in_oUDM, in_CompIndex, in_ImagePath, in_AttachPoint, in_FixedPoint, in_ZetaFactor, in_Friction ) 'Get access to the Template for this user data map dim oTemplate set oTemplate = in_oUDM.Template 'Fill in the parameters on the template oTemplate.Parameters( "ImagePath" ).Value = in_ImagePath oTemplate.Parameters( "AttachmentPoint" ).Value = in_AttachPoint oTemplate.Parameters( "FixedPoint" ).Value = in_FixedPoint oTemplate.Parameters( "ZetaFactor" ).Value = in_ZetaFactor oTemplate.Parameters( "Friction" ).Value = in_Friction 'Now that the parameters are specified we need to associated 'these values with the specified vertex in_oUDM.ItemValue(in_CompIndex) = oTemplate.BinaryData end sub 'This routine prints out the contents of our user data map sub LogUserData( in_oUDM ) dim oTemplate, i, strAttachPnt, strFixedPnt Logmessage "User data on " & in_oUDM set oTemplate = in_oUDM.Template for i = 0 to in_oUDM.count 'We can only print out non-empty user data items if ( NOT in_oUDM.IsEmpty( i ) ) then 'Take the values from the user data and put them in the template 'so that we can read them oTemplate.BinaryData = in_oUDM.ItemValue( i ) 'Look at the boolean values to convert into readable strings if ( oTemplate.Parameters("AttachmentPoint").Value ) then strAttachPnt = "AttachmentPoint " else strAttachPnt = "" end if if ( oTemplate.Parameters("FixedPoint").Value ) then strFixedPnt = "FixedPoint " else strFixedPnt = "" end if 'Print a 1 line representation of all the values on this particular point logmessage "pnt[" & i & "]: " & _ " ZetaFactor:" & oTemplate.Parameters("ZetaFactor").Value & _ " Friction:" & oTemplate.Parameters("Friction").Value & _ " " & strAttachPnt & strFixedPnt & _ "Image: " & oTemplate.Parameters("ImagePath").Value end if next end sub |