fixed frame overflow bug
[swftools.git] / lib / as3 / scripts.c
1 /* scripts.c
2
3    Some hardcoded abc scripts.
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008,2009 Matthias Kramm <kramm@quiss.org>
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23
24 #include "abc.h"
25
26 void swf_AddButtonLinks(SWF*swf, char stop_each_frame, char events)
27 {
28     int num_frames = 0;
29     int has_buttons = 0;
30     TAG*tag=swf->firstTag;
31     while(tag) {
32         if(tag->id == ST_SHOWFRAME)
33             num_frames++;
34         if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2)
35             has_buttons = 1;
36         tag = tag->next;
37     }
38
39     abc_file_t*file = abc_file_new();
40     abc_method_body_t*c = 0;
41    
42     abc_class_t*cls = abc_class_new2(file, "rfx::MainTimeline", "flash.display::MovieClip");
43     abc_class_protectedNS(cls, "rfx:MainTimeline");
44   
45     TAG*abctag = swf_InsertTagBefore(swf, swf->firstTag, ST_DOABC);
46     
47     tag = swf_InsertTag(abctag, ST_SYMBOLCLASS);
48     swf_SetU16(tag, 1);
49     swf_SetU16(tag, 0);
50     swf_SetString(tag, "rfx.MainTimeline");
51
52     c = abc_class_getstaticconstructor(cls, 0)->body;
53     c->old.max_stack = 1;
54     c->old.local_count = 1;
55     c->old.init_scope_depth = 9;
56     c->old.max_scope_depth = 10;
57
58     __ getlocal_0(c);
59     __ pushscope(c);
60     __ returnvoid(c);
61
62     c = abc_class_getconstructor(cls, 0)->body;
63     c->old.max_stack = 3;
64     c->old.local_count = 1;
65     c->old.init_scope_depth = 10;
66     c->old.max_scope_depth = 11;
67     
68     debugfile(c, "constructor.as");
69
70     __ getlocal_0(c);
71     __ pushscope(c);
72
73     __ getlocal_0(c);
74     __ constructsuper(c,0);
75
76     __ getlex(c, "[package]flash.system::Security");
77     __ pushstring(c, "*");
78     __ callpropvoid(c, "[package]::allowDomain", 1);
79     
80     if(stop_each_frame || has_buttons) {
81         int frame = 0;
82         tag = swf->firstTag;
83         abc_method_body_t*f = 0; //frame script
84         while(tag && tag->id!=ST_END) {
85             char framename[80];
86             char needs_framescript=0;
87             char buttonname[80];
88             char functionname[80];
89             sprintf(framename, "[packageinternal]rfx::frame%d", frame);
90             
91             if(!f && (tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2 || stop_each_frame)) {
92                 /* make the contructor add a frame script */
93                 __ findpropstrict(c,"[package]::addFrameScript");
94                 __ pushuint(c,frame);
95                 __ getlex(c,framename);
96                 __ callpropvoid(c,"[package]::addFrameScript",2);
97
98                 f = abc_class_method(cls, 0, multiname_fromstring(framename))->body;
99                 f->old.max_stack = 3;
100                 f->old.local_count = 1;
101                 f->old.init_scope_depth = 10;
102                 f->old.max_scope_depth = 11;
103                 __ debugfile(f, "framescript.as");
104                 __ debugline(f, 1);
105                 __ getlocal_0(f);
106                 __ pushscope(f);
107                 if(stop_each_frame) {
108                     __ findpropstrict(f, "[package]::stop");
109                     __ callpropvoid(f, "[package]::stop", 0);
110                 }
111             }
112
113             if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) {
114                 U16 id = swf_GetDefineID(tag);
115                 sprintf(buttonname, "::button%d", swf_GetDefineID(tag));
116                 __ getlex(f,buttonname);
117                 __ getlex(f,"flash.events::MouseEvent");
118                 __ getproperty(f, "::CLICK");
119                 sprintf(functionname, "::clickbutton%d", swf_GetDefineID(tag));
120                 __ getlex(f,functionname);
121                 __ callpropvoid(f, "::addEventListener" ,2);
122
123                 needs_framescript = 1;
124
125                 abc_method_body_t*h =
126                     abc_class_method(cls, 0, multiname_fromstring(functionname))->body;
127                 list_append(h->method->parameters, multiname_fromstring("flash.events::MouseEvent"));
128
129                 h->old.max_stack = 6;
130                 h->old.local_count = 2;
131                 h->old.init_scope_depth = 10;
132                 h->old.max_scope_depth = 11;
133                 __ getlocal_0(h);
134                 __ pushscope(h);
135
136                 ActionTAG*oldaction = swf_ButtonGetAction(tag);
137                 if(oldaction && oldaction->op == ACTION__GOTOFRAME) {
138                     int framenr = GET16(oldaction->data);
139                     if(!events) {
140                         __ findpropstrict(h,"[package]::gotoAndStop");
141                         __ pushuint(h,framenr+1);
142                         __ callpropvoid(h,"[package]::gotoAndStop", 1);
143                     } else {
144                         char framename[80];
145                         sprintf(framename, "frame%d", framenr);
146                         __ getlocal_0(h); //this
147                         __ findpropstrict(h, "[package]flash.events::TextEvent");
148                         __ pushstring(h, "link");
149                         __ pushtrue(h);
150                         __ pushtrue(h);
151                         __ pushstring(h, framename);
152                         __ constructprop(h,"[package]flash.events::TextEvent", 4);
153                         __ callpropvoid(h,"[package]::dispatchEvent", 1);
154                     }
155                 } else if(oldaction && oldaction->op == ACTION__GETURL) {
156                     if(!events) {
157                         __ findpropstrict(h,"flash.net::navigateToURL");
158                         __ findpropstrict(h,"flash.net::URLRequest");
159                         // TODO: target _blank
160                         __ pushstring(h,oldaction->data); //url
161                         __ constructprop(h,"flash.net::URLRequest", 1);
162                         __ callpropvoid(h,"flash.net::navigateToURL", 1);
163                     } else {
164                         __ getlocal_0(h); //this
165                         __ findpropstrict(h, "[package]flash.events::TextEvent");
166                         __ pushstring(h, "link");
167                         __ pushtrue(h);
168                         __ pushtrue(h);
169                         __ pushstring(h,oldaction->data); //url
170                         __ constructprop(h,"[package]flash.events::TextEvent", 4);
171                         __ callpropvoid(h,"[package]::dispatchEvent", 1);
172                     }
173                 } else if(oldaction) {
174                     fprintf(stderr, "Warning: Couldn't translate button code of button %d to flash 9 abc action\n", id);
175                 }
176                 __ returnvoid(h);
177                 swf_ActionFree(oldaction);
178             }
179             if(tag->id == ST_SHOWFRAME) {
180                 if(f) {
181                     __ returnvoid(f);
182                     f = 0;
183                 }
184                 frame++;
185             }
186             tag = tag->next;
187         }
188         if(f) {
189             __ returnvoid(f);
190         }
191     }
192     __ returnvoid(c);
193
194     tag = swf->firstTag;
195     while(tag) {
196         if(tag->id == ST_DEFINEBUTTON || tag->id == ST_DEFINEBUTTON2) {
197             char buttonname[80];
198             sprintf(buttonname, "::button%d", swf_GetDefineID(tag));
199             multiname_t*s = multiname_fromstring(buttonname);
200             //abc_class_slot(cls, multiname_fromstring(buttonname), s);
201             abc_class_slot(cls, multiname_fromstring(buttonname), 
202                                 multiname_fromstring("flash.display::SimpleButton"));
203         }
204         tag = tag->next;
205     }
206
207
208     abc_script_t*s = abc_initscript(file);
209     c = s->method->body;
210     c->old.max_stack = 2;
211     c->old.local_count = 1;
212     c->old.init_scope_depth = 1;
213     c->old.max_scope_depth = 9;
214
215     __ getlocal_0(c);
216     __ pushscope(c);
217     __ getscopeobject(c, 0);
218     __ getlex(c,"::Object");
219     __ pushscope(c);
220     __ getlex(c,"flash.events::EventDispatcher");
221     __ pushscope(c);
222     __ getlex(c,"flash.display::DisplayObject");
223     __ pushscope(c);
224     __ getlex(c,"flash.display::InteractiveObject");
225     __ pushscope(c);
226     __ getlex(c,"flash.display::DisplayObjectContainer");
227     __ pushscope(c);
228     __ getlex(c,"flash.display::Sprite");
229     __ pushscope(c);
230     __ getlex(c,"flash.display::MovieClip");
231     __ pushscope(c);
232     __ getlex(c,"flash.display::MovieClip");
233     __ newclass(c,cls);
234     __ popscope(c);
235     __ popscope(c);
236     __ popscope(c);
237     __ popscope(c);
238     __ popscope(c);
239     __ popscope(c);
240     __ popscope(c);
241     __ initproperty(c,"rfx::MainTimeline");
242     __ returnvoid(c);
243
244     //abc_method_body_addClassTrait(c, "rfx:MainTimeline", 1, cls);
245     multiname_t*classname = multiname_fromstring("rfx::MainTimeline");
246     abc_initscript_addClassTrait(s, classname, cls);
247     multiname_destroy(classname);
248
249     swf_WriteABC(abctag, file);
250 }
251
252 TAG*swf_AddAS3FontDefine(TAG*tag, U16 id, char*fontname)
253 {
254     tag = swf_InsertTag(tag, ST_DOABC);
255     abc_file_t*file = abc_file_new();
256
257     //abc_class_t*cls = abc_class_new2(file, fontname, "flash.display::MovieClip");
258     //abc_class_slot(cls, multiname_fromstring(fontname), multiname_fromstring("flash.text::Font"));
259
260     abc_class_t*cls = abc_class_new2(file, fontname, "flash.text::Font");
261
262     abc_script_t*s = abc_initscript(file);
263     code_t*c = s->method->body->code;
264     c = abc_getlocal_0(c);
265     c = abc_pushscope(c);
266     c = abc_getscopeobject(c, 0);
267     c = abc_getlex(c,"flash.text::Font");
268     c = abc_pushscope(c);
269     c = abc_getlex(c,"flash.text::Font");
270     c = abc_newclass(c,cls);
271     c = abc_popscope(c);
272     c = abc_initproperty(c, fontname);
273     c = abc_returnvoid(c);
274     s->method->body->code = c;
275
276     abc_initscript_addClassTrait(s, multiname_fromstring(fontname), cls);
277     swf_WriteABC(tag, file);
278         
279     tag = swf_InsertTag(tag, ST_SYMBOLCLASS);
280     swf_SetU16(tag, 1);
281     swf_SetU16(tag, id);
282     swf_SetString(tag, fontname);
283
284     return tag;
285 }
286