⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameswf_action.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// gameswf_action.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2003// This source code has been donated to the Public Domain.  Do// whatever you want with it.// Implementation and helpers for SWF actions.#include "gameswf_action.h"#include "gameswf_impl.h"#include "gameswf_log.h"#include "gameswf_stream.h"#include "base/tu_random.h"#include "gameswf_string.h"#include "gameswf_movie.h"#include "gameswf_timers.h"#include "gameswf_textformat.h"#include "gameswf_sound.h"#ifdef HAVE_LIBXML#include "gameswf_xml.h"#include "gameswf_xmlsocket.h"#endif#ifdef _WIN32#define snprintf _snprintf#endif // _WIN32// NOTES://// Buttons// on (press)                 onPress// on (release)               onRelease// on (releaseOutside)        onReleaseOutside// on (rollOver)              onRollOver// on (rollOut)               onRollOut// on (dragOver)              onDragOver// on (dragOut)               onDragOut// on (keyPress"...")         onKeyDown, onKeyUp      <----- IMPORTANT//// Sprites// onClipEvent (load)         onLoad// onClipEvent (unload)       onUnload                Hm.// onClipEvent (enterFrame)   onEnterFrame// onClipEvent (mouseDown)    onMouseDown// onClipEvent (mouseUp)      onMouseUp// onClipEvent (mouseMove)    onMouseMove// onClipEvent (keyDown)      onKeyDown// onClipEvent (keyUp)        onKeyUp// onClipEvent (data)         onData// Text fields have event handlers too!// Sprite built in methods:// play()// stop()// gotoAndStop()// gotoAndPlay()// nextFrame()// startDrag()// getURL()// getBytesLoaded()// getBytesTotal()// Built-in functions: (do these actually exist in the VM, or are they just opcodes?)// Number()// String()// TODO builtins//// Number.toString() -- takes an optional arg that specifies the base//// parseInt(), parseFloat()//// Boolean() type cast//// typeof operator --> "number", "string", "boolean", "object" (also// for arrays), "null", "movieclip", "function", "undefined"//// isNaN()//// Number.MAX_VALUE, Number.MIN_VALUE//// String.fromCharCode()namespace gameswf{		//	// action stuff	//	void	action_init();	// Statics.	bool	s_inited = false;	smart_ptr<as_object>	s_global;	fscommand_callback	s_fscommand_handler = NULL;#define EXTERN_MOVIE	#ifdef EXTERN_MOVIE	void attach_extern_movie(const char* url, const movie* target, const movie* root_movie)	{		tu_string infile = get_workdir();		infile += url;		movie_definition_sub*	md = create_library_movie_sub(infile.c_str());		if (md == NULL)		{			log_error("can't create movie_definition_sub for %s\n", infile.c_str());			return;		}		gameswf::movie_interface* extern_movie;		if (target == root_movie)		{			extern_movie = create_library_movie_inst_sub(md);						if (extern_movie == NULL)			{				log_error("can't create extern root movie_interface for %s\n", infile.c_str());				return;			}			set_current_root(extern_movie);			movie* m = extern_movie->get_root_movie();			m->on_event(event_id::LOAD);		}		else		{			extern_movie = md->create_instance();			if (extern_movie == NULL)			{				log_error("can't create extern movie_interface for %s\n", infile.c_str());				return;			}      			save_extern_movie(extern_movie);      			character* tar = (character*)target;			const char* name = tar->get_name();			Uint16 depth = tar->get_depth();			bool use_cxform = false;			cxform color_transform =  tar->get_cxform();			bool use_matrix = false;			matrix mat = tar->get_matrix();			float ratio = tar->get_ratio();			Uint16 clip_depth = tar->get_clip_depth();			movie* parent = tar->get_parent();			movie* new_movie = extern_movie->get_root_movie();			assert(parent != NULL);			((character*)new_movie)->set_parent(parent);       			parent->replace_display_object(				(character*) new_movie,				name,				depth,				use_cxform,				color_transform,				use_matrix,				mat,				ratio,				clip_depth);		}	}#endif // EXTERN_MOVIE	void	register_fscommand_callback(fscommand_callback handler)	// External interface.	{		s_fscommand_handler = handler;	}	static bool string_to_number(double* result, const char* str)	// Utility.  Try to convert str to a number.  If successful,	// put the result in *result, and return true.  If not	// successful, put 0 in *result, and return false.	{		char* tail = 0;		*result = strtod(str, &tail);		if (tail == str || *tail != 0)		{			// Failed conversion to Number.			return false;		}		return true;	}	//	// array object	//	struct as_array_object : public as_object	{// @@ TODO//		as_array_object()//		{//			this->set_member("length", &array_not_impl);//			this->set_member("join", &array_not_impl);//			this->set_member("concat", &array_not_impl);//			this->set_member("slice", &array_not_impl);//			this->set_member("push", &array_not_impl);//			this->set_member("unshift", &array_not_impl);//			this->set_member("pop", &array_not_impl);//			this->set_member("shift", &array_not_impl);//			this->set_member("splice", &array_not_impl);//			this->set_member("sort", &array_not_impl);//			this->set_member("sortOn", &array_not_impl);//			this->set_member("reverse", &array_not_impl);//			this->set_member("toString", &array_not_impl);//		}	};	void	array_not_impl(const fn_call& fn)	{		log_error("array methods not implemented yet\n");	}	//	// as_as_function	//	void	as_as_function::operator()(const fn_call& fn)	// Dispatch.	{		as_environment*	our_env = m_env;		if (our_env == NULL)		{			our_env = fn.env;		}		assert(our_env);		// Set up local stack frame, for parameters and locals.		int	local_stack_top = our_env->get_local_frame_top();		our_env->add_frame_barrier();		if (m_is_function2 == false)		{			// Conventional function.			// Push the arguments onto the local frame.			int	args_to_pass = imin(fn.nargs, m_args.size());			for (int i = 0; i < args_to_pass; i++)			{				assert(m_args[i].m_register == 0);				our_env->add_local(m_args[i].m_name, fn.arg(i));			}		}		else		{			// function2: most args go in registers; any others get pushed.						// Create local registers.			our_env->add_local_registers(m_local_register_count);			// Handle the explicit args.			int	args_to_pass = imin(fn.nargs, m_args.size());			for (int i = 0; i < args_to_pass; i++)			{				if (m_args[i].m_register == 0)				{					// Conventional arg passing: create a local var.					our_env->add_local(m_args[i].m_name, fn.arg(i));				}				else				{					// Pass argument into a register.					int	reg = m_args[i].m_register;					*(our_env->local_register_ptr(reg)) = fn.arg(i);				}			}			// Handle the implicit args.			int	current_reg = 1;			if (m_function2_flags & 0x01)			{				// preload 'this' into a register.				(*(our_env->local_register_ptr(current_reg))).set_as_object_interface(our_env->m_target);				current_reg++;			}			if (m_function2_flags & 0x02)			{				// Don't put 'this' into a local var.			}			else			{				// Put 'this' in a local var.				our_env->add_local("this", as_value(our_env->m_target));			}			// Init arguments array, if it's going to be needed.			smart_ptr<as_array_object>	arg_array;			if ((m_function2_flags & 0x04) || ! (m_function2_flags & 0x08))			{				arg_array = new as_array_object;				as_value	index_number;				for (int i = 0; i < fn.nargs; i++)				{					index_number.set_int(i);					arg_array->set_member(index_number.to_string(), fn.arg(i));				}			}			if (m_function2_flags & 0x04)			{				// preload 'arguments' into a register.				(*(our_env->local_register_ptr(current_reg))).set_as_object_interface(arg_array.get_ptr());				current_reg++;			}			if (m_function2_flags & 0x08)			{				// Don't put 'arguments' in a local var.			}			else			{				// Put 'arguments' in a local var. 				our_env->add_local("arguments", as_value(arg_array.get_ptr()));			}			if (m_function2_flags & 0x10)			{				// Put 'super' in a register.				log_error("TODO: implement 'super' in function2 dispatch (reg)\n");				current_reg++;			}			if (m_function2_flags & 0x20)			{				// Don't put 'super' in a local var.			}			else			{				// Put 'super' in a local var.				log_error("TODO: implement 'super' in function2 dispatch (var)\n");			}			if (m_function2_flags & 0x40)			{				// Put '_root' in a register.				(*(our_env->local_register_ptr(current_reg))).set_as_object_interface(					our_env->m_target->get_root_movie());				current_reg++;			}			if (m_function2_flags & 0x80)			{				// Put '_parent' in a register.				array<with_stack_entry>	dummy;				as_value	parent = our_env->get_variable("_parent", dummy);				(*(our_env->local_register_ptr(current_reg))) = parent;				current_reg++;			}			if (m_function2_flags & 0x100)			{				// Put '_global' in a register.				(*(our_env->local_register_ptr(current_reg))).set_as_object_interface(s_global.get_ptr());				current_reg++;			}		}		// Execute the actions.		m_action_buffer->execute(our_env, m_start_pc, m_length, fn.result, m_with_stack, m_is_function2);		// Clean up stack frame.		our_env->set_local_frame_top(local_stack_top);		if (m_is_function2)		{			// Clean up the local registers.			our_env->drop_local_registers(m_local_register_count);		}	}	//	// Function/method dispatch.	//	as_value	call_method(		const as_value& method,		as_environment* env,		as_object_interface* this_ptr,		int nargs,		int first_arg_bottom_index)	// first_arg_bottom_index is the stack index, from the bottom, of the first argument.	// Subsequent arguments are at *lower* indices.  E.g. if first_arg_bottom_index = 7,	// then arg1 is at env->bottom(7), arg2 is at env->bottom(6), etc.	{		as_value	val;		as_c_function_ptr	func = method.to_c_function();		if (func)		{			// It's a C function.  Call it.			(*func)(fn_call(&val, this_ptr, env, nargs, first_arg_bottom_index));		}		else if (as_as_function* as_func = method.to_as_function())		{			// It's an ActionScript function.  Call it.			(*as_func)(fn_call(&val, this_ptr, env, nargs, first_arg_bottom_index));		}		else		{			log_error("error in call_method(): method is not a function\n");		}		return val;	}	as_value	call_method0(		const as_value& method,		as_environment* env,		as_object_interface* this_ptr)	{		return call_method(method, env, this_ptr, 0, env->get_top_index() + 1);	}			const char*	call_method_parsed(		as_environment* env,		as_object_interface* this_ptr,		const char* method_name,		const char* method_arg_fmt,		va_list args)	// Printf-like vararg interface for calling ActionScript.	// Handy for external binding.	{		log_msg("FIXME(%d): %s\n", __LINE__, __FUNCTION__);#if 0		static const int	BUFSIZE = 1000;		char	buffer[BUFSIZE];		array<const char*>	tokens;		// Brutal crap parsing.  Basically null out any		// delimiter characters, so that the method name and		// args sit in the buffer as null-terminated C		// strings.  Leave an intial ' character as the first		// char in a string argument.		// Don't verify parens or matching quotes or anything.		{			strncpy(buffer, method_call, BUFSIZE);			buffer[BUFSIZE - 1] = 0;			char*	p = buffer;			char	in_quote = 0;			bool	in_arg = false;			for (;; p++)			{				char	c = *p;				if (c == 0)				{					// End of string.					break;				}				else if (c == in_quote)				{					// End of quotation.					assert(in_arg);					*p = 0;					in_quote = 0;					in_arg = false;				}				else if (in_arg)				{					if (in_quote == 0)					{						if (c == ')' || c == '(' || c == ',' || c == ' ')						{							// End of arg.							*p = 0;							in_arg = false;						}					}				}				else				{					// Not in arg.  Watch for start of arg.					assert(in_quote == 0);					if (c == '\'' || c == '\"')					{						// Start of quote.						in_quote = c;						in_arg = true;						*p = '\'';	// ' at the start of the arg, so later we know this is a string.						tokens.push_back(p);					}					else if (c == ' ' || c == ',')					{						// Non-arg junk, null it out.						*p = 0;					}					else					{						// Must be the start of a numeric arg.						in_arg = true;						tokens.push_back(p);					}				}			}		}#endif // 0		// Parse va_list args		int	starting_index = env->get_top_index();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -