% Copyright 2018 by Till Tantau % % This file may be distributed and/or modified % % 1. under the LaTeX Project Public License and/or % 2. under the GNU Public License. % % See the file doc/generic/pgf/licenses/LICENSE for more details. \ProvidesFileRCS{tikzlibraryanimations.code.tex} \usepgfmodule{animations}% % Scope syntax extension: \def\tikz@collect@scope@anims#1{% \let\tikz@scope@anims\pgfutil@empty% \let\tikz@collect@command#1% \tikz@collect@scope@anims@parse% }% \def\tikz@collect@scope@anims@parse{% \pgfutil@ifnextchar[{\tikz@collect@scope@anims@opt}{% \pgfutil@ifnextchar:{\tikz@collect@scope@anims@go}{% \tikz@collect@scope@anims@done}}%] }% \def\tikz@collect@scope@anims@done{% \expandafter\tikz@collect@command\expandafter[\tikz@scope@anims]% }% \def\tikz@collect@scope@anims@opt[{%] \expandafter\tikz@collect@command\expandafter[\tikz@scope@anims%] }% \def\tikz@collect@scope@anims@go:#1=#2{% \expandafter\def\expandafter\tikz@scope@anims\expandafter{\tikz@scope@anims animate={myself:={:{#1}={#2}}},}% \tikz@collect@scope@anims@parse% }% % % The main keys: % \def\tikzanimateset{\pgfqkeys{/tikz/animate}}% \tikzanimateset{ .code={ \pgfkeys{/handlers/first char syntax=true} \pgfkeyssetvalue{/handlers/first char syntax/the character "}{\tikz@animation@value}% \def\tikz@anim@t{0}% \def\tikz@anim@t@base{0}% \def\tikz@anim@t@current{0}% \tikzanimateset{#1} }, scope/.code=\tikz@anim@scope{#1}{}{}, sync/.code=\tikz@anim@sync@scope{#1}{}{}, entry/.code=\tikz@anim@make@entry, object/.code=\tikz@anim@set@object{#1}, attribute/.code=\tikz@anim@set@attr{#1}, id/.code=\tikz@anim@set@id{#1}, time/.code=\tikz@anim@set@time{#1}, value/.code=\tikz@anim@add{\tikz@anim@value{#1}},% remember/.code=\pgfmathadd@{\tikz@anim@t}{\tikz@anim@t@base}\global\let#1\pgfmathresult, resume/.code=\tikz@anim@resume{#1}, fork/.code={\tikz@anim@parse@time{#1}\pgfmathadd@\tikz@anim@t\tikz@anim@t@base\let\tikz@anim@t@base\pgfmathresult\def\tikz@anim@t{0}}, fork/.default = 0later, base/.style={scope={/utils/exec=\let\tikz@animation@time\tikz@anim@base@text,#1,entry}}, }% \tikzset{ make snapshot of/.code=\edef\tikz@temp{#1}\ifx\tikz@temp\pgfutil@empty\else\pgfsnapshot{#1}\fi, make snapshot after/.code=\edef\tikz@temp{#1}\ifx\tikz@temp\pgfutil@empty\else\pgfsnapshotafter{#1}\fi, make snapshot if necessary/.code=\ifpgfsysanimationsupported\else\pgfsnapshot{#1}\fi, make snapshot if necessary/.default=0s, }% \def\tikz@anim@scope#1#2#3{% {#2\tikzanimateset{#1}#3}% }% \def\tikz@anim@sync@scope#1#2#3{% {% #2% \tikzanimateset{#1}% #3% \pgfmathadd@{\tikz@anim@t}{\tikz@anim@t@base}% \expandafter% }\expandafter\pgfmathsubtract@\expandafter{\pgfmathresult}{\tikz@anim@t@base}% \tikz@anim@set@time{\pgfmathresult}% }% \def\tikz@anim@set@time#1{% \tikz@anim@parse@time{#1}% \let\tikz@anim@t@current\tikz@anim@t% \pgfmathadd@\tikz@anim@t\tikz@anim@t@base% \let\tikz@animation@time\pgfmathresult% }% \def\tikz@anim@value#1{% \def\tikz@anim@result{#1} \ifx\tikz@anim@result\pgf@special@current@text% \else% \ifx\tikz@animation@parser\relax% \else% \tikz@animation@parser{#1}% \fi% \fi% }% \def\tikz@anim@resume#1{% \pgfparsetime{#1}% \pgfmathsubtract@{\pgftimeresult}{\tikz@anim@t@base}% \tikz@anim@set@time{\pgfmathresult}% }% % The object--attribute entries are of the following forms: % % objects:attributes % objects:attributes_id % \def\tikz@animation@syntax@check#1#2{% \def\tikz@animation@rest{#1}% \expandafter\pgfutil@in@\expandafter:\expandafter{\tikz@key}% \ifpgfutil@in@% \expandafter\tikz@anim@parse@colon\tikz@key\pgf@stop% \else% #2% \fi% }% \def\tikz@anim@parse@colon#1:#2\pgf@stop{% \expandafter\tikz@anim@sync@scope\expandafter{\tikz@animation@rest}{% \tikz@anim@set@object{#1}% \pgfutil@in@_{#2}% \ifpgfutil@in@% \tikz@anim@parse@under#2\pgf@stop% \else% \tikz@anim@parse@under#2_\pgf@stop% \fi% }{\tikz@anim@make@entry}% }% \def\tikz@anim@parse@under#1_#2\pgf@stop{% \tikz@anim@set@attr{#1}% \tikz@anim@set@id{#2}% }% \def\tikz@anim@set@attr#1{% \pgfkeys@spdef\tikz@anim@a{#1}% \ifx\tikz@anim@a\pgfutil@empty% \else% \let\tikz@anim@tl@attributes\tikz@anim@a% \fi% }% \def\tikz@anim@set@id#1{% \pgfkeys@spdef\tikz@anim@a{#1}% \ifx\tikz@anim@a\pgfutil@empty% \else% \let\tikz@anim@tl@id\tikz@anim@a% \fi% }% \def\tikz@anim@set@object#1{% \pgfkeys@spdef\tikz@anim@a{#1}% \ifx\tikz@anim@a\pgfutil@empty% \else% \let\tikz@anim@tl@objects\tikz@anim@a% \fi% }% % % Parsing of values % \def\tikz@animation@value#1{% \tikz@animation@value@parser#1\pgf@stop% }% \def\tikz@animation@value@parser"#1"{% \def\tikz@animation@value@head{#1}% \pgfutil@ifnextchar\pgf@stop{\tikz@animation@value@rest=}{% \pgfutil@ifnextchar b\tikz@animation@value@rest@base\tikz@animation@value@rest% }% }% \def\tikz@animation@value@rest=#1\pgf@stop{% \tikz@anim@sync@scope{#1}{\expandafter\tikz@anim@add\expandafter{\expandafter\tikz@anim@value\expandafter{\tikz@animation@value@head}}}{\tikz@anim@make@entry}% }% \def\tikz@animation@value@rest@base base{% \tikz@anim@sync@scope{}{/utils/exec=\let\tikz@animation@time\tikz@anim@base@text\expandafter\tikz@anim@add\expandafter{\expandafter\tikz@anim@value\expandafter{\tikz@animation@value@head}}}{\tikz@anim@make@entry}% \pgfutil@ifnextchar\pgf@stop{\tikz@animation@value@rest=}{\tikz@animation@value@rest}% }% % % The parsers % \def\tikz@anim@simple@parse#1{} % nothing to do, \def\tikz@anim@result{#1} is already done \def\tikz@anim@slant@parse#1{\pgfmathsetmacro\tikz@anim@result{atan(#1)}}% \def\tikz@anim@dashpattern@parse#1{% \pgfmathsetmacro\tikz@anim@dash@phase{\tikz@dashphase}% \def\tikz@dashpattern{}% \expandafter\tikz@scandashon\pgfutil@gobble#1o\@nil% \edef\tikz@anim@result{{\tikz@dashpattern}{\tikz@anim@dash@phase pt}}% }% \def\tikz@anim@dashoffset@parse#1{% \pgfmathparse{#1}% \edef\tikz@anim@result{{\tikz@dashpattern}{\pgfmathresult pt}}% }% \def\tikz@anim@dash@parse#1{% \tikz@anim@dash@parse@#1\pgf@stop% }% \def\tikz@anim@dash@parse@#1phase#2\pgf@stop{% \pgfmathsetmacro\tikz@anim@dash@phase{#2}% \def\tikz@dashpattern{}% \expandafter\tikz@scandashon\pgfutil@gobble#1o\@nil% \edef\tikz@anim@result{{\tikz@dashpattern}{\tikz@anim@dash@phase pt}}% }% \def\tikz@anim@xshift@parse#1{\pgfmathparse{#1}\edef\tikz@anim@result{\noexpand\pgfqpoint{\pgfmathresult pt}{0pt}}}% \def\tikz@anim@yshift@parse#1{\pgfmathparse{#1}\edef\tikz@anim@result{\noexpand\pgfqpoint{0pt}{\pgfmathresult pt}}}% \def\tikz@anim@xscale@parse#1{\pgfmathparse{#1}\edef\tikz@anim@result{\pgfmathresult,1}}% \def\tikz@anim@yscale@parse#1{\pgfmathparse{#1}\edef\tikz@anim@result{1,\pgfmathresult}}% \def\tikz@anim@shift@parse#1{\tikz@scan@one@point\tikz@anim@do@shift#1}% \def\tikz@anim@do@shift#1{\def\tikz@anim@result{#1}}% \def\tikz@anim@position@parse#1{% \begingroup% \let\tikz@transform=\relax% \pgf@xc-\pgf@pt@x% \pgf@yc-\pgf@pt@y% \pgfsettransform\tikz@anim@saved@transform% \tikz@scan@one@point\tikz@anim@do@position#1}% \def\tikz@anim@do@position#1{% \pgf@process{\pgfpointtransformed{#1}}% \advance\pgf@x by\pgf@xc% \advance\pgf@y by\pgf@yc% \xdef\tikz@anim@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% \endgroup% \let\tikz@anim@result\tikz@anim@temp% }% \def\tikz@anim@view@parse#1{\tikz@anim@view@parse@#1\pgf@stop}% \def\tikz@anim@view@parse@{% \pgfutil@ifnextchar({\tikz@scan@one@point\tikz@anim@view@parse@a}{\tikz@anim@view@node}% }% \def\tikz@anim@view@parse@a#1{% \def\tikz@anim@result{{#1}}% \pgfutil@ifnextchar r{\tikz@anim@view@parsed@rec}{\tikz@scan@one@point\tikz@anim@view@parse@b}% }% \def\tikz@anim@view@parsed@rec rectangle{\tikz@scan@one@point\tikz@anim@view@parse@b}% \def\tikz@anim@view@parse@b#1{% \expandafter\def\expandafter\tikz@anim@result\expandafter{\tikz@anim@result{#1}}% \pgfutil@ifnextchar\pgf@stop\pgfutil@gobble{\tikzerror{Wrong view syntax}}% }% \def\tikz@anim@view@node#1\pgf@stop{% \expandafter\ifx\csname pgf@sh@ns@#1\endcsname\relax% \tikzerror{Undefined node '#1'}% \else% % Compute a bounding box for the node: {% \pgf@process{\pgfpointanchor{#1}{west}}% \pgf@xa\pgf@x \pgf@ya\pgf@y \pgf@xb\pgf@x \pgf@yb\pgf@y \pgf@process{\pgfpointanchor{#1}{north}}% \ifdim\pgf@x<\pgf@xa \pgf@xa=\pgf@x\fi% \ifdim\pgf@x>\pgf@xb \pgf@xb=\pgf@x\fi% \ifdim\pgf@y<\pgf@ya \pgf@ya=\pgf@y\fi% \ifdim\pgf@y>\pgf@yb \pgf@yb=\pgf@y\fi% \pgf@process{\pgfpointanchor{#1}{south}}% \ifdim\pgf@x<\pgf@xa \pgf@xa=\pgf@x\fi% \ifdim\pgf@x>\pgf@xb \pgf@xb=\pgf@x\fi% \ifdim\pgf@y<\pgf@ya \pgf@ya=\pgf@y\fi% \ifdim\pgf@y>\pgf@yb \pgf@yb=\pgf@y\fi% \pgf@process{\pgfpointanchor{#1}{east}}% \ifdim\pgf@x<\pgf@xa \pgf@xa=\pgf@x\fi% \ifdim\pgf@x>\pgf@xb \pgf@xb=\pgf@x\fi% \ifdim\pgf@y<\pgf@ya \pgf@ya=\pgf@y\fi% \ifdim\pgf@y>\pgf@yb \pgf@yb=\pgf@y\fi% \xdef\tikz@anim@result{{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}} }% \fi% }% \def\tikz@anim@path@parse#1{% {% \setbox0=\hbox{{% protext against side effects \pgfinterruptpath% \expandafter\tikz@scan@next@command#1\pgf@stop% \pgfsyssoftpath@getcurrentpath\tikz@anim@result% \pgfprocessround{\tikz@anim@result}{\tikz@anim@result}% \global\let\tikz@anim@result\tikz@anim@result% \endpgfinterruptpath% }}% }% }% % The special along parser \def\tikz@anim@along#1#2{% % Parse the path... {% \setbox0=\hbox{{% protect against side effects \pgfinterruptpath% \pgf@relevantforpicturesizefalse% \iftikz@anim@is@position% \let\tikz@transform=\relax% \pgf@x-\pgf@pt@x% \pgf@y-\pgf@pt@y% \edef\tikz@anim@along@shift{\pgf@xc\the\pgf@x\pgf@yc\the\pgf@y}% \pgfsettransformentries#1% \else% \pgftransformreset% \fi \tikz@scan@next@command#2\pgf@stop% \pgfsyssoftpath@getcurrentpath\tikz@anim@parsed@path% \pgfprocessround{\tikz@anim@parsed@path}{\tikz@anim@parsed@path}% \iftikz@anim@is@position% \tikz@anim@shift@path% \global\let\tikz@anim@parsed@path\tikz@anim@patched@path% \else% \global\let\tikz@anim@parsed@path\tikz@anim@parsed@path% \fi% \endpgfinterruptpath% }}% }% \pgfanimationset{along softpath/.expand once=\tikz@anim@parsed@path}% }% \def\tikz@anim@shift@path{% \let\tikz@anim@patched@path\pgfutil@empty% \tikz@anim@along@shift% \expandafter\tikz@anim@shift@path@\tikz@anim@parsed@path\pgf@stop% }% \def\tikz@anim@shift@path@{% \pgfutil@ifnextchar\pgf@stop\pgfutil@gobble{% \pgfutil@ifnextchar\bgroup\tikz@anim@shift@path@sub\tikz@anim@shift@path@copy}% }% \def\tikz@anim@shift@path@copy#1{% \expandafter\def\expandafter\tikz@anim@patched@path\expandafter{\tikz@anim@patched@path#1}% \tikz@anim@shift@path@% }% \def\tikz@anim@shift@path@sub#1#2{% \pgf@x#1% \pgf@y#2% \advance\pgf@x by\pgf@xc% \advance\pgf@y by\pgf@yc% \edef\tikz@temp{{\the\pgf@x}{\the\pgf@y}}% \expandafter\tikz@anim@shift@path@copy\expandafter{\tikz@temp}% }% \def\tikz@anim@parse@origin#1{% \tikz@scan@one@point\tikz@anim@parse@origin@#1\relax% }% \def\tikz@anim@parse@origin@#1{\tikz@anim@add{\pgfanimationset{origin={#1}}}}% % Internals \def\tikz@anim@tl@objects{}% \def\tikz@anim@tl@attributes{}% \def\tikz@anim@tl@id{default}% \let\tikz@anim@tl@exec@options\pgfutil@empty \let\tikz@anim@tl@early@options\pgfutil@empty \def\tikz@anim@add@early#1{\expandafter\def\expandafter\tikz@anim@tl@early@options\expandafter{\tikz@anim@tl@early@options#1}}% \def\tikz@anim@add@once@early#1{% \global\advance\tikz@anim@once@count by1\relax% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\tikz@anim@tl@early@options% \expandafter\expandafter\expandafter{\expandafter\tikz@anim@tl@early@options\expandafter\tikz@anim@exec@once\expandafter{\the\tikz@anim@once@count}{#1}}% }% \def\tikz@anim@add#1{\expandafter\def\expandafter\tikz@anim@tl@exec@options\expandafter{\tikz@anim@tl@exec@options#1}}% \def\tikz@anim@add@once#1{% \global\advance\tikz@anim@once@count by1\relax% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\tikz@anim@tl@exec@options% \expandafter\expandafter\expandafter{\expandafter\tikz@anim@tl@exec@options\expandafter\tikz@anim@exec@once\expandafter{\the\tikz@anim@once@count}{#1}}% }% \newcount\tikz@anim@once@count% \def\tikz@anim@exec@once#1#2{% \expandafter\ifx\csname tikz@anim@once@#1\endcsname\pgf@stop% \else% \expandafter\let\csname tikz@anim@once@#1\endcsname\pgf@stop% #2% \fi% }% \newif\iftikz@anim@do@entry \def\tikz@anim@make@entry{% \tikz@anim@do@entrytrue% \ifx\tikz@anim@tl@objects\pgfutil@empty\tikz@anim@do@entryfalse\fi% \ifx\tikz@anim@tl@attributes\pgfutil@empty\tikz@anim@do@entryfalse\fi% \ifx\tikz@anim@tl@exec@options\pgfutil@empty\ifx\tikz@anim@tl@early@options\pgfutil@empty\tikz@anim@do@entryfalse\fi\fi% \iftikz@anim@do@entry% \foreach\tikz@anim@tl@object in\tikz@anim@tl@objects{% \expandafter\tikzanimationattributesset\expandafter{\tikz@anim@tl@attributes}% }% \fi% }% \def\tikzanimationattributesset#1{\pgfqkeys{/tikz/animate/attributes}{#1}}% \tikzanimationattributesset{ .unknown/.code={ \let\tikz@anim@attribute@name\pgfkeyscurrentname \expandafter\let\expandafter\pgf@temp\csname tikz@anim@def@pgf@attr@\tikz@anim@attribute@name\endcsname% \ifx\pgf@temp\relax% \tikzerror{Unknown animation attribute '\tikz@anim@attribute@name'}% \else% \expandafter\tikz@timeline@config\expandafter\tikz@anim@tl@object\expandafter\tikz@anim@attribute@name\expandafter\tikz@anim@tl@id\expandafter{\tikz@anim@configs}% \edef\pgf@marshal{\noexpand\tikz@timeline@entry{\tikz@anim@tl@object}{\tikz@anim@attribute@name}{\tikz@anim@tl@id}}% \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgf@marshal\expandafter\expandafter\expandafter{\expandafter\pgf@marshal\expandafter{\tikz@anim@tl@early@options}}% \expandafter\expandafter\expandafter\pgf@marshal\expandafter\expandafter\expandafter{\expandafter\expandafter\expandafter\tikz@anim@entry\expandafter\expandafter\expandafter{\expandafter\tikz@anim@tl@exec@options\expandafter\def\expandafter\tikz@animation@time\expandafter{\tikz@animation@time}}}% \fi% } }% \let\tikz@anim@configs\pgfutil@empty \def\tikz@anim@entry#1{% % Reset splines and value: \let\tikz@anim@result\pgfutil@empty% \pgf@anim@reset@linear% #1% \ifx\tikz@anim@result\pgfutil@empty% \else% \ifx\tikz@animation@time\pgfutil@empty% \else% \ifx\tikz@animation@time\tikz@anim@base@text% \expandafter\pgf@anim@base\expandafter{\tikz@anim@result}% \else% \expandafter\expandafter\expandafter\pgf@anim@entry% \expandafter\expandafter\expandafter{\expandafter\tikz@animation@time\expandafter}\expandafter{\tikz@anim@result}% \fi% \fi% \fi% }% \let\tikz@animation@time\pgfutil@empty% \def\tikz@anim@base@text{base}% \tikzanimateset{ .unknown/.code={% \let\tikz@key\pgfkeyscurrentname% \tikz@animation@syntax@check{#1}{\tikz@anim@options{#1}}% } }% \def\tikz@anim@options#1{ \let\tikz@anim@key\pgfkeyscurrentname% \pgfqkeys{/tikz/animate/options}{\tikz@anim@key/.try={#1}}% \ifpgfkeyssuccess% \else% \def\tikz@anim@unparsed@value{#1}% \expandafter\tikz@anim@time@test\tikz@anim@key\pgf@stop% \fi% }% \tikzanimateset{ options/.cd, name/.code=\tikz@anim@add{\pgfanimationset{name={#1}}}, forever/.code=\tikz@anim@add{\pgfanimationset{freeze at end}}, freeze/.code=\tikz@anim@add{\pgfanimationset{freeze at end}}, restart/.code=\tikz@anim@add{\pgfanimationset{restart={#1}}}, repeats/.code=\tikz@anim@add{\pgfanimationset{repeats={#1}}}, repeats/.default=, repeat/.code=\tikz@anim@add{\pgfanimationset{repeats={#1}}}, repeat/.default=, begin/.code=\tikz@anim@add@once{\pgfanimationset{begin={#1}}}, end/.code=\tikz@anim@add@once{\pgfanimationset{end={#1}}}, begin on/.code=\tikz@anim@event{begin}{#1}, end on/.code=\tikz@anim@event{begin}{#1}, begin snapshot/.code=\tikz@anim@add{\pgfanimationset{begin snapshot={#1}}}, origin/.code=\tikz@anim@parse@origin{#1}, transform/.code=\tikz@anim@add{\pgfanimationset{transform={\let\tikz@transform\relax\tikzset{#1}}}}, along/.code=\tikz@anim@handle@along#1\pgf@stop, entry control/.code=\tikz@anim@add{\pgfanimationset{entry control=#1}}, exit control/.code=\tikz@anim@add{\pgfanimationset{exit control=#1}}, stay/.code=\tikz@anim@add{\pgfanimationset{stay}}, jump/.code=\tikz@anim@add{\pgfanimationset{jump}}, ease/.style={ entry control={1-(#1)}{1}, exit control={#1}{0} }, ease/.default=0.5, ease in/.style={ entry control={1-(#1)}{1}, }, ease in/.default=0.5, ease out/.style={ exit control={#1}{0}, }, ease out/.default=0.5, arrows/.code=\tikz@anim@add@early{\pgfanimationset{arrows={#1}}}, shorten >/.code=\tikz@anim@add@early{\pgfanimationset{shorten >={#1}}}, shorten