Keyframes update with xform

Keyframes update with xform

hamsterHamster
Advisor Advisor
1,144 Views
10 Replies
Message 1 of 11

Keyframes update with xform

hamsterHamster
Advisor
Advisor

Hey everyone,

An user asked about rotation order change and animation preservation. Obviously the

xform -p true -roo zxy ;

is a way to go, and it executes beautifully for a single frame. However, when I push it through the timeline and execute for every frame, it doesn't influence keyframes.

 

$sel = `ls -sl` ;
$cur_t = `currentTime -q` ;

// save current rot order for every object in selection
string $roos[] ;
$i = 0 ;
for ( $s in $sel ) {
    $roos[$i] = `xform -q -roo $s` ;
    $i++ ;
}

// resample keyframes within the playback range
$start = `playbackOptions -q -min` ;
$end = `playbackOptions -q -max` ;
print("Resampling range: "+ $start +" - "+ $end +"\n") ;
for ( $i = $start; $i <= $end; $i++ ) {
    xform -roo xyz ;
    currentTime -e $i ;
    xform -p true -roo zxy ;
}
/*
for ( $i = $start; $i <= $end; $i++ ) {
    currentTime -e $i ; 
    for ( $j = 0; $j < size($sel); $j++ ) {
        xform -roo $roos[$j] $sel[$j];
        xform -p true -roo zxy $sel[$j];
        $x = `getAttr ($sel[$j]+".rotateX")` ;
        $y = `getAttr ($sel[$j]+".rotateY")` ;
        $z = `getAttr ($sel[$j]+".rotateZ")` ;
        setKeyframe -at ($sel[$j]+".rotateX") -v $x -itt "linear" -ott "linear" ;
        setKeyframe -at ($sel[$j]+".rotateY") -v $y -itt "linear" -ott "linear" ;
        setKeyframe -at ($sel[$j]+".rotateZ") -v $z -itt "linear" -ott "linear" ;
    }
}
*/

 

Without the getAttr-setKeyframe it just spits out autoKeyframe message after every frame, with it the changes maybe are there, but the animation is altered, which doesn't happen, when xform is executed for a single frame.

How to make it update keyframes as per single frame?


,,,_°(O__O)°_,,,
Maya2019.1 @ Windows10 & GeForce GTX1080Ti

If the post was helpful, click the
 ACCEPT SOLUTION  button, so others might find it much more easily.

Accepted solutions (1)
1,145 Views
10 Replies
Replies (10)
Message 2 of 11

mcw0
Advisor
Advisor

Interesting.  I haven't had to do this.  But if I had to, I'd make a duplicate node.  Set the rotation order.  Orient constrain it back to the original.  Set keyframes at your original keyframes and then delete the orient constraint.  Now delete the animation on your original node.  Set the rotation order.  Copy the animation from the duplicate to the original and delete the duplicate.

0 Likes
Message 3 of 11

hamsterHamster
Advisor
Advisor

@mcw0yes, this is what I was doing previously in my own scenes, where I had to correct mocap and had a small number of transforms. Here that user was asking for transferring entire skeleton to a different rotation order - writing a script for that constraint approach would be much more complex and idk if worth candles burnt.

Here, when executing the script, it just ignores any autoKeyframe states, runs through the timeline without keeping the changes.


,,,_°(O__O)°_,,,
Maya2019.1 @ Windows10 & GeForce GTX1080Ti

If the post was helpful, click the
 ACCEPT SOLUTION  button, so others might find it much more easily.

0 Likes
Message 4 of 11

mcw0
Advisor
Advisor

Then I wonder if running "refresh" would cause the autoKey to activate.  There are a few functions that when run in a script won't yield the same change as when performed manually.  And the only difference is the screen gets refreshed.

0 Likes
Message 5 of 11

hamsterHamster
Advisor
Advisor

It rather seems that xform -p --roo zxy converts the values, but getAttr still gets old-keyframed info, and apparently setKeyframe just sets over the same value, I don't know how to check if the fault is elsewhere. The -roo changes to zxy, the orientation differs (-p ignored), and once I switch back to xyz, the orientation is restored. No effect.

I tried to put refresh -f in several places, and it changed nothing. Perhaps any specific place you'd suggest?


,,,_°(O__O)°_,,,
Maya2019.1 @ Windows10 & GeForce GTX1080Ti

If the post was helpful, click the
 ACCEPT SOLUTION  button, so others might find it much more easily.

0 Likes
Message 6 of 11

mcw0
Advisor
Advisor

I thought a refresh after "xform -p true -roo zxy" would do the trick.  Maybe try a dgeval or dgdirty instead of the refresh.  There needs to be some event to trigger an update.

0 Likes
Message 7 of 11

hamsterHamster
Advisor
Advisor

Nah, as much as I've tried, neither refresh, dgeval nor dgdirty after that line had an effect.
Current iteration:

$sel = `ls -sl` ;
$cur_t = `currentTime -q` ;

// save current rot order for every object in selection
string $roos[] ;
$i = 0 ;
for ( $s in $sel ) {
    $roos[$i] = `xform -q -roo $s` ;
    $i++ ;
}

