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

📄 gameswf_button.cpp

📁 一个开源的嵌入式flash播放器 具体看文档和例子就可
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// gameswf_button.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2003// This source code has been donated to the Public Domain.  Do// whatever you want with it.// SWF buttons.  Mouse-sensitive update/display, actions, etc.#include "gameswf_button.h"#include "gameswf_action.h"#include "gameswf_render.h"#include "gameswf_sound.h"#include "gameswf_stream.h"/*Observations about button & mouse behaviorEntities that receive mouse events: only buttons and sprites, AFAIKWhen the mouse button goes down, it becomes "captured" by whateverelement is topmost, directly below the mouse at that moment.  Whilethe mouse is captured, no other entity receives mouse events,regardless of how the mouse or other elements move.The mouse remains captured until the mouse button goes up.  The mouseremains captured even if the element that captured it is removed fromthe display list.If the mouse isn't above a button or sprite when the mouse button goesdown, then the mouse is captured by the background (i.e. mouse eventsjust don't get sent, until the mouse button goes up again).Mouse events:+------------------+---------------+-------------------------------------+| Event            | Mouse Button  | description                         |=========================================================================| onRollOver       |     up        | sent to topmost entity when mouse   ||                  |               | cursor initially goes over it       |+------------------+---------------+-------------------------------------+| onRollOut        |     up        | when mouse leaves entity, after     ||                  |               | onRollOver                          |+------------------+---------------+-------------------------------------+| onPress          |  up -> down   | sent to topmost entity when mouse   ||                  |               | button goes down.  onRollOver       ||                  |               | always precedes onPress.  Initiates ||                  |               | mouse capture.                      |+------------------+---------------+-------------------------------------+| onRelease        |  down -> up   | sent to active entity if mouse goes ||                  |               | up while over the element           |+------------------+---------------+-------------------------------------+| onDragOut        |     down      | sent to active entity if mouse      ||                  |               | is no longer over the entity        |+------------------+---------------+-------------------------------------+| onReleaseOutside |  down -> up   | sent to active entity if mouse goes ||                  |               | up while not over the entity.       ||                  |               | onDragOut always precedes           ||                  |               | onReleaseOutside                    |+------------------+---------------+-------------------------------------+| onDragOver       |     down      | sent to active entity if mouse is   ||                  |               | dragged back over it after          ||                  |               | onDragOut                           |+------------------+---------------+-------------------------------------+There is always one active entity at any given time (considering NULL tobe an active entity, representing the background, and other objects thatdon't receive mouse events).When the mouse button is up, the active entity is the topmost elementdirectly under the mouse pointer.When the mouse button is down, the active entity remains whatever itwas when the button last went down.The active entity is the only object that receives mouse events.!!! The "trackAsMenu" property alters this behavior!  If trackAsMenuis set on the active entity, then onReleaseOutside is filtered out,and onDragOver from another entity is allowed (from the background, oranother trackAsMenu entity). !!!Pseudocode:active_entity = NULLmouse_button_state = UPmouse_inside_entity_state = falseframe loop:  if mouse_button_state == DOWN    // Handle trackAsMenu    if (active_entity->trackAsMenu)      possible_entity = topmost entity below mouse      if (possible_entity != active_entity && possible_entity->trackAsMenu)        // Transfer to possible entity	active_entity = possible_entity	active_entity->onDragOver()	mouse_inside_entity_state = true;    // Handle onDragOut, onDragOver    if (mouse_inside_entity_state == false)      if (mouse is actually inside the active_entity)        // onDragOver	active_entity->onDragOver()        mouse_inside_entity_state = true;    else // mouse_inside_entity_state == true      if (mouse is actually outside the active_entity)        // onDragOut	active_entity->onDragOut()	mouse_inside_entity_state = false;    // Handle onRelease, onReleaseOutside    if (mouse button is up)      if (mouse_inside_entity_state)        // onRelease        active_entity->onRelease()      else        // onReleaseOutside	if (active_entity->trackAsMenu == false)          active_entity->onReleaseOutside()      mouse_button_state = UP      if mouse_button_state == UP    new_active_entity = topmost entity below the mouse    if (new_active_entity != active_entity)      // onRollOut, onRollOver      active_entity->onRollOut()      active_entity = new_active_entity      active_entity->onRollOver()        // Handle press    if (mouse button is down)      // onPress      active_entity->onPress()      mouse_inside_entity_state = true      mouse_button_state = DOWN*/namespace gameswf{	void	generate_mouse_button_events(mouse_button_state* ms)	{		smart_ptr<movie>	active_entity = ms->m_active_entity;		smart_ptr<movie>	topmost_entity = ms->m_topmost_entity;		if (ms->m_mouse_button_state_last == 1)		{			// Mouse button was down.			// Handle trackAsMenu dragOver			if (active_entity == NULL			    || active_entity->get_track_as_menu())			{				if (topmost_entity != NULL				    && topmost_entity != active_entity				    && topmost_entity->get_track_as_menu() == true)				{					// Transfer to topmost entity, dragOver					active_entity = topmost_entity;					active_entity->on_button_event(event_id::DRAG_OVER);					ms->m_mouse_inside_entity_last = true;				}			}			// Handle onDragOut, onDragOver			if (ms->m_mouse_inside_entity_last == false)			{				if (topmost_entity == active_entity)				{					// onDragOver					if (active_entity != NULL)					{						active_entity->on_button_event(event_id::DRAG_OVER);					}					ms->m_mouse_inside_entity_last = true;				}			}			else			{				// mouse_inside_entity_last == true				if (topmost_entity != active_entity)				{					// onDragOut					if (active_entity != NULL)					{						active_entity->on_button_event(event_id::DRAG_OUT);					}					ms->m_mouse_inside_entity_last = false;				}			}			// Handle onRelease, onReleaseOutside			if (ms->m_mouse_button_state_current == 0)			{				// Mouse button just went up.				ms->m_mouse_button_state_last = 0;				if (active_entity != NULL)				{					if (ms->m_mouse_inside_entity_last)					{						// onRelease						active_entity->on_button_event(event_id::RELEASE);					}					else					{						// onReleaseOutside						if (active_entity->get_track_as_menu() == false)						{							active_entity->on_button_event(event_id::RELEASE_OUTSIDE);						}					}				}			}		}    		if (ms->m_mouse_button_state_last == 0)		{			// Mouse button was up.			// New active entity is whatever is below the mouse right now.			if (topmost_entity != active_entity)			{				// onRollOut				if (active_entity != NULL)				{					active_entity->on_button_event(event_id::ROLL_OUT);				}				active_entity = topmost_entity;				// onRollOver				if (active_entity != NULL)				{					active_entity->on_button_event(event_id::ROLL_OVER);				}				ms->m_mouse_inside_entity_last = true;			}    			// mouse button press			if (ms->m_mouse_button_state_current == 1)			{				// onPress				if (active_entity != NULL)				{					active_entity->on_button_event(event_id::PRESS);				}				ms->m_mouse_inside_entity_last = true;				ms->m_mouse_button_state_last = 1;			}		}		// Write the (possibly modified) smart_ptr copies back		// into the state struct.		ms->m_active_entity = active_entity;		ms->m_topmost_entity = topmost_entity;	}	struct button_character_instance : public character	{		button_character_definition*	m_def;		array< smart_ptr<character> >	m_record_character;		enum mouse_flags		{			IDLE = 0,			FLAG_OVER = 1,			FLAG_DOWN = 2,			OVER_DOWN = FLAG_OVER|FLAG_DOWN,			// aliases			OVER_UP = FLAG_OVER,			OUT_DOWN = FLAG_DOWN		};		int	m_last_mouse_flags, m_mouse_flags;		enum e_mouse_state		{			UP = 0,			DOWN,			OVER		};		e_mouse_state m_mouse_state;		button_character_instance(button_character_definition* def, movie* parent, int id)			:			character(parent, id),			m_def(def),			m_last_mouse_flags(IDLE),			m_mouse_flags(IDLE),			m_mouse_state(UP)		{			assert(m_def);			int r, r_num =  m_def->m_button_records.size();			m_record_character.resize(r_num);			movie_definition_sub*	movie_def = static_cast<movie_definition_sub*>(				parent->get_root_movie()->get_movie_definition());			for (r = 0; r < r_num; r++)			{				button_record*	bdef = &m_def->m_button_records[r];				if (bdef->m_character_def == NULL)				{					// Resolve the character id.					bdef->m_character_def = movie_def->get_character_def(bdef->m_character_id);				}				assert(bdef->m_character_def != NULL);				const matrix&	mat = m_def->m_button_records[r].m_button_matrix;				const cxform&	cx = m_def->m_button_records[r].m_button_cxform;				smart_ptr<character>	ch = bdef->m_character_def->create_character_instance(this, id);				m_record_character[r] = ch;				ch->set_matrix(mat);				ch->set_cxform(cx);				ch->restart();			}		}		~button_character_instance()		{		}		movie_root*	get_root() { return get_parent()->get_root(); }		movie*	get_root_movie() { return get_parent()->get_root_movie(); }		void	restart()		{			m_last_mouse_flags = IDLE;			m_mouse_flags = IDLE;			m_mouse_state = UP;			int r, r_num =  m_record_character.size();			for (r = 0; r < r_num; r++)			{				m_record_character[r]->restart();			}		}		virtual void	advance(float delta_time)		{			// Implement mouse-drag.			character::do_mouse_drag();			matrix	mat = get_world_matrix();			// Advance our relevant characters.			{for (int i = 0; i < m_def->m_button_records.size(); i++)			{				button_record&	rec = m_def->m_button_records[i];				if (m_record_character[i] == NULL)				{					continue;				}				// Matrix				matrix sub_matrix = mat;				sub_matrix.concatenate(rec.m_button_matrix);				// Advance characters that are activated by the new mouse state				if (((m_mouse_state == UP) && (rec.m_up)) ||				    ((m_mouse_state == DOWN) && (rec.m_down)) ||				    ((m_mouse_state == OVER) && (rec.m_over)))				{					m_record_character[i]->advance(delta_time);				}			}}		}		void	display()		{			for (int i = 0; i < m_def->m_button_records.size(); i++)			{				button_record&	rec = m_def->m_button_records[i];				if (m_record_character[i] == NULL)				{					continue;				}				if ((m_mouse_state == UP && rec.m_up)				    || (m_mouse_state == DOWN && rec.m_down)				    || (m_mouse_state == OVER && rec.m_over))				{					m_record_character[i]->display();				}			}			do_display_callback();		}		inline int	transition(int a, int b) const		// Combine the flags to avoid a conditional. It would be faster with a macro.		{			return (a << 2) | b;		}		virtual movie*	get_topmost_mouse_entity(float x, float y)		// Return the topmost entity that the given point covers.  NULL if none.		// I.e. check against ourself.		{			if (get_visible() == false) {				return false;			}			matrix	m = get_matrix();			point	p;			m.transform_by_inverse(&p, point(x, y));			{for (int i = 0; i < m_def->m_button_records.size(); i++)			{				button_record&	rec = m_def->m_button_records[i];				if (rec.m_character_id < 0 || rec.m_hit_test == false)				{					continue;				}				// Find the mouse position in button-record space.				point	sub_p;				rec.m_button_matrix.transform_by_inverse(&sub_p, p);				if (rec.m_character_def->point_test_local(sub_p.m_x, sub_p.m_y))				{					// The mouse is inside the shape.					return this;					// @@ Are there any circumstances where this is correct:					//return m_record_character[i].get_ptr();				}			}}			return NULL;		}		virtual void	on_button_event(event_id event)		{			// Set our mouse state (so we know how to render).			switch (event.m_id)			{			case event_id::ROLL_OUT:			case event_id::RELEASE_OUTSIDE:				m_mouse_state = UP;				break;			case event_id::RELEASE:			case event_id::ROLL_OVER:			case event_id::DRAG_OUT:				m_mouse_state = OVER;				break;			case event_id::PRESS:			case event_id::DRAG_OVER:				m_mouse_state = DOWN;				break;			default:				assert(0);	// missed a case?				break;			};			// Button transition sounds.			if (m_def->m_sound != NULL)			{				int bi; // button sound array index [0..3]				sound_handler* s = get_sound_handler();				// Check if there is a sound handler				if (s != NULL) {					switch (event.m_id)					{					case event_id::ROLL_OUT:						bi = 0;						break;					case event_id::ROLL_OVER:						bi = 1;						break;					case event_id::PRESS:						bi = 2;						break;					case event_id::RELEASE:						bi = 3;						break;					default:						bi = -1;						break;					}					if (bi >= 0)					{						button_character_definition::button_sound_info& bs = m_def->m_sound->m_button_sounds[bi];						// character zero is considered as null character						if (bs.m_sound_id > 0)						{							assert(m_def->m_sound->m_button_sounds[bi].m_sam != NULL);							if (bs.m_sound_style.m_stop_playback)

⌨️ 快捷键说明

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