📄 gameswf_action.cpp
字号:
const char* p = method_arg_fmt; for (;; p++) { char c = *p; if (c == 0) { // End of args. break; } else if (c == '%') { p++; c = *p; // Here's an arg. if (c == 'd') { // Integer. env->push(va_arg(args, int)); } else if (c == 'f') { // Double env->push(va_arg(args, double)); } else if (c == 's') { // String env->push(va_arg(args, const char *)); } else if (c == 'l') { p++; c = *p; if (c == 's') { // Wide string. env->push(va_arg(args, const wchar_t *)); } else { log_error("call_method_parsed('%s','%s') -- invalid fmt '%%l%c'\n", method_name, method_arg_fmt, c); } } else { // Invalid fmt, warn. log_error("call_method_parsed('%s','%s') -- invalid fmt '%%%c'\n", method_name, method_arg_fmt, c); } } else { // Ignore whitespace and commas. if (c == ' ' || c == '\t' || c == ',') { // OK } else { // Invalid arg; warn. log_error("call_method_parsed('%s','%s') -- invalid char '%c'\n", method_name, method_arg_fmt, c); } } } array<with_stack_entry> dummy_with_stack; as_value method = env->get_variable(method_name, dummy_with_stack); // check method // Reverse the order of pushed args int nargs = env->get_top_index() - starting_index; for (int i = 0; i < (nargs >> 1); i++) { int i0 = starting_index + 1 + i; int i1 = starting_index + nargs - i; assert(i0 < i1); swap(&(env->bottom(i0)), &(env->bottom(i1))); } // Do the call. as_value result = call_method(method, env, this_ptr, nargs, env->get_top_index()); env->drop(nargs); // Return pointer to static string for return value. static tu_string s_retval; s_retval = result.to_tu_string(); return s_retval.c_str(); } // // sound object // struct sound_as_object : public as_object { tu_string sound; int sound_id; }; void movie_load() { IF_VERBOSE_ACTION(log_msg("-- start movie \n")); } void sound_start(const fn_call& fn) { IF_VERBOSE_ACTION(log_msg("-- start sound \n")); sound_handler* s = get_sound_handler(); if (s != NULL) { sound_as_object* so = (sound_as_object*) (as_object*) fn.this_ptr; assert(so); s->play_sound(so->sound_id, 0); } } void sound_stop(const fn_call& fn) { IF_VERBOSE_ACTION(log_msg("-- stop sound \n")); sound_handler* s = get_sound_handler(); if (s != NULL) { sound_as_object* so = (sound_as_object*) (as_object*) fn.this_ptr; assert(so); s->stop_sound(so->sound_id); } } void sound_attach(const fn_call& fn) { IF_VERBOSE_ACTION(log_msg("-- attach sound \n")); if (fn.nargs < 1) { log_error("attach sound needs one argument\n"); return; } sound_as_object* so = (sound_as_object*) (as_object*) fn.this_ptr; assert(so); so->sound = fn.arg(0).to_tu_string(); // check the import. movie_definition_sub* def = (movie_definition_sub*) fn.env->get_target()->get_root_movie()->get_movie_definition(); assert(def); smart_ptr<resource> res = def->get_exported_resource(so->sound); if (res == NULL) { log_error("import error: resource '%s' is not exported\n", so->sound.c_str()); return; } int si = 0; sound_sample_impl* ss = (sound_sample_impl*) res->cast_to_sound_sample(); if (ss != NULL) { si = ss->m_sound_handler_id; } else { log_error("sound sample is NULL\n"); return; } // sanity check assert(si >= 0 && si < 1000); so->sound_id = si; } // // Built-in objects // // // math object //#if 0 // One-argument simple functions. #define MATH_WRAP_FUNC1(funcname) \ void math_##funcname(as_value* result, as_object_interface* this_ptr, \ as_environment* env, int nargs, int first_arg_bottom_index) \ { \ double arg = env->bottom(first_arg_bottom_index).to_number(); \ result->set_double(funcname(arg)); \ }#else // One-argument simple functions. #define MATH_WRAP_FUNC1(funcname) \ void math_##funcname(const fn_call& fn) \ { \ double arg = fn.arg(0).to_number(); \ fn.result->set_double(funcname(arg)); \ }#endif MATH_WRAP_FUNC1(fabs); MATH_WRAP_FUNC1(acos); MATH_WRAP_FUNC1(asin); MATH_WRAP_FUNC1(atan); MATH_WRAP_FUNC1(ceil); MATH_WRAP_FUNC1(cos); MATH_WRAP_FUNC1(exp); MATH_WRAP_FUNC1(floor); MATH_WRAP_FUNC1(log); MATH_WRAP_FUNC1(sin); MATH_WRAP_FUNC1(sqrt); MATH_WRAP_FUNC1(tan);#if 0 // Two-argument functions. #define MATH_WRAP_FUNC2_EXP(funcname, expr) \ void math_##funcname(as_value* result, as_object_interface* this_ptr, as_environment* env, int nargs, int first_arg_bottom_index) \ { \ double arg0 = env->bottom(first_arg_bottom_index).to_number(); \ double arg1 = env->bottom(first_arg_bottom_index - 1).to_number(); \ result->set_double(expr); \ }#else // Two-argument functions. #define MATH_WRAP_FUNC2_EXP(funcname, expr) \ void math_##funcname(const fn_call& fn) \ { \ double arg0 = fn.arg(0).to_number(); \ double arg1 = fn.arg(1).to_number(); \ fn.result->set_double(expr); \ }#endif MATH_WRAP_FUNC2_EXP(atan2, (atan2(arg0, arg1))); MATH_WRAP_FUNC2_EXP(max, (arg0 > arg1 ? arg0 : arg1)); MATH_WRAP_FUNC2_EXP(min, (arg0 < arg1 ? arg0 : arg1)); MATH_WRAP_FUNC2_EXP(pow, (pow(arg0, arg1))); // A couple of oddballs. void math_random(const fn_call& fn) { // Random number between 0 and 1. fn.result->set_double(tu_random::next_random() / double(Uint32(0x0FFFFFFFF))); } void math_round(const fn_call& fn) { // round argument to nearest int. double arg0 = fn.arg(0).to_number(); fn.result->set_double(floor(arg0 + 0.5)); } void math_init() { // Create built-in math object. as_object* math_obj = new as_object; // constant math_obj->set_member("e", 2.7182818284590452354); math_obj->set_member("ln2", 0.69314718055994530942); math_obj->set_member("log2e", 1.4426950408889634074); math_obj->set_member("ln10", 2.30258509299404568402); math_obj->set_member("log10e", 0.43429448190325182765); math_obj->set_member("pi", 3.14159265358979323846); math_obj->set_member("sqrt1_2", 0.7071067811865475244); math_obj->set_member("sqrt2", 1.4142135623730950488); // math methods math_obj->set_member("abs", &math_fabs); math_obj->set_member("acos", &math_acos); math_obj->set_member("asin", &math_asin); math_obj->set_member("atan", &math_atan); math_obj->set_member("ceil", &math_ceil); math_obj->set_member("cos", &math_cos); math_obj->set_member("exp", &math_exp); math_obj->set_member("floor", &math_floor); math_obj->set_member("log", &math_log); math_obj->set_member("random", &math_random); math_obj->set_member("round", &math_round); math_obj->set_member("sin", &math_sin); math_obj->set_member("sqrt", &math_sqrt); math_obj->set_member("tan", &math_tan); math_obj->set_member("atan2", &math_atan2); math_obj->set_member("max", &math_max); math_obj->set_member("min", &math_min); math_obj->set_member("pow", &math_pow); s_global->set_member("math", math_obj); } void event_test(const fn_call& fn) { log_msg("FIXME: %s\n", __FUNCTION__); } // // key object // struct key_as_object : public as_object { Uint8 m_keymap[key::KEYCOUNT / 8 + 1]; // bit-array array<weak_ptr<as_object_interface> > m_listeners; int m_last_key_pressed; key_as_object() : m_last_key_pressed(0) { memset(m_keymap, 0, sizeof(m_keymap)); } bool is_key_down(int code) { if (code < 0 || code >= key::KEYCOUNT) return false; int byte_index = code >> 3; int bit_index = code - (byte_index << 3); int mask = 1 << bit_index; assert(byte_index >= 0 && byte_index < int(sizeof(m_keymap)/sizeof(m_keymap[0]))); if (m_keymap[byte_index] & mask) { return true; } else { return false; } } void set_key_down(int code) { if (code < 0 || code >= key::KEYCOUNT) return; m_last_key_pressed = code; int byte_index = code >> 3; int bit_index = code - (byte_index << 3); int mask = 1 << bit_index; assert(byte_index >= 0 && byte_index < int(sizeof(m_keymap)/sizeof(m_keymap[0]))); m_keymap[byte_index] |= mask; // Notify listeners. int i; int n = m_listeners.size(); for (i = 0; i < n; i++) { smart_ptr<as_object_interface> listener = m_listeners[i]; as_value method; if (listener != NULL && listener->get_member(event_id(event_id::KEY_DOWN).get_function_name(), &method)) { call_method(method, NULL /* or root? */, listener.get_ptr(), 0, 0); } } } void set_key_up(int code) { if (code < 0 || code >= key::KEYCOUNT) return; int byte_index = code >> 3; int bit_index = code - (byte_index << 3); int mask = 1 << bit_index; assert(byte_index >= 0 && byte_index < int(sizeof(m_keymap)/sizeof(m_keymap[0]))); m_keymap[byte_index] &= ~mask; // Notify listeners. for (int i = 0, n = m_listeners.size(); i < n; i++) { smart_ptr<as_object_interface> listener = m_listeners[i]; as_value method; if (listener != NULL && listener->get_member(event_id(event_id::KEY_UP).get_function_name(), &method)) { call_method(method, NULL /* or root? */, listener.get_ptr(), 0, 0); } } } void cleanup_listeners() // Remove dead entries in the listeners list. (Since // we use weak_ptr's, listeners can disappear without // notice.) { for (int i = m_listeners.size() - 1; i >= 0; i--) { if (m_listeners[i] == NULL) { m_listeners.remove(i); } } } void add_listener(as_object_interface* listener) { cleanup_listeners(); for (int i = 0, n = m_listeners.size(); i < n; i++) { if (m_listeners[i] == listener) { // Already in the list. return; } } m_listeners.push_back(listener); } void remove_listener(as_object_interface* listener) { cleanup_listeners(); for (int i = m_listeners.size() - 1; i >= 0; i--) { if (m_listeners[i] == listener) { m_listeners.remove(i); } } } int get_last_key_pressed() const { return m_last_key_pressed; } }; void key_add_listener(const fn_call& fn) // Add a listener (first arg is object reference) to our list. // Listeners will have "onKeyDown" and "onKeyUp" methods // called on them when a key changes state. { if (fn.nargs < 1) { log_error("key_add_listener needs one argument (the listener object)\n"); return; } as_object_interface* listener = fn.arg(0).to_object(); if (listener == NULL) { log_error("key_add_listener passed a NULL object; ignored\n"); return; } key_as_object* ko = (key_as_object*) (as_object*) fn.this_ptr; assert(ko); ko->add_listener(listener); } void key_get_ascii(const fn_call& fn) // Return the ascii value of the last key pressed. { key_as_object* ko = (key_as_object*) (as_object*) fn.this_ptr; assert(ko); fn.result->set_undefined(); int code = ko->get_last_key_pressed(); if (code > 0) { // @@ Crude for now; just jamming the key code in a string, as a character. // Need to apply shift/capslock/numlock, etc... char buf[2]; buf[0] = (char) code; buf[1] = 0; fn.result->set_string(buf); } } void key_get_code(const fn_call& fn) // Returns the keycode of the last key pressed. { key_as_object* ko = (key_as_object*) (as_object*) fn.this_ptr; assert(ko); fn.result->set_int(ko->get_last_key_pressed()); } void key_is_down(const fn_call& fn) // Return true if the specified (first arg keycode) key is pressed. { if (fn.nargs < 1) { log_error("key_is_down needs one argument (the key code)\n"); return; } int code = (int) fn.arg(0).to_number(); key_as_object* ko = (key_as_object*) (as_object*) fn.this_ptr; assert(ko); fn.result->set_bool(ko->is_key_down(code)); } void key_is_toggled(const fn_call& fn) // Given the keycode of NUM_LOCK or CAPSLOCK, returns true if // the associated state is on. { // @@ TODO fn.result->set_bool(false); } void key_remove_listener(const fn_call& fn) // Remove a previously-added listener.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -