1% Copyright 2004--2006 Alexander Grahn
2%
3% This material is subject to the LaTeX Project Public License. See
4%   http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
5% for the details of that license.
6%
7% This package allows inclusion of multimedia content into PDF files
8% following Adobe's PDF-1.5 and 1.6 specifications.
9%
10
11\NeedsTeXFormat{LaTeX2e}
12\ProvidesPackage{movie15}[2007/09/21]
13\RequirePackage{keyval}
14\RequirePackage{ifthen}
15\RequirePackage{ifpdf}
16\RequirePackage{ifdraft}
17
18\newboolean{@MXV@iiiDfeat} % enable 3D features from PDF-1.6 spec?
19\setboolean{@MXV@iiiDfeat}{false}%
20\newboolean{@MXV@iiid} %set to true if a 3D file is being embedded
21\newboolean{@MXV@draft} %according to global setting
22\newboolean{@MXV@@draft} %per inclusion setting
23
24\ifdraft{%globally set by document class
25  \setboolean{@MXV@draft}{true}%
26}{%
27  \setboolean{@MXV@draft}{false}%
28}%
29
30%override global setting
31\DeclareOption{draft}{%
32  \setboolean{@MXV@draft}{true}%
33}
34\DeclareOption{final}{%
35  \setboolean{@MXV@draft}{false}%
36}
37
38\DeclareOption{3D}{%
39  \setboolean{@MXV@iiiDfeat}{true}%
40}
41
42\DeclareOption*{%
43  \PackageWarning{movie15}{Unknown option \CurrentOption}
44}
45
46\ProcessOptions*\relax
47
48%testing for correct TeX version,
49\ifpdf
50 \ifnum\pdftexversion<120
51   \PackageError{movie15}{%
52     pdfeTeX, version >= 1.20, required
53   }{%
54     Install a more recent version!
55   }%
56 \fi
57\fi
58
59\ifx\@undefined\pdfmdfivesum
60  \def\pdfmdfivesum file #1{#1}
61\fi
62
63\ifpdf %allows pdftex to directly import Metapost generated Postscript
64  \ifx\MPtoPDF\@undefined
65    \InputIfFileExists{supp-pdf}{}{}%
66  \fi
67\fi
68
69%for conditionals where \ifthenelse doesn't work
70\gdef\@MXV@if#1{\csname if#1\endcsname}%
71
72\newboolean{@MXV@beamer} %set to true if beamer class has been loaded
73%\newboolean{@MXV@powerdot} %the same for
74\newboolean{@MXV@presentation} %used with presentation making package?
75\newboolean{@MXV@hide} %contents hidden on the current slide?
76\@ifclassloaded{beamer}{%
77  \setboolean{@MXV@beamer}{true}%
78  \setboolean{@MXV@presentation}{true}%
79}{%
80  \setboolean{@MXV@beamer}{false}%
81  \setboolean{@MXV@presentation}{false}%
82}
83%\@ifclassloaded{powerdot}{%
84%  \setboolean{@MXV@powerdot}{true}%
85%  \setboolean{@MXV@presentation}{true}%
86%}{%
87%  \setboolean{@MXV@powerdot}{false}%
88%  \setboolean{@MXV@presentation}{false}%
89%}
90
91\AtBeginDocument{%
92  \provideboolean{Hy@colorlinks}% set by hyperref
93  \ifHy@colorlinks% coloured (movieref-)link text instead of link border
94    \gdef\@MXV@pdfborder{/Border [0 0 0]}%
95  \else%
96    \gdef\@MXV@pdfborder{}%
97  \fi%
98}
99
100\RequirePackage{everyshi}%
101\newcount\@MXV@page% counter for absolute page number
102\EveryShipout{%
103  \global\advance\@MXV@page by 1%
104}
105
106%define our own label making commands
107\def\@MXV@newlabel#1#2{{%
108  \expandafter\xdef\csname#1\endcsname{#2}}}%
109
110\def\@MXV@getlabelvalue#1{%
111  \expandafter\ifx\csname#1\endcsname\relax%
112    undefined%
113  \else%
114    \csname#1\endcsname%
115  \fi%
116}%
117
118%macro for writing labels to external *.aux file
119\def\@MXV@labeltoaux#1#2{%
120  \@bsphack\protected@write\@auxout{}{%
121    \string\@MXV@newlabel{#1}{#2}%
122    \string\@MXV@newlabel{@#1@}{\@MXV@getlabelvalue{#1}}%
123  }\@esphack%
124  \ifthenelse{%
125    \equal{\@MXV@getlabelvalue{#1}}{undefined}\OR%
126    %double check that the value hasn't changed
127    \NOT\equal{\@MXV@getlabelvalue{#1}}{\@MXV@getlabelvalue{@#1@}}%
128  }{%
129    \ifthenelse{\isundefined{\@MXV@warning}}{% issue warning only once, at end
130      \gdef\@MXV@warning{}%                    of document
131      \AtEndDocument{%
132        \PackageWarningNoLine{movie15}{%
133        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak
134        @@ Rerun to get object references right! @@\MessageBreak
135        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
136      }%
137    }{}%
138  }{}%
139}%
140%
141\ifpdf%
142  %for storing pdf object numbers (must be counters)
143  \newcount\@MXV@adict%
144  \newcount\@MXV@aadict%
145  %
146  %returns pdf page object number
147  \def\@MXV@pdfpageref#1{%
148    \expandafter\ifx\csname#1\endcsname\relax%
149      0%
150    \else%
151      \expandafter\pdfpageref\csname#1\endcsname\space%
152    \fi%
153  }%
154\else%
155  \PassOptionsToPackage{pdfmark}{hyperref}%
156\fi
157
158%counter for absolute number of inclusions,
159%used for labelling each annotation
160\newcount\@MXV@includes
161
162%counter for absolute number of movie players
163\newcount\@MXV@players
164
165%counter for absolute number of movierefs
166\newcount\@MXV@links
167
168%measuring things
169%textbox
170\newdimen\@MXV@width
171\newdimen\@MXV@height
172\newdimen\@MXV@depth
173\newdimen\@MXV@totalheight
174\newdimen\@MXV@@boxdepth
175%for centring the textbox within display box
176\newdimen\@MXV@traiselen
177\newdimen\@MXV@braiselen
178%for compatibility options
179\newdimen\@MXV@start
180\newdimen\@MXV@end
181
182%stores textbox given as argument to text option
183\newsavebox{\@MXV@textbox}
184
185%some booleans we need
186\newboolean{@MXV@autoplay}
187\newboolean{@MXV@autostop}
188\newboolean{@MXV@autoresume}
189\newboolean{@MXV@autoclose}
190\newboolean{@MXV@autopause}
191\newboolean{@MXV@mouse}%mouse interaction
192\newboolean{@MXV@inline}%inline movie data
193\newboolean{@MXV@attachment}%make embedded file extractable?
194\newboolean{@MXV@externalviewer}%if true, screen annot will be removed
195\newboolean{@MXV@url}
196\newboolean{@MXV@boxopt}%true if text option is set
197\newboolean{@MXV@textoverposter}
198\newboolean{@MXV@runposter}% render poster from movie at runtime
199\newboolean{@MXV@linkplay}% for \movieref command
200\newboolean{@MXV@linkpause}
201\newboolean{@MXV@linkresume}
202\newboolean{@MXV@linkstop}
203\newboolean{@MXV@linkclose}
204\newboolean{@MXV@linkreset}
205\newboolean{@MXV@issound}
206
207%macro to reset all macros and booleans
208\def\@MXV@reset{%
209  \setboolean{@MXV@autoplay}{false}%
210  \setboolean{@MXV@autostop}{true}%
211  \setboolean{@MXV@autoresume}{false}%
212  \setboolean{@MXV@autopause}{false}%
213  \setboolean{@MXV@autoclose}{false}%
214  \setboolean{@MXV@mouse}{false}%
215  \setboolean{@MXV@inline}{true}%
216  \setboolean{@MXV@attachment}{true}%
217  \setboolean{@MXV@externalviewer}{false}%
218  \setboolean{@MXV@issound}{false}%
219  \setboolean{@MXV@url}{false}%
220  \setboolean{@MXV@boxopt}{false}%
221  \setboolean{@MXV@textoverposter}{true}%
222  \setboolean{@MXV@runposter}{false}%
223  \setboolean{@MXV@linkplay}{true}%
224  \setboolean{@MXV@linkpause}{false}%
225  \setboolean{@MXV@linkresume}{false}%
226  \setboolean{@MXV@linkstop}{false}%
227  \setboolean{@MXV@linkclose}{false}%
228  \setboolean{@MXV@linkreset}{false}%
229  \ifthenelse{\boolean{@MXV@draft}}{%
230    \setboolean{@MXV@@draft}{true}%
231  }{%
232    \setboolean{@MXV@@draft}{false}%
233  }%
234  %
235  \gdef\@MXV@label{}% for movieref
236  \gdef\@MXV@@label{}% for movieref
237  \gdef\@MXV@mime{@MXV@auto}%
238  \gdef\@MXV@player{}%
239  \gdef\@MXV@fsentry{}%
240  \gdef\@MXV@repeat{}%
241  \gdef\@MXV@@repeat{}%
242  \gdef\@MXV@volume{100}%
243  \gdef\@MXV@@volume{}%
244  \gdef\@MXV@ctrls{}%
245  \gdef\@MXV@@ctrls{}%
246  \gdef\@MXV@palindrome{}%
247  \gdef\@MXV@rate{}%
248  \gdef\@MXV@startat{}%
249  \gdef\@MXV@endat{}%
250  \gdef\@MXV@poevent{}%
251  \gdef\@MXV@pcevent{}%
252  \gdef\@MXV@box##1##2##3{\raisebox{0pt}[##2][##3]{\makebox[##1]{}}}%
253  \setlength{\@MXV@depth}{0pt}%
254  \setlength{\@MXV@height}{0pt}%
255  \setlength{\@MXV@width}{0pt}%
256  \setlength{\@MXV@braiselen}{0pt}%
257  \setlength{\@MXV@traiselen}{0pt}%
258  \gdef\@MXV@boxdepth{}%
259  \gdef\@MXV@boxheight{}%
260  \gdef\@MXV@boxwidth{}%
261  %
262  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
263    \setboolean{@MXV@iiid}{false}%
264    \gdef\@MXV@aac{30}% aperture angle of camera
265    \gdef\@MXV@roll{0}% camera roll angle
266    \gdef\@MXV@background{}%
267    \gdef\@MXV@jscriptiiidfile{}%
268    \gdef\@MXV@coo{0 0 0}% centre of orbit
269    \gdef\@MXV@ctoc{0 -1 0}% centre of orbit to camera vector
270    \gdef\@MXV@roo{0}% radius of orbit
271    \gdef\@MXV@viewsfile{}% file containing views of the 3D object
272    \setboolean{@MXV@viewsprovided}{false}%
273    \setboolean{@MXV@defaultviewprovided}{false}%
274    \gdef\@MXV@iiidview{}%
275    \gdef\@MXV@iiidtoolb{/TB false}% don't show toolbar by default
276    \gdef\@MXV@iiidia{}% 3D interactive by default
277    \gdef\@MXV@calc{}% camera aperture for coo and roo calculation
278    \setboolean{@MXV@iiidgetview}{false}%
279    \gdef\@MXV@iiidopt{}% option string to be passed to internal macro
280    \setboolean{@MXV@resource}{false}%
281    \gdef\@MXV@resourcetree{}% name tree of embedded 3D resources
282    \xdef\@MXV@animstyle{}%
283    \gdef\@MXV@iiidpalindrome{/Subtype/Linear}% forward
284    \gdef\@MXV@iiidrate{}% animation speed
285    \global\@MXV@iiidrepeat=-1% repeat count
286    \gdef\@MXV@lights{}% default lighting scheme
287  }{}%
288}%
289
290%missing package error message
291\def\@MXV@missing#1{%
292  \PackageError{movie15}{%
293    Package `#1' has not been loaded yet
294  }{%
295    Put the line `\protect\usepackage{#1}' somewhere after
296    `\protect\usepackage{movie15}' to the preamble of your
297    document!
298  }%
299}
300
301%3D-need-be-enabled error message
302\def\@MXV@neediiiD{%
303  \PackageError{movie15}{%
304    If you wish to embed 3D objects, enable the\MessageBreak
305    3D feature first by passing option `3D' to movie15!\MessageBreak
306    Make sure the `fp' package for fixed point calculus\MessageBreak
307    is installed in your TeX system
308  }{Package `fp' is available from CTAN.}%
309}
310
311%macro to guess the mime type of the media file
312\def\@MXV@guessmime#1#2{%
313  \ifthenelse{\equal{#2}{aiff}\OR\equal{#2}{AIFF}\OR%
314              \equal{#2}{aif}\OR\equal{#2}{AIF}\OR%
315              \equal{#2}{aifc}\OR\equal{#2}{AIFC}}{%
316    \gdef\@MXV@mime{audio/aiff}%
317  }{%
318  \ifthenelse{\equal{#2}{wav}\OR\equal{#2}{WAV}}{%
319    \gdef\@MXV@mime{audio/wav}%
320  }{%
321  \ifthenelse{\equal{#2}{wma}\OR\equal{#2}{WMA}}{%
322    \gdef\@MXV@mime{audio/x-ms-wma}%
323  }{%
324  \ifthenelse{\equal{#2}{wmv}\OR\equal{#2}{WMV}}{%
325    \gdef\@MXV@mime{video/x-ms-wmv}%
326  }{%
327  \ifthenelse{\equal{#2}{au}\OR\equal{#2}{AU}\OR%
328              \equal{#2}{snd}\OR\equal{#2}{SND}}{%
329    \gdef\@MXV@mime{audio/basic}%
330  }{%
331  \ifthenelse{\equal{#2}{mid}\OR\equal{#2}{MID}\OR%
332              \equal{#2}{rmi}\OR\equal{#2}{RMI}}{%
333    \gdef\@MXV@mime{audio/midi}%
334  }{%
335  \ifthenelse{\equal{#2}{mov}\OR\equal{#2}{MOV}\OR%
336              \equal{#2}{qt}\OR\equal{#2}{QT}}{%
337    \gdef\@MXV@mime{video/quicktime}%
338  }{%
339  \ifthenelse{\equal{#2}{mp3}\OR\equal{#2}{MP3}\OR%
340              \equal{#2}{m3u}\OR\equal{#2}{M3U}}{%
341    \gdef\@MXV@mime{audio/x-mp3}%
342  }{%
343  \ifthenelse{\equal{#2}{mp4}\OR\equal{#2}{MP4}}{%
344    \gdef\@MXV@mime{video/mp4}%
345  }{%
346  \ifthenelse{\equal{#2}{avi}\OR\equal{#2}{AVI}}{%
347    \gdef\@MXV@mime{video/avi}%
348  }{%
349  \ifthenelse{\equal{#2}{gif}\OR\equal{#2}{GIF}}{%
350    \gdef\@MXV@mime{image/gif}%
351  }{%
352  \ifthenelse{\equal{#2}{mpeg}\OR\equal{#2}{MPEG}\OR%
353              \equal{#2}{mpg}\OR\equal{#2}{MPG}}{%
354    \gdef\@MXV@mime{video/mpeg}%
355  }{%
356  \ifthenelse{\equal{#2}{smil}\OR\equal{#2}{SMIL}}{%
357    \gdef\@MXV@mime{application/smil}%
358  }{%
359  \ifthenelse{\equal{#2}{swf}\OR\equal{#2}{SWF}}{%
360    \gdef\@MXV@mime{application/x-shockwave-flash}%
361  }{%
362  \ifthenelse{\equal{#2}{u3d}\OR\equal{#2}{U3D}}{%
363    \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
364      \setboolean{@MXV@iiid}{true}%
365      \gdef\@MXV@mime{model/u3d}% (unofficial)
366      \gdef\@MXV@iiidsubtype{U3D}%
367    }{%
368      \@MXV@neediiiD%
369    }%
370  }{%
371  \ifthenelse{\equal{#2}{ra}\OR\equal{#2}{RA}\OR%
372              \equal{#2}{ram}\OR\equal{#2}{RAM}\OR%
373              \equal{#2}{rm}\OR\equal{#2}{RM}}{%
374    \gdef\@MXV@mime{audio/x-pn-realaudio}%
375  }{%
376    \PackageError{movie15}{%
377      I couldn't determine MIME type of file:\MessageBreak`#1':\MessageBreak
378      Unknown file name extension: `#2'
379    }{%
380      When using media files of unknown type or with a\MessageBreak
381      non-standard file name extension, the MIME type must\MessageBreak
382      explicitly be specified. Try option `mimetype=<mime type>'!
383    }%
384  }}}}}}}}}}}}}}}}%
385}
386
387%sets @MXV@issound boolean
388\def\@MXV@@issound#1/#2.{% argument: \@MXV@mime.
389   \def\@MXV@firstarg{#1}%
390   \def\@MXV@audio{audio}%
391   \ifx\@MXV@firstarg\@MXV@audio%
392     \setboolean{@MXV@issound}{true}%
393   \fi%
394}
395
396%draft box
397\def\@MXV@draftbox#1#2#3#4{%width height depth filename
398  \edef\@MXV@oldfboxsep{\the\fboxsep}%
399  \setlength{\fboxsep}{-\fboxrule}%
400  \framebox[#1][l]{%
401    \vrule width 0pt height #2 depth #3%
402    \edef\@tempa{#4}%
403    \raisebox{\depth}[0pt][0pt]{ \ttfamily\expandafter\strip@prefix\meaning\@tempa}%
404  }%
405  \setlength{\fboxsep}{\@MXV@oldfboxsep}%
406}
407
408\ifthenelse{\boolean{@MXV@iiiDfeat}}{% 3D related definitions and macros
409  \RequirePackage{fp}% needed for fixed point calculus
410  \newcount\@MXV@viewscount%counter for number of 3D views per inclusion
411  \newboolean{@MXV@viewsprovided}%3d views file provided?
412  \newboolean{@MXV@iiidgetview}% print current 3D settings?
413  \newboolean{@MXV@defaultviewprovided}%default 3D view provided?
414  \newboolean{@MXV@resource}%3d resource file provided?
415  \ifpdf\else\newcount\@MXV@rescount\fi% number of embedded resource files
416  \newcount\@MXV@iiidrepeat% play count
417  \newcount\@MXV@iiidoncurpage%index of 3D annot on current page
418  \global\@MXV@iiidoncurpage=0%
419  \gdef\@MXV@oldpage{0}% needed together with previous counter
420
421  %macro for building the transformation matrix
422  \def\@MXV@ciiwmatrix#1 #2 #3 #4 #5 #6 #7 #8 {%
423    % #1,#2,#3 centre of orbit coordinates (coo)
424    % #4,#5,#6 centre of orbit to camera direction vector (c2c)
425    % #7 orbital radius (roo)
426    % #8 camera roll (roll)
427    %view vector (opposite to c2c)
428    \FPupn\@MXV@viewx{#4 neg}%
429    \FPupn\@MXV@viewy{#5 neg}%
430    \FPupn\@MXV@viewz{#6 neg}%
431    %normalize view vector
432    \FPupn\@MXV@modulo{\@MXV@viewx{} copy mul %
433      \@MXV@viewy{} copy mul + %
434      \@MXV@viewz{} copy mul + 2 swap root%
435    }%
436    \FPupn\@MXV@viewx{\@MXV@viewx{} \@MXV@modulo{} div}%
437    \FPupn\@MXV@viewy{\@MXV@viewy{} \@MXV@modulo{} div}%
438    \FPupn\@MXV@viewz{\@MXV@viewz{} \@MXV@modulo{} div}%
439    %camera roll
440    \FPupn\@MXV@sinroll{#8 180.0 div \FPpi{} mul sin}%
441    \FPupn\@MXV@cosroll{#8 180.0 div \FPpi{} mul cos}%
442    %
443    %top and bottom views
444    \FPupn\@MXV@leftx{-1.0}%
445    \FPupn\@MXV@lefty{0.0}%
446    \FPupn\@MXV@leftz{0.0}%
447    %
448    \FPifneg\@MXV@viewz% top view
449      %up-vector
450      \FPupn\@MXV@upx{0.0}%
451      \FPupn\@MXV@upy{1.0}%
452      \FPupn\@MXV@upz{0.0}%
453    \else% bottom view
454      %up-vector
455      \FPupn\@MXV@upx{0.0}%
456      \FPupn\@MXV@upy{-1.0}%
457      \FPupn\@MXV@upz{0.0}%
458    \fi%
459    \FPupn\@MXV@sumxy{\@MXV@viewx{} abs \@MXV@viewy{} abs add}%
460    \FPifeq\@MXV@sumxy{0}\else% other views than top and bottom
461      %up-vector = up_world - (up_world dot view) view
462      \FPupn\@MXV@upx{\@MXV@viewz{} \@MXV@viewx{} mul neg}%
463      \FPupn\@MXV@upy{\@MXV@viewz{} \@MXV@viewy{} mul neg}%
464      \FPupn\@MXV@upz{\@MXV@viewz{} \@MXV@viewz{} mul neg 1.0 add}%
465      %normalize up-vector
466      \FPupn\@MXV@modulo{\@MXV@upx{} copy mul \@MXV@upy{} copy %
467        mul + \@MXV@upz{} copy mul + 2 swap root}%
468      \FPupn\@MXV@upx{\@MXV@upx{} \@MXV@modulo{} div}%
469      \FPupn\@MXV@upy{\@MXV@upy{} \@MXV@modulo{} div}%
470      \FPupn\@MXV@upz{\@MXV@upz{} \@MXV@modulo{} div}%
471      %left vector = up x view
472      \FPupn\@MXV@leftx{\@MXV@viewz{} \@MXV@upy{} mul %
473        \@MXV@viewy{} \@MXV@upz{} mul sub}%
474      \FPupn\@MXV@lefty{\@MXV@viewx{} \@MXV@upz{} mul %
475        \@MXV@viewz{} \@MXV@upx{} mul sub}%
476      \FPupn\@MXV@leftz{\@MXV@viewy{} \@MXV@upx{} mul %
477        \@MXV@viewx{} \@MXV@upy{} mul sub}%
478      %normalize left vector
479      \FPupn\@MXV@modulo{\@MXV@leftx{} copy mul \@MXV@lefty{} %
480        copy mul + \@MXV@leftz{} copy mul + 2 swap root}%
481      \FPupn\@MXV@leftx{\@MXV@leftx{} \@MXV@modulo{} div}%
482      \FPupn\@MXV@lefty{\@MXV@lefty{} \@MXV@modulo{} div}%
483      \FPupn\@MXV@leftz{\@MXV@leftz{} \@MXV@modulo{} div}%
484    \fi%
485    %apply camera roll
486    \FPupn\@MXV@leftxprime{\@MXV@leftx{} \@MXV@cosroll{} mul \@MXV@upx{} \@MXV@sinroll{} mul +}%
487    \FPupn\@MXV@leftyprime{\@MXV@lefty{} \@MXV@cosroll{} mul \@MXV@upy{} \@MXV@sinroll{} mul +}%
488    \FPupn\@MXV@leftzprime{\@MXV@leftz{} \@MXV@cosroll{} mul \@MXV@upz{} \@MXV@sinroll{} mul +}%
489    \FPupn\@MXV@upxprime{\@MXV@upx{} \@MXV@cosroll{} mul \@MXV@leftx{} \@MXV@sinroll{} mul sub}%
490    \FPupn\@MXV@upyprime{\@MXV@upy{} \@MXV@cosroll{} mul \@MXV@lefty{} \@MXV@sinroll{} mul sub}%
491    \FPupn\@MXV@upzprime{\@MXV@upz{} \@MXV@cosroll{} mul \@MXV@leftz{} \@MXV@sinroll{} mul sub}%
492    \FPupn\@MXV@leftx{\@MXV@leftxprime}%
493    \FPupn\@MXV@lefty{\@MXV@leftyprime}%
494    \FPupn\@MXV@leftz{\@MXV@leftzprime}%
495    \FPupn\@MXV@upx{\@MXV@upxprime}%
496    \FPupn\@MXV@upy{\@MXV@upyprime}%
497    \FPupn\@MXV@upz{\@MXV@upzprime}%
498    %rotation matrix
499    \xdef\@MXV@matrix{\@MXV@leftx\space\@MXV@lefty\space\@MXV@leftz\space%
500                      \@MXV@upx\space\@MXV@upy\space\@MXV@upz\space%
501                      \@MXV@viewx\space\@MXV@viewy\space\@MXV@viewz}%
502    %translation vector
503    \FPupn\@MXV@roo{#7 abs}%
504    \FPifeq\@MXV@roo{0}\FPupn\@MXV@roo{0.000000000000000001}\fi%
505    \FPupn\@MXV@transx{#1 \@MXV@roo{} \@MXV@viewx{} mul sub}%
506    \FPupn\@MXV@transy{#2 \@MXV@roo{} \@MXV@viewy{} mul sub}%
507    \FPupn\@MXV@transz{#3 \@MXV@roo{} \@MXV@viewz{} mul sub}%
508    %transformation matrix
509    \xdef\@MXV@matrix{%
510      \@MXV@matrix\space\@MXV@transx\space\@MXV@transy\space\@MXV@transz%
511    }%
512  }
513
514  %macro for parsing one line of 3D views file
515  \newcommand{\@MXV@parseline}[6][]{%
516    \xdef\@MXV@xname{#1}% name of the view (optional)
517    \ifthenelse{\equal{#2}{}}{%
518      \xdef\@MXV@coo{0 0 0}%
519    }{%
520      \xdef\@MXV@coo{#2}%
521    }%
522    \ifthenelse{\equal{#3}{}}{%
523      \xdef\@MXV@ctoc{0 -1 0}%
524    }{%
525      \xdef\@MXV@ctoc{#3}%
526    }%
527    \ifthenelse{\equal{#4}{}}{%
528      \xdef\@MXV@roo{0}%
529    }{%
530      \xdef\@MXV@roo{#4}%
531    }%
532    \ifthenelse{\equal{#5}{}}{%
533      \xdef\@MXV@roll{0}%
534    }{%
535      \xdef\@MXV@roll{#5}%
536    }%
537    \ifthenelse{\equal{#6}{}}{%
538      \xdef\@MXV@aac{30}%
539    }{%
540      \xdef\@MXV@aac{#6}%
541    }%
542  }
543
544  %macro for generating an array of 3D views (varray)
545  \def\@MXV@buildva{%
546    \global\@MXV@viewscount=0%
547    \xdef\@MXV@varray{}% empty varray
548    %
549    %default view
550    \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}%
551    \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix
552    \xdef\@MXV@xname{Default}%
553    \@MXV@viewobj% create pdf object of 3D view
554    \edef\@MXV@defaultview{\@MXV@@viewobj}%
555    %
556    %read out 3D views file
557    \IfFileExists{\@MXV@viewsfile}{%
558      \edef\@MXV@endlinechar{\the\endlinechar}%
559      \endlinechar=-1% suppress trailing space at input line end
560      \newread\@MXV@@viewsfile%
561      \openin\@MXV@@viewsfile=\@MXV@viewsfile%
562      \loop%
563        \read\@MXV@@viewsfile to \@MXV@inputline%
564      \if\@MXV@inputline\relax\else%
565        \expandafter\@MXV@parseline\@MXV@inputline%
566        \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}%
567        \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix
568        \global\advance\@MXV@viewscount by 1%
569        \ifthenelse{\equal{\@MXV@xname}{}}{%
570          \xdef\@MXV@xname{View \the\@MXV@viewscount}%
571        }{}%
572        \@MXV@viewobj% create pdf object of 3D view
573        %append current view obj ref to VA array
574        \xdef\@MXV@varray{\@MXV@varray\space\@MXV@@viewobj}%
575        \setboolean{@MXV@viewsprovided}{true}%
576      \repeat%
577      \closein\@MXV@@viewsfile%
578      \endlinechar=\@MXV@endlinechar% reset endlinechar
579    }{}%
580    %
581    %make the first view in the VA array the default view, if no default one has
582    %explicitly been provided, but if the VA array itself is empty too (no
583    %additional views provided) use our fallback view (c2c=0 -1 0) as default
584    \ifthenelse{\NOT\boolean{@MXV@defaultviewprovided}%
585      \AND\boolean{@MXV@viewsprovided}}{%
586      \xdef\@MXV@defaultview{/3DV /F}%
587    }{%
588      \xdef\@MXV@defaultview{/3DV \@MXV@defaultview}%
589    }%
590  }
591
592  %following macros, including the 3D inclusion macro have driver specific
593  %implementations
594  \ifpdf%
595    %pdfLaTeX versions
596    %macro for creating 3D view object
597    \def\@MXV@viewobj{%
598      %projection dict
599      \pdfobj {<</Subtype/P/FOV \@MXV@aac/PS/Min>>}%
600      \pdfrefobj\pdflastobj%
601      %
602      \pdfobj {<<%
603        /MS/M% define the view as C2W matrix
604        /CO \@MXV@roo% orbital radius
605        /P \the\pdflastobj\space 0 R%
606        /C2W [\@MXV@matrix]%
607        /XN(\@MXV@xname)% name of the view appearing in the drop down list
608        \@MXV@background%
609        \@MXV@lights%
610      >>}\pdfrefobj\pdflastobj%
611      \xdef\@MXV@@viewobj{\the\pdflastobj\space 0 R}%
612    }%
613
614    %macro for creating resource objects from 3D and image files, to be used
615    %in 3D JavaScript
616    \def\@MXV@addresource#1{%
617      %determine file type
618      \filename@parse{#1}%
619      \ifthenelse{%
620        \equal{\filename@ext}{u3d}\OR%
621        \equal{\filename@ext}{U3D}%
622      }{%
623        \def\@MXV@restype{U3D}%
624      }{%
625        \def\@MXV@restype{image}%
626      }%
627      \ifthenelse{\equal{\@MXV@restype}{image}}{%
628        %embed the same image file only once
629        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
630          \immediate\pdfximage {#1}%
631          \xdef\@MXV@resourcetree{% build name tree for embedded resources
632            \@MXV@resourcetree\space (#1) \the\pdflastximage\space 0 R%
633          }%
634          \@MXV@newlabel{\pdfmdfivesum file {#1}}{\the\pdflastximage}%
635        }{%
636          \xdef\@MXV@resourcetree{%
637            \@MXV@resourcetree\space (#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}\space 0 R%
638          }%
639        }%
640      }{%
641        %embed the same 3D file only once
642        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
643          \pdfobj stream %
644            attr {%
645              /Subtype/\@MXV@restype%
646            }%
647            file {#1}%
648          \pdfrefobj\pdflastobj%
649          \xdef\@MXV@resourcetree{%
650            \@MXV@resourcetree\space (#1) \the\pdflastobj\space 0 R%
651          }%
652          \@MXV@newlabel{\pdfmdfivesum file {#1}}{\the\pdflastobj}%
653        }{%
654          \xdef\@MXV@resourcetree{%
655            \@MXV@resourcetree\space (#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}\space 0 R%
656          }%
657        }%
658      }%
659    }
660
661    %3D inclusion macro
662    \newcommand{\@MXV@includeiiid}[5][]{%
663      %insert box or poster
664      \@MXV@box{#2}{#3}{#4}%
665      %
666      \if@MXV@externalviewer\else%
667        \setkeys{MXV@iiid}{#1}%process deferred options
668        \ifnum\@MXV@iiidrepeat=0\else%
669          \edef\@MXV@animstyle{% animation style dict
670            /AN <<%
671              \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat%
672            >>%
673          }%
674        \fi%
675        %java script file, stream object
676        \IfFileExists{\@MXV@jscriptiiidfile}{%
677          \pdfobj stream file {\@MXV@jscriptiiidfile}%
678          \pdfrefobj\pdflastobj%
679          \xdef\@MXV@jscriptiiid{/OnInstantiate \the\pdflastobj\space 0 R}%
680        }{\xdef\@MXV@jscriptiiid{}}%
681        %
682        %build the array of 3D views
683        \@MXV@buildva%
684      \fi%
685      %
686      %3D stream object
687      \if@MXV@inline%
688        \ifthenelse{%
689          \NOT\boolean{@MXV@presentation}\OR%
690          \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}%
691        }{%
692          \pdfobj stream%
693            attr {%
694              /Subtype/\@MXV@iiidsubtype%
695              \if@MXV@externalviewer\else%
696                /VA [\@MXV@varray]%
697                /DV/F% use first entry in VA as default view
698                \@MXV@animstyle%
699                \@MXV@jscriptiiid%
700                \if@MXV@resource%
701                  /Resources <<%
702                    /Names [\@MXV@resourcetree]%
703                  >>%
704                \fi%
705              \fi%
706            }%
707            file {#5}%
708          \pdfrefobj\pdflastobj%
709          \edef\@MXV@iiidstream{\the\pdflastobj}%
710          \if@MXV@presentation%
711            \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}%
712          \fi%
713        }{%
714          \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}%
715        }%
716      \fi%
717      %
718      \makebox[0pt][r]{\makebox[#2][l]{%
719      %insert FileAttachment annotation
720      \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}%
721%        since Reader 7.0.7, we cannot place a file attachment annot behind
722%        the 3D annot :-(
723%        \OR\boolean{@MXV@attachment}
724      }{%
725        \pdfannot width #2 height #3 depth #4 {%
726          /Subtype /FileAttachment%
727          /F 0%
728          /T (\@MXV@filename)%
729          /Contents (3D Object (\@MXV@mime))%
730          \if@MXV@externalviewer%
731            /Name/Paperclip%
732            /C [1 1 1]%
733          \else%
734            /AP <</N<<>>/R<<>>/D<<>>>>%
735          \fi%
736          /FS <<%
737            /F(#5)%
738            /Type/Filespec%
739            /EF << /F \@MXV@iiidstream\space 0 R >>%
740          >>%
741        }%
742      }{%
743        \if@MXV@url%
744          %insert Link annotation, if 3D file is a URL
745          \pdfannot width #2 height #3 depth #4 {%
746            /Subtype /Link%
747            /F 0%
748            \if@MXV@externalviewer%
749              \@MXV@urlattr%
750            \else%
751              /H /N%
752              /Border [0 0 0]%
753            \fi%
754            /A <</URI (#5) /S/URI>>%
755            /Contents (3D Object (\@MXV@mime))%
756          }%
757        \else%
758          %else insert Launch action for local external 3D file
759          \if@MXV@inline\else%
760            \pdfannot width #2 height #3 depth #4 {%
761              /Subtype /Link%
762              /F 0%
763              \if@MXV@externalviewer%
764                \@MXV@runattr%
765              \else%
766                /H /N%
767                /Border [0 0 0]%
768              \fi%
769              /A <<%
770                /F (#5)%
771                /S /Launch%
772              >>%
773              /Contents (3D Object (\@MXV@mime))%
774            }%
775          \fi%
776        \fi%
777      }%
778      %
779      \if@MXV@externalviewer\else%
780        %appearance dict dummy, to be shared by all 3D annots
781        \ifthenelse{\isundefined{\@MXV@apdict}}{%
782          \pdfobj stream {}\pdfrefobj\pdflastobj%
783          \xdef\@MXV@apdict{/AP << /N \the\pdflastobj\space 0 R >>}%
784        }{}%
785        %3D reference dict
786        \if@MXV@presentation%
787          \ifthenelse{%
788            \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}%
789          }{%
790            \pdfobj {<<%
791              /Type/3DRef%
792              /3DD \@MXV@iiidstream\space 0 R% 3D stream object
793            >>}\pdfrefobj\pdflastobj%
794            \edef\@MXV@iiidstreamorref{\the\pdflastobj}%
795            \@MXV@newlabel{\@MXV@label.3dref}{\the\pdflastobj}%
796          }{%
797            \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}%
798          }%
799        \else%
800          \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}%
801        \fi%
802        %annotation object of subtype `3D'
803        \pdfannot width #2 height #3 depth #4 {%
804          /Subtype/3D%
805          /F 4% we cannot put F 5 here; bug in Reader; 3D annot would be
806          /T (\@MXV@filename)%    disabled even if plugin were available
807          /Contents (3D Object (\@MXV@mime))%
808          \ifx\@MXV@@label\@empty\else%
809            /NM (\@MXV@@label)%
810          \fi%
811          /P \@MXV@pdfpageref{@MXV@annot\the\@MXV@includes.page} 0 R%
812          \@MXV@apdict% /AP <</N<<>>/R<<>>/D<<>>>> doesn't work here
813          \@MXV@defaultview%
814          \@MXV@iiidia%
815          /3DD \@MXV@iiidstreamorref\space 0 R% 3D stream or reference object
816          /3DA << \@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb >>%
817        }%
818        %label for later annot obj number determination, to be used in
819        %movieref's
820        \ifx\@MXV@@label\@empty\else%
821          \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\pdflastannot}%
822          \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\pdflastannot}%
823        \fi%
824      \fi}}%
825    }%
826  \else%
827    %dvips versions
828    %macro for creating 3D view object and associated projection dict
829    \def\@MXV@viewobj{%
830      %projection dict
831      \pdfmark{%
832        pdfmark=/OBJ,%
833        Raw={%
834          /_objdef {pdict\the\@MXV@includes_\the\@MXV@viewscount}%
835          /type/dict%
836        }%
837      }%
838      \pdfmark{%
839        pdfmark=/PUT,%
840        Raw={%
841          {pdict\the\@MXV@includes_\the\@MXV@viewscount} <<%
842            /Subtype/P/FOV \@MXV@aac/PS/Min%
843          >>%
844        }%
845      }%
846      %
847      \pdfmark{%
848        pdfmark=/OBJ,%
849        Raw={%
850          /type/dict%
851          /_objdef {viewobj\the\@MXV@includes_\the\@MXV@viewscount}%
852        }%
853      }%
854      \pdfmark{%
855        pdfmark=/PUT,%
856        Raw={%
857          {viewobj\the\@MXV@includes_\the\@MXV@viewscount} <<%
858            /MS/M%
859            /CO \@MXV@roo%
860            /P {pdict\the\@MXV@includes_\the\@MXV@viewscount}%
861            /C2W[\@MXV@matrix]%
862            /XN(\@MXV@xname)%
863            \@MXV@background%
864            \@MXV@lights%
865          >>%
866        }%
867      }%
868      \xdef\@MXV@@viewobj{{viewobj\the\@MXV@includes_\the\@MXV@viewscount}}%
869    }%
870    %
871    %macro for creating resource objects from 3D and image files
872    \def\@MXV@addresource#1{%
873      %determine file type
874      \filename@parse{#1}%
875      \ifthenelse{%
876        \equal{\filename@ext}{u3d}\OR%
877        \equal{\filename@ext}{U3D}%
878      }{%
879        \def\@MXV@restype{U3D}%
880      }{%
881        \def\@MXV@restype{image}%
882      }%
883      \ifthenelse{\equal{\@MXV@restype}{image}}{%
884        %embed the same image file only once
885        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
886          %increment counter of embedded resource files
887          \global\advance\@MXV@rescount by 1%
888          %create Image XObject from next raster image
889          \special{ps:% read image resource from file
890            [ /_objdef {resource\the\@MXV@rescount} /NI pdfmark
891            save gsave
892            {
893              /showpage {} def
894              /setpagedevice /pop load def
895              newpath clip
896              (#1) run
897            } ?pdfmark
898            0 0 1 [1 0 0 1 0 0] {} image %empty dummy, in case #1 is not
899            grestore restore             %a valid image file
900          }%
901          \xdef\@MXV@resourcetree{% build name tree for embedded resources
902            \@MXV@resourcetree\space (#1) {resource\the\@MXV@rescount}%
903          }%
904          \@MXV@newlabel{\pdfmdfivesum file {#1}}{resource\the\@MXV@rescount}%
905        }{%
906          \xdef\@MXV@resourcetree{%
907            \@MXV@resourcetree\space (#1) {\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}%
908          }%
909        }%
910      }{%
911        %embed the same 3D file only once
912        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
913          \global\advance\@MXV@rescount by 1%
914          \special{ps:
915            [ /_objdef {resource\the\@MXV@rescount} /type/stream /OBJ pdfmark
916            [ {resource\the\@MXV@rescount} <<%
917                /Subtype/\@MXV@restype%
918              >> /PUT pdfmark%
919            [ {resource\the\@MXV@rescount} (#1) (r) file /PUT pdfmark
920          }%
921          \xdef\@MXV@resourcetree{%
922            \@MXV@resourcetree\space (#1) {resource\the\@MXV@rescount}%
923          }%
924          \@MXV@newlabel{\pdfmdfivesum file {#1}}{resource\the\@MXV@rescount}%
925        }{%
926          \xdef\@MXV@resourcetree{%
927            \@MXV@resourcetree\space (#1) {\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}%
928          }%
929        }%
930      }%
931    }
932    %
933    %3D inclusion macro
934    \newcommand{\@MXV@includeiiid}[5][]{%
935      %
936      \if@MXV@externalviewer\else%
937        \setkeys{MXV@iiid}{#1}%process deferred options
938        \ifnum\@MXV@iiidrepeat=0\else%
939          \edef\@MXV@animstyle{% animation style dict
940            /AN <<%
941              \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat%
942            >>%
943          }%
944        \fi%
945        %java script file, stream object
946        \IfFileExists{\@MXV@jscriptiiidfile}{%
947          \pdfmark{%
948            pdfmark=/OBJ,%
949            Raw={%
950              /_objdef {jscriptiiid\the\@MXV@includes}%
951              /type/stream%
952            }%
953          }%
954          \pdfmark{%
955            pdfmark=/PUT,%
956            Raw={%
957              {jscriptiiid\the\@MXV@includes}%
958              (\@MXV@jscriptiiidfile) (r) file%
959            }%
960          }%
961          \xdef\@MXV@jscriptiiid{%
962            /OnInstantiate {jscriptiiid\the\@MXV@includes}%
963          }%
964        }{\def\@MXV@jscriptiiid{}}%
965        %
966        %build the array of 3D views
967        \@MXV@buildva%
968      \fi%
969      %
970      %3D stream object
971      \if@MXV@inline%
972        \ifthenelse{%
973          \NOT\boolean{@MXV@presentation}\OR%
974          \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}%
975        }{%
976         \pdfmark{%
977            pdfmark=/OBJ,%
978            Raw={%
979              /_objdef {iiiDfile\the\@MXV@includes}%
980              /type/stream%
981            }%
982          }%
983          \pdfmark{%
984            pdfmark=/PUT,%
985            Raw={%
986              {iiiDfile\the\@MXV@includes} <<%
987                /Subtype/\@MXV@iiidsubtype%
988                \if@MXV@externalviewer\else%
989                  /VA [\@MXV@varray]%
990                  /DV/F% use first entry in VA as default view
991                  \@MXV@animstyle%
992                  \if@MXV@resource%
993                    /Resources <<%
994                      /Names [\@MXV@resourcetree]%
995                    >>%
996                  \fi%
997                  \@MXV@jscriptiiid%
998                \fi%
999              >>%
1000            }%
1001          }%
1002          \pdfmark{%
1003            pdfmark=/PUT,%
1004            Raw={%
1005              {iiiDfile\the\@MXV@includes}%
1006              (#5) (r) file%
1007            }%
1008          }%
1009          \edef\@MXV@iiidstream{iiiDfile\the\@MXV@includes}%
1010          \if@MXV@presentation%
1011            \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}%
1012          \fi%
1013        }{%
1014          \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}%
1015        }%
1016      \fi%
1017      %
1018      %insert FileAttachment annotation
1019      \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}%
1020%        \OR\boolean{@MXV@attachment}
1021      }{%
1022        \makebox[0pt][l]{%
1023          \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
1024            pdfmark=/ANN,%
1025            Subtype=/FileAttachment,%
1026            Raw={%
1027              /F 0%
1028              /T (\@MXV@filename)%
1029              /Contents (3D Object (\@MXV@mime))%
1030              \if@MXV@externalviewer%
1031                /Name/Paperclip%
1032                /C [1 1 1]%
1033              \else%
1034                /AP <</N<<>>/R<<>>/D<<>>>>%
1035              \fi%
1036              /FS <<%
1037                /F(#5)%
1038                /Type/Filespec%
1039                /EF <</F {\@MXV@iiidstream}>>%
1040              >>%
1041            }%
1042          }%
1043        }%
1044      }{%
1045        \if@MXV@url%
1046          %insert Link annotation, if 3D file is a URL
1047          \makebox[0pt][l]{%
1048            \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
1049              pdfmark=/ANN,%
1050              Subtype=/Link,%
1051              Raw={%
1052                /F 0%
1053                \if@MXV@externalviewer%
1054                  /C [\@urlbordercolor]%
1055                  /H \@pdfhighlight%
1056                \else%
1057                  /H /N%
1058                  /Border [0 0 0]%
1059                \fi%
1060                /Action <</URI (#5) /S/URI>>%
1061                /Contents (3D Object (\@MXV@mime))%
1062              }%
1063            }%
1064          }%
1065        \else%
1066          %else insert Launch action for local external 3D file
1067          \if@MXV@inline\else%
1068            \makebox[0pt][l]{%
1069              \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
1070                pdfmark=/ANN,%
1071                Subtype=/Link,%
1072                Raw={%
1073                  /F 0%
1074                  \if@MXV@externalviewer%
1075                    /C [\@urlbordercolor]%
1076                    /H \@pdfhighlight%
1077                  \else%
1078                    /H /N%
1079                    /Border [0 0 0]%
1080                  \fi%
1081                  /Action <<%
1082                    /F (#5)%
1083                    /S /Launch%
1084                  >>%
1085                  /Contents (3D Object (\@MXV@mime))%
1086                }%
1087              }%
1088            }%
1089          \fi%
1090        \fi%
1091      }%
1092      \if@MXV@externalviewer%
1093        \phantom{\@MXV@box{#2}{#3}{#4}}%
1094      \else%
1095        %appearance dict dummy, to be shared by all 3D annots
1096        \ifthenelse{\isundefined{\@MXV@apdict}}{%
1097          \pdfmark{%
1098            pdfmark=/OBJ,%
1099            Raw={%
1100              /_objdef {apdict}%
1101              /type/stream%
1102            }%
1103          }%
1104          \pdfmark{%
1105            pdfmark=/PUT,%
1106            Raw={%
1107              {apdict}%
1108              ()%
1109            }%
1110          }%
1111          \xdef\@MXV@apdict{/AP << /N {apdict}>>}%
1112        }{}%
1113        %3D reference dict
1114        \if@MXV@presentation%
1115          \ifthenelse{%
1116            \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}%
1117          }{%
1118            \pdfmark{%
1119              pdfmark=/OBJ,%
1120              Raw={%
1121                /_objdef {iiiDref\the\@MXV@includes}%
1122                /type/dict%
1123              }%
1124            }%
1125            \pdfmark{%
1126              pdfmark=/PUT,%
1127              Raw={%
1128                {iiiDref\the\@MXV@includes} <<%
1129                  /Type/3DRef%
1130                  /3DD {\@MXV@iiidstream}% 3D stream object
1131                >>%
1132              }%
1133            }%
1134            \edef\@MXV@iiidstreamorref{iiiDref\the\@MXV@includes}%
1135            \@MXV@newlabel{\@MXV@label.3dref}{\@MXV@iiidstreamorref}%
1136          }{%
1137            \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}%
1138          }%
1139        \else%
1140          \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}%
1141        \fi%
1142        %annotation object of subtype `3D'
1143        \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
1144          pdfmark=/ANN,%
1145          Subtype=/3D,%
1146          Raw={%
1147            /_objdef {3Dannot\the\@MXV@includes}%
1148            /F 4%
1149            /T (\@MXV@filename)%
1150            \ifx\@MXV@@label\@empty\else%
1151              /NM (\@MXV@@label)%
1152            \fi%
1153            /Contents (3D Object (\@MXV@mime))%
1154            /P {ThisPage}%
1155            \@MXV@apdict% /AP <</N<<>>/R<<>>/D<<>>>> doesn't work here
1156            \@MXV@defaultview%
1157            \@MXV@iiidia%
1158            /3DD {\@MXV@iiidstreamorref}% 3D stream or reference object
1159            /3DA <<\@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb>>%
1160          }%
1161        }%
1162        \ifx\@MXV@@label\@empty\else%
1163          \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
1164          \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
1165        \fi%
1166      \fi%
1167    }%
1168  \fi%
1169}{}
1170
1171%settings for newly opened media players
1172\def\@MXV@settings#1#2#3#4#5#6#7{%
1173  var settings={%
1174    privateData: {%
1175      paused: false
1176    },
1177    autoPlay: false,
1178    visible: false,
1179    volume: #7
1180    #1% showUI (controls)
1181    #2% palindrome
1182    #3% repeat
1183    #4% rate
1184    #5% startAt
1185    #6% endAt
1186  };
1187}
1188
1189%JavaScript event handler routines for 2D media activation
1190\def\@MXV@events#1#2#3{% #1: playerid, #2: mouse?, #3: autoplay?
1191  var events=new app.media.Events({%
1192    %on focus change from one movie to another, events are fired in the
1193    %following order: (1) onBlur, (2) onFocus, (3) afterBlur, (4) afterFocus
1194    onBlur: function (e) {%
1195      if(focusonplayer > 0){%
1196        focusonplayer=0;
1197      }
1198    },
1199    afterBlur: function (e) {%
1200      %only resume if we click outside of any media
1201      if(focusonplayer==0){%
1202        try{
1203          e.target.settings.privateData.paused=false;
1204          e.target.play();
1205        }catch(e){}
1206      }
1207    },
1208    onFocus: function (e) {%
1209      focusonplayer=#1;
1210    },
1211    afterFocus: function (e) {%
1212      if(!e.target.isPlaying){%play on click if paused
1213        try{
1214          e.target.settings.privateData.paused=false;
1215          e.target.play();
1216          if(!e.target.isPlaying){%still not playing?!
1217            %sometimes play() fails, in particular if the movie has reached
1218            %its end before getting the focus; but this works:
1219            if(
1220              e.target.settings.startAt.time
1221              || e.target.settings.startAt.frame
1222              || e.target.settings.startAt.marker
1223              || e.target.id == 'vnd.adobe.swname:AAPL_QuickTime'
1224            ){
1225              e.target.seek(e.target.settings.startAt);
1226            }else{
1227              e.target.stop();
1228            }
1229            e.target.play();
1230          }
1231        }
1232        catch (e){}
1233      }
1234      \@MXV@if{#2}%
1235      else{%
1236        %media can only be paused if mouse option is set
1237        try{
1238          e.target.pause();
1239          e.target.settings.privateData.paused=true;
1240        }catch (e){}
1241      }
1242      \fi%
1243      \if@MXV@issound\else e.target.visible=true;\fi%
1244    },
1245    onPlay: function (e) {%
1246      e.target.settings.privateData.paused=false;
1247    },
1248    onPause: function (e) {%
1249      e.target.settings.privateData.paused=true;
1250    },
1251    afterReady: function (e) {%
1252      try{
1253        if(
1254          e.target.settings.startAt.time
1255          || e.target.settings.startAt.frame
1256          || e.target.settings.startAt.marker
1257        ){
1258          e.target.play();
1259          e.target.pause();
1260          e.target.stop();
1261          e.target.settings.privateData.paused=false;
1262          e.target.seek(e.target.settings.startAt);
1263        }
1264        \if@MXV@issound\else e.target.visible=true;\fi%
1265        \@MXV@if{#3}
1266          e.target.settings.privateData.paused=false;
1267          e.target.play();
1268        \fi
1269      }
1270      catch (e){}
1271    }
1272  });
1273}%
1274
1275%output driver specific implementations of the 2D inclusion macro
1276\ifpdf%
1277  %pdfLaTeX version
1278  \def\@MXV@includemovie#1#2#3#4{%
1279    %insert box or poster
1280    \@MXV@box{#1}{#2}{#3}%
1281    %
1282    \if@MXV@externalviewer\else%
1283      %new action dict
1284      \pdfobj reserveobjnum%
1285      \@MXV@adict=\pdflastobj%
1286      %
1287      %new additional actions dict
1288      \pdfobj reserveobjnum%
1289      \@MXV@aadict=\pdflastobj%
1290      %
1291    \fi%
1292    %embedded file entry `/EF'
1293    \if@MXV@inline%
1294      %embed the same media file only once
1295      \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{%
1296        \pdfobj stream %
1297          attr {%
1298              /Type/EmbeddedFile%
1299              /Subtype (\@MXV@mime)%
1300          }%
1301          file {#4}%
1302          \pdfrefobj\pdflastobj%
1303          \edef\@MXV@efentry{%
1304          /EF << /F \the\pdflastobj\space 0 R >>%
1305        }%
1306        \@MXV@newlabel{\pdfmdfivesum file {#4}}{\the\pdflastobj}%
1307      }{%
1308        \edef\@MXV@efentry{%
1309          /EF << /F \@MXV@getlabelvalue{\pdfmdfivesum file {#4}}\space 0 R >>%
1310        }%
1311      }%
1312    \else\def\@MXV@efentry{}\fi%
1313    %
1314    \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{%
1315      %new file specification object
1316      \pdfobj {<<%
1317        /F(#4)%
1318        \@MXV@fsentry%
1319        \@MXV@efentry%
1320        /Type/Filespec%
1321      >>}\pdfrefobj\pdflastobj%
1322      \edef\@MXV@filespec{\the\pdflastobj}%
1323    }%
1324    %
1325    \makebox[0pt][r]{\makebox[#1][l]{%
1326    %insert FileAttachment annotation
1327    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR%
1328      \boolean{@MXV@attachment}%
1329    }{%
1330      \pdfannot width #1 height #2 depth #3 {%
1331        /Subtype /FileAttachment%
1332        /F 0%
1333        /T (\@MXV@filename)%
1334        /Contents (Media File (\@MXV@mime))%
1335        \if@MXV@externalviewer%
1336          %a coloured border, as with external links, would be much nicer
1337          /Name/Paperclip%
1338          /C [1 1 1]%
1339        \else%
1340          /AP <</N<<>>/R<<>>/D<<>>>>%
1341        \fi%
1342        /FS \@MXV@filespec\space 0 R%
1343      }%
1344    }{%
1345      \if@MXV@url%
1346        %insert Link annotation, if media file is a URL
1347        \pdfannot width #1 height #2 depth #3 {%
1348          /Subtype /Link%
1349          /F 0%
1350          \if@MXV@externalviewer%
1351            \@MXV@urlattr%
1352          \else%
1353            /H /N%
1354            /Border [0 0 0]%
1355          \fi%
1356          /A <</URI (#4) /S/URI>>%
1357          /Contents (Media File (\@MXV@mime))%
1358        }%
1359      \else%
1360        %else insert Launch action for local external media file
1361        \if@MXV@inline\else%
1362          \pdfannot width #1 height #2 depth #3 {%
1363            /Subtype /Link%
1364            /F 0%
1365            \if@MXV@externalviewer%
1366              \@MXV@runattr%
1367            \else%
1368              /H /N%
1369              /Border [0 0 0]%
1370            \fi%
1371            /A <<%
1372              /F (#4)%
1373              /S /Launch%
1374            >>%
1375            /Contents (Media File (\@MXV@mime))%
1376          }%
1377        \fi%
1378      \fi%
1379    }%
1380    %
1381    \if@MXV@externalviewer\else%
1382      %annotation object of subtype `Screen'
1383      \pdfannot width #1 height #2 depth #3 {%
1384        /Subtype /Screen%
1385        /Border [0 0 0]% no border (PDF-1.1)
1386        /BS <</S/S/W 0>>% no border (PDF-1.5)
1387        /F 5% disable annot if multimedia is not available
1388        /T (\@MXV@filename)%
1389        /Contents (Media File (\@MXV@mime))%
1390        /P \@MXV@pdfpageref{@MXV@annot\the\@MXV@includes.page} 0 R%
1391        /A \the\@MXV@adict\space 0 R%
1392        /AA \the\@MXV@aadict\space 0 R%
1393        /AP <</N<<>>/R<<>>/D<<>>>>%
1394      }\edef\@MXV@screenannot{\the\pdflastannot}%
1395      %label for later annot obj number determination, to be used in
1396      %movieref's only
1397      \ifx\@MXV@@label\@empty\else%
1398        \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}%
1399        \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}%
1400      \fi%
1401      %
1402      %new media clip object of subtype `Media Clip Data' (/S/MCD)
1403      \pdfobj {<<%
1404        /D \@MXV@filespec\space 0 R%
1405        /P <</TF(TEMPACCESS)>>%
1406        /S/MCD%
1407        /CT (\@MXV@mime)%
1408      >>}\pdfrefobj\pdflastobj%
1409      %
1410      %new rendition object of subtype `Media Rendition' (/S/MR)
1411      \pdfobj {<<%
1412        /C \the\pdflastobj\space 0 R%
1413        /S/MR%
1414        /SP <</BE<</O 0.0>>>>%
1415        /P <<%
1416          \@MXV@player%
1417          /BE <<%
1418            /F 2%
1419            \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls%
1420            /D <</S /F>>%
1421          >>%
1422        >>%
1423      >>}\edef\@MXV@mediarendition{\the\pdflastobj}\pdfrefobj\pdflastobj%
1424      %label for later rendition obj number determination
1425      \ifx\@MXV@@label\@empty\else%
1426        \@MXV@labeltoaux{@MXV@\@MXV@@label.rendition}{\@MXV@mediarendition}%
1427        \@MXV@newlabel{@MXV@\@MXV@@label.rendition}{\@MXV@mediarendition}%
1428      \fi%
1429      %
1430      %action dictionary
1431      \pdfobj useobjnum \@MXV@adict {<<%
1432        /R \@MXV@mediarendition\space 0 R%
1433        /S/Rendition%
1434        /OP 0% fallback if /JS doesn't work or is empty
1435        \@MXV@activationjsentry%
1436        /AN \@MXV@screenannot\space 0 R%
1437      >>}\pdfrefobj\pdflastobj%
1438      %
1439      %create play/stop/resume/pause actions
1440      \pdfobj {<<%
1441        /R \@MXV@mediarendition\space 0 R%
1442        /S/Rendition%
1443        \@MXV@pageopenopentry% /OP fallback if /JS doesn't work
1444        \@MXV@pageopenjsentry%
1445        /AN \@MXV@screenannot\space 0 R%
1446      >>}\edef\@MXV@pageopenaction{\the\pdflastobj}\pdfrefobj\pdflastobj%
1447      %
1448      \pdfobj {<<%
1449        /R \@MXV@mediarendition\space 0 R%
1450        /S/Rendition%
1451        \@MXV@pagecloseopentry%
1452        \@MXV@pageclosejsentry%
1453        /AN \@MXV@screenannot\space 0 R%
1454      >>}\edef\@MXV@pagecloseaction{\the\pdflastobj}\pdfrefobj\pdflastobj%
1455      %
1456      %populate additional actions dictionary
1457      \pdfobj useobjnum \@MXV@aadict {<<%
1458        /PO \@MXV@pageopenaction\space 0 R%
1459        /PC \@MXV@pagecloseaction\space 0 R%
1460      >>}\pdfrefobj\pdflastobj%
1461    \fi}}%
1462  }%
1463\else%
1464  %dvips version
1465  \def\@MXV@includemovie#1#2#3#4{%
1466    %insert FileAttachment annotation
1467    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR%
1468      \boolean{@MXV@attachment}%
1469    }{%
1470      \makebox[0pt][l]{%
1471        \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{%
1472          pdfmark=/ANN,%
1473          Subtype=/FileAttachment,%
1474          Raw={%
1475            /F 0%
1476            /T (\@MXV@filename)%
1477            /Contents (Media File (\@MXV@mime))%
1478            \if@MXV@externalviewer%
1479              /Name/Paperclip%
1480              /C [1 1 1]%
1481            \else%
1482              /AP <</N<<>>/R<<>>/D<<>>>>%
1483            \fi%
1484            /FS {filespec\the\@MXV@includes}%
1485          }%
1486        }%
1487      }%
1488    }{%
1489      \if@MXV@url%
1490        %insert Link annotation, if media file is a URL
1491        \makebox[0pt][l]{%
1492          \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{%
1493            pdfmark=/ANN,%
1494            Subtype=/Link,%
1495            Raw={%
1496              /F 0%
1497              \if@MXV@externalviewer%
1498                /C [\@urlbordercolor]%
1499                /H \@pdfhighlight%
1500              \else%
1501                /H /N%
1502                /Border [0 0 0]%
1503              \fi%
1504              /Action <</URI (#4) /S/URI>>%
1505              /Contents (Media File (\@MXV@mime))%
1506            }%
1507          }%
1508        }%
1509      \else%
1510        %else insert Launch action for local external media file
1511        \if@MXV@inline\else%
1512          \makebox[0pt][l]{%
1513            \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{%
1514              pdfmark=/ANN,%
1515              Subtype=/Link,%
1516              Raw={%
1517                /F 0%
1518                \if@MXV@externalviewer%
1519                  /C [\@urlbordercolor]%
1520                  /H \@pdfhighlight%
1521                \else%
1522                  /H /N%
1523                  /Border [0 0 0]%
1524                \fi%
1525                /Action <<%
1526                  /F (#4)%
1527                  /S /Launch%
1528                >>%
1529                /Contents (Media File (\@MXV@mime))%
1530              }%
1531            }%
1532          }%
1533        \fi%
1534      \fi%
1535    }%
1536    %
1537    \if@MXV@externalviewer%
1538      \@MXV@box{#1}{#2}{#3}%
1539    \else%
1540      %annotation object of subtype `Screen'
1541      \pdfmark[\@MXV@box{#1}{#2}{#3}]{%
1542        pdfmark=/ANN,%
1543        Subtype=/Screen,%
1544        Border={0 0 0},%
1545        Raw={%
1546          /_objdef {screenannot\the\@MXV@includes}%
1547          /F 5%
1548          /T (\@MXV@filename)%
1549          /Contents (Media File (\@MXV@mime))%
1550          /BS <</S/S/W 0>>% no border (PDF-1.5)
1551          /P {ThisPage}%
1552          /AA {aadict\the\@MXV@includes}%
1553          /AP <</N<<>>/R<<>>/D<<>>>>%
1554        }%
1555      }%
1556      \ifx\@MXV@@label\@empty\else%
1557        \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
1558        \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
1559      \fi%
1560      %
1561      %entire action entry moved outside screen annotation
1562      \pdfmark{%
1563        pdfmark=/PUT,%
1564        Raw={%
1565          {screenannot\the\@MXV@includes} <<%
1566            /A <<%
1567              /R {mediarendition\the\@MXV@includes}%
1568              /S/Rendition%
1569              /OP 0% fallback, if /JS doesn't work or is empty
1570              \@MXV@activationjsentry%
1571              /AN {screenannot\the\@MXV@includes}%
1572            >>%
1573          >>%
1574        }%
1575      }%
1576      %
1577      %new rendition object of subtype `Media Rendition' (/S/MR)
1578      \pdfmark{%
1579        pdfmark=/OBJ,%
1580        Raw={%
1581          /type/dict%
1582          /_objdef {mediarendition\the\@MXV@includes}%
1583        }%
1584      }%
1585      \pdfmark{%
1586        pdfmark=/PUT,%
1587        Raw={%
1588          {mediarendition\the\@MXV@includes} <<%
1589            /C {mediaclipdata\the\@MXV@includes}%
1590            /S/MR%
1591            %screen parameters: fully transparent, hidden if audio mime type
1592            /SP <</BE<</O 0.0>>>>%
1593            /P <<%Media Play Parameters
1594              \@MXV@player%
1595              /BE <<%Parameters need only be honored by the player in
1596                  %the best effort sense
1597                /F 2%scale media's width and height to fit the
1598                   %annotation rectangle
1599                \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls%
1600                /D <</S /F>>%movie remains opened
1601              >>%
1602            >>%
1603          >>%
1604        }%
1605      }%
1606      %
1607      %new media clip object of subtype `Media Clip Data' (/S/MCD)
1608      \pdfmark{%
1609        pdfmark=/OBJ,%
1610        Raw={%
1611          /_objdef {mediaclipdata\the\@MXV@includes}%
1612          /type/dict%
1613        }%
1614      }%
1615      \pdfmark{%
1616        pdfmark=/PUT,%
1617        Raw={%
1618          {mediaclipdata\the\@MXV@includes} <<%
1619            /D {filespec\the\@MXV@includes}%
1620            /P <</TF(TEMPACCESS)>>%
1621            /S/MCD%
1622            /CT (\@MXV@mime)% mime type
1623          >>%
1624        }%
1625      }%
1626    \fi%
1627    %
1628    %new file specification object
1629    \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{%
1630      \pdfmark{%
1631        pdfmark=/OBJ,%
1632        Raw={%
1633          /_objdef {filespec\the\@MXV@includes}%
1634          /type/dict%
1635        }%
1636      }%
1637      \pdfmark{%
1638        pdfmark=/PUT,%
1639        Raw={%
1640          {filespec\the\@MXV@includes} <<%
1641            \@MXV@fsentry
1642            /F(#4)% file name
1643            /Type/Filespec%
1644          >>%
1645        }%
1646      }%
1647    }%
1648    %
1649    %embedded file entry `/EF'
1650    \if@MXV@inline%
1651      %embed the same media file only once
1652      \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{%
1653        %new stream object
1654        \pdfmark{%
1655          pdfmark=/OBJ,%
1656          Raw={%
1657            /_objdef {fstream\the\@MXV@includes}%
1658            /type/stream%
1659          }%
1660        }%
1661        \pdfmark{%
1662          pdfmark=/PUT,%
1663          Raw={%
1664            {fstream\the\@MXV@includes}%
1665            (#4) (r) file% read in file contents
1666          }%
1667        }%
1668        \pdfmark{%
1669          pdfmark=/PUT,%
1670          Raw={%
1671            {fstream\the\@MXV@includes} <<%
1672              /Type/EmbeddedFile%
1673              /Subtype(\@MXV@mime)%
1674            >>%
1675          }%
1676        }%
1677        \edef\@MXV@moviestream{fstream\the\@MXV@includes}%
1678        \@MXV@newlabel{\pdfmdfivesum file {#4}}{fstream\the\@MXV@includes}%
1679      }{%
1680        \edef\@MXV@moviestream{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}%
1681      }%
1682      % put the embedded file entry into file spec object
1683      \pdfmark{%
1684        pdfmark=/PUT,%
1685        Raw={%
1686          {filespec\the\@MXV@includes} <<%
1687            /EF << /F {\@MXV@moviestream} >>%
1688          >>%
1689        }%
1690      }%
1691    \fi%
1692    %
1693    \if@MXV@externalviewer\else%
1694      %create actions for page open/close events
1695      \pdfmark{%
1696        pdfmark=/OBJ,%
1697        Raw={%
1698          /_objdef {pageopenaction\the\@MXV@includes}%
1699          /type/dict%
1700        }%
1701      }%
1702      \pdfmark{%
1703        pdfmark=/PUT,%
1704        Raw={%
1705          {pageopenaction\the\@MXV@includes} <<%
1706            /R {mediarendition\the\@MXV@includes}%
1707            /S/Rendition%
1708            \@MXV@pageopenopentry% /OP fallback, if /JS doesn't work
1709            \@MXV@pageopenjsentry%
1710            /AN {screenannot\the\@MXV@includes}%
1711          >>%
1712        }%
1713      }%
1714      \pdfmark{%
1715        pdfmark=/OBJ,%
1716        Raw={%
1717          /_objdef {pagecloseaction\the\@MXV@includes}%
1718          /type/dict%
1719        }%
1720      }%
1721      \pdfmark{%
1722        pdfmark=/PUT,%
1723        Raw={%
1724          {pagecloseaction\the\@MXV@includes} <<%
1725            /R {mediarendition\the\@MXV@includes}%
1726            /S/Rendition%
1727            \@MXV@pagecloseopentry%
1728            \@MXV@pageclosejsentry%
1729            /AN {screenannot\the\@MXV@includes}%
1730          >>%
1731        }%
1732      }%
1733      %
1734      %create and populate additional actions dictionary, always add entries
1735      %for page open/close events
1736      \pdfmark{%
1737        pdfmark=/OBJ,%
1738        Raw={%
1739          /type/dict%
1740          /_objdef {aadict\the\@MXV@includes}%
1741        }%
1742      }%
1743      %
1744      \pdfmark{%
1745        pdfmark=/PUT,%
1746        Raw={%
1747          {aadict\the\@MXV@includes} <<%
1748            /PO {pageopenaction\the\@MXV@includes}%
1749            /PC {pagecloseaction\the\@MXV@includes}%
1750          >>%
1751        }%
1752      }%
1753    \fi%
1754  }%
1755\fi
1756
1757%definition of user command `\includemovie'
1758\newcommand{\includemovie}[4][]{%
1759  %test for hyperref package
1760  \ifpdf\else%
1761    \ifthenelse{\isundefined{\pdfmark}}{\@MXV@missing{hyperref}}{}%
1762  \fi%
1763  %
1764  \leavevmode%
1765  \@MXV@reset% all macros and options
1766  \setkeys{MXV@user}{#1}% parse options
1767  %
1768  %total height of text
1769  \@MXV@totalheight=\@MXV@height%
1770  \advance\@MXV@totalheight by \@MXV@depth%
1771  %traiselen=distance at which text is to be raised to centre it vertically
1772  %braiselen=vertical centre of media box (auxiliary measure)
1773  \@MXV@traiselen=0.5\@MXV@height%
1774  \advance\@MXV@traiselen by -0.5\@MXV@depth%
1775  %
1776  \ifthenelse{\equal{#3}{}}{% no height argument
1777    \@MXV@braiselen=0.5\@MXV@height%
1778  }{%override height of text, height argument given
1779    \@MXV@braiselen=#3%
1780    \@MXV@braiselen=0.5\@MXV@braiselen%
1781    \setlength{\@MXV@height}{#3}%
1782  }%
1783  %
1784  \ifthenelse{\equal{\@MXV@boxdepth}{}}{% no depth option given
1785    \ifthenelse{\lengthtest{\@MXV@totalheight>\@MXV@height}}{%
1786      %depth of text only taken into account, if the total height
1787      %is smaller than the height of the display box
1788      \advance\@MXV@braiselen by -0.5\@MXV@depth%
1789    }{%
1790      \@MXV@depth=0pt%
1791    }%
1792  }{%override depth of text, depth option given
1793    \setlength{\@MXV@@boxdepth}{\@MXV@boxdepth}%
1794    \advance\@MXV@braiselen by -0.5\@MXV@@boxdepth%
1795    \setlength{\@MXV@depth}{\@MXV@boxdepth}%
1796  }%
1797  %finally centre text vertically
1798  \ifthenelse{\NOT\equal{#3}{}\OR\NOT\equal{\@MXV@boxdepth}{}}{%
1799    \advance\@MXV@traiselen by -\@MXV@braiselen%
1800    \@MXV@traiselen=-\@MXV@traiselen%
1801    \savebox{\@MXV@textbox}{\raisebox{\@MXV@traiselen}[0pt][0pt]{%
1802      \usebox{\@MXV@textbox}}}%
1803  }{}%
1804  \ifthenelse{\equal{#2}{}}{}{%override horiz. dimension of text
1805    \setlength{\@MXV@width}{#2}%
1806    %centre text horizontally
1807    \savebox{\@MXV@textbox}{\makebox[\@MXV@width][c]{\usebox{\@MXV@textbox}}}%
1808  }%
1809  %
1810  %find out whether the contents should be hidden or not (for presentations)
1811  \setboolean{@MXV@hide}{false}%
1812%  \ifthenelse{\boolean{@MXV@powerdot}}{%
1813%    \ifthenelse{\boolean{pd@overlay}}{}{%
1814%      \ifthenelse{\pd@method=2}{}{%
1815%        \setboolean{@MXV@hide}{true}%
1816%      }%
1817%    }%
1818%  }{}%
1819  \ifthenelse{\boolean{@MXV@beamer}}{%
1820    \ifthenelse{\boolean{beamer@anotherslide}}{%
1821      \setboolean{@MXV@hide}{true}%
1822    }{}%
1823  }{}%
1824  %
1825  \ifthenelse{\boolean{@MXV@hide}}{%
1826    %insert whitespace instead of annot
1827    \phantom{\vrule width \@MXV@width height \@MXV@height depth \@MXV@depth}%
1828  }{%
1829    \ifthenelse{\NOT\boolean{@MXV@url}\AND\boolean{@MXV@inline}}{%
1830      \IfFileExists{#4}{}{%
1831        \PackageError{movie15}{%
1832          File `#4' cannot be opened for embedding.\MessageBreak
1833          Did you forget to set option `url' or `inline=false'?
1834        }{%
1835          Try any of the options `url' or `inline=false'!
1836        }%
1837      }%
1838    }{}%
1839    %
1840    %guess the mime type based on the filename extension
1841    \filename@parse{#4}%
1842    \ifthenelse{\equal{\@MXV@mime}{@MXV@auto}}{%
1843      \@MXV@guessmime{#4}{\filename@ext}}{}%
1844    \if\filename@ext\relax%
1845      \xdef\@MXV@filename{\filename@base}%
1846    \else%
1847      \xdef\@MXV@filename{\filename@base.\filename@ext}%
1848    \fi%
1849    \expandafter\@MXV@@issound\@MXV@mime.%
1850    %
1851    %if 3D object is not embedded inline we must use some external player :(
1852    \ifthenelse{%
1853      \boolean{@MXV@iiid}%
1854      \AND\NOT\boolean{@MXV@inline}%
1855    }{%
1856      \setboolean{@MXV@externalviewer}{true}%
1857    }{}%
1858    %
1859    %some link attributes (if hyperref not loaded)
1860    \ifthenelse{\isundefined{\@pdfborder}}{%
1861      \def\@MXV@urlattr{}%
1862      \def\@MXV@runattr{}%
1863    }{%
1864      \edef\@MXV@urlattr{%
1865        \if@MXV@beamer%
1866          /Border [1 1 1]%
1867        \else%
1868          /Border [\@pdfborder]%
1869        \fi%
1870        /C [\@urlbordercolor]%
1871        /H \@pdfhighlight%
1872      }%
1873      \edef\@MXV@runattr{%
1874        \if@MXV@beamer%
1875          /Border [1 1 1]%
1876        \else%
1877          /Border [\@pdfborder]%
1878        \fi%
1879        /C [\@runbordercolor]%
1880        /H \@pdfhighlight%
1881      }%
1882    }%
1883    %
1884    \global\advance\@MXV@includes by 1%increment counter
1885    %
1886    %label this annotation for later page number determination
1887    \@MXV@labeltoaux{@MXV@annot\the\@MXV@includes.page}{%
1888                       \noexpand\the\@MXV@page}%
1889    %
1890    %label this annotation for later annot id number determination &
1891    %check for multiply-defined labels
1892    % \@MXV@label  -->  automatic (presentation mode) or user defined label
1893    % \@MXV@@label = \@MXV@label (non presentation doc classes)
1894    % \@MXV@@label = \@MXV@label + physical page No. (presentation mode)
1895    \ifx\@MXV@label\@empty%
1896      %when used with presentation packages, annots must be labelled,
1897      %use the media file name, if no label provided
1898      \ifthenelse{\boolean{@MXV@presentation}}{%
1899        \xdef\@MXV@label{#4}%
1900      }{}%
1901    \fi%
1902    \ifx\@MXV@label\@empty\else%
1903      \ifthenelse{\boolean{@MXV@presentation}}{%
1904        %in presentation mode, the label must be extended by the physical page No.
1905        \xdef\@MXV@@label{\@MXV@label.\@MXV@getlabelvalue{@MXV@annot\the\@MXV@includes.page}}%
1906      }{%
1907        \xdef\@MXV@@label{\@MXV@label}%
1908      }%
1909    \fi%
1910    \ifx\@MXV@@label\@empty\else%
1911      \ifthenelse{%
1912        \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{undefined}%
1913        \AND%
1914        \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{%
1915                                                        \the\@MXV@includes}%
1916      }{%
1917        \PackageWarning{movie15}{%
1918          Label `\@MXV@label' multiply defined%
1919        }%
1920        \ifthenelse{\isundefined{\@MXV@multiwarning}}{%
1921          \gdef\@MXV@multiwarning{}%
1922          \AtEndDocument{%
1923            \PackageWarningNoLine{movie15}{%
1924            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak
1925            @@ There were multiply-defined labels! @@\MessageBreak
1926            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
1927          }%
1928        }{}%
1929      }{}%
1930      \if@MXV@@draft%
1931        \@MXV@labeltoaux{@MXV@\@MXV@label.draft}{true}%
1932      \else%
1933        \@MXV@labeltoaux{@MXV@\@MXV@label.draft}{false}%
1934      \fi%
1935      \@MXV@labeltoaux{@MXV@\@MXV@@label.annotid}{\the\@MXV@includes}%
1936      \if@MXV@presentation\else%
1937        \@MXV@newlabel{@MXV@\@MXV@@label.annotid}{\the\@MXV@includes}%
1938      \fi%
1939    \fi%
1940    %
1941    \ifthenelse{\boolean{@MXV@@draft}}{}{%
1942    \ifthenelse{\boolean{@MXV@externalviewer}}{%
1943      \ifx\@MXV@label\@empty\else%
1944        \@MXV@labeltoaux{@MXV@\@MXV@label.externalviewer}{true}%
1945        \@MXV@newlabel{@MXV@\@MXV@label.externalviewer}{true}%
1946      \fi%
1947    }{%
1948      %what is to be put into movie link annot depends on the following
1949      \ifx\@MXV@label\@empty\else%
1950        \@MXV@labeltoaux{@MXV@\@MXV@label.externalviewer}{false}%
1951        \@MXV@newlabel{@MXV@\@MXV@label.externalviewer}{false}%
1952      \fi%
1953      %
1954      %depending on options do content specific stuff
1955      \ifthenelse{\boolean{@MXV@iiid}}{%
1956        % #### 3D ####
1957        \if@MXV@externalviewer\else%
1958          \ifthenelse{\equal{\@MXV@iiidpalindrome}{/Subtype/Oscillating}}{%
1959            \global\multiply\@MXV@iiidrepeat by 2%
1960          }{}%
1961          \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@autoresume}}{%
1962            \def\@MXV@activation{/A/PV/AIS/L}% open 3D object, run animation
1963          }{%
1964            \if@MXV@runposter%
1965              \def\@MXV@activation{/A/PV/AIS/I}%open 3D obj but don't run animation
1966            \else%
1967              \def\@MXV@activation{/A/XA}% explicit activation by user
1968            \fi%
1969          }%
1970          \if@MXV@autostop%
1971            \def\@MXV@deactivation{/D/PI/DIS/I}%
1972          \else%
1973            \if@MXV@autopause%
1974              \def\@MXV@deactivation{/D/PI/DIS/I}%
1975            \else%
1976              \if@MXV@autoclose%
1977                \def\@MXV@deactivation{/D/PI/DIS/U}%
1978              \else%@MXV@continue
1979                \def\@MXV@deactivation{/D/PI/DIS/L}%
1980              \fi%
1981            \fi%
1982          \fi%
1983          %counter for 3D inclusion on current page
1984          \ifthenelse{%
1985            \equal{%
1986              \@MXV@getlabelvalue{@MXV@annot\the\@MXV@includes.page}%
1987            }{\@MXV@oldpage}%
1988          }{%
1989            \global\advance\@MXV@iiidoncurpage by 1%
1990          }{%
1991            \global\@MXV@iiidoncurpage=1%
1992          }%
1993          \xdef\@MXV@oldpage{\@MXV@getlabelvalue{%
1994            @MXV@annot\the\@MXV@includes.page}}%
1995        \fi%
1996        \ifx\@MXV@label\@empty\else%
1997          \@MXV@labeltoaux{@MXV@\@MXV@label.3D}{true}%
1998          \@MXV@newlabel{@MXV@\@MXV@label.3D}{true}%
1999          \@MXV@labeltoaux{@MXV@\@MXV@label.3Dlights}{\@MXV@lights}%
2000          \@MXV@newlabel{@MXV@\@MXV@label.3Dlights}{\@MXV@lights}%
2001        \fi%
2002        \ifx\@MXV@@label\@empty\else%
2003          \@MXV@labeltoaux{@MXV@\@MXV@@label.3Doncurpage}{\the\@MXV@iiidoncurpage}%
2004          \@MXV@newlabel{@MXV@\@MXV@@label.3Doncurpage}{\the\@MXV@iiidoncurpage}%
2005        \fi%
2006      }{%#### 2D ####
2007        %get the player ID
2008        \if@MXV@presentation%
2009          \ifthenelse{%
2010            \equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}{undefined}%
2011          }{%
2012            \global\advance\@MXV@players by 1%increment counter
2013          }{%
2014            \global\@MXV@players=\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}%
2015          }%
2016          \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@players}%
2017          \@MXV@newlabel{@MXV@\@MXV@label.playerid}{\the\@MXV@players}%
2018          \edef\@MXV@currplayer{\the\@MXV@players}%
2019        \else%
2020          \ifx\@MXV@label\@empty\else%
2021            \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}%
2022            \@MXV@newlabel{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}%
2023          \fi%
2024          \edef\@MXV@currplayer{\the\@MXV@includes}%
2025        \fi%
2026        %
2027        \ifx\@MXV@startat\@empty% default start position
2028          \gdef\@MXV@startat{, startAt: 0}%
2029        \fi%
2030        %write player settings to aux file
2031        \ifx\@MXV@label\@empty\else%
2032          \@MXV@labeltoaux{@MXV@\@MXV@label.mouse}{%
2033                       \if@MXV@mouse true\else false\fi}%
2034          \@MXV@labeltoaux{@MXV@\@MXV@label.showUI}{\@MXV@ctrls}%
2035          \@MXV@labeltoaux{@MXV@\@MXV@label.palindrome}{\@MXV@palindrome}%
2036          \@MXV@labeltoaux{@MXV@\@MXV@label.repeat}{\@MXV@repeat}%
2037          \@MXV@labeltoaux{@MXV@\@MXV@label.rate}{\@MXV@rate}%
2038          \@MXV@labeltoaux{@MXV@\@MXV@label.startAt}{\@MXV@startat}%
2039          \@MXV@labeltoaux{@MXV@\@MXV@label.endAt}{\@MXV@endat}%
2040          \@MXV@labeltoaux{@MXV@\@MXV@label.volume}{\@MXV@volume}%
2041          \@MXV@labeltoaux{@MXV@\@MXV@label.autoplay}{%
2042                    \if@MXV@autoplay true\else false\fi}%
2043          \@MXV@labeltoaux{@MXV@\@MXV@label.3D}{false}%
2044          \@MXV@labeltoaux{@MXV@\@MXV@label.issound}{%
2045                    \if@MXV@issound true\else false\fi}%
2046          %
2047          \@MXV@newlabel{@MXV@\@MXV@label.mouse}{%
2048                       \if@MXV@mouse true\else false\fi}%
2049          \@MXV@newlabel{@MXV@\@MXV@label.showUI}{\@MXV@ctrls}%
2050          \@MXV@newlabel{@MXV@\@MXV@label.palindrome}{\@MXV@palindrome}%
2051          \@MXV@newlabel{@MXV@\@MXV@label.repeat}{\@MXV@repeat}%
2052          \@MXV@newlabel{@MXV@\@MXV@label.rate}{\@MXV@rate}%
2053          \@MXV@newlabel{@MXV@\@MXV@label.startAt}{\@MXV@startat}%
2054          \@MXV@newlabel{@MXV@\@MXV@label.endAt}{\@MXV@endat}%
2055          \@MXV@newlabel{@MXV@\@MXV@label.volume}{\@MXV@volume}%
2056          \@MXV@newlabel{@MXV@\@MXV@label.autoplay}{%
2057                    \if@MXV@autoplay true\else false\fi}%
2058          \@MXV@newlabel{@MXV@\@MXV@label.3D}{false}%
2059          \@MXV@newlabel{@MXV@\@MXV@label.issound}{%
2060                    \if@MXV@issound true\else false\fi}%
2061          %
2062        \fi%
2063        %
2064        \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@runposter}}{%
2065          \xdef\@MXV@pageopenopentry{/OP 4}%
2066        }{%
2067          \if@MXV@autoresume%
2068            \xdef\@MXV@pageopenopentry{/OP 3}%
2069          \else%
2070            \xdef\@MXV@pageopenopentry{/OP 2}%
2071          \fi%
2072        }%
2073        %
2074        \if@MXV@autostop%
2075          \xdef\@MXV@pagecloseopentry{/OP 1}%
2076        \else%
2077          \if@MXV@autopause%
2078            \xdef\@MXV@pagecloseopentry{/OP 2}%
2079          \else%
2080            \if@MXV@autoclose%
2081              \xdef\@MXV@pagecloseopentry{/OP 1}%
2082            \else% @MXV@continue
2083              \xdef\@MXV@pagecloseopentry{/OP 3}%
2084            \fi%
2085          \fi%
2086        \fi%
2087        %
2088        %JavaScripts for playback control
2089        %script for page invisible event
2090        \if@MXV@autopause%
2091          \xdef\@MXV@pageclosejsentry{%
2092            /JS (
2093              try{%
2094                if(player\@MXV@currplayer.isPlaying){%
2095                  player\@MXV@currplayer.pause();
2096                  player\@MXV@currplayer.settings.privateData.paused=true;
2097                }
2098                focusonplayer=-1; %page change
2099                player\@MXV@currplayer.visible=false;
2100              }
2101              catch(e){}
2102            )%
2103          }%
2104        \else%
2105          \if@MXV@autostop%
2106            \xdef\@MXV@pageclosejsentry{%
2107              /JS (
2108                try{%
2109                  player\@MXV@currplayer.settings.privateData.paused=false;
2110                  %players tend to be bugged, always stop from playing state
2111                  if(!player\@MXV@currplayer.isPlaying){
2112                    player\@MXV@currplayer.play();
2113                  }
2114                  player\@MXV@currplayer.stop();
2115                  if(
2116                    player\@MXV@currplayer.settings.startAt.time
2117                    || player\@MXV@currplayer.settings.startAt.frame
2118                    || player\@MXV@currplayer.settings.startAt.marker
2119                    || player\@MXV@currplayer.id ==
2120                       'vnd.adobe.swname:AAPL_QuickTime'
2121                  ){
2122                    player\@MXV@currplayer.seek(%
2123                      player\@MXV@currplayer.settings.startAt);
2124                  }
2125                  focusonplayer=-1;
2126                  player\@MXV@currplayer.visible=false;
2127                }
2128                catch(e){}
2129              )%
2130            }%
2131          \else%
2132            \if@MXV@autoclose%
2133              \xdef\@MXV@pageclosejsentry{%
2134                /JS (
2135                  try{%
2136                    player\@MXV@currplayer.close(app.media.closeReason.general);
2137                    focusonplayer=-1; %page change
2138                    player\@MXV@currplayer.visible=false;
2139                  }
2140                  catch(e){}
2141                )%
2142              }%
2143            \else%
2144              \xdef\@MXV@pageclosejsentry{%@MXV@continue
2145                /JS (
2146                  try{%
2147                    focusonplayer=-1; %page change
2148                    player\@MXV@currplayer.visible=false;
2149                  }
2150                  catch(e){}
2151                )%
2152              }%
2153            \fi%
2154          \fi%
2155        \fi%
2156        %
2157        %script for activation/resume on page open event
2158        \xdef\@MXV@pageopenjsentry{%
2159          /JS (
2160            try{%
2161              if(player\@MXV@currplayer.isOpen){%
2162                %drag the player on the current slide (presentation mode)
2163                player\@MXV@currplayer.page=this.pageNum;
2164                %... and make it visible
2165                \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi%
2166                %
2167                %start or resume media which have autoplay option set;
2168                %also resume paused media which have autoresume option set
2169                \if@MXV@autoplay%
2170                  player\@MXV@currplayer.settings.privateData.paused=false;
2171                  player\@MXV@currplayer.play();
2172                  if(!player\@MXV@currplayer.isPlaying){% still not playing?!
2173                    if(
2174                      player\@MXV@currplayer.settings.startAt.time
2175                      || player\@MXV@currplayer.settings.startAt.frame
2176                      || player\@MXV@currplayer.settings.startAt.marker
2177                      || player\@MXV@currplayer.id=='vnd.adobe.swname:AAPL_QuickTime'
2178                    ){
2179                      player\@MXV@currplayer.seek(
2180                        player\@MXV@currplayer.settings.startAt);
2181                    }else{
2182                      player\@MXV@currplayer.stop();
2183                    }
2184                    player\@MXV@currplayer.play();
2185                  }
2186                \else%
2187                  \if@MXV@autoresume%
2188                    if(player\@MXV@currplayer.settings.privateData.paused){%
2189                      player\@MXV@currplayer.settings.privateData.paused=false;
2190                      player\@MXV@currplayer.play();
2191                      if(!player\@MXV@currplayer.isPlaying){%
2192                        if(
2193                          player\@MXV@currplayer.settings.startAt.time
2194                          || player\@MXV@currplayer.settings.startAt.frame
2195                          || player\@MXV@currplayer.settings.startAt.marker
2196                          || player\@MXV@currplayer.id ==
2197                             'vnd.adobe.swname:AAPL_QuickTime'
2198                        ){
2199                          player\@MXV@currplayer.seek(%
2200                            player\@MXV@currplayer.settings.startAt);
2201                        }else{
2202                          player\@MXV@currplayer.stop();%
2203                        }
2204                        player\@MXV@currplayer.play();
2205                      }
2206                    }
2207                  \fi%
2208                \fi%
2209              }
2210              else{%
2211                throw 'isClosed';
2212              }
2213            }
2214            catch(e){%
2215              \@MXV@if{\if@MXV@autoplay true\else\if@MXV@runposter true\else %
2216                                                                   false\fi\fi}%
2217                if(focusonplayer==undefined){%
2218                  var focusonplayer=0; %shared by all annots
2219                }
2220                \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
2221                     {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
2222                \@MXV@events{\@MXV@currplayer}%
2223                  {\if@MXV@mouse true\else false\fi}%
2224                  {\if@MXV@autoplay true\else false\fi}%
2225                var player\@MXV@currplayer=app.media.openPlayer({%
2226                  settings: settings,
2227                  events: events
2228                });
2229              \fi%
2230            }%
2231          )
2232        }%
2233        %
2234        %script for normal activation by mouse click
2235        \xdef\@MXV@activationjsentry{%
2236          /JS (
2237		    app.focusRect=true;%
2238            if(focusonplayer==undefined){%
2239              var focusonplayer=0; %shared by all annots
2240            }
2241            \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
2242                 {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
2243            \@MXV@events{\@MXV@currplayer}{\if@MXV@mouse true\else false\fi}%
2244                                                                        {true}%
2245            var player\@MXV@currplayer=app.media.openPlayer({%
2246              settings: settings,
2247              events: events
2248            });
2249          )
2250        }%
2251      }%
2252    }%
2253    }% draft?
2254    %
2255    %insert link target, if media has been labelled
2256    \ifthenelse{\NOT\equal{\@MXV@@label}{}}{%
2257      \raisebox{\@MXV@height}{%
2258        \ifpdf%
2259          \pdfdest name {@MXV@\@MXV@@label} xyz %
2260        \else%
2261          \hypertarget{@MXV@\@MXV@@label}{}%
2262        \fi%
2263      }%
2264    }{}%
2265    %
2266    \ifthenelse{\boolean{@MXV@@draft}}{%
2267      \makebox[0pt][l]{\usebox{\@MXV@textbox}}%
2268      \@MXV@draftbox{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}%
2269    }{%
2270      %insert textbox, obscured by poster
2271      \ifthenelse{\boolean{@MXV@boxopt}\AND\NOT\boolean{@MXV@textoverposter}}{%
2272          \makebox[0pt][l]{\usebox{\@MXV@textbox}}%
2273      }{}%
2274      %
2275      %insert annotation
2276      \ifthenelse{\boolean{@MXV@iiid}}{%
2277        \edef\@MXV@iiidopt{[\@MXV@iiidopt]}%
2278        \expandafter\@MXV@includeiiid\@MXV@iiidopt{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}%
2279      }{%
2280        \@MXV@includemovie{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}%
2281      }%
2282      %
2283      %insert textbox, overprinting the poster
2284      \ifthenelse{\boolean{@MXV@boxopt}\AND\boolean{@MXV@textoverposter}}{%
2285          \makebox[0pt][r]{\usebox{\@MXV@textbox}}%
2286      }{}%
2287    }%
2288  }%
2289}
2290
2291%for remote control of media
2292\newcommand\movieref[3][]{%
2293  \ifpdf\else%
2294    \ifthenelse{\isundefined{\pdfmark}}{\@MXV@missing{hyperref}}{}%
2295  \fi%
2296  \leavevmode%
2297  % save text argument
2298  \savebox{\@MXV@textbox}{\ifHy@colorlinks\color{\@linkcolor}\fi#3}%
2299  %
2300  %find out whether the contents should be hidden or not (for presentations)
2301  \setboolean{@MXV@hide}{false}%
2302%  \ifthenelse{\boolean{@MXV@powerdot}}{%
2303%    \ifthenelse{\boolean{pd@overlay}}{}{%
2304%      \ifthenelse{\pd@method=2}{}{%
2305%        \setboolean{@MXV@hide}{true}%
2306%      }%
2307%    }%
2308%  }{}%
2309  \ifthenelse{\boolean{@MXV@beamer}}{%
2310    \ifthenelse{\boolean{beamer@anotherslide}}{%
2311      \setboolean{@MXV@hide}{true}%
2312    }{}%
2313  }{}%
2314  %
2315  \ifthenelse{\boolean{@MXV@hide}}{%
2316    %put whitespace instead of link annot
2317    \phantom{\usebox{\@MXV@textbox}}%
2318  }{%
2319    \@MXV@reset%
2320    %
2321    \xdef\@MXV@label{#2}%
2322    %
2323    \global\advance\@MXV@links by 1%increment link counter
2324    %
2325    %label this link for later page number determination
2326    \@MXV@labeltoaux{@MXV@link\the\@MXV@links.page}{\noexpand\the\@MXV@page}%
2327    %
2328    \ifthenelse{\boolean{@MXV@presentation}}{%
2329      %in presentation mode the label must be extended by the physical page No.
2330      \xdef\@MXV@@label{\@MXV@label.\@MXV@getlabelvalue{@MXV@link\the\@MXV@links.page}}%
2331    }{%
2332      \xdef\@MXV@@label{\@MXV@label}%
2333    }%
2334    %
2335    %check if label is defined at all
2336    \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{undefined}}{%
2337      \usebox{\@MXV@textbox}% write out text box
2338      \PackageWarning{movie15}{%
2339        Reference `\@MXV@label' on page \thepage \space undefined%
2340      }%
2341      \ifthenelse{\isundefined{\@MXV@undefwarning}}{%
2342        \gdef\@MXV@undefwarning{}%
2343        \AtEndDocument{%
2344          \PackageWarningNoLine{movie15}{%
2345          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak%
2346          @@ There were undefined references! @@\MessageBreak%
2347          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
2348        }%
2349      }{}%
2350    }{%
2351      \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.draft}}{true}}{%
2352        \setboolean{@MXV@@draft}{true}% if the screen annotation is in draft mode
2353      }{}%
2354      \if@MXV@@draft\else%
2355      \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.externalviewer}}{true}}{%
2356        \setboolean{@MXV@externalviewer}{true}%
2357      }{%
2358        \setboolean{@MXV@externalviewer}{false}%
2359      }%
2360      \if@MXV@externalviewer\else%
2361        %movieref used in 3D context?
2362        \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3D}}{true}}{%
2363          \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
2364            \setboolean{@MXV@iiid}{true}%
2365          }{%
2366            \@MXV@neediiiD%
2367          }%
2368        }{}%
2369        %
2370        %actions completely different in 3D & 2D context
2371        \ifthenelse{\boolean{@MXV@iiid}}{% #### 3D ####
2372          %retrieve default lighting scheme
2373          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dlights}}{undefined}}{%
2374            \edef\@MXV@lights{}%
2375          }{%
2376            \edef\@MXV@lights{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dlights}}%
2377          }%
2378          \setkeys{MXV@user}{#1}%
2379          \if@MXV@defaultviewprovided% define a new view,
2380            %using any of the coo, c2c, roo, caa options
2381            \xdef\@MXV@xname{}%
2382            \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}%
2383            \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix
2384            \@MXV@viewobj% create pdf object of 3D view
2385            \edef\@MXV@iiidview{\@MXV@@viewobj}%
2386          %else use the indexed view specified by option `3Dviewindex'
2387          \fi%
2388          %
2389          %create JavaScript (options 3Djscript, 3Dcalculate, 3Dgetview)
2390          \ifthenelse{\NOT\equal{\@MXV@jscriptiiidfile}{}%
2391                      \OR\NOT\equal{\@MXV@calc}{}%
2392                      \OR\boolean{@MXV@iiidgetview}%
2393          }{%
2394            \edef\@MXV@linkjscriptiiid{%
2395              try{%
2396                %fill hash (annot3D) with refs to Annot3D objects
2397                annot3D['\@MXV@label']=getAnnots3D(%
2398                  \@MXV@getlabelvalue{%
2399                    @MXV@annot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}.page%
2400                  }-1%
2401                )[\@MXV@getlabelvalue{@MXV@\@MXV@@label.3Doncurpage}-1];%
2402                annot3D['\@MXV@label'].activated=true;%
2403              }catch(e){%
2404                try{%
2405                  annot3D=new Array;%
2406                  annot3D['\@MXV@label']=getAnnots3D(%
2407                    \@MXV@getlabelvalue{%
2408                      @MXV@annot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}.page%
2409                    }-1%
2410                  )[\@MXV@getlabelvalue{@MXV@\@MXV@@label.3Doncurpage}-1];%
2411                  annot3D['\@MXV@label'].activated=true;%
2412                }catch(e){%
2413                  var spc=String.fromCharCode(32);%
2414                  app.alert('3D' + spc + 'annotation' + spc + 'could' + spc +%
2415                  'not' + spc + 'be' + spc + 'activated!');%
2416                }%
2417              }%
2418            }%
2419            \if@MXV@iiidgetview%
2420              \edef\@MXV@linkjscriptiiid{%
2421                \@MXV@linkjscriptiiid
2422                try{
2423                  %JavaScript to print the camera settings of the current view
2424                  var camera=annot3D['\@MXV@label'].context3D.scene.cameras.getByIndex(0);%
2425                  var coo=camera.targetPosition;%
2426                  var c2c=camera.position.subtract(coo);%
2427                  var roo=c2c.length;%
2428                  c2c.normalize();%
2429                  %
2430                  %assemble result string
2431                  %{<coo_x> <coo_y> <coo_z>}{<c2c_x> <c2c_y> <c2c_z>}{<roo>}{<aac>}
2432                  var spc=String.fromCharCode(32);%
2433                  var res='{';%
2434                  var x = (Math.abs(coo.x) < 1e-18 ? 0 : coo.x);%
2435                  var y = (Math.abs(coo.y) < 1e-18 ? 0 : coo.y);%
2436                  var z = (Math.abs(coo.z) < 1e-18 ? 0 : coo.z);%
2437                  if(Math.sqrt(x*x + y*y + z*z) > 0){%
2438                    res+=util.printf('\%s' + spc + '\%s' + spc + '\%s',%
2439                        (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?%
2440                          util.printf('\%.18f', x): x),%
2441                        (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?%
2442                          util.printf('\%.18f', y): y),%
2443                        (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?%
2444                          util.printf('\%.18f', z): z)%
2445                    );%
2446                  }%
2447                  res+='}{';%
2448                  x = (Math.abs(c2c.x) < 1e-18 ? 0 : c2c.x);%
2449                  y = (Math.abs(c2c.y) < 1e-18 ? 0 : c2c.y);%
2450                  z = (Math.abs(c2c.z) < 1e-18 ? 0 : c2c.z);%
2451                  if(!(x==0 && y==-1 && z==0)){%
2452                    res+=util.printf('\%s' + spc + '\%s' + spc + '\%s',%
2453                        (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?%
2454                          util.printf('\%.18f', x): x),%
2455                        (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?%
2456                          util.printf('\%.18f', y): y),%
2457                        (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?%
2458                          util.printf('\%.18f', z): z)%
2459                    );%
2460                  }%
2461                  res+='}{';%
2462                  if(roo > 0.11e-17){%
2463                    res+=util.printf('\%s',%
2464                      (roo < 1.001e-6 ? util.printf('\%.18f', roo): roo)%
2465                    );%
2466                  }%
2467                  res+='}{';%
2468                  %determine the camera roll (camera.roll is bugged)
2469                  %camera up-vector from camera.up, the latter being the positional vector
2470                  %of the actual camera up-vector tip
2471                  var up = camera.up.subtract(camera.position);%
2472                  up.normalize();%
2473                  %find the camera up-vector up0, that corresponds to zero roll
2474                  %(Gram-Schmitt orthogonalisation)
2475                  var worldup=new annot3D['\@MXV@label'].context3D.Vector3();%
2476                  worldup.set(0,0,1);%
2477                  var out=c2c.scale(-1);%
2478                  var up0=worldup.subtract(out.scale(out.dot(worldup)));%
2479                  up0.normalize();%
2480                  var up0xup=up0.cross(up);%
2481                  var roll=0;%
2482                  if(up0xup.length>0){%
2483                    up0xup.normalize();%
2484                    var up0dotup=up.dot(up0);%
2485                    up0dotup=(Math.abs(up0dotup) > 1 ? Math.round(up0dotup) : up0dotup);%
2486                    %compute the angle between camera up and up0 vectors
2487                    roll=Math.acos(up0dotup)*180/Math.PI*out.dot(up0xup);%
2488                  }%
2489                  if(util.printf('\%.5f', roll)!=0){%
2490                    res+=util.printf('\%s', roll);%
2491                  }%
2492                  res+='}{';%
2493                  aac=camera.fov * 180/Math.PI;%
2494                  if(util.printf('\%.5f', aac)!=30){%
2495                    res+=util.printf('\%s',%
2496                      (Math.abs(aac) < 1.001e-6 ? util.printf('\%.18f', aac): aac)%
2497                    );%
2498                  }%
2499                  res+='}';%
2500                  %open pop-up displaying the result string
2501                  var settings={%
2502                    initialize: function(dialog) {%
2503                      dialog.load({%
2504                        'text': res%
2505                      });%
2506                    },%
2507                    description: {%
2508                      name: 'Current' + spc + '3D' + spc + 'Camera' + spc + 'Settings',%
2509                      elements: [%
2510                          {%
2511                            type: 'static_text',%
2512                            name: 'Add' + spc + 'the' + spc + 'following' + spc + 'line' + spc +%
2513                                  'to' + spc + 'a' + spc + 'file' + spc + 'of' + spc +%
2514                                  'predefined' + spc + 'views.' + spc +%
2515                                  '(See' + spc + 'option' + spc + '3Dviews!)'%
2516                          },%
2517                          {%
2518                            type: 'edit_text',%
2519                            item_id: 'text',%
2520                            alignment: 'align_fill',%
2521                            readonly: false%
2522                          },%
2523                          {%
2524                            type: 'ok',%
2525                            ok_name: 'Close'%
2526                          }%
2527                      ]%
2528                    }%
2529                  };%
2530                  app.execDialog(settings);%
2531                }catch(e){%
2532                    var spc=String.fromCharCode(32);%
2533                    app.alert('Error' + spc + 'while' + spc + 'executing' + spc +%
2534                    '3Dgetview:' + spc + e);%
2535                }%
2536              }%
2537            \fi%
2538            \ifx\@MXV@calc\@empty\else%
2539              \edef\@MXV@linkjscriptiiid{%
2540                \@MXV@linkjscriptiiid
2541                try{
2542                  %constructor for doubly linked list
2543                  function List(){%
2544                    this.first_node=null;%
2545                    this.last_node=new Node(undefined);%
2546                  }%
2547                  List.prototype.push_back=function(x){%
2548                    var new_node=new Node(x);%
2549                    if(this.first_node==null){%
2550                      this.first_node=new_node;%
2551                      new_node.prev=null;%
2552                    }else{%
2553                      new_node.prev=this.last_node.prev;%
2554                      new_node.prev.next=new_node;%
2555                    }%
2556                    new_node.next=this.last_node;%
2557                    this.last_node.prev=new_node;%
2558                  };%
2559                  List.prototype.move_to_front=function(it){%
2560                    var node=it.get();%
2561                    if(node.next!=null && node.prev!=null){%
2562                      node.next.prev=node.prev;%
2563                      node.prev.next=node.next;%
2564                      node.prev=null;%
2565                      node.next=this.first_node;%
2566                      this.first_node.prev=node;%
2567                      this.first_node=node;%
2568                    }%
2569                  };%
2570                  List.prototype.begin=function(){%
2571                    var i=new Iterator();%
2572                    i.target=this.first_node;%
2573                    return(i);%
2574                  };%
2575                  List.prototype.end=function(){%
2576                    var i=new Iterator();%
2577                    i.target=this.last_node;%
2578                    return(i);%
2579                  };%
2580                  function Iterator(it){%
2581                    if( it!=undefined ){%
2582                      this.target=it.target;%
2583                    }else {%
2584                      this.target=null;%
2585                    }%
2586                  }%
2587                  Iterator.prototype.set=function(it){this.target=it.target;};%
2588                  Iterator.prototype.get=function(){return(this.target);};%
2589                  Iterator.prototype.deref=function(){return(this.target.data);};%
2590                  Iterator.prototype.incr=function(){%
2591                    if(this.target.next!=null){this.target=this.target.next;}%
2592                  };%
2593                  %constructor for node objects that populate the linked list
2594                  function Node(x){%
2595                    this.prev=null;%
2596                    this.next=null;%
2597                    this.data=x;%
2598                  }%
2599                  function sqr(r){return(r*r);}%helper function
2600                  %The following code borrows heavily from Bernd Gaertners `Miniball' software,
2601                  %originally written in C++, for computing the smallest enclosing ball of a
2602                  %set of points; see: http://www.inf.ethz.ch/personal/gaertner/miniball.html
2603                  function Basis(){%
2604                    this.m=0;%
2605                    this.q0=new Array(3);%
2606                    this.z=new Array(4);%
2607                    this.f=new Array(4);%
2608                    this.v=new Array(new Array(3), new Array(3), new Array(3), new Array(3));%
2609                    this.a=new Array(new Array(3), new Array(3), new Array(3), new Array(3));%
2610                    this.c=new Array(new Array(3), new Array(3), new Array(3), new Array(3));%
2611                    this.sqr_r=new Array(4);%
2612                    this.current_c=this.c[0];%
2613                    this.current_sqr_r=0;%
2614                    this.reset();%
2615                  }%
2616                  Basis.prototype.center=function(){return(this.current_c);};%
2617                  Basis.prototype.size=function(){return(this.m);};%
2618                  Basis.prototype.pop=function(){--this.m;};%
2619                  Basis.prototype.excess=function(p){%
2620                    var e=-this.current_sqr_r;%
2621                    for(var k=0;k<3;++k){%
2622                      e+=sqr(p[k]-this.current_c[k]);%
2623                    }%
2624                    return(e);%
2625                  };%
2626                  Basis.prototype.reset=function(){%
2627                    this.m=0;%
2628                    for(var j=0;j<3;++j){%
2629                      this.c[0][j]=0;%
2630                    }%
2631                    this.current_c=this.c[0];%
2632                    this.current_sqr_r=-1;%
2633                  };%
2634                  Basis.prototype.push=function(p){%
2635                    var i, j;%
2636                    var eps=1e-32;%
2637                    if(this.m==0){%
2638                      for(i=0;i<3;++i){%
2639                        this.q0[i]=p[i];%
2640                      }%
2641                      for(i=0;i<3;++i){%
2642                        this.c[0][i]=this.q0[i];%
2643                      }%
2644                      this.sqr_r[0]=0;%
2645                    }else {%
2646                      for(i=0;i<3;++i){%
2647                        this.v[this.m][i]=p[i]-this.q0[i];%
2648                      }%
2649                      for(i=1;i<this.m;++i){%
2650                        this.a[this.m][i]=0;%
2651                        for(j=0;j<3;++j){%
2652                          this.a[this.m][i]+=this.v[i][j]*this.v[this.m][j];%
2653                        }%
2654                        this.a[this.m][i]*=(2/this.z[i]);%
2655                      }%
2656                      for(i=1;i<this.m;++i){%
2657                        for(j=0;j<3;++j){%
2658                          this.v[this.m][j]-=this.a[this.m][i]*this.v[i][j];%
2659                        }%
2660                      }%
2661                      this.z[this.m]=0;%
2662                      for(j=0;j<3;++j){%
2663                        this.z[this.m]+=sqr(this.v[this.m][j]);%
2664                      }%
2665                      this.z[this.m]*=2;%
2666                      if(this.z[this.m]<eps*this.current_sqr_r){%
2667                        return(false);%
2668                      }%
2669                      var e=-this.sqr_r[this.m-1];%
2670                      for(i=0;i<3;++i){%
2671                        e+=sqr(p[i]-this.c[this.m-1][i]);%
2672                      }%
2673                      this.f[this.m]=e/this.z[this.m];%
2674                      for(i=0;i<3;++i){%
2675                        this.c[this.m][i]=this.c[this.m-1][i]+this.f[this.m]*this.v[this.m][i];%
2676                      }%
2677                      this.sqr_r[this.m]=this.sqr_r[this.m-1]+e*this.f[this.m]/2;%
2678                    }%
2679                    this.current_c=this.c[this.m];%
2680                    this.current_sqr_r=this.sqr_r[this.m];%
2681                    ++this.m;%
2682                    return(true);%
2683                  };%
2684                  function Miniball(){%
2685                    this.L=new List();%
2686                    this.B=new Basis();%
2687                    this.support_end=new Iterator();%
2688                  }%
2689                  Miniball.prototype.mtf_mb=function(it){%
2690                    var i=new Iterator(it);%
2691                    this.support_end.set(this.L.begin());%
2692                    if((this.B.size())==4){return;}%
2693                    for(var k=new Iterator(this.L.begin());k.get()!=i.get();){%
2694                      var j=new Iterator(k);%
2695                      k.incr();%
2696                      if(this.B.excess(j.deref()) > 0){%
2697                        if(this.B.push(j.deref())){%
2698                          this.mtf_mb(j);%
2699                          this.B.pop();%
2700                          if(this.support_end.get()==j.get()){%
2701                            this.support_end.incr();%
2702                          }%
2703                          this.L.move_to_front(j);%
2704                        }%
2705                      }%
2706                    }%
2707                  };%
2708                  Miniball.prototype.check_in=function(b){%
2709                    this.L.push_back(b);%
2710                  };%
2711                  Miniball.prototype.build=function(){%
2712                    this.B.reset();%
2713                    this.support_end.set(this.L.begin());%
2714                    this.mtf_mb(this.L.end());%
2715                  };%
2716                  Miniball.prototype.center=function(){%
2717                    return(this.B.center());%
2718                  };%
2719                  Miniball.prototype.radius=function(){%
2720                    return(Math.sqrt(this.B.current_sqr_r));%
2721                  };%
2722                  %create Miniball object
2723                  var mb=new Miniball();%
2724                  %aperture angle of the virtual camera
2725                  var aac=\@MXV@calc;%
2726                  %list of mesh nodes
2727                  var meshes=annot3D['\@MXV@label'].context3D.scene.meshes;%
2728                  %auxiliary vectors
2729                  var dir=new annot3D['\@MXV@label'].context3D.Vector3();%
2730                  var up=new annot3D['\@MXV@label'].context3D.Vector3();%
2731                  var corner=new annot3D['\@MXV@label'].context3D.Vector3();%
2732                  %auxiliary 4x4 matrix
2733                  var bbox4x4=new annot3D['\@MXV@label'].context3D.Matrix4x4();%
2734                  %iterate over all mesh nodes in the scene
2735                  for(i=0;i<meshes.count;i++){%
2736                    var mesh=meshes.getByIndex(i);%
2737                    %get the bbox of the mesh (local coordinates)
2738                    var bbox=mesh.computeBoundingBox();%
2739                    %local to parent transformation matrix
2740                    var trans=mesh.transform.transpose;%
2741                    %build local to world transformation matrix by recursively
2742                    %multiplying the parent's transf. matrix on the left
2743                    var parent=mesh.parent;%
2744                    while(parent.transform){%
2745                      trans=parent.transform.transpose.multiply(trans);%
2746                      parent=parent.parent;%
2747                    }%
2748                    %transform the local bounding box corner coordinates to
2749                    %world coordinates for bounding sphere determination;
2750                    %Matrix4x4 method transformDirection(<Vector3>) seems
2751                    %to be bugged, therefore we must resort to the
2752                    %multiply(<Matrix4x4>) method using an auxiliary matrix
2753                    %which contains the local bounding box corner coordinates
2754                    %
2755                    %auxiliary matrix from bbox.min coordinates
2756                    bbox4x4.setView(bbox.min, dir, up);%
2757                    %transform to world coordinates
2758                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2759                    %extract the transformed coordinates
2760                    corner.set(bbox4x4.transpose.translation);%
2761                    %check-in corner position into Miniball
2762                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2763                    %the same procedure with bbox.max
2764                    bbox4x4.setView(bbox.max, dir, up);%
2765                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2766                    corner.set(bbox4x4.transpose.translation);%
2767                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2768                    %and with all remaining 6 bbox corners
2769                    corner.set(bbox.min.x, bbox.max.y, bbox.max.z);%
2770                    bbox4x4.setView(corner, dir, up);%
2771                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2772                    corner.set(bbox4x4.transpose.translation);%
2773                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2774                    corner.set(bbox.min.x, bbox.min.y, bbox.max.z);%
2775                    bbox4x4.setView(corner, dir, up);%
2776                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2777                    corner.set(bbox4x4.transpose.translation);%
2778                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2779                    corner.set(bbox.min.x, bbox.max.y, bbox.min.z);%
2780                    bbox4x4.setView(corner, dir, up);%
2781                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2782                    corner.set(bbox4x4.transpose.translation);%
2783                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2784                    corner.set(bbox.max.x, bbox.min.y, bbox.min.z);%
2785                    bbox4x4.setView(corner, dir, up);%
2786                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2787                    corner.set(bbox4x4.transpose.translation);%
2788                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2789                    corner.set(bbox.max.x, bbox.min.y, bbox.max.z);%
2790                    bbox4x4.setView(corner, dir, up);%
2791                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2792                    corner.set(bbox4x4.transpose.translation);%
2793                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2794                    corner.set(bbox.max.x, bbox.max.y, bbox.min.z);%
2795                    bbox4x4.setView(corner, dir, up);%
2796                    bbox4x4=trans.multiply(bbox4x4.transpose);%
2797                    corner.set(bbox4x4.transpose.translation);%
2798                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
2799                  }%
2800                  %compute the smallest enclosing bounding sphere
2801                  mb.build();%
2802                  %bounding sphere centre
2803                  var coo=new annot3D['\@MXV@label'].context3D.Vector3();%
2804                  coo.set((mb.center())[0], (mb.center())[1], (mb.center())[2]);%
2805                  %radius of orbit
2806                  var roo=mb.radius()/ Math.sin(aac * Math.PI/ 360.);%
2807                  %result string
2808                  var res='';%
2809                  var spc=String.fromCharCode(32);%
2810                  if(aac!=30){%
2811                    res+=util.printf('3Daac=\%s,' + spc,%
2812                      (Math.abs(aac) < 1.001e-6 && Math.abs(aac) > 0 ?%
2813                        util.printf('\%.18f', aac): aac)%
2814                    );%
2815                  }%
2816                  if(coo.length){%
2817                    res+=util.printf( '3Dcoo=\%s' + spc + '\%s' + spc + '\%s,'%
2818                        + spc,%
2819                        (Math.abs(coo.x) < 1.001e-6 && Math.abs(coo.x) > 0 ?%
2820                          util.printf('\%.18f', coo.x): coo.x),%
2821                        (Math.abs(coo.y) < 1.001e-6 && Math.abs(coo.y) > 0 ?%
2822                          util.printf('\%.18f', coo.y): coo.y),%
2823                        (Math.abs(coo.z) < 1.001e-6 && Math.abs(coo.z) > 0 ?%
2824                          util.printf('\%.18f', coo.z): coo.z)%
2825                    );%
2826                  }%
2827                  res+=util.printf(%
2828                    '3Droo=\%s,' + spc, (roo < 1.001e-6 ? util.printf('\%.18f', roo): roo)
2829                  );%
2830                  var settings={%
2831                    initialize: function(dialog){%
2832                      dialog.load({%
2833                        'text': res%
2834                      });%
2835                    },%
2836                    description: {%
2837                      name: '3D' + spc + 'Camera' + spc + 'Settings',%
2838                      elements: [%
2839                        {%
2840                          type: 'static_text',%
2841                          name: 'Copy' + spc + 'and' + spc + 'paste' + spc +%
2842                                'the' + spc + 'following' + spc + 'to' + spc +%
2843                                'the' + spc + 'option' + spc + 'list' + spc +%
2844                                'of' + spc + spc + '\string\\\string\\includemovie!'%
2845                        },%
2846                        {%
2847                          type: 'edit_text',%
2848                          item_id: 'text',%
2849                          alignment: 'align_fill',%
2850                          readonly: false%
2851                        },%
2852                        {%
2853                          type: 'ok',%
2854                          ok_name: 'Close'%
2855                        }%
2856                      ]%
2857                    }%
2858                  };%
2859                  app.execDialog(settings);%
2860                }catch(e){%
2861                    var spc=String.fromCharCode(32);%
2862                    app.alert('Error' + spc + 'while' + spc + 'executing' + spc +%
2863                    '3Dcalculate:' + spc + e);%
2864                }%
2865              }%
2866            \fi%
2867            %create stream from user provided JavaScript file
2868            \ifx\@MXV@jscriptiiidfile\@empty\else%
2869              \ifthenelse{% create only once
2870                \equal{\@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}}{undefined}%
2871              }{%
2872                \ifpdf%
2873                  \pdfobj stream file {\@MXV@jscriptiiidfile}%
2874                  \pdfrefobj\pdflastobj%
2875                  \edef\@MXV@userjscriptiiidstream{\the\pdflastobj\space 0 R}%
2876                  \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}{\the\pdflastobj}%
2877                \else%
2878                  \pdfmark{%
2879                    pdfmark=/OBJ,%
2880                    Raw={%
2881                      /_objdef {linkuserjscriptiiid\the\@MXV@links}%
2882                      /type/stream%
2883                    }%
2884                  }%
2885                  \pdfmark{%
2886                    pdfmark=/PUT,%
2887                    Raw={%
2888                      {linkuserjscriptiiid\the\@MXV@links}%
2889                      (\@MXV@jscriptiiidfile) (r) file%
2890                    }%
2891                  }%
2892                  \edef\@MXV@userjscriptiiidstream{%
2893                    {linkuserjscriptiiid\the\@MXV@links}%
2894                  }%
2895                  \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}%
2896                        {linkuserjscriptiiid\the\@MXV@links}%
2897                \fi%
2898              }{%
2899                \ifpdf%
2900                  \edef\@MXV@userjscriptiiidstream{%
2901                    \@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}\space 0 R%
2902                  }%
2903                \else%
2904                  \edef\@MXV@userjscriptiiidstream{%
2905                    {\@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}}%
2906                  }%
2907                \fi%
2908              }%
2909            \fi%
2910            \edef\@MXV@jscriptiiidaction{%
2911              /Next <<%
2912                /S/JavaScript%
2913                /JS (\@MXV@linkjscriptiiid)%
2914                \ifx\@MXV@jscriptiiidfile\@empty\else%
2915                  /Next <<%
2916                    /S/JavaScript%
2917                    /JS \@MXV@userjscriptiiidstream% user provided script
2918                  >>%
2919                \fi%
2920              >>%
2921            }%
2922          }{\edef\@MXV@jscriptiiidaction{}}%
2923        }{% #### 2D ####
2924          %retrieve original settings
2925          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.mouse}}{true}}{%
2926            \setboolean{@MXV@mouse}{true}%
2927          }{%
2928            \setboolean{@MXV@mouse}{false}%
2929          }%
2930          \edef\@MXV@ctrls{\@MXV@getlabelvalue{@MXV@\@MXV@label.showUI}}%
2931          \edef\@MXV@palindrome{\@MXV@getlabelvalue{@MXV@\@MXV@label.palindrome}}%
2932          \edef\@MXV@repeat{\@MXV@getlabelvalue{@MXV@\@MXV@label.repeat}}%
2933          \edef\@MXV@rate{\@MXV@getlabelvalue{@MXV@\@MXV@label.rate}}%
2934          \edef\@MXV@startat{\@MXV@getlabelvalue{@MXV@\@MXV@label.startAt}}%
2935          \edef\@MXV@endat{\@MXV@getlabelvalue{@MXV@\@MXV@label.endAt}}%
2936          \edef\@MXV@volume{\@MXV@getlabelvalue{@MXV@\@MXV@label.volume}}%
2937          \setkeys{MXV@user}{#1}%override with new settings
2938          %
2939          \edef\@MXV@operation{}%
2940          %
2941          %get the player ID
2942          \edef\@MXV@currplayer{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}%
2943          %
2944          %see whether a sound inclusion is being referenced
2945          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.issound}}{true}}{%
2946            \setboolean{@MXV@issound}{true}%
2947          }{%
2948            \setboolean{@MXV@issound}{false}%
2949          }%
2950          %
2951          %create /OP and /JS entries
2952          \if@MXV@linkplay%
2953            \edef\@MXV@operation{%
2954              /OP 0%
2955              /JS (%
2956                if(focusonplayer==undefined){%
2957                  var focusonplayer=0; %shared by all annots
2958                }%
2959                \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
2960                     {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
2961                \@MXV@events{\@MXV@currplayer}%
2962                           {\if@MXV@mouse true\else false\fi}{true}%
2963                try{%
2964                  if(player\@MXV@currplayer.isOpen){%
2965                    player\@MXV@currplayer.close(%
2966                                          app.media.closeReason.general);
2967                    player\@MXV@currplayer=null;
2968                  }%
2969                }%
2970                catch(e){}%
2971                %
2972                try{%
2973                  var player\@MXV@currplayer=app.media.openPlayer({%
2974                    settings: settings,%
2975                    events: events%
2976                  });
2977                }%
2978                catch (e){}%
2979              )%
2980            }%
2981          \fi%
2982          \if@MXV@linkresume% resume/pause
2983            \edef\@MXV@operation{%
2984              /OP 3%
2985              /JS (%
2986                try{%
2987                  \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi%
2988                  if(!player\@MXV@currplayer.isPlaying){%
2989                    player\@MXV@currplayer.settings.privateData.paused=false;
2990                    player\@MXV@currplayer.play();
2991                    if(!player\@MXV@currplayer.isPlaying){%
2992                      %media at end will restart from beginning
2993                      if(
2994                        player\@MXV@currplayer.settings.startAt.time
2995                        || player\@MXV@currplayer.settings.startAt.frame
2996                        || player\@MXV@currplayer.settings.startAt.marker
2997                        || player\@MXV@currplayer.id ==
2998                           'vnd.adobe.swname:AAPL_QuickTime'
2999                      ){
3000                        player\@MXV@currplayer.seek(
3001                          player\@MXV@currplayer.settings.startAt);
3002                      }else{
3003                        player\@MXV@currplayer.stop();
3004                      }
3005                      player\@MXV@currplayer.play();
3006                    }%
3007                  }%
3008                  else{%
3009                    player\@MXV@currplayer.pause();
3010                    player\@MXV@currplayer.settings.privateData.paused=true;
3011                  }%
3012                }%
3013                catch(e){% open new player if not yet open
3014                  if(focusonplayer==undefined){%
3015                    var focusonplayer=0; %shared by all annots
3016                  }%
3017                  \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
3018                       {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
3019                  \@MXV@events{\@MXV@currplayer}%
3020                             {\if@MXV@mouse true\else false\fi}{true}%
3021                  try{%
3022                    var player\@MXV@currplayer=app.media.openPlayer({%
3023                      settings: settings,%
3024                      events: events%
3025                    });
3026                  }%
3027                  catch (e){}%
3028                }%
3029              )%
3030            }%
3031          \fi%
3032          \if@MXV@linkstop%
3033            \edef\@MXV@operation{%
3034              /OP 1%
3035              /JS (%
3036                try{%
3037                  if(!player\@MXV@currplayer.isPlaying){%
3038                    player\@MXV@currplayer.settings.privateData.paused=false;
3039                    player\@MXV@currplayer.play();
3040                  }%
3041                  player\@MXV@currplayer.stop();
3042                  if(
3043                    player\@MXV@currplayer.settings.startAt.time
3044                    || player\@MXV@currplayer.settings.startAt.frame
3045                    || player\@MXV@currplayer.settings.startAt.marker
3046                    || player\@MXV@currplayer.id ==
3047                       'vnd.adobe.swname:AAPL_QuickTime'
3048                  ){
3049                    player\@MXV@currplayer.seek(%
3050                      player\@MXV@currplayer.settings.startAt);
3051                  }
3052                }%
3053                catch(e){}%
3054              )%
3055            }%
3056          \fi%
3057          \if@MXV@linkpause% pause/resume
3058            \edef\@MXV@operation{%
3059              /OP 2%
3060              /JS (%
3061                try{%
3062                  \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi%
3063                  if(!player\@MXV@currplayer.isPlaying){%
3064                    player\@MXV@currplayer.settings.privateData.paused=false;
3065                    player\@MXV@currplayer.play();
3066                    if(!player\@MXV@currplayer.isPlaying){%
3067                      %media at end will restart from beginning
3068                      if(
3069                        player\@MXV@currplayer.settings.startAt.time
3070                        || player\@MXV@currplayer.settings.startAt.frame
3071                        || player\@MXV@currplayer.settings.startAt.marker
3072                        || player\@MXV@currplayer.id ==
3073                           'vnd.adobe.swname:AAPL_QuickTime'
3074                      ){
3075                        player\@MXV@currplayer.seek(
3076                          player\@MXV@currplayer.settings.startAt);
3077                      }else{
3078                        player\@MXV@currplayer.stop();
3079                      }
3080                      player\@MXV@currplayer.play();
3081                    }%
3082                  }%
3083                  else{%
3084                    player\@MXV@currplayer.pause();
3085                    player\@MXV@currplayer.settings.privateData.paused=true;
3086                  }%
3087                }%
3088                catch(e){% open new player if not yet open
3089                  if(focusonplayer==undefined){%
3090                    var focusonplayer=0; %shared by all annots
3091                  }%
3092                  \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
3093                       {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
3094                  \@MXV@events{\@MXV@currplayer}%
3095                             {\if@MXV@mouse true\else false\fi}{true}%
3096                  try{%
3097                    var player\@MXV@currplayer=app.media.openPlayer({%
3098                      settings: settings,%
3099                      events: events%
3100                    });
3101                  }%
3102                  catch (e){}%
3103                }%
3104              )%
3105            }%
3106          \fi%
3107          \if@MXV@linkclose%
3108            \edef\@MXV@operation{%
3109              /OP 1%
3110              /JS (%
3111                try{%
3112                  player\@MXV@currplayer.close(%
3113                                        app.media.closeReason.general);
3114                  player\@MXV@currplayer=null;
3115                }%
3116                catch(e){}%
3117              )%
3118            }%
3119          \fi%
3120          \if@MXV@linkreset% reset to orig. settings
3121            %retrieve original settings
3122            \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.mouse}}{true}}{%
3123              \setboolean{@MXV@mouse}{true}%
3124            }{%
3125              \setboolean{@MXV@mouse}{false}%
3126            }%
3127            \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.autoplay}}{true}}{%
3128              \setboolean{@MXV@autoplay}{true}%
3129            }{%
3130              \setboolean{@MXV@autoplay}{false}%
3131            }%
3132            %
3133            \edef\@MXV@operation{%
3134              /OP 0%
3135              /JS (%
3136                if(focusonplayer==undefined){%
3137                  var focusonplayer=0; %shared by all annots
3138                }%
3139                \@MXV@settings{\@MXV@getlabelvalue{@MXV@\@MXV@label.showUI}}%
3140                              {\@MXV@getlabelvalue{@MXV@\@MXV@label.palindrome}}%
3141                              {\@MXV@getlabelvalue{@MXV@\@MXV@label.repeat}}%
3142                              {\@MXV@getlabelvalue{@MXV@\@MXV@label.rate}}%
3143                              {\@MXV@getlabelvalue{@MXV@\@MXV@label.startAt}}%
3144                              {\@MXV@getlabelvalue{@MXV@\@MXV@label.endAt}}%
3145                              {\@MXV@getlabelvalue{@MXV@\@MXV@label.volume}}%
3146                \@MXV@events{\@MXV@currplayer}%
3147                            {\if@MXV@mouse true\else false\fi}%
3148                            {\if@MXV@autoplay true\else false\fi}%
3149                try{%
3150                  if(player\@MXV@currplayer.isOpen){%
3151                    player\@MXV@currplayer.close(%
3152                      app.media.closeReason.general);
3153                    player\@MXV@currplayer=null;
3154                  }%
3155                }%
3156                catch(e){}%
3157                %
3158                try{%
3159                  var player\@MXV@currplayer=app.media.openPlayer({%
3160                      settings: settings,%
3161                      events: events%
3162                  });
3163                }%
3164                catch (e){}%
3165              )%
3166            }%
3167          \fi%
3168        }%
3169      \fi%
3170      \fi%
3171      %
3172      \ifpdf%
3173        \ifthenelse{\isundefined{\@pdfborder}}{%
3174          \def\@MXV@linkattr{}%
3175        }{%
3176          \edef\@MXV@linkattr{%
3177            \if@MXV@beamer%
3178              \@MXV@pdfborder%
3179            \else%
3180              /Border [\@pdfborder]%
3181            \fi%
3182            /C [\@linkbordercolor]%
3183            /H \@pdfhighlight%
3184          }%
3185        }%
3186        %
3187        \pdfstartlink%
3188          attr{\@MXV@linkattr}%
3189          user{%
3190            /Subtype /Link%
3191            /A <<%
3192              /S/GoTo%
3193              /D (@MXV@\@MXV@@label)%
3194              \if@MXV@@draft\else%
3195                \if@MXV@externalviewer\else%
3196                  \if@MXV@iiid%
3197                    \ifx\@MXV@iiidview\@empty\else%
3198                      /Next <<%
3199                        /S/GoTo3DView%
3200                        /TA \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}\space 0 R%
3201                        /V \@MXV@iiidview%
3202                    \fi%
3203                        \@MXV@jscriptiiidaction%
3204                    \ifx\@MXV@iiidview\@empty\else%
3205                      >>%
3206                    \fi%
3207                  \else%
3208                    /Next <<%
3209                      /S/Rendition%
3210                      /R \@MXV@getlabelvalue{@MXV@\@MXV@@label.rendition}\space 0 R%
3211                      /AN \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}\space 0 R%
3212                      \@MXV@operation%
3213                    >>%
3214                  \fi%
3215                \fi%
3216              \fi%
3217            >>%
3218          }%
3219          \usebox{\@MXV@textbox}% write out text box
3220        \pdfendlink%
3221      \else%
3222        \pdfmark[{\usebox{\@MXV@textbox}}]{%
3223          pdfmark=/ANN,%
3224          Subtype=/Link,%
3225          Color=\@linkbordercolor,%
3226          AcroHighlight=\@pdfhighlight,%
3227          Raw={%
3228            \@MXV@pdfborder%
3229            /_objdef {linkannot\the\@MXV@links}%
3230            /Action <<%
3231              /S/GoTo%
3232              /D/@MXV@\@MXV@@label%
3233              \if@MXV@@draft\else%
3234                \if@MXV@externalviewer\else%
3235                  \if@MXV@iiid%
3236                    \ifx\@MXV@iiidview\@empty\else%
3237                      /Next <<%
3238                        /S/GoTo3DView%
3239                        /TA {3Dannot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}}%
3240                        /V \@MXV@iiidview%
3241                    \fi%
3242                        \@MXV@jscriptiiidaction%
3243                    \ifx\@MXV@iiidview\@empty\else%
3244                      >>%
3245                    \fi%
3246                  \else%
3247                    /Next <<%
3248                      /S /Rendition%
3249                      /R {mediarendition\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}%
3250                      /AN {screenannot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}}%
3251                      \@MXV@operation%
3252                    >>%
3253                  \fi%
3254                \fi%
3255              \fi%
3256            >>%
3257          }%
3258        }%
3259      \fi%
3260    }%
3261  }%
3262}
3263
3264%standard keys to be processed first
3265%key definitions for options to \includemovie
3266\define@key{MXV@user}{draft}[true]{%
3267  \setboolean{@MXV@@draft}{#1}%
3268}
3269\define@key{MXV@user}{final}[true]{%
3270  \ifthenelse{\equal{#1}{true}}{%
3271    \setboolean{@MXV@@draft}{false}%
3272  }{%
3273    \setboolean{@MXV@@draft}{true}%
3274  }%
3275}
3276\define@key{MXV@user}{label}{%for use with movieref
3277  \gdef\@MXV@label{#1}%
3278}
3279\define@key{MXV@user}{controls}[true]{%
3280  \xdef\@MXV@ctrls{, showUI: #1}%
3281  \xdef\@MXV@@ctrls{/C #1}%
3282  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3283    \gdef\@MXV@iiidtoolb{/TB #1}%
3284  }{}%
3285}
3286\define@key{MXV@user}{toolbar}[true]{%
3287  \xdef\@MXV@ctrls{, showUI: #1}%
3288  \xdef\@MXV@@ctrls{/C #1}%
3289  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3290    \gdef\@MXV@iiidtoolb{/TB #1}%
3291  }{}%
3292}
3293\define@key{MXV@user}{volume}{%
3294  \def\@MXV@@volume{/V #1}%
3295  \def\@MXV@volume{#1}%
3296}
3297\define@key{MXV@user}{mimetype}{%
3298  \ifthenelse{\equal{#1}{model/u3d}}{%
3299    \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3300      \setboolean{@MXV@iiid}{true}%
3301      \xdef\@MXV@iiidsubtype{U3D}%
3302    }{\@MXV@neediiiD}%
3303  }{}%
3304  \def\@MXV@mime{#1}%
3305}
3306\define@key{MXV@user}{playerid}{%
3307  \def\@MXV@player{%
3308    /PL<</MU [<</PID<</U (vnd.adobe.swname:#1)>>>>]>>%
3309  }%
3310}
3311\define@key{MXV@user}{autoplay}[true]{%
3312  \setboolean{@MXV@autoplay}{#1}%
3313  \if@MXV@autoplay%
3314    \setboolean{@MXV@autoresume}{false}%
3315  \fi%
3316}
3317\define@key{MXV@user}{autostop}[true]{%
3318  \setboolean{@MXV@autostop}{#1}%
3319  \if@MXV@autostop%
3320    \setboolean{@MXV@autopause}{false}%
3321  \fi%
3322}
3323\define@key{MXV@user}{autoresume}[true]{%
3324  \setboolean{@MXV@autoresume}{#1}%
3325  \if@MXV@autoresume%
3326    \setboolean{@MXV@autoplay}{false}%
3327    \setboolean{@MXV@autoclose}{false}%
3328  \fi%
3329}
3330\define@key{MXV@user}{autopause}[true]{%
3331  \setboolean{@MXV@autopause}{#1}%
3332  \if@MXV@autopause%
3333    \setboolean{@MXV@autostop}{false}%
3334    \setboolean{@MXV@autoclose}{false}%
3335  \fi%
3336}
3337\define@key{MXV@user}{autoclose}[true]{%
3338  \setboolean{@MXV@autoclose}{#1}%
3339  \if@MXV@autoclose%
3340    \setboolean{@MXV@autostop}{false}%
3341    \setboolean{@MXV@autopause}{false}%
3342  \fi%
3343}
3344\define@key{MXV@user}{continue}[true]{%
3345  \setboolean{@MXV@autostop}{false}%
3346  \setboolean{@MXV@autopause}{false}%
3347  \setboolean{@MXV@autoclose}{false}%
3348}
3349\define@key{MXV@user}{open}[true]{%
3350  %no longer supported; once open, media remains loaded
3351  %to avoid reloading when media is to be played again
3352}
3353\define@key{MXV@user}{mouse}[true]{%
3354  \setboolean{@MXV@mouse}{#1}%
3355  \ifthenelse{\equal{false}{#1}\AND\boolean{@MXV@iiiDfeat}}{%
3356    \def\@MXV@iiidia{/3DI #1}%
3357  }{}%
3358}
3359\define@key{MXV@user}{palindrome}[true]{%
3360  \xdef\@MXV@palindrome{, palindrome: #1}%
3361  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3362    \gdef\@MXV@iiidpalindrome{/Subtype/Oscillating}%
3363  }{}%
3364}
3365\define@key{MXV@user}{rate}{%
3366  \xdef\@MXV@rate{, rate: #1}%
3367  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3368    \gdef\@MXV@iiidrate{/TM #1}%
3369  }{}%
3370}
3371\define@key{MXV@user}{repeat}[Infinity]{%
3372  \ifthenelse{%
3373    \equal{#1}{Infinity}\OR%
3374    \equal{#1}{0}%
3375  }{%
3376    \xdef\@MXV@repeat{, repeat: Infinity}%
3377    \xdef\@MXV@@repeat{/RC 0}%
3378  }{%
3379    \xdef\@MXV@repeat{, repeat: #1}%
3380    \xdef\@MXV@@repeat{/RC #1}%
3381  }%
3382  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3383    \ifthenelse{\equal{#1}{Infinity}}{%
3384      \global\@MXV@iiidrepeat=-1%
3385    }{%
3386      \global\@MXV@iiidrepeat=#1%
3387    }%
3388  }{}%
3389}
3390\define@key{MXV@user}{startat}{%
3391  \xdef\@MXV@startat{, startAt: {#1}}%
3392}
3393\define@key{MXV@user}{endat}{%
3394  \xdef\@MXV@endat{, endAt: {#1}}%
3395}
3396\define@key{MXV@user}{poster}[true]{%
3397  \ifthenelse{\equal{#1}{true}}{% option without arg
3398    \setboolean{@MXV@runposter}{true}%
3399  }{%
3400    \def\@MXV@box##1##2##3{%
3401      \ifpdf%
3402        \mbox{\pdfximage width ##1 height ##2 depth ##3 {#1}}%
3403        \pdfrefximage\pdflastximage%
3404      \else%
3405        \ifthenelse{\isundefined{\includegraphics}}{\@MXV@missing{graphics}}{}%
3406        \@MXV@totalheight=##2%
3407        \advance\@MXV@totalheight by ##3%
3408        \raisebox{-##3}[##2][##3]{%
3409          \includegraphics[%
3410            width=##1,height=##2,totalheight=\@MXV@totalheight,clip]{#1}%
3411        }%
3412      \fi%
3413    }%
3414  }%
3415}
3416\define@key{MXV@user}{externalviewer}[true]{%
3417  \setboolean{@MXV@externalviewer}{#1}%
3418}
3419\define@key{MXV@user}{inline}[true]{%
3420  \if@MXV@url%
3421    \setboolean{@MXV@inline}{false}%
3422  \else%
3423    \setboolean{@MXV@inline}{#1}%
3424  \fi%
3425  \if@MXV@inline\else%
3426    \setboolean{@MXV@attachment}{false}%
3427  \fi%
3428}
3429\define@key{MXV@user}{url}[true]{%
3430  \setboolean{@MXV@url}{#1}%
3431  \if@MXV@url%
3432    \setboolean{@MXV@inline}{false}%
3433    \setboolean{@MXV@attachment}{false}%
3434    \def\@MXV@fsentry{/FS /URL}%
3435  \fi%
3436}
3437\define@key{MXV@user}{attach}[true]{%
3438  \setboolean{@MXV@attachment}{#1}%
3439  \if@MXV@attachment%
3440    \setboolean{@MXV@inline}{true}%
3441  \fi%
3442}
3443\define@key{MXV@user}{text}{%
3444  \setboolean{@MXV@boxopt}{true}%
3445  \savebox{\@MXV@textbox}{#1}%
3446  \@MXV@width=\wd\@MXV@textbox%
3447  \@MXV@height=\ht\@MXV@textbox%
3448  \@MXV@depth=\dp\@MXV@textbox%
3449}
3450\define@key{MXV@user}{textoverposter}[true]{%
3451  \setboolean{@MXV@textoverposter}{#1}%
3452}
3453\define@key{MXV@user}{depth}{%set depth of display area
3454  \gdef\@MXV@boxdepth{#1}%
3455}
3456%3D specific options
3457\define@key{MXV@user}{3Dbg}{%
3458  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3459    \def\@MXV@background{/BG<</CS/DeviceRGB/C[#1]>>}%
3460  }{\@MXV@neediiiD}%
3461}
3462\define@key{MXV@user}{3Djscript}{%
3463  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3464    \IfFileExists{#1}{%
3465      \def\@MXV@jscriptiiidfile{#1}%
3466    }{%
3467      \PackageError{movie15}{Script file `#1' cannot be opened for embedding%
3468      }{%
3469        Make sure file `#1' exists and is readable!%
3470      }%
3471    }%
3472  }{\@MXV@neediiiD}%
3473}
3474\define@key{MXV@user}{3Dcoo}{%
3475  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3476    \def\@MXV@coo{#1}%
3477    \setboolean{@MXV@defaultviewprovided}{true}%
3478  }{\@MXV@neediiiD}%
3479}
3480\define@key{MXV@user}{3Dc2c}{%
3481  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3482    \def\@MXV@ctoc{#1}%
3483    \setboolean{@MXV@defaultviewprovided}{true}%
3484  }{\@MXV@neediiiD}%
3485}
3486\define@key{MXV@user}{3Droo}{%
3487  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3488    \def\@MXV@roo{#1}%
3489    \setboolean{@MXV@defaultviewprovided}{true}%
3490  }{\@MXV@neediiiD}%
3491}
3492\define@key{MXV@user}{3Daac}{%
3493  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3494    \def\@MXV@aac{#1}%
3495    \setboolean{@MXV@defaultviewprovided}{true}%
3496  }{\@MXV@neediiiD}%
3497}
3498\define@key{MXV@user}{3Droll}{%
3499  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3500    \def\@MXV@roll{#1}%
3501    \setboolean{@MXV@defaultviewprovided}{true}%
3502  }{\@MXV@neediiiD}%
3503}
3504\define@key{MXV@user}{3Dviews}{%
3505  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3506    \IfFileExists{#1}{%
3507      \def\@MXV@viewsfile{#1}%
3508    }{%
3509      \PackageError{movie15}{3D views  file `#1' cannot be opened%
3510      }{%
3511        Make sure file `#1' exists and is readable!%
3512      }%
3513    }%
3514  }{\@MXV@neediiiD}%
3515}
3516\define@key{MXV@user}{3Dlights}{%
3517  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3518    \gdef\@MXV@lights{/LS <</Subtype/#1>>}%
3519  }{\@MXV@neediiiD}%
3520}
3521%options for \movieref command
3522\define@key{MXV@user}{play}[true]{%
3523  \setboolean{@MXV@linkplay}{#1}%
3524  \if@MXV@linkplay%
3525   \setboolean{@MXV@linkpause}{false}%
3526   \setboolean{@MXV@linkresume}{false}%
3527   \setboolean{@MXV@linkstop}{false}%
3528   \setboolean{@MXV@linkclose}{false}%
3529   \setboolean{@MXV@linkreset}{false}%
3530  \fi%
3531}
3532\define@key{MXV@user}{pause}[true]{%
3533  \setboolean{@MXV@linkpause}{#1}%
3534  \if@MXV@linkpause%
3535    \setboolean{@MXV@linkresume}{false}%
3536    \setboolean{@MXV@linkstop}{false}%
3537    \setboolean{@MXV@linkclose}{false}%
3538    \setboolean{@MXV@linkreset}{false}%
3539    \setboolean{@MXV@linkplay}{false}%
3540  \fi%
3541}
3542\define@key{MXV@user}{resume}[true]{%
3543  \setboolean{@MXV@linkresume}{#1}%
3544  \if@MXV@linkresume%
3545    \setboolean{@MXV@linkpause}{false}%
3546    \setboolean{@MXV@linkstop}{false}%
3547    \setboolean{@MXV@linkclose}{false}%
3548    \setboolean{@MXV@linkreset}{false}%
3549    \setboolean{@MXV@linkplay}{false}%
3550  \fi%
3551}
3552\define@key{MXV@user}{stop}[true]{%
3553  \setboolean{@MXV@linkstop}{#1}%
3554  \if@MXV@linkstop%
3555    \setboolean{@MXV@linkpause}{false}%
3556    \setboolean{@MXV@linkresume}{false}%
3557    \setboolean{@MXV@linkclose}{false}%
3558    \setboolean{@MXV@linkreset}{false}%
3559    \setboolean{@MXV@linkplay}{false}%
3560  \fi%
3561}
3562\define@key{MXV@user}{close}[true]{%
3563  \setboolean{@MXV@linkclose}{#1}%
3564  \if@MXV@linkclose%
3565    \setboolean{@MXV@linkpause}{false}%
3566    \setboolean{@MXV@linkresume}{false}%
3567    \setboolean{@MXV@linkstop}{false}%
3568    \setboolean{@MXV@linkreset}{false}%
3569    \setboolean{@MXV@linkplay}{false}%
3570  \fi%
3571}
3572\define@key{MXV@user}{reset}[true]{%
3573  \setboolean{@MXV@linkreset}{#1}%
3574  \if@MXV@linkreset%
3575    \setboolean{@MXV@linkpause}{false}%
3576    \setboolean{@MXV@linkresume}{false}%
3577    \setboolean{@MXV@linkstop}{false}%
3578    \setboolean{@MXV@linkclose}{false}%
3579    \setboolean{@MXV@linkplay}{false}%
3580  \fi%
3581}
3582\define@key{MXV@user}{3Dviewindex}{%
3583  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3584    \ifthenelse{%
3585      \equal{#1}{F}%
3586      \OR\equal{#1}{L}%
3587      \OR\equal{#1}{N}%
3588      \OR\equal{#1}{P}%
3589      \OR\equal{#1}{D}%
3590    }{%
3591      \gdef\@MXV@iiidview{/#1}% any of F, L, N, P, D
3592    }{%
3593      \gdef\@MXV@iiidview{#1}% number (index)
3594    }%
3595    \setboolean{@MXV@defaultviewprovided}{false}%
3596  }{\@MXV@neediiiD}%
3597}
3598\define@key{MXV@user}{3Dcalculate}[30]{%
3599  %calculate optimal 3D settings for roo and coo for a given aac
3600  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3601    \gdef\@MXV@calc{#1}%
3602  }{\@MXV@neediiiD}%
3603}
3604\define@key{MXV@user}{3Dgetview}[true]{%
3605  %print current 3D camera settings
3606  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3607    \setboolean{@MXV@iiidgetview}{#1}%
3608  }{\@MXV@neediiiD}%
3609}
3610\define@key{MXV@user}{3Dresource}{%
3611  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
3612    \IfFileExists{#1}{%
3613      \setboolean{@MXV@resource}{true}%
3614      \xdef\@MXV@iiidopt{3Dresource=#1, \@MXV@iiidopt}%
3615    }{%
3616      \PackageError{movie15}{3D resource file `#1' cannot be opened%
3617      }{%
3618        Make sure file `#1' exists and is readable!%
3619      }%
3620    }%
3621  }{\@MXV@neediiiD}%
3622}
3623
3624%compatibility options for \movie and \hyperlinkmovie commands
3625\define@key{MXV@user}{borderwidth}{%
3626  %ignored; acroread doesn't draw borders around screen annots anyway
3627}
3628\define@key{MXV@user}{height}{%set height of display area
3629  \gdef\@MXV@boxheight{#1}%
3630}
3631\define@key{MXV@user}{width}{%set width of display area
3632  \gdef\@MXV@boxwidth{#1}%
3633}
3634\define@key{MXV@user}{autostart}[true]{%
3635  \xdef\@MXV@autostart{, autoplay=#1}%
3636}
3637\define@key{MXV@user}{loop}[Infinity]{%
3638  \xdef\@MXV@loop{, repeat=#1}%
3639}
3640\define@key{MXV@user}{once}[]{%
3641  \xdef\@MXV@loop{, repeat=1}%
3642}
3643\define@key{MXV@user}{showcontrols}[true]{%
3644  \xdef\@MXV@showcontrols{, controls=#1}%
3645}
3646\define@key{MXV@user}{start}{%
3647  \gdef\@MXV@starttime##1s{%
3648    \global\@MXV@start=##1pt%
3649  }%
3650  \@MXV@starttime #1%
3651}
3652\define@key{MXV@user}{duration}{%
3653  \gdef\@MXV@durationtime##1s{%
3654    \global\@MXV@end=##1pt%
3655  }%
3656  \@MXV@durationtime #1%
3657}
3658
3659%options to be passed to internal macro \@MXV@includeiiid
3660\define@key{MXV@iiid}{3Dresource}{%
3661  \@MXV@addresource{#1}%
3662}
3663
3664%compatibility macros
3665\providecommand\movie[3][]{%
3666  \ifpdf\else%
3667    \ifthenelse{\isundefined{\pdfmark}}{\@MXV@missing{hyperref}}{}%
3668  \fi%
3669  \leavevmode%
3670  \@MXV@reset%
3671  \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}%
3672  \def\@MXV@starttime{}\def\@MXV@durationtime{}%
3673  \setkeys{MXV@user}{#1}%
3674  %
3675  %sanity checks
3676  \if@MXV@boxopt%
3677    \PackageError{movie15}{%
3678      Option `text' cannot be used with command `\string\movie'.\MessageBreak
3679      Instead, put text into the 1st argument of `\string\movie'
3680    }{}%
3681  \fi%
3682  %
3683  \ifx\@MXV@durationtime\@empty\else\ifx\@MXV@startat\@empty\else%
3684    \PackageError{movie15}{%
3685      Options `startat' and `duration' cannot be used\MessageBreak
3686      together.\MessageBreak
3687      Possible combinations are `startat'/`endat',\MessageBreak
3688      `start'/`endat' or `start'/`duration'
3689    }{}%
3690  \fi\fi%
3691  %
3692  %option list
3693  \edef\@MXV@movieoptions{#1\@MXV@autostart\@MXV@loop\@MXV@showcontrols}%
3694  %
3695  %determine playback section
3696  \ifx\@MXV@starttime\@empty\else%
3697    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
3698                              startat=time:\strip@pt\@MXV@start}%
3699  \fi%
3700  \ifx\@MXV@durationtime\@empty\else%
3701    \advance\@MXV@end by \@MXV@start%
3702    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
3703                              endat=time:\strip@pt\@MXV@end}%
3704  \fi%
3705  %
3706  %text option from 2nd argument
3707  \savebox{\@MXV@textbox}{#2}%
3708  \edef\@MXV@movieoptions{[\@MXV@movieoptions, text={\noexpand\usebox{%
3709                                            \noexpand\@MXV@textbox}}]}%
3710  \expandafter%
3711    \includemovie\@MXV@movieoptions{\@MXV@boxwidth}{\@MXV@boxheight}{#3}%
3712}
3713
3714\newcommand\hyperlinkmovie[3][]{%
3715  \ifpdf\else%
3716    \ifthenelse{\isundefined{\pdfmark}}{\@MXV@missing{hyperref}}{}%
3717  \fi%
3718  \leavevmode%
3719  \@MXV@reset%
3720  \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}%
3721  \def\@MXV@starttime{}\def\@MXV@durationtime{}%
3722  \setkeys{MXV@user}{#1}%
3723  %
3724  %sanity check
3725  \ifx\@MXV@durationtime\@empty\else\ifx\@MXV@startat\@empty\else%
3726    \PackageError{movie15}{%
3727      Options `startat' and `duration' cannot be used\MessageBreak
3728      together.\MessageBreak
3729      Possible combinations are `startat'/`endat',\MessageBreak
3730      `start'/`endat' or `start'/`duration'
3731    }{}%
3732  \fi\fi%
3733  %
3734  %option list
3735  \edef\@MXV@movieoptions{#1\@MXV@autostart\@MXV@loop\@MXV@showcontrols}%
3736  %
3737  %determine playback section
3738  \ifx\@MXV@starttime\@empty\else%
3739    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
3740                              startat=time:\strip@pt\@MXV@start}%
3741  \fi%
3742  \ifx\@MXV@durationtime\@empty\else%
3743    \advance\@MXV@end by \@MXV@start%
3744    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
3745                              endat=time:\strip@pt\@MXV@end}%
3746  \fi%
3747  %
3748  \edef\@MXV@movieoptions{[\@MXV@movieoptions]}%
3749  \expandafter\movieref\@MXV@movieoptions{#2}{#3}%
3750}
3751