package AA::Anim;
+my @timer_queue;
+my $debug = 0;
+my $now = 0;
+
our $timer = AA->new('T');
$timer->DefSet('T', 0);
-sub time($) {
+sub now($) {
return $timer->Get('T');
}
+sub add_timer($$$) {
+ my ($class, $after, $sub) = @_;
+ my $t = $now + $after;
+ push @timer_queue, [ $t, $sub ];
+ print "@@@ Adding timer for $t\n" if $debug;
+ @timer_queue = sort { $a->[0] <=> $b->[0] } @timer_queue;
+}
+
+sub add_final($$) {
+ my ($class, $sub) = @_;
+ push @timer_queue, [ 1000000, $sub ];
+}
+
+sub start($) {
+ AA::Anim->add_final(sub { });
+ $now = 0;
+}
+
sub step($) {
- $timer->Set('T', $timer->Get('T') + 1);
- AA->calculate;
+ print "@@@ Tick tock: it's $now o'clock\n" if $debug;
+ $timer->Set('T', $now);
+ my $tm;
+ if (!@timer_queue) {
+ print "@@@ idle\n" if $debug;
+ return 0;
+ } elsif ($timer_queue[0]->[0] >= 1000000) {
+ while ($tm = shift @timer_queue) {
+ print "@@@ finalizer\n" if $debug;
+ &{$tm->[1]};
+ }
+ } else {
+ while (@timer_queue && $timer_queue[0]->[0] <= $now) {
+ print "@@@ timer for ", $timer_queue[0]->[0], "\n" if $debug;
+ $tm = shift @timer_queue;
+ &{$tm->[1]};
+ }
+ }
+ $now++;
+ return 1;
}
sub ticker($$$$) {
my ($class, $x0, $x1, $dt) = @_;
- my $t0 = AA::Anim->time;
+ my $t0 = $now;
return sub {
- my $t = AA::Anim->time;
+ my $t = AA::Anim->now;
if ($t - $t0 >= $dt) {
return $x1;
} else {
package AA::UI;
+use strict;
+use warnings;
+
sub new($$) {
my ($class, $name) = @_;
if ($name eq "") {
package AA::UI::GTK;
-@ISA = ('AA::UI');
+my $debug = 1;
+
+our @ISA = ('AA::UI');
sub new($$) {
my ($class, $mode) = @_;
my $u_scenario;
my $u_scene;
+my $u_frame;
+my $u_direction;
my @u_scenes = ();
my $window;
my $area;
my $pixmap;
my $timer;
-my $stopped = 1;
+my $stopped = 0;
my $fullscreen = 0;
+my $movie = 0;
my ($lastw, $lasth, $lastd) = (-1, -1, -1);
my ($pixw, $pixh) = (-1, -1);
+my ($last_scene, $last_frame) = (-1, -1);
sub draw($) {
my ($force) = @_;
$pixw = $w;
$pixh = int($w/4*3);
}
- print "Resized to ${w}x${h}, pixmap size ${pixw}x${pixh}\n";
+ print "Resized to ${w}x${h}, pixmap size ${pixw}x${pixh}\n" if $debug;
$pixmap = Gtk2::Gdk::Pixmap->new($win, $pixw, $pixh, $d);
$cairo = Gtk2::Gdk::Cairo::Context->create($pixmap);
$cairo->fill;
if (@u_scenes) {
- $u_scenes[$u_scene]->Draw($cairo);
+ print "@@@ Scene $u_scene frame $u_frame\n" if $debug;
+ $u_scenes[$u_scene]->[$u_frame]->Draw($cairo);
$cairo->set_source_rgb(.5, .5, .5);
$cairo->set_font_size(15);
$cairo->move_to(950,750);
}
$win->draw_drawable($wgc, $pixmap, 0, 0, 0, 0, $pixw, $pixh);
+ $last_scene = $u_scene;
+ $last_frame = $u_frame;
}
sub step() {
- AA::Anim->step;
+ # FIXME: the timer still runs
+ if (@u_scenes) {
+ if ($u_direction > 0) {
+ if ($u_frame < @{$u_scenes[$u_scene]}-1) {
+ $u_frame++;
+ } elsif ($movie && $u_scene < @u_scenes - 1) {
+ $u_scene++;
+ $u_frame = 0;
+ }
+ } elsif ($u_direction < 0) {
+ if ($u_frame) {
+ $u_frame--;
+ } elsif ($movie && $u_scene) {
+ $u_scene--;
+ $u_frame = @{$u_scenes[$u_scene]} - 1;
+ }
+ }
+ return if ($u_scene == $last_scene && $u_frame == $last_frame);
+ } else {
+ AA::Anim->step;
+ }
draw(0);
}
$area->signal_connect('key-press-event' => sub {
my ($w, $evt) = @_;
my $k = Gtk2::Gdk::keyval_name(0, $evt->keyval);
- print "Pressed key $k\n";
+ print "Pressed key $k\n" if $debug;
if ($k eq "Escape") {
Gtk2->main_quit;
} elsif ($k eq "f") {
}
} elsif ($k eq "space" || $k eq "Right" || $k eq "Page_Down") {
if (@u_scenes) {
- if ($u_scene+1 < @u_scenes) {
+ if ($u_direction > 0 && $u_scene+1 < @u_scenes) {
$u_scene++;
- draw(0);
+ $u_frame = 0;
}
+ $u_direction = 1;
+ draw(0);
} else {
+ while (AA::Anim->step) { AA->calculate; }
if ($u_scene+1 < @$u_scenario) {
$u_scene++;
+ AA::Anim->start;
&{$u_scenario->[$u_scene]};
draw(0);
}
}
} elsif ($k eq "BackSpace" || $k eq "Left" || $k eq "Page_Up") {
if (@u_scenes && $u_scene) {
- $u_scene--;
+ if (!$u_frame || $u_direction < 0) {
+ $u_scene--;
+ $u_frame = @{$u_scenes[$u_scene]}-1;
+ }
+ $u_direction = -1;
draw(0);
}
} elsif ($k eq "Home" || $k eq "0") {
if (@u_scenes) {
$u_scene = 0;
+ $u_frame = 0;
+ $u_direction = 1;
draw(0);
}
} elsif ($k eq "End" || $k eq "9") {
if (@u_scenes) {
$u_scene = $#u_scenes;
+ $u_frame = @{$u_scenes[$u_scene]}-1;
+ $u_direction = 1;
draw(0);
}
+ } elsif ($k eq "p") {
+ $stopped = !$stopped;
+ print "Stopped is $stopped\n" if $debug;
+ } elsif ($k eq "m") {
+ $movie = !$movie;
+ print "Movie mode is $movie\n" if $debug;
+ } elsif ($k eq "Return") {
+ if (@u_scenes) {
+ $u_frame = ($u_direction > 0) ? @{$u_scenes[$u_scene]}-1 : 0;
+ } else {
+ while (AA::Anim->step) { AA->calculate; }
+ }
}
});
if ($ui->{MODE}) {
print "Rendering...\n";
foreach my $s (@$scenario) {
+ print ">>> Scene ", scalar @u_scenes, "\n" if $debug;
+ AA::Anim->start;
&$s;
- AA->calculate;
- push @u_scenes, AA::Scene->new();
+ my $show = [];
+ while (AA::Anim->step) {
+ print "\t>>> Frame ", scalar @$show, "\n" if $debug;
+ AA->calculate;
+ push @$show, AA::Scene->new();
+ }
+ push @u_scenes, $show;
}
print "Ready.\n";
} else {
$u_scenario = $scenario;
+ AA::Anim->start;
&{$scenario->[0]};
}
$u_scene = 0;
+ $u_frame = 0;
+ $u_direction = 1;
prepare();
Gtk2->main;
}
package AA::UI::PDF;
-@ISA = ('AA::UI');
+our @ISA = ('AA::UI');
sub new($$) {
my ($class, $name) = @_;
foreach my $s (@$scenario) {
$page++;
print "### Page $page ###\n";
+ AA::Anim->start;
&$s();
- AA->calculate;
+ do {
+ AA->calculate;
+ } while (AA::Anim->step);
AA->draw($ui->{CAIRO});
$ui->{CAIRO}->show_page;
}
package AA::UI::PNG;
-@ISA = ('AA::UI');
+our @ISA = ('AA::UI');
sub new($$) {
my ($class, $name) = @_;
foreach my $s (@$scenario) {
$page++;
print "### Page $page ###\n";
+ AA::Anim->start;
&$s();
- AA->calculate;
+ do {
+ AA->calculate;
+ } while (AA::Anim->step);
AA->draw($cairo);
$cairo->show_page;
my $name = sprintf($ui->{NAME}, $page);