1 Le fond
2 Les boutons
3 Le source des animations
4 L'emballement final


Voici les différents fichiers ou patrons qui m'ont servi à monter la version des chorégraphies de C. Simò sous forme d'animations flash.

1 - Le fond


Le fond est composé avec MetaPost, comme il y a des éléments variables j'utilise un patron fond.pat (les éléments qui varient sont identifiés sous la forme %%élément%%), le fichier résultant porte le nom fond.mp.


fond.pat
 
% clés : num titre 
prologues := 1;

verbatimtex
%&latex
\documentclass[10pt]{article}
\usepackage[latin1]{inputenc}
\usepackage{t1enc}
\usepackage{times}
\begin{document}
etex

beginfig(1);
    fill (0,0)--(600,0)--(600,400)--(0,400)--cycle 
        withcolor (72/255,86/255,146/255);
        
    labeloffset := 0;

    label(btex \textbf{Syracuse} etex xscaled 12 yscaled 5,(300,372))
        withcolor(92/255,106/255,166/255);

    label.rt(btex \it\textbf{Les chorégraphies} etex scaled 3,(10,380))
        withcolor white;

    label.lft(btex 
		\textsf{%%titre%%} 
	      etex xscaled 1.85 yscaled 1.5,(590,355))
        withcolor 0.8white;

    label.lft(btex 
		\textsf{%%num%%} 
	      etex xscaled 2.5 yscaled 1.8,(590,373))
        withcolor (235/255,235/255,165/255);
    
endfig;

end

Une fois ce fichier chargé et compilé, je dispose d'un fichier fond.1 que je transforme en pdf en m'aidant d'un fichier pilote fond.ps.


fond.ps
 
<</PageSize [600 400]>> setpagedevice

/TeXBase1Encoding [
% 0x00 (encoded characters from Adobe Standard not in Windows 3.1)
  /.notdef /dotaccent /fi /fl
  /fraction /hungarumlaut /Lslash /lslash
  /ogonek /ring /.notdef
  /breve /minus /.notdef 
% These are the only two remaining unencoded characters, so may as
% well include them.
  /Zcaron /zcaron 
% 0x10
 /caron /dotlessi 
% (unusual TeX characters available in, e.g., Lucida Bright)
 /dotlessj /ff /ffi /ffl 
 /.notdef /.notdef /.notdef /.notdef
 /.notdef /.notdef /.notdef /.notdef
 % very contentious; it's so painful not having quoteleft and quoteright
 % at 96 and 145 that we move the things normally found there down to here.
 /grave /quotesingle 
% 0x20 (ASCII begins)
 /space /exclam /quotedbl /numbersign
 /dollar /percent /ampersand /quoteright
 /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash
% 0x30
 /zero /one /two /three /four /five /six /seven
 /eight /nine /colon /semicolon /less /equal /greater /question
% 0x40
 /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O
% 0x50
 /P /Q /R /S /T /U /V /W
 /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore
% 0x60
 /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o
% 0x70
 /p /q /r /s /t /u /v /w
 /x /y /z /braceleft /bar /braceright /asciitilde
 /.notdef % rubout; ASCII ends
% 0x80
 /Euro /.notdef /quotesinglbase /florin
 /quotedblbase /ellipsis /dagger /daggerdbl
 /circumflex /perthousand /Scaron /guilsinglleft
 /OE /.notdef /.notdef /.notdef
% 0x90
 /.notdef /.notdef /.notdef /quotedblleft
 /quotedblright /bullet /endash /emdash
 /tilde /trademark /scaron /guilsinglright
 /oe /.notdef /.notdef /Ydieresis
% 0xA0
 /.notdef % nobreakspace
 /exclamdown /cent /sterling
 /currency /yen /brokenbar /section
 /dieresis /copyright /ordfeminine /guillemotleft
 /logicalnot
 /hyphen % Y&Y (also at 45); Windows' softhyphen
 /registered
 /macron
% 0xD0
 /degree /plusminus /twosuperior /threesuperior
 /acute /mu /paragraph /periodcentered
 /cedilla /onesuperior /ordmasculine /guillemotright
 /onequarter /onehalf /threequarters /questiondown
% 0xC0
 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla
 /Egrave /Eacute /Ecircumflex /Edieresis
 /Igrave /Iacute /Icircumflex /Idieresis
% 0xD0
 /Eth /Ntilde /Ograve /Oacute
 /Ocircumflex /Otilde /Odieresis /multiply
 /Oslash /Ugrave /Uacute /Ucircumflex
 /Udieresis /Yacute /Thorn /germandbls
% 0xE0
 /agrave /aacute /acircumflex /atilde
 /adieresis /aring /ae /ccedilla
 /egrave /eacute /ecircumflex /edieresis
 /igrave /iacute /icircumflex /idieresis
% 0xF0
 /eth /ntilde /ograve /oacute
 /ocircumflex /otilde /odieresis /divide
 /oslash /ugrave /uacute /ucircumflex
 /udieresis /yacute /thorn /ydieresis
] def