// resample keyframes within the playback range
$start = `playbackOptions -q -min` ;
$end = `playbackOptions -q -max` ;
print("Resampling range: "+ $start +" - "+ $end +"\n") ;
/*
// short version
for ( $i = $start; $i <= $end; $i++ ) {
    xform -roo xyz ;
    currentTime -e $i ;
    xform -p true -roo zxy ;
}
*/
// explicit version
$axis = { "x", "y", "z"} ;
for ( $i = $start; $i <= $end; $i++ ) {
    currentTime -e $i ; 
    for ( $j = 0; $j < size($sel); $j++ ) {
        print(`currentTime -q`) ;
        select -r $sel[$j] ;
        print(" Change ") ;
        autoKeyframe -st off ;
        xform -roo $roos[$j] $sel[$j] ;
        print($roos[$j] + " to ") ;
        autoKeyframe -st on ;
        xform -p true -roo zxy $sel[$j];      // HERE YOU SET DESIRED ROT ORDER
        dgeval -v $sel[$j] ;                  // <-- anything else?
        print(`xform -q -roo $sel[$j]` +" with ") ;
        for ($a in $axis){
            $val = `getAttr ($sel[$j] +".r"+ $a)` ;
            setKeyframe -at (".r"+ $a) -v $val ;
            print($val +" ") ;
        }
        print(" for "+ $sel[$j] +"\n") ;
    }
}

Could you have a look yourself, please?

All you need is to select any object with animation in Rxyz and open AttrEd.


,,,_°(O__O)°_,,,
Maya2019.1 @ Windows10 & GeForce GTX1080Ti

If the post was helpful, click the
 ACCEPT SOLUTION  button, so others might find it much more easily.

0 Likes
Message 8 of 11

mcw0
Advisor
Advisor
Accepted solution

This appears to be working.  Of course the interpolation is different due to the different rotation order.  But the keyframes are correct.

 

mel.PNG

Message 9 of 11

hamsterHamster
Advisor
Advisor

Woooow, @mcw0 , magic happens and you are a magician! 😄 It really resampled curves.

Actually, my script also works now, I borrowed one line from yours - replaced the first xform with setAttr - that was the deal-maker. Works for multiple selection in a single run. Thanks! 😃

 

 

$sel = `ls -sl` ;
$cur_t = `currentTime -q` ;

// save current rot order for every object in selection
string $roos[] ;
$i = 0 ;
for ( $s in $sel ) {
    $roos[$i] = `xform -q -roo $s` ;
    $i++ ;
}

// resample keyframes within the playback range
$start = `playbackOptions -q -min` ;
$end = `playbackOptions -q -max` ;
print("Resampling range: "+ $start +" - "+ $end +"\n") ;
$axis = { "x", "y", "z"} ;
for ( $i = $start; $i <= $end; $i++ ) {
    currentTime -e $i ; 
    for ( $j = 0; $j < size($sel); $j++ ) {
        select -r $sel[$j] ;
        setAttr ($sel[$j]+".rotateOrder") 0 ;
        xform -p true -roo zxy $sel[$j];      // HERE YOU SET DESIRED ROT ORDER
        for ($a in $axis){
            $val = `getAttr ($sel[$j] +".r"+ $a)` ;
            setKeyframe -at (".r"+ $a) -v $val ;
        }
    }
}

 

 

 

Your script takes in account entire range of each curve, and with just a small injection works with multiple selection too, just runs for each object separately. Will post it here, because it has its own perks.

 

 

 

string $sel[] = `ls -sl` ;
for ($s in $sel) {
    string $anims[] =`listConnections -s 1 -d 0 -type "animCurve" $s` ;
    float $keys[] ;
    clear $keys ;
    for ($anim in $anims) {
        float $resultsF[] = `keyframe -q -tc $anim` ;
        for ($resultF in $resultsF) {
            int $found = 0 ;
            for ($key in $keys) {
                if ($resultF == $key) {
                    $found = 1 ;
                    break ;
                }
            }
            if (!$found)
                $keys[size($keys)] = $resultF ;
        }
    }

    for ( $key in $keys ) {
        currentTime $key ;
        setAttr ($s+".rotateOrder") 0 ;
        xform -p 1 -roo zxy ;
    }
}

 

 

 

 


,,,_°(O__O)°_,,,
Maya2019.1 @ Windows10 & GeForce GTX1080Ti

If the post was helpful, click the
 ACCEPT SOLUTION  button, so others might find it much more easily.

0 Likes
Message 10 of 11

mcw0
Advisor
Advisor

Glad I could help.  Be careful...that setAttr is hardcoded to "xyz" as the current rotation order.  I think your original code of querying the current rotation order should be added to the current code...to set the appropriate rotation order.

0 Likes
Message 11 of 11

hamsterHamster
Advisor
Advisor

Yeah, thanks, noticed, updated.

Strangely shorthand of .rotateOrder => .roo didn't work there.

Anyways, submitted as an Idea and this will come in handy for my project too.

Cheers.


,,,_°(O__O)°_,,,
Maya2019.1 @ Windows10 & GeForce GTX1080Ti

If the post was helpful, click the
 ACCEPT SOLUTION  button, so others might find it much more easily.

0 Likes