@@ -351,6 +351,8 @@ def exportAction(self, context, root, objects, action):
351351 animation .SetLooping (self .is_looped )
352352
353353 curves = {}
354+ uniqueKeyframes = set ()
355+ uniqueCurves = []
354356
355357 with ProgressReport (context .window_manager ) as progress :
356358 progress .enter_substeps (len (action .fcurves ))
@@ -371,59 +373,66 @@ def exportAction(self, context, root, objects, action):
371373
372374 poseBone = target .data
373375
376+ # Precompute a list of keyframes for export.
377+ keyframes = [int (x .co [0 ]) for x in curve .keyframe_points ]
378+ # Update the unique keyframe list so we only iterate once.
379+ uniqueKeyframes .update (keyframes )
380+
374381 if target == poseBone .location .owner :
375382 result = curves .get (poseBone , [])
376- result .append (
377- (curve , "location" , curve .array_index ))
383+ result .append ((curve ,
384+ "location" ,
385+ curve .array_index ,
386+ keyframes ))
387+
378388 curves [poseBone ] = result
379389 elif target == poseBone .rotation_quaternion .owner or target == poseBone .rotation_euler .owner :
380390 result = curves .get (poseBone , [])
381- result .append (
382- (curve , "rotation_quaternion" , curve .array_index ))
391+ result .append ((curve ,
392+ "rotation_quaternion" ,
393+ curve .array_index ,
394+ keyframes ))
395+
383396 curves [poseBone ] = result
384397 elif target == poseBone .scale .owner :
385398 result = curves .get (poseBone , [])
386- result .append (
387- (curve , "scale" , curve .array_index ))
399+ result .append ((curve ,
400+ "scale" ,
401+ curve .array_index ,
402+ keyframes ))
403+
388404 curves [poseBone ] = result
389405
390406 progress .step ()
391407
392408 progress .leave_substeps ()
393409 progress .enter_substeps (len (curves .keys ()))
394410
395- # Iterate on the target/curves and generate the proper cast curves.
396411 for target , curves in curves .items ():
397- # We must handle quaternions separately, and key them together .
412+ # Quaternions are combined into their own curve .
398413 rotationQuaternion = [
399414 x for x in curves if x [1 ] == "rotation_quaternion" ]
400415
401- if len ( rotationQuaternion ) > 0 :
416+ if rotationQuaternion :
402417 curveNode = animation .CreateCurve ()
403418 curveNode .SetNodeName (target .name )
404419 curveNode .SetKeyPropertyName ("rq" )
405420 curveNode .SetMode ("absolute" )
406421
407- keyframes = []
422+ keyframes = set ()
408423
409424 for curve in rotationQuaternion :
410- keyframes .extend ([int (x .co [0 ])
411- for x in curve [0 ].keyframe_points ])
412-
413- keyframes = list (set (keyframes ))
414-
415- curveNode .SetKeyFrameBuffer (keyframes )
425+ keyframes .update (curve [3 ])
416426
417- keyvalues = []
427+ uniqueCurves .append ((curveNode ,
428+ target ,
429+ "rotation_quaternion" ,
430+ 0 ,
431+ keyframes ,
432+ [],
433+ []))
418434
419- for keyframe in keyframes :
420- context .scene .frame_set (keyframe )
421- quat = utilityGetQuatKeyValue (target )
422- keyvalues .append ((quat .x , quat .y , quat .z , quat .w ))
423-
424- curveNode .SetVec4KeyValueBuffer (keyvalues )
425-
426- for (curve , property , index ) in curves :
435+ for (curve , property , index , keyframes ) in curves :
427436 switcherProperty = {
428437 "location" : ["tx" , "ty" , "tz" ],
429438 "scale" : ["sx" , "sy" , "sz" ]
@@ -432,27 +441,70 @@ def exportAction(self, context, root, objects, action):
432441 if property not in switcherProperty :
433442 continue
434443
444+ propertyName = switcherProperty [property ][index ]
445+
435446 curveNode = animation .CreateCurve ()
436447 curveNode .SetNodeName (target .name )
437- curveNode .SetKeyPropertyName (switcherProperty [ property ][ index ] )
448+ curveNode .SetKeyPropertyName (propertyName )
438449 curveNode .SetMode ("absolute" )
439450
440- keyframes = [int (x .co [0 ]) for x in curve .keyframe_points ]
451+ uniqueCurves .append ((curveNode ,
452+ target ,
453+ property ,
454+ index ,
455+ keyframes ,
456+ [],
457+ []))
441458
442- curveNode . SetKeyFrameBuffer ( keyframes )
459+ progress . step ( )
443460
444- keyvalues = []
461+ progress .leave_substeps ()
462+ progress .enter_substeps (len (uniqueKeyframes ))
463+
464+ # Iterate over the keyframes in this animation.
465+ for keyframe in uniqueKeyframes :
466+ context .scene .frame_set (keyframe )
467+
468+ for (_ ,
469+ target ,
470+ property ,
471+ index ,
472+ frames ,
473+ keyframes ,
474+ keyvalues ) in uniqueCurves :
475+ if keyframe not in frames :
476+ continue
445477
446- if property == "location" :
447- scale = self .scale
448- else :
449- scale = 1.0
478+ keyframes .append (keyframe )
450479
451- for keyframe in keyframes :
452- context .scene .frame_set (keyframe )
453- keyvalues .append (utilityGetSimpleKeyValue (
454- target , property )[index ] * scale )
480+ if property == "rotation_quaternion" :
481+ quat = utilityGetQuatKeyValue (target )
482+ keyvalues .append ((quat .x , quat .y , quat .z , quat .w ))
483+ elif property == "location" :
484+ simple = utilityGetSimpleKeyValue (target , property )[index ]
485+ keyvalues .append (simple * self .scale )
486+ elif property == "scale" :
487+ simple = utilityGetSimpleKeyValue (target , property )[index ]
488+ keyvalues .append (simple )
455489
490+ progress .step ()
491+
492+ progress .leave_substeps ()
493+ progress .enter_substeps (len (uniqueCurves ))
494+
495+ # Apply the keyframe and keyvalue buffers to the curve.
496+ for (curveNode ,
497+ _ ,
498+ property ,
499+ _ ,
500+ _ ,
501+ keyframes ,
502+ keyvalues ) in uniqueCurves :
503+ curveNode .SetKeyFrameBuffer (keyframes )
504+
505+ if property == "rotation_quaternion" :
506+ curveNode .SetVec4KeyValueBuffer (keyvalues )
507+ else :
456508 curveNode .SetFloatKeyValueBuffer (keyvalues )
457509
458510 progress .step ()
0 commit comments