% Activer l'encodage ISO latin1 au moment de la conversion
/ISOEncode {
    dup length dict begin
	{1 index /FID ne {def} {pop pop} ifelse} forall
	/Encoding TeXBase1Encoding def
	currentdict
    end
    /Temporary exch definefont
} bind def

% Récupération dans le systemdict de la procédure setfont
/syssetfont {
    systemdict /setfont get exec
} def

% Création dans le userdict d'une procédure setfont adaptée
/setfont {ISOEncode syssetfont} def

% Documentation du PDF
[ /Author (Jean-Michel Sarlat) /DOCINFO pdfmark
[ /Title (fond d'animation flash) /DOCINFO pdfmark
[ /Subject (Les chorégraphies) /DOCINFO pdfmark
[ /Creator (Metapost + ps2pdf + pdf2swf) /DOCINFO pdfmark

% Insertion du code généré par MetaPost (prologues != 0)
(fond.1) run

Il ne reste plus qu'à transformer en clip d'animation à l'aide de pdf2swf.

2 - Les boutons


Les trois boutons + rapide, + lent et trace o/n sont aussi écrits avec MetaPost en s'appuyant sur une procédure bouton définie dans btn.mp.


btn.mp
 
vardef bouton(expr txt) =
    picture $;
    path $$;
    pair BLLC,BULC,BURC,BLRC;
    numeric RRAY,wray;
    wray = 4pt;
    RRAY = 1-1/sqrt(2);
    $ = thelabel(txt,(0,0)); % acquisition du texte à encadrer sous forme d'image
    BLLC = (0,0)  ; BULC = (0,14);
    BURC = (50,14); BLRC = (50,0);
    % construction du bord de la boîte
    $$ = (BLLC + (0,wray)) -- (BULC - (0,wray)) .. (BULC + RRAY*(wray,-wray)) .. 
	 (BULC + (wray,0)) -- (BURC - (wray,0)) .. (BURC - RRAY*(wray,wray)) .. 
	 (BURC - (0,wray)) -- (BLRC + (0,wray)) .. (BLRC + RRAY*(-wray,wray)) .. 
	 (BLRC - (wray,0)) -- (BLLC + (wray,0)) .. (BLLC + RRAY*(wray,wray)) .. cycle;
    fill $$ withcolor (1,1,0.7);
    draw $ shifted (25,7);
    draw $$ withcolor (0,0,.3) withpen pencircle scaled 1;
enddef;

btnrapide.mp
 
prologues := 1;

input btn.mp;

verbatimtex
\font\sfb=cmssbx10 at 10pt
etex

beginfig(1);
    
  bouton(btex $+$\sfb rapide etex);    
    
endfig;
end

btnlent.mp
 
prologues := 1;

input btn.mp;

verbatimtex
\font\sfb=cmssbx10 at 10pt
etex

beginfig(1);
    
  bouton(btex $+$\sfb lent etex);    
    
endfig;
end

btntrace.mp
 
prologues := 1;

input btn.mp;

verbatimtex
\font\sfb=cmssbx10 at 10pt
etex

beginfig(1);
    
  bouton(btex \sfb Trace o/n etex);    
    
endfig;
end

Il leur est associé un fichier PostScript pour préparer la conversion en PDF.


btnrapide.ps
 
<</PageSize [50 14]>> setpagedevice

% Insertion du code généré par MetaPost (prologues != 0)
(btnrapide.1) run

btnlent.ps
 
<</PageSize [50 14]>> setpagedevice

% Insertion du code généré par MetaPost (prologues != 0)
(btnlent.1) run

btntrace.ps
 
<</PageSize [50 14]>> setpagedevice

% Insertion du code généré par MetaPost (prologues != 0)
(btntrace.1) run

Les compilations sont, en fait, exécutées à l'aide d'un petit script. Ghostscript est, quand à lui, configuré pour trouver le fichier cmbx10.pfb.


compilations3
 
mpost btntrace.mp
ps2pdf14 btntrace.ps
pdf2swf btntrace.pdf
mpost btnlent.mp
ps2pdf14 btnlent.ps
pdf2swf btnlent.pdf
mpost btnrapide.mp
ps2pdf14 btnrapide.ps
pdf2swf btnrapide.pdf
rm -f *.1 *.log *.mpx btn*.pdf

3 - Le source des animations


Il est construit à partir d'un patron: trajectoire.pat transformé en trajectoire.sc.


trajectoire.pat
 
# clés : nom orbite b d e nb t
.flash name="%%nom%%.swf"  bbox=600x400 version=6

# Le fond de l'image
.swf fondmp "fond.swf"
# .box fond width=600 height=400 line=0 fill=fondmp
.put fondmp 0 0

# Les corps
.circle c0 r=3 color=red fill=red
.circle c1 r=3 color=blue fill=blue
.put c0 245 10 .put c1 257 10

# Le cadre de la trajectoire
.box cadre width=578 height=333 line=2 color=#886644 fill=#BBBBBB
.put cadre 11 56

.swf btntrace "btntrace.swf"
.put btntrace 535 382

.swf btnrapide "btnrapide.swf"
.put btnrapide 15 382

.swf btnlent "btnlent.swf"
.put btnlent  70 382

.sprite s0
    .put c0 -3 -3
.end

.sprite s1
    .put c1 -3 -3
.end

.put s0 -10 0
.put s1 -10 0

.action:
_global.orbite = %%orbite%%;
_global.b   = %%b%%;
_global.d   = %%d%%;
_global.e   = %%e%%;
_global.nb  = %%nb%%;
_global.t   = %%t%%;
_global.pas = 20;
_global.trace = 1;

function posX(i,t) {
    return orbite[(t + i * b) % d][0];
}
function posY(i,t) {
    return orbite[(t + i * b) % d][1];
}

_root.createEmptyMovieClip("orbiteDesNCorps",1);
orbiteDesNCorps.lineStyle(1,0xAA8866,100);
orbiteDesNCorps.moveTo(orbite[0][0],orbite[0][1]);
for(var i=1; i < orbite.length; i++) { 
    orbiteDesNCorps.lineTo(orbite[i][0],orbite[i][1]);
}

btnrapide.onPress = function () { 
    if (pas > 5) {
        pas /= 1.5;
    }
    clearInterval(tmp);
    btnrapide._alpha = 60;
    tmp = setInterval(deplaceCorps,pas);
};

btnrapide.onRelease = btnrapide.onReleaseOutside = function () {
    btnrapide._alpha = 100;
};
    
btnlent.onPress = function () { 
    pas *= 1.5 ;
    clearInterval(tmp);
    btnlent._alpha = 60;
    tmp = setInterval(deplaceCorps,pas);
};

btnlent.onRelease = btnlent.onReleaseOutside = function () {
    btnlent._alpha = 100;
};

btntrace.onPress = function () { 
    var couleurs = new Color(orbiteDesNCorps);
    var trans = couleurs.getTransform();
    if (trace == 1) {
        trans.aa = 0;
        couleurs.setTransform(trans);
    } else {
        trans.aa = 100;
        couleurs.setTransform(trans);
    }
    trace = 1 - trace;
    btntrace._alpha = 50;
};

btntrace.onRelease = btntrace.onReleaseOutside = function () {
    btntrace._alpha = 100;
};

var corps = new Array();
corps[0] = _root.attachMovie('s0','corps0',2);
for(var i=1; i < nb; i++) {
    corps[i] = _root.attachMovie('s1','corps'+i,i+2);
}

function deplaceCorps() {
    t += e;
    t = t % d;
    for(var i = 0; i < nb; i++) {
        corps[i]._x = posX(i,t);
        corps[i]._y = posY(i,t);
    }
    updateAfterEvent();
}	
_global.tmp = setInterval(deplaceCorps,pas);
.end

.end

4 - L'emballement final


C'est un script perl qui acquiert les données, construit les patrons et actionne les compilations.


swfsimo
 
#!/usr/bin/perl

my $N = $ARGV[0];

open(LST,"simo/liste.txt"); my @liste = <LST>; chop(@liste); close(LST);
foreach (@liste) {
    if ($_ =~ /^$N:/) {
        ($null,$fichier,$a,$b,$c,$d,$e,$f,$k,$titre) = split(/:/,$_);
        $fichier =~ s/\s+$//;
        $titre   =~ s/^\s+//;
    }
}

exit(0) if $fichier eq "";

print "Taitement de $fichier ($N)\n";

print " -> construction des patrons...\n";

$orbite   = `./orb2tab.pl simo/$fichier`;
$orbitemp = `./orb2path.pl simo/$fichier`;
$orbitemp =~ s/§/\n/g;

%C = (
    orbite      => $orbite,
    orbitemp    => $orbitemp,
    nom         => sprintf("simo%02d",$N),
    a           => $a,
    b           => $b,
    c           => $c,
    d           => $d,
    e           => $e,
    f           => $f,
    t           => 1,
    nb          => sprintf("%d", $d/$b),
    num         => $N,
    titre       => $titre
);


open(MP,">fond.mp");
print MP &Patron("fond.pat",\%C);
close(MP);

open(MP,">image.mp");
print MP &Patron("image.pat",\%C);
close(MP);

open(SC,">trajectoire.sc");
print SC &Patron("trajectoire.pat",\%C);
close(SC);

open(HTM,">$C{nom}.html");
print HTM &Patron("popup.pat",\%C);
close(HTM);

open(HTM,">$C{nom}w.html");
print HTM &Patron("popupw.pat",\%C);
close(HTM);

print " -> compilations vers swf...\n";
print `. compilations1`;
print " -> compilations vers png...\n";
print `. compilations2`;

if (-e "image.png") {
    print `mv image.png $C{nom}.png`;
}

if (-e "image.mp") {
    print `mv image.mp  $C{nom}.mp`;
}
sub Patron {
    my ($nom_patron,$remplissage) = @_;
    my $texte;
    local $/;
    local *F;
    open (F,"< $nom_patron\0") || return;
    $texte = <F>;
    close(F);
    $texte =~ s{ %%(.*?)%% }
              { exists( $remplissage->{$1} )
                      ? $remplissage->{$1}
                      : ""
              }gsex;
    return $texte;
}

orb2tab.pl
 
#!/usr/bin/perl

$n = 0;			  # Compteur
$xmax = $ymax = -1000;    # maximums en abscisse et ordonnée
$xmin = $ymin = 1000;	  # minimums en abscisse et ordonnée

# === Acquisition des points de la trajectoire
open(F,"$ARGV[0]"); @liste = <F>; close(F); chop(@liste);

foreach (@liste) {
    if ($_ ne "") {
	$n++;
	($null,$x,$y) = split(/\s+/,$_);
	$xmax = $x if $x > $xmax;
	$xmin = $x if $x < $xmin;
	$ymax = $y if $y > $ymax;
	$ymin = $y if $y < $ymin;
	push(@X,$x); push(@Y,$y);
    }
}

$fx = ($xmax - $xmin) / 558.0;
$fy = ($ymax - $ymin) / 310.0;


$f  = $fx > $fy ? $fx : $fy ;

$mx = ($xmin + $xmax) / 2;
$my = ($ymin + $ymax) / 2;
 
$n = 0 ;
print STDOUT "[";
while(@X) {
    $n++;
    $x = shift @X;
    $x = sprintf("%.3f",($x - $mx) / $f + 300);
    $y = shift @Y;
    $y = sprintf("%.3f",($my - $y) / $f + 223);
    if ($n == 1) {
    	print STDOUT "[$x,$y]";
    } else {
    	print STDOUT ",[$x,$y]";
    }
}
print STDOUT "]";

orb2path.pl
 
#!/usr/bin/perl

$n = 0;			  # Compteur
$xmax = $ymax = -1000;    # maximums en abscisse et ordonnée
$xmin = $ymin = 1000;	  # minimums en abscisse et ordonnée

# === Acquisition des points de la trajectoire
open(F,"$ARGV[0]"); @liste = <F>; close(F); chop(@liste);

foreach (@liste) {
    if ($_ ne "") {
	$n++;
	($null,$x,$y) = split(/\s+/,$_);
	$xmax = $x if $x > $xmax;
	$xmin = $x if $x < $xmin;
	$ymax = $y if $y > $ymax;
	$ymin = $y if $y < $ymin;
	push(@X,$x); push(@Y,$y);
    }
}

$fx = ($xmax - $xmin) / 300;
$fy = ($ymax - $ymin) / 300;


$f  = $fx > $fy ? $fx : $fy ;

$mx = ($xmin + $xmax) / 2;
$my = ($ymin + $ymax) / 2;
 
$n = 0 ;
while(@X) {
    $n++;
    $sep = ($n % 5) == 1 ? "§" : "";
    $x = shift @X;
    $x = sprintf("%.3f",($x - $mx) / $f + 160);
    $y = shift @Y;
    $y = sprintf("%.3f",($y - $my) / $f + 160);
    if ($n == 1) {
    	print STDOUT "($x,$y)";
    } else {
    	print STDOUT "$sep..($x,$y)";
    }
}

compilations1
 
mpost fond.mp
ps2pdf14 fond.ps
pdf2swf fond.pdf
swfc trajectoire.sc
rm -f fond.1 fond.mpx fond.log fond.swf