UserDataMap

Object Hierarchy | 関連する C++クラス:UserDataMap

継承

SIObject

ProjectItem

Property

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引数に対応します。

ユーザデータマップのプリセットを保存しておけば、別のオブジェクトにそのユーザデータを適用できます。最良の結果を得るためには、両クラスタのコンポーネント数を揃えるようにしてください。

メソッド

AddCustomOp AddScriptedOp AddScriptedOpFromFile AnimatedParameters2
BelongsToオペレータ Clearオペレータ ClearItemオペレータ EvaluateAt
GetICEAttributeFromName GetItem2オペレータ GetItemSize2オペレータ GetItemValue2オペレータ
IsA IsAnimated2 IsClassOfオペレータ IsEqualToオペレータ
IsKindOf IsLockedオペレータ IsSelectedオペレータ LockOwners
SetAsSelectedオペレータ SetCapabilityFlagオペレータ SetLock TaggedParameters
UnSetLock      
       

プロパティ

Application Branchオペレータ BranchFlagオペレータ Capabilitiesオペレータ
Categories Countオペレータ EvaluationID Familiesオペレータ
FullNameオペレータ Help HierarchicalEvaluationID ICEAttributes
IsEmptyオペレータ Itemオペレータ ItemSizeオペレータ ItemValueオペレータ
LittleEndianオペレータ LockLevelオペレータ LockMastersオペレータ LockTypeオペレータ
Model Nameオペレータ NestedObjects ObjectID
Origin OriginPath Owners PPGLayoutオペレータ
Parametersオペレータ Parent Parent3DObject Selectedオペレータ
Singletonオペレータ Templateオペレータ Typeオペレータ  
       

1. VBScript の例

'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"

2. JScript の例

//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"

3. VBScript の例

'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

4. VBScript の例

'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

関連項目

UserDataItem UserDataBlob CustomProperty Cluster ClusterProperty