Adding a StartAtFrame parameter to Button.Animate

Started by vga256, Mon 14/03/2022 20:32:57

Previous topic - Next topic

vga256

As the title suggests - I'm looking for a recommended workaround that would allow me to choose the starting frame for a Button animation. The start frame option was added to Object and Character a few years ago, but Button fell by the wayside.

Because there is no function overloading allowed, what I'm asking for in the topic isn't possible in AGS. It seems that rewriting the entire Animate function, and replicating (in a new module) what Button.Animate does may be necessary. Can someone recommend a workaround that falls short of rewriting the entire Button.Animate implementation?

Cassiebsg

The "obvious" workaround to me seems to be to manually animate the button.
Set the start frame as default, then change the button sprite to the next one with a while/for condition on a timer.
There are those who believe that life here began out there...

eri0o

Just for kicks...

animate_btn.ash
Spoiler
Code: ags
// new module header

 import void AnimateEx(this Button*, int view, int loop = 0, int delay = 1, RepeatStyle style = eOnce, int frame = 0);
 
 import void Stop(this Button*);
 
[close]


animate_btn.asc
Spoiler
Code: ags
// new module script
#define MAX_ANIM_BTNS 32
#define ITERATE_BTNS for(int i=0; i<_btn_count; i++)

struct animated_ex_btn {
  int Frame;
  int Loop;
  int View;
  int Delay;
  int Ticks;
  RepeatStyle RepeatStyle;
  Button* Button;
};

int _btn_count;
animated_ex_btn _btn[MAX_ANIM_BTNS];

void _remove_btn(Button* btn)
{
  int k = MAX_ANIM_BTNS + 1;
  
  ITERATE_BTNS
  {
    if(_btn[i].Button == btn)
    {
      k = i;
    }
    
    if(i > k)
    {
      _btn[i-1].Frame = _btn[i].Frame;
      _btn[i-1].Loop = _btn[i].Loop;
      _btn[i-1].View = _btn[i].View;
      _btn[i-1].Delay = _btn[i].Delay;
      _btn[i-1].Ticks = _btn[i].Ticks;
      _btn[i-1].RepeatStyle = _btn[i].RepeatStyle;
      _btn[i-1].Button = _btn[i].Button;
    }
  }
  
  if(k <= MAX_ANIM_BTNS) {
    _btn_count--;
  }
}

void _add_btn(Button* btn, int view, int loop, int delay, RepeatStyle style, int frame)
{
  _btn[_btn_count].Frame = frame;
  _btn[_btn_count].Loop = loop;
  _btn[_btn_count].View = view;
  _btn[_btn_count].Delay = delay;
  _btn[_btn_count].RepeatStyle = style;
  _btn[_btn_count].Button = btn;
  _btn[_btn_count].Ticks = 0;
  
  _btn_count++;
}

void repeatedly_execute_always()
{
  ITERATE_BTNS
  { 
    _btn[i].Ticks++;
    
    if(_btn[i].Ticks < _btn[i].Delay) continue;
    
    int loop = _btn[i].Loop;
    int view = _btn[i].View;
    
    int loop_count = Game.GetLoopCountForView(view);
    if(loop >= loop_count) continue;
        
    int frame_count = Game.GetFrameCountForLoop(view, loop);
    
    _btn[i].Ticks = 0;
    _btn[i].Frame++;
    if(_btn[i].Frame >= frame_count) _btn[i].Frame = 0;
    int frame = _btn[i].Frame;
    
    ViewFrame* vf = Game.GetViewFrame(view, loop, frame);
    int sprite = vf.Graphic;
    
    _btn[i].Button.NormalGraphic = sprite;
  }  
}

// public interface

void AnimateEx(this Button*, int view, int loop, int delay, RepeatStyle style, int frame) {
  _add_btn(this, view, loop, delay, style, frame);
}

void Stop(this Button*) {
  _remove_btn(this);
}
[close]

Not sure how well it works, but hey! It was a shot!

vga256

Haha wow @eri0o! Looks like you wrote almost the exact same implementation as me, and you solved a few of my problems with Views along the way! I'll give this a shot and provide an update in a bit.

eri0o

Hey, the code has no safeguards, like you can make it wrong if you animate something twice without stopping before, there's no easy way to read the current frame and things like that.

If you think this is somewhat useful I may properly put this in a module and try to add the safeguards. I was kinda trying to see how small I could code this and it wasn't as small as I thought but still reasonably compact. :P

eri0o

There's a reasonable chance this will be featured in a beta release in a near future.

vga256

Excellent! I'm still in the process of rewriting it for my code styling. Will keep you posted.

Crimson Wizard

For information, 3.6.0 Beta now includes extended Button.Animate that has "starting frame" among the new parameters.

SMF spam blocked by CleanTalk