]> mj.ucw.cz Git - anim.git/commitdiff
A bit of animation.
authorMartin Mares <mj@ucw.cz>
Mon, 29 Oct 2007 08:57:05 +0000 (09:57 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 29 Oct 2007 08:57:05 +0000 (09:57 +0100)
AA.pm
AA/Anim.pm
AA/UI.pm
goldberg.pl

diff --git a/AA.pm b/AA.pm
index 233df11bc0dda43cbbad5397e1b113db583d4a4a..673cd250390a281626e3682170a03ad6103554fc 100644 (file)
--- a/AA.pm
+++ b/AA.pm
@@ -190,6 +190,12 @@ sub MultiSet($@) {
        }
 }
 
+sub SetTicker($$$$$) {
+       my ($o, $a, $x0, $x1, $dt) = @_;
+       $o->Bind($a, AA::Anim->ticker($x0, $x1, $dt));
+       AA::Anim->add_timer($dt, sub { $o->Set($a, $x1); });
+}
+
 package AA::Scene;
 
 sub new($) {
index a399d6b1b9b5c3356f2682f22c82ecb51975ad40..07a669d26c6bd75468874dc42e9a0d4e77b48d66 100644 (file)
@@ -1,22 +1,62 @@
 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 {
index 1d4bb8acc678d26738669794ac7508a6fe329167..2b66016752a7cbc43457fc9572bb1b534af64a28 100644 (file)
--- a/AA/UI.pm
+++ b/AA/UI.pm
@@ -1,5 +1,8 @@
 package AA::UI;
 
+use strict;
+use warnings;
+
 sub new($$) {
        my ($class, $name) = @_;
        if ($name eq "") {
@@ -15,7 +18,9 @@ sub new($$) {
 
 package AA::UI::GTK;
 
-@ISA = ('AA::UI');
+my $debug = 1;
+
+our @ISA = ('AA::UI');
 
 sub new($$) {
        my ($class, $mode) = @_;
@@ -27,6 +32,8 @@ sub new($$) {
 
 my $u_scenario;
 my $u_scene;
+my $u_frame;
+my $u_direction;
 my @u_scenes = ();
 
 my $window;
@@ -34,10 +41,12 @@ my $cairo;
 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) = @_;
@@ -58,7 +67,7 @@ sub draw($) {
                        $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);
@@ -78,7 +87,8 @@ sub draw($) {
        $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);
@@ -89,10 +99,32 @@ sub draw($) {
        }
 
        $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);
 }
 
@@ -110,7 +142,7 @@ sub prepare() {
        $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") {
@@ -121,32 +153,56 @@ sub prepare() {
                        }
                } 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; }
+                       }
                }
        });
 
@@ -164,24 +220,34 @@ sub RunScenario($$) {
        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) = @_;
@@ -198,8 +264,11 @@ sub RunScenario($$$) {
        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;
        }
@@ -207,7 +276,7 @@ sub RunScenario($$$) {
 
 package AA::UI::PNG;
 
-@ISA = ('AA::UI');
+our @ISA = ('AA::UI');
 
 sub new($$) {
        my ($class, $name) = @_;
@@ -225,8 +294,11 @@ sub RunScenario($$$) {
        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);
index af30927afbd2811c2892407ac3342253292008fd..c555a068efee495539e9ab625aa86920ffa2e62a 100755 (executable)
@@ -58,14 +58,18 @@ sub flow($$) {
 
 sub up($) {
        my ($i) = @_;
-       $v[$i]->Set('h', $v[$i]->Get('h') + 1);
+       my $v = $v[$i];
+       my $h = $v[$i]->Get('h');
+       $v->SetTicker('h', $h, $h+1, 10);
 }
 
 sub hint($) {
        my ($h) = @_;
-       for (my $i=0; $i<@v; $i++) {
-               $v[$i]->Set('hint', $i == $h);
-       }
+       AA::Anim->add_final(sub {
+               for (my $i=0; $i<@v; $i++) {
+                       $v[$i]->Set('hint', $i == $h);
+               }
+       });
 }
 
 my $scenario;