From: Martin Mares Date: Mon, 29 Oct 2007 08:57:05 +0000 (+0100) Subject: A bit of animation. X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=f9cc7586e18929662233accfaceda7f467249c29;p=anim.git A bit of animation. --- diff --git a/AA.pm b/AA.pm index 233df11..673cd25 100644 --- 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($) { diff --git a/AA/Anim.pm b/AA/Anim.pm index a399d6b..07a669d 100644 --- a/AA/Anim.pm +++ b/AA/Anim.pm @@ -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 { diff --git a/AA/UI.pm b/AA/UI.pm index 1d4bb8a..2b66016 100644 --- 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); diff --git a/goldberg.pl b/goldberg.pl index af30927..c555a06 100755 --- a/goldberg.pl +++ b/goldberg.pl @@ -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;