Skip to main content
oliverIntergrafika
Inspiring
December 12, 2015
Answered

Is there a way to get the current timeline frame number in Frame Animation mode?

  • December 12, 2015
  • 2 replies
  • 5376 views

I would like to know which frame is the active frame in Frame Animation mode.

I am using three scriptListener funcitons in order to avoid frame 1 propagation to ruin the timeline when something is changing in frame 1:

duplicateTimelineFrame(); <<< do something with layers >>>; deleteTimelineFrame(); stepBackOneTimelineFrame();

But when im doing something on the last frame, this sequence is stepping back one more frame.

I have found a few user made getCurrentFrame(), getFrameCount() functions but they all working on Video Timeline, and returnning 0 when I am trying to use them on a Frame Animation.

The PS DOM dont have any timeline related calsses or methods and I am confused from the script listener output. I dont have the willpower and intelligence to reverse engineer the code and make modifications in it.

Thank You!

This topic has been closed for replies.
Correct answer c.pfaffenbichler

Actually my own grasp on AM code is tenuous …

But in this example I can provide the code:

////// get framedelay //////

function getFrameDelay (theIndex) {

var ref = new ActionReference(); 

ref.putProperty(charIDToTypeID('Prpr'), stringIDToTypeID('animationFrameDelay')); 

ref.putIndex(stringIDToTypeID('animationFrameClass'), theIndex);

//ref.putEnumerated(stringIDToTypeID('animationFrameClass'), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ));

var desc=new ActionDescriptor(); 

desc.putReference(charIDToTypeID('null'), ref);          

var aaa = executeAction(charIDToTypeID('getd'), desc, DialogModes.NO);

//checkDesc2 (aaa);

return aaa.getDouble(stringIDToTypeID('animationFrameDelay'))

};

2 replies

c.pfaffenbichler
Community Expert
Community Expert
December 15, 2015

If a direct determination should be impossible a work-around presents itself:

• set the animationFrameDelay of the selected Frame/s to some outlandish number

• check all the Frames for that number thus identifying the affected Frames

• undo the changing of the animationFrameDelay

Now the second part may not be as straightforward as would be desirable as I am unsure one can determine the total number of Frames beforehand, but either deleting the first frame within a try clause until it throws an error or marking first and last Frame with another outlandish animationFrameDelay would be options.

oliverIntergrafika
Inspiring
December 15, 2015

Hi c.pfaffenbichler!

Thanks for your answer! How do you know these actionDescriptor and actionReference solutions? I am trying to understand them since weeks, searching for script examples, making modifications to them without success. I am unable to find a tutorial, or figure, or diagram about their structure.

Is there a .jsx library which is handlig these cryptic statements and constants? Did someone code the the missig DOM classes?

I feel myself an idiot, because all the wasted time and effort trying to solve these basic problems.

The sciptListener plugin exported the code below:

function setFrameDelay( delay )

{

var idsetd = charIDToTypeID( "setd" );

    var desc5 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref2 = new ActionReference();

        var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref2.putEnumerated( idanimationFrameClass, idOrdn, idTrgt );

    desc5.putReference( idnull, ref2 );

    var idT = charIDToTypeID( "T  " );

        var desc6 = new ActionDescriptor();

        var idanimationFrameDelay = stringIDToTypeID( "animationFrameDelay" );

        desc6.putDouble( idanimationFrameDelay, delay );

    var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

    desc5.putObject( idT, idanimationFrameClass, desc6 );

executeAction( idsetd, desc5, DialogModes.NO );

}

Could you please instruct me, how to turn this into a getter function?

Thanks a lot!
Oliver

oliverIntergrafika
Inspiring
December 15, 2015

I’m just trying to "pass on" some of the help I got from (at the time) Forum regulars like xbytor, Mike Hale, Paul Riggott and others.


//////////////// TIMELINE

