Trouble Accessing RTVal Dictionary Elements via Python

Hi. I'm a bit stuck.

I've got an RTVal object which contains a dictionary. I'm trying to access this via python without any luck. Anybody have an idea of what I'm doing wrong?

import FabricEngine.Core
#contextID = cmds.fabricSplice('getClientContextID')
client = FabricEngine.Core.createClient()

klCode = """
object TTObject  {

    Integer intDict[String];
    RTVal defaultValuesDict[String];
};

function TTObject()
{
  this.intDict["negativeNine"] = -9;

  Integer parentIndexes[1];
  parentIndexes[0] = -3;
  this.defaultValuesDict["parentIndexes"] = parentIndexes;
}

"""
ext = [{
            "filename": "TT.kl",
            "sourceCode": klCode
        }]

result = client.registerKLExtension(
            "TTObject",
            ext,
            version="1.0.0",
            loadExt=True,
            reloadExt=False
        )

TTObj = client.RT.types.TTObject.create()
print(TTObj)
print(TTObj.intDict.isDict())
#TTObj.intDict.getDictElement("Integer", "negativeNine")

That last line that is comment out is what I'm trying to run, but get an error:

AttributeError: KL compile failed: no such method SInt32[String].getDictElement(String)

What I really want to do is access the other dict "defaultValuesDict" which is of generic RTVal type and cast back to the right type, but I can't even get the simple integer dict to work.

Anybody have ideas?

-TT

Tagged:

Comments

  • EricTEricT Administrator, Moderator, Fabric Employee Posts: 305 admin

    Hey Todd,

    I sent you the code already but to post here too for others:

    negativeNine = TTObj.intDict["negativeNine"].getSimpleType()
    
    # Then if you want to access the parentIndexes of the defaultValuesDict
    # To note here you need to cast the RTVal back to the type you're looking for.
    parentIndexes = client.RT.types.Integer(TTObj.defaultValuesDict['parentIndexes']).getSimpleType()
    print parentIndexes
    

    Eric Thivierge
    Kraken Developer
    Kraken Rigging Framework

  • TodderasesareddoTTodderasesareddoT Posts: 11
    edited June 2016

    Thanks, Eric.
    The simple case of the integer dict works ok, but your second example just returns 1 for me. What do you get?

    (parentIndexes is an integer array)

  • I would try:

    intArrType = getattr(client.RT.types, "Integer[]")
    parentIndexes = intArrType(TTObj.defaultValuesDict['parentIndexes']).getSimpleType()
    

    but that errors in the constructor.

    [FABRIC:MT] constructArgs__FA1_SI32.kl:2:136: error: no resolution for constructor SInt32[](SInt32[1])
    
  • parentIndexes is a generic RTVal in the dict, but really it's an SInt32[]. I'm thinking of a way to do an implicit cast instead of using a constructor for a new array.

  • EricTEricT Administrator, Moderator, Fabric Employee Posts: 305 admin

    Finally got it. It's a bit tricky

    defaultDictRTVal = TTObj.defaultValuesDict
    
    # Cast Default Dict to RTVal
    valTypeName = defaultDictRTVal.type('String').getSimpleType()
    rtValType = getattr(client.RT.types, valTypeName) # RTVal[String]
    pythonRTVal = rtValType(defaultDictRTVal)
    
    # Convert Parent Indexes to SInt32[1] fixed size array
    parentIndTypeName = defaultDictRTVal['parentIndexes'].type('String').getSimpleType()
    parentIndRTValType = getattr(client.RT.types, parentIndTypeName) # SInt32[1]
    parentIndexes = parentIndRTValType(defaultDictRTVal['parentIndexes'])
    print len(parentIndexes)
    print parentIndexes[0].getSimpleType()
    
    

    Eric Thivierge
    Kraken Developer
    Kraken Rigging Framework

  • EricTEricT Administrator, Moderator, Fabric Employee Posts: 305 admin
    edited June 2016

    A helper method can be created to do this too:

    def convertFromRTVal(target):
        valTypeName = target.type('String').getSimpleType()
        rtValType = getattr(client.RT.types, valTypeName)
        pythonRTVal = rtValType(target)
    
        return pythonRTVal
    

    You'll still need to convert to the simple type via the .getSimpleType() after this but at least it helps.

    Eric Thivierge
    Kraken Developer
    Kraken Rigging Framework

  • Ah, OK. So you can cast the data to an integer array of specific length. Nice. Thanks, Eric. Now I can finish up this code to give to you. ;)

  • StephenTStephenT Fabric for MotionBuilder Posts: 77

    a simple one-liner that for casting most types from Fabric->Python could be

    myPyVal = json.loads(myRTVal.getJSON().getSimpleType())

    the resulting structure pure native python, no need for further getSimpleType calls

    Although - this involves quite a bit of processing in the background. Best used when programmer efficiency > code efficiency

  • JulienCouetJulienCouet Fabric Employee Posts: 10 Fabric Employee

    Hello Stephen.

    We have also some documentation on how accessing RTVals in Python : http://docs.fabric-engine.com/FabricEngine/2.4.0/HTML/RTValProgrammingGuide/python.html?highlight=rtval

    Hope it helps too.

Sign In or Register to comment.