void as_mcloader_loadclip(const fn_call& fn) { as_mcloader* mcl = cast_to<as_mcloader>(fn.this_ptr); assert(mcl); fn.result->set_bool(false); // on default if (fn.nargs == 2) { array<as_value> event_args; // for event handler args event_args.push_back(as_value()); // undefined tu_string infile = get_full_url(fn.get_player()->get_workdir(), fn.arg(0).to_string()); movie_definition* md = fn.get_player()->create_movie(infile.c_str()); if (md == NULL) { IF_VERBOSE_ACTION(log_msg("can't create movie from %s\n", fn.arg(0).to_string())); event_args.push_back("URLNotFound"); // 2-d param mcl->m_listeners.notify(event_id(event_id::ONLOAD_ERROR, &event_args)); return; } as_mcloader::loadable_movie lm; lm.m_def = cast_to<movie_def_impl>(md); lm.m_target = cast_to<character>(fn.env->find_target(fn.arg(1))); mcl->m_lm.push_back(lm); mcl->m_listeners.notify(event_id(event_id::ONLOAD_START, &event_args)); fn.result->set_bool(true); } }
void as_global_movieclip_ctor(const fn_call& fn) // Constructor for ActionScript class XMLSocket { root* rm = fn.get_player()->get_root(); sprite_definition* empty_sprite_def = new sprite_definition(fn.get_player(), NULL); character* ch = new sprite_instance(fn.get_player(), empty_sprite_def, rm, rm->get_root_movie(), 0); fn.result->set_as_object(ch); }
// for asBroadcaster, ... void listener::notify(const tu_string& event_name, const fn_call& fn) { // may be called from multithread plugin ==> // we should check current root if (fn.get_player()->get_root() == NULL) { return; } // event handler may affects m_listeners using addListener & removeListener // iterate through a copy of it array< weak_ptr<as_object> > listeners(m_listeners); for (int i = 0, n = listeners.size(); i < n; i++) { smart_ptr<as_object> obj = listeners[i]; if (obj != NULL) // is listener destroyed ? { as_value function; if (obj->get_member(event_name, &function)) { call_method(function, fn.env, obj.get_ptr(), fn.nargs, fn.env->get_top_index()); } } } }
// Invokes the function represented by a Function object. // public call(thisObject:Object, [parameter1:Object]) : Object void as_s_function_call(const fn_call& fn) { assert(fn.this_ptr); if (fn.nargs > 0) { as_object* properties = fn.this_ptr; if (properties->m_this_ptr != NULL) { as_object* func = properties->m_this_ptr.get_ptr(); if (func) { as_environment env(fn.get_player()); int nargs = 0; if (fn.nargs > 1) { nargs = 1; env.push(fn.arg(1)); } *fn.result = call_method(func, &env, fn.arg(0).to_object(), nargs, env.get_top_index()); } } } }
void as_point_subtract(const fn_call& fn) { if (fn.nargs < 1) { return; } as_point* point = cast_to<as_point>(fn.this_ptr); if (point == NULL) { return; } if (fn.arg(0).to_object() == NULL) { return; } as_point* other_point = cast_to<as_point>(fn.arg(0).to_object()); if (other_point) { smart_ptr<as_point> obj; obj = new as_point(fn.get_player(), point->m_point.m_x - other_point->m_point.m_x, point->m_point.m_y - other_point->m_point.m_y); fn.result->set_as_object(obj.get_ptr()); } }
// Transform( mc:MovieClip ) void as_global_transform_ctor(const fn_call& fn) { if (fn.nargs == 1) { gc_ptr<as_transform> obj; if (character* movie = cast_to<character>(fn.arg(0).to_object())) { obj = new as_transform(fn.get_player(), movie); } fn.result->set_as_object(obj.get_ptr()); } }
void as_global_array_ctor(const fn_call& fn) // Constructor for ActionScript class Array. { smart_ptr<as_array> ao = new as_array(fn.get_player()); // case of "var x = ["abc","def", 1,2,3,4,..];" // called from "init array" operation only if (fn.nargs == -1 && fn.first_arg_bottom_index == -1) { // Use the arguments as initializers. int size = fn.env->pop().to_int(); as_value index_number; for (int i = 0; i < size; i++) { index_number.set_int(i); ao->set_member(index_number.to_string(), fn.env->pop()); } } else // case of "var x = new Array(777)" if (fn.nargs == 1) { // Create an empty array with the given number of undefined elements. int size = fn.arg(0).to_int(); as_value index_number; for (int i = 0; i < size; i++) { index_number.set_int(i); ao->set_member(index_number.to_string(), as_value()); } } else // case of "var x = new Array(1,2,3,4,5,6,7,8,..);" { assert(fn.env); // Use the arguments as initializers. as_value index_number; for (int i = 0; i < fn.nargs; i++) { index_number.set_int(i); ao->set_member(index_number.to_string(), fn.arg(i)); } } fn.result->set_as_object(ao.get_ptr()); }
void as_global_textformat_ctor(const fn_call& fn) { gc_ptr<as_textformat> obj = new as_textformat(fn.get_player()); assert(unsigned(fn.nargs) <= TU_ARRAYSIZE(as_global_textformat_ctor_paramnames)); // TODO: check parameters type for (int i = 0; i < fn.nargs; i++) { obj->set_member(as_global_textformat_ctor_paramnames[i], fn.arg(i)); } fn.result->set_as_object(obj.get_ptr()); }
// public static initialize(obj:Object) : Void // Adds event notification and listener management functionality to a given object. // This is a static method; it must be called by using the AsBroadcaster class void as_broadcaster_initialize(const fn_call& fn) { if (fn.nargs == 1) { as_object* obj = fn.arg(0).to_object(); if (obj) { obj->set_member("_listeners", new as_listener(fn.get_player())); obj->set_member("addListener", as_broadcast_addlistener); obj->set_member("removeListener", as_broadcast_removelistener); obj->set_member("broadcastMessage", as_broadcast_sendmessage); } } }
// Point(x:Number, y:Number) void as_global_point_ctor(const fn_call& fn) { smart_ptr<as_point> obj; float x = 0.0f; float y = 0.0f; if (fn.nargs == 2) { y = fn.arg(1).to_float(); x = fn.arg(0).to_float(); } obj = new as_point(fn.get_player(), x, y); fn.result->set_as_object(obj.get_ptr()); }
void as_mcloader_getprogress(const fn_call& fn) { if (fn.nargs == 1) { sprite_instance* m = cast_to<sprite_instance>(fn.arg(0).to_object()); if (m) { as_object* info = new as_object(fn.get_player()); info->set_member("bytesLoaded", (int) m->get_loaded_bytes()); info->set_member("bytesTotal", (int) m->get_file_bytes()); fn.result->set_as_object(info); return; } } fn.result->set_as_object(NULL); }
// Sound([target:Object]) // Creates a new Sound object for a specified movie clip. void as_global_sound_ctor(const fn_call& fn) { smart_ptr<as_sound> snd = new as_sound(fn.get_player()); if (fn.nargs > 0) { assert(fn.env); snd->m_target = cast_to<character>(fn.env->find_target(fn.arg(0))); } // methods snd->builtin_member("attachSound", sound_attach); snd->builtin_member("start", sound_start); snd->builtin_member("stop", sound_stop); snd->builtin_member("setVolume", sound_volume); snd->builtin_member("loadSound", sound_load); snd->builtin_member("position", as_value(get_position, NULL)); fn.result->set_as_object(snd.get_ptr()); }
// setInterval(functionReference:Function, interval:Number, [param1:Object, param2, ..., paramN]) : Number // setInterval(objectReference:Object, methodName:String, interval:Number, [param1:Object, param2, ..., paramN]) : Number void as_global_setinterval(const fn_call& fn) { if (fn.nargs >= 2) { gc_ptr<as_timer> t = new as_timer(fn.get_player()); int first_arg_index = 2; if (fn.arg(0).is_function()) { t->m_func = fn.arg(0).to_function(); t->m_interval = fn.arg(1).to_float() / 1000.0f; assert(fn.env); t->m_this_ptr = fn.env->get_target(); } else if (fn.arg(0).to_object() != NULL) { as_value func; as_object* this_ptr = fn.arg(0).to_object(); this_ptr->get_member(fn.arg(1).to_tu_string(), &func); t->m_func = func.to_function(); t->m_interval = fn.arg(2).to_float() / 1000.0f; t->m_this_ptr = this_ptr; first_arg_index = 3; } else { // invalid args return; } // pass args t->m_arg.resize(fn.nargs - first_arg_index); for (int i = first_arg_index; i < fn.nargs; i++) { t->m_arg.push_back(fn.arg(i)); } fn.get_root()->add_listener(t); fn.result->set_as_object(t); } }
// public loadSound(url:String, isStreaming:Boolean) : Void void sound_load(const fn_call& fn) { if (fn.nargs > 1) { sound_handler* s = get_sound_handler(); if (s != NULL) { as_sound* snd = cast_to<as_sound>(fn.this_ptr); assert(snd); tu_string full_url = get_full_url(fn.get_player()->get_workdir(), fn.arg(0).to_string()); int id = s->load_sound(full_url.c_str()); if (id >= 0) { snd->clear(); snd->m_id = id; snd->m_is_loaded_sound = true; } } } }
void as_global_netstream_ctor(const fn_call& fn) // Constructor for ActionScript class NetStream. { as_object* netstream = new as_netstream(fn.get_player()); // properties netstream->builtin_member("time", as_value(netstream_time, as_value())); netstream->builtin_member("bufferLength", as_value(netstream_buffer_length, as_value())); netstream->builtin_member("bufferTime", as_value(netstream_buffer_time, as_value())); // methods netstream->builtin_member("close", netstream_close); netstream->builtin_member("pause", netstream_pause); netstream->builtin_member("play", netstream_play); netstream->builtin_member("seek", netstream_seek); netstream->builtin_member("setbuffertime", netstream_setbuffertime); // gameswf extension, video width & height netstream->builtin_member("_width", as_value(netstream_video_width, as_value())); netstream->builtin_member("_height", as_value(netstream_video_height, as_value())); fn.result->set_as_object(netstream); }
void as_global_assetpropflags(const fn_call& fn) // Undocumented ASSetPropFlags function // Works only for as_object for now { int version = fn.get_player()->get_root()->get_movie_version(); // Check the arguments assert(fn.nargs == 3 || fn.nargs == 4); assert((version == 5) ? (fn.nargs == 3) : true); // object as_object* obj = fn.arg(0).to_object(); if (obj == NULL) { log_error("error: assetpropflags for NULL object\n"); return; } // The second argument is a list of child names, // may be in the form array(like ["abc", "def", "ggggg"]) or in the form a string(like "abc, def, ggggg") // the NULL second parameter means that assetpropflags is applied to all children as_object* props = fn.arg(1).to_object(); int as_prop_flags_mask = 7; // DONT_ENUM | DONT_DELETE | READ_ONLY; // a number which represents three bitwise flags which // are used to determine whether the list of child names should be hidden, // un-hidden, protected from over-write, un-protected from over-write, // protected from deletion and un-protected from deletion int true_flags = fn.arg(2).to_int() & as_prop_flags_mask; // Is another integer bitmask that works like true_flags, // except it sets the attributes to false. The // false_flags bitmask is applied before true_flags is applied // ASSetPropFlags was exposed in Flash 5, however the fourth argument 'false_flags' // was not required as it always defaulted to the value '~0'. int false_flags = (fn.nargs == 3 ? (version == 5 ? ~0 : 0) : fn.arg(3).to_int()) & as_prop_flags_mask; // Evan: it seems that if true_flags == 0 and false_flags == 0, this function // acts as if the parameters where (object, null, 0x1, 0) ... if (false_flags == 0 && true_flags == 0) { props = NULL; false_flags = 0; true_flags = 0x1; } if (props == NULL) { // Takes all members of the object and sets its property flags for (stringi_hash<as_value>::const_iterator it = obj->m_members.begin(); it != obj->m_members.end(); ++it) { const as_value& val = it->second; int flags = val.get_flags(); flags = flags & (~false_flags); flags |= true_flags; val.set_flags(flags); } } else { // Takes all string type prop and sets property flags of obj[prop] for (stringi_hash<as_value>::const_iterator it = props->m_members.begin(); it != props->m_members.end(); ++it) { const as_value& key = it->second; if (key.is_string()) { stringi_hash<as_value>::iterator obj_it = obj->m_members.find(key.to_tu_string()); if (obj_it != obj->m_members.end()) { const as_value& val = obj_it->second; int flags = val.get_flags(); flags = flags & (~false_flags); flags |= true_flags; val.set_flags(flags); } } } } }
void as_global_xmlsock_ctor(const fn_call& fn) // Constructor for ActionScript class XMLSocket { fn.result->set_as_object(new as_xmlsock(fn.get_player())); }
void as_global_mcloader_ctor(const fn_call& fn) // Constructor for ActionScript class MovieClipLoader { fn.result->set_as_object(new as_mcloader(fn.get_player())); }
// Date([yearOrTimevalue:Number], [month:Number], [date:Number], // [hour:Number], [minute:Number], [second:Number], [millisecond:Number]) as_date::as_date(const fn_call& fn) : as_object(fn.get_player()) { // reset if there are args if (fn.nargs > 0) { int arg = fn.arg(0).to_int(); set(FULLYEAR, arg); if (fn.nargs > 1) { arg = fn.arg(1).to_int(); set(MON, arg); if (fn.nargs > 2) { arg = fn.arg(2).to_int(); set(MDAY, arg); if (fn.nargs > 3) { arg = fn.arg(3).to_int(); set(HOUR, arg); if (fn.nargs > 4) { arg = fn.arg(4).to_int(); set(MIN, arg); if (fn.nargs > 5) { arg = fn.arg(5).to_int(); set(SEC, arg); } } } } } } builtin_member("getTime", as_date_gettime); builtin_member("setTime", as_date_settime); builtin_member("getYear", as_date_getyear); builtin_member("setYear", as_date_setyear); builtin_member("getMonth", as_date_getmonth); builtin_member("setMonth", as_date_setmonth); builtin_member("getDate", as_date_getdate); builtin_member("setDate", as_date_setdate); builtin_member("getDay", as_date_getday); builtin_member("setDay", as_date_setday); builtin_member("getFullYear", as_date_getfullyear); builtin_member("setFullYear", as_date_setfullyear); builtin_member("getHours", as_date_gethours); builtin_member("setHours", as_date_sethours); builtin_member("getMilliseconds", as_date_getmilli); builtin_member("setMilliseconds", as_date_setmilli); builtin_member("getMinutes", as_date_getminutes); builtin_member("setMinutes", as_date_setminutes); builtin_member("getSeconds", as_date_getseconds); builtin_member("setSeconds", as_date_setseconds); }
void as_global_netconnection_ctor(const fn_call& fn) // Constructor for ActionScript class NetConnection. { fn.result->set_as_object(new as_netconnection(fn.get_player())); }
void as_global_object_ctor(const fn_call& fn) // Constructor for ActionScript class Object. { fn.result->set_as_object(new as_object(fn.get_player())); }
void string_split(const fn_call& fn) { const tu_string& this_str = fn.this_value.to_tu_string(); gc_ptr<as_array> arr = new as_array(fn.get_player()); tu_string delimiter; if (fn.nargs >= 1) { delimiter = fn.arg(0).to_string(); } int max_count = this_str.utf8_length(); if (fn.nargs >= 2) { max_count = fn.arg(1).to_int(); } const char* p = this_str.c_str(); const char* word_start = p; for (int i = 0; i < max_count; ) { const char* n = p; if (delimiter.size() == 0) { utf8::decode_next_unicode_character(&n); if (n == p) { break; } tu_string word(p, (int) (n - p)); as_value val; as_value index(i); val.set_tu_string(word); arr->set_member(index.to_tu_string(), val); p = n; i++; } else { bool match = strncmp(p, delimiter.c_str(), delimiter.size()) == 0; if (*p == 0 || match) { // Emit the previous word. tu_string word(word_start, int(p - word_start)); as_value val; as_value index(i); val.set_tu_string(word); arr->set_member(index.to_tu_string(), val); i++; if (match) { // Skip the delimiter. p += delimiter.size(); word_start = p; } if (*p == 0) { break; } } else { utf8::decode_next_unicode_character(&p); } } } fn.result->set_as_object(arr.get_ptr()); }