I'm currently working on the Animation Nodes and I'm trying to read all fcurves of one object and dynamically set the evaluated values on other objects.
data_path = fCurve.data_path
array_index = fCurve.array_index
value = fCurve.evaluate(frame)
targetObject = some object
# How can I know wether to do this:
exec("targetObject.{} = value".format(data_path))
# or this:
exec("targetObject.{}[{}] = value".format(data_path, array_index))
I have a working version using try and except statements but this isn't really nice. I hoped that fcurve.array_index is -1 if it isn't used but it is 0 by default, so I cannot use it.
Just some extra notes:
Ideally the solution is fast but that isn't absolutely necessary because I can cache the result. Based on the decision wether the property at the data path is subscriptable or not, I dynamically create a setAttribute function so that I don't have to use exec for each execution. I talk about > 10.000 executions per second.
cache = {}
def getSetFunction(object, attribute):
if attribute in cache: return cache[attribute]
function = createSetFunction(object, attribute)
cache[attribute] = function
return function
def createSetFunction(object, attribute):
data = {}
try:
eval("object.{}[0]".format(attribute))
exec(setAttributeWithIndex.replace("attribute", attribute), data, data)
return data["setAttributeWithIndex"]
except:
try:
# when the property is not subscriptable
eval("object." + attribute)
exec(setAttributeWithoutIndex.replace("attribute", attribute), data, data)
return data["setAttributeWithoutIndex"]
except: pass
return None
setAttributeWithIndex = '''
def setAttributeWithIndex(object, index, value):
object.attribute[index] = value
'''
setAttributeWithoutIndex = '''
def setAttributeWithoutIndex(object, index, value):
object.attribute = value
'''