try{

#target "Photoshop" ;

Timeline = {

  selectFrame: function( theIndex )

  {

  try

  {

  var idslct = charIDToTypeID( "slct" );

  var desc152 = new ActionDescriptor();

  var idnull = charIDToTypeID( "null" );

  var ref84 = new ActionReference();

  var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

  ref84.putIndex( idanimationFrameClass, theIndex );

  desc152.putReference( idnull, ref84 );

  executeAction( idslct, desc152, DialogModes.NO );

  }

  catch ( e ) {

  return false;

  }

  return theIndex;

  },

  getFrameCount: function () // till no faster way to retrieve it

  {

  this.markFrame();

  var f = 1;

  while( this.selectFrame( f++ ) )

  this.selectMarkedFrame();

  this.unMarkFrame();

  return f-2;

  },

  selectMarkedFrame: function () {

  var f = 1;

  while( this.selectFrame( f++ ) && !this.isMarked() )

  },

  markFrame: function ()

  {

  this.setFrameDelay ( this.getFrameDelay() + 1000 );

  },

  unMarkFrame: function ()

  {

  this.setFrameDelay ( this.getFrameDelay() - 1000 );

  },

  isMarked: function ()

  {

  return this.getFrameDelay() >= 1000;

  },

  setFrameDelay: function ( delay )

  {

  var idsetd = charIDToTypeID( "setd" );

     var desc = new ActionDescriptor();

     var ref = new ActionReference();

  ref.putEnumerated(stringIDToTypeID('animationFrameClass'), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ));

     desc.putReference( charIDToTypeID( "null" ), ref );

     var idT = charIDToTypeID( "T   " );

     var desc6 = new ActionDescriptor();

     desc6.putDouble( stringIDToTypeID( "animationFrameDelay" ), delay );

     desc.putObject( idT, stringIDToTypeID( "animationFrameClass" ), desc6 );

  executeAction( idsetd, desc, DialogModes.NO );

  },

  getFrameDelay: function ( theIndex )

  {

     var ref = new ActionReference();

     ref.putProperty(charIDToTypeID('Prpr'), stringIDToTypeID('animationFrameDelay'));

  if ( theIndex ) {

  ref.putIndex(stringIDToTypeID('animationFrameClass'), theIndex);

  }

  else {

  ref.putEnumerated(stringIDToTypeID('animationFrameClass'), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ));

  }

   

     var desc=new ActionDescriptor();

     desc.putReference(charIDToTypeID('null'), ref);        

     var aaa = executeAction(charIDToTypeID('getd'), desc, DialogModes.NO);

     // this.checkDesc2 (aaa);

     return aaa.getDouble(stringIDToTypeID('animationFrameDelay'))

  },

  duplicateFrame: function()

  {

  executeAction( stringIDToTypeID( "makeFrameAnimation" ), undefined, DialogModes.NO ); // crate timeline

     var desc = new ActionDescriptor();

     var ref = new ActionReference();

     ref.putEnumerated( stringIDToTypeID( "animationFrameClass" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );

     desc.putReference( charIDToTypeID( "null" ), ref );

     executeAction( charIDToTypeID( "Dplc" ), desc, DialogModes.NO );

  },

  deleteFrame: function()

  {

     try

     {

         var desc = new ActionDescriptor();

         var ref = new ActionReference();

         ref.putEnumerated( stringIDToTypeID( "animationFrameClass" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );

         desc.putReference( charIDToTypeID( "null" ), ref );

         executeAction( charIDToTypeID( "Dlt " ), desc, DialogModes.NO );

     } catch ( e )

     {

         $.writeln("No Timeline, Cannot delete!")

     }

  },

  stepBackOneFrame: function()

  {

  var idanimationFrameActivate = stringIDToTypeID( "animationFrameActivate" );

     var desc9 = new ActionDescriptor();

     var idnull = charIDToTypeID( "null" );

         var ref4 = new ActionReference();

         var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

         var idOrdn = charIDToTypeID( "Ordn" );

         var idPrvs = charIDToTypeID( "Prvs" );

         ref4.putEnumerated( idanimationFrameClass, idOrdn, idPrvs );

     desc9.putReference( idnull, ref4 );

  executeAction( idanimationFrameActivate, desc9, DialogModes.NO );

  },

////// based on code by michael l hale //////

  checkDesc2: function  ( theDesc ) {

     var c = theDesc.count;

     var str = '';

     for( var i=0; i<c; i++ ){ //enumerate descriptor's keys

         str = str + 'Key '+ i + ' = ' + typeIDToStringID(theDesc.getKey(i)) + ': ' + theDesc.getType(theDesc.getKey(i))+'\n'+ this.getValues (theDesc, i)+'\n';

     };

     alert("desc\n\n"+str);

  },

  ////// check //////

  getValues: function  ( theDesc, theNumber ) {

     switch (theDesc.getType(theDesc.getKey(theNumber))) {

     case DescValueType.BOOLEANTYPE:

     return theDesc.getBoolean(theDesc.getKey(theNumber));

     break;

     case DescValueType.CLASSTYPE:

     return theDesc.getClass(theDesc.getKey(theNumber));

     break;

     case DescValueType.DOUBLETYPE:

     return theDesc.getDouble(theDesc.getKey(theNumber));

     break;

     case DescValueType.ENUMERATEDTYPE:

     return (typeIDToStringID(theDesc.getEnumerationValue(theDesc.getKey(theNumber)))+"_"+typeIDToStringID(theDesc.getEnumerationType(theDesc.getKey(theNumber))));

     break;

     case DescValueType.INTEGERTYPE:

     return theDesc.getInteger(theDesc.getKey(theNumber));

     break;

     case DescValueType.LISTTYPE:

     return theDesc.getList(theDesc.getKey(theNumber));

     break;

     case DescValueType.OBJECTTYPE:

     return (theDesc.getObjectValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getObjectType(theDesc.getKey(theNumber))));

     break;

     case DescValueType.REFERENCETYPE:

     return theDesc.getReference(theDesc.getKey(theNumber));

     break;

     case DescValueType.STRINGTYPE:

     return theDesc.getString(theDesc.getKey(theNumber));

     break;

     case DescValueType.UNITDOUBLE:

     return (theDesc.getUnitDoubleValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getUnitDoubleType(theDesc.getKey(theNumber))));

     break;

     default:

     break;

     };

  },

}

} catch ( e ) { alert ( e ) };

This is a short timeline manipulation .jsx. Now I can continue working on my little project.

Inspiring
December 12, 2015

‌i too have this question. I could only figure out how to set selection to a frame. But not how to retrieve current selection