[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog libbase/image_filters.cpp libba...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog libbase/image_filters.cpp libba... |
Date: |
Sat, 26 Aug 2006 22:58:13 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 06/08/26 22:58:12
Modified files:
. : ChangeLog
libbase : image_filters.cpp utility.cpp
server : Makefile.am impl.cpp movie_root.cpp
movie_root.h
server/asobj : ASSound.cpp MovieClipLoader.h
server/parser : Makefile.am movie_def_impl.h movie_definition.h
server/swf : tag_loaders.cpp
Added files:
server : button_character_instance.cpp
button_character_instance.h
mouse_button_state.h
server/parser : button_character_def.cpp button_character_def.h
Removed files:
server : button.cpp button.h
Log message:
* Split button.{h,cpp} into button_character_instance.{cpp,h},
mouse_button_events.h and parser/button_character_def.{cpp,h};
headers inclusion shaking.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.730&r2=1.731
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/image_filters.cpp?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/utility.cpp?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.62&r2=1.63
http://cvs.savannah.gnu.org/viewcvs/gnash/server/impl.cpp?cvsroot=gnash&r1=1.53&r2=1.54
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.cpp?cvsroot=gnash&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.h?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/server/button_character_instance.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/button_character_instance.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/mouse_button_state.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/button.cpp?cvsroot=gnash&r1=1.29&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/button.h?cvsroot=gnash&r1=1.10&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/ASSound.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/MovieClipLoader.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/Makefile.am?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/movie_def_impl.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/movie_definition.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/button_character_def.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/button_character_def.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/tag_loaders.cpp?cvsroot=gnash&r1=1.33&r2=1.34
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.730
retrieving revision 1.731
diff -u -b -r1.730 -r1.731
--- ChangeLog 26 Aug 2006 22:09:12 -0000 1.730
+++ ChangeLog 26 Aug 2006 22:58:12 -0000 1.731
@@ -1,3 +1,9 @@
+2006-08-27 Sandro Santilli <address@hidden>
+
+ * Split button.{h,cpp} into button_character_instance.{cpp,h},
+ mouse_button_events.h and parser/button_character_def.{cpp,h};
+ headers inclusion shaking.
+
2006-08-26 Markus Gothe <address@hidden>
* server/asobj/Global.cpp, libbase/image.cpp: Found and fixed memory
Index: libbase/image_filters.cpp
===================================================================
RCS file: /sources/gnash/gnash/libbase/image_filters.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libbase/image_filters.cpp 26 Aug 2006 00:12:37 -0000 1.9
+++ libbase/image_filters.cpp 26 Aug 2006 22:58:12 -0000 1.10
@@ -752,7 +752,7 @@
rgba *csp, *sp;
sp = csp = (rgba *) src->m_data;
rgba *dp = (rgba *) dst->m_data;
- int sgap = src->m_pitch - src->m_width * 4;
+ //int sgap = src->m_pitch - src->m_width * 4;
int dgap = dst->m_pitch - dst->m_width * 4;
/* Interpolating Zoom */
Index: libbase/utility.cpp
===================================================================
RCS file: /sources/gnash/gnash/libbase/utility.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- libbase/utility.cpp 25 Aug 2006 23:35:20 -0000 1.8
+++ libbase/utility.cpp 26 Aug 2006 22:58:12 -0000 1.9
@@ -68,7 +68,7 @@
#endif
-void dump_memory_stats(const char *from, int line, const char *label)
+void dump_memory_stats(const char* from, int line, const char *label)
// Dump the internal statistics from malloc() so we can track memory leaks
{
Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -b -r1.62 -r1.63
--- server/Makefile.am 26 Aug 2006 10:14:51 -0000 1.62
+++ server/Makefile.am 26 Aug 2006 22:58:12 -0000 1.63
@@ -86,7 +86,7 @@
string.cpp \
action.cpp \
ActionExec.cpp \
- button.cpp \
+ button_character_instance.cpp \
dlist.cpp \
edit_text_character.cpp \
font.cpp \
@@ -122,7 +122,8 @@
as_member.h \
as_prop_flags.h \
as_object.h \
- button.h \
+ button_character_instance.h \
+ mouse_button_state.h \
dlist.h \
character.h \
generic_character.h \
Index: server/impl.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/impl.cpp,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -b -r1.53 -r1.54
--- server/impl.cpp 26 Aug 2006 17:58:24 -0000 1.53
+++ server/impl.cpp 26 Aug 2006 22:58:12 -0000 1.54
@@ -52,7 +52,7 @@
#include "tu_file.h"
#include "utility.h"
#include "action.h"
-#include "button.h"
+//#include "button.h"
#include "impl.h"
#include "font.h"
#include "fontlib.h"
Index: server/movie_root.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- server/movie_root.cpp 23 Aug 2006 21:30:49 -0000 1.13
+++ server/movie_root.cpp 26 Aug 2006 22:58:12 -0000 1.14
@@ -145,6 +145,151 @@
fire_mouse_event();
}
+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
+
+ // set/kill focus for current root
+ movie_root* mroot = (movie_root*) get_current_root();
+ movie* current_active_entity =
mroot->get_active_entity();
+
+ // It's another entity ?
+ if (current_active_entity != active_entity.get_ptr())
+ {
+ // First to clean focus
+ if (current_active_entity != NULL)
+ {
+
current_active_entity->on_event(event_id::KILLFOCUS);
+ mroot->set_active_entity(NULL);
+ }
+
+ // Then to set focus
+ if (active_entity != NULL)
+ {
+ if
(active_entity->on_event(event_id::SETFOCUS))
+ {
+
mroot->set_active_entity(active_entity.get_ptr());
+ }
+ }
+ }
+
+ 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;
+}
+
+
void
movie_root::fire_mouse_event()
{
Index: server/movie_root.h
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/movie_root.h 26 Aug 2006 02:08:31 -0000 1.11
+++ server/movie_root.h 26 Aug 2006 22:58:12 -0000 1.12
@@ -39,7 +39,7 @@
#define GNASH_MOVIE_ROOT_H
#include "container.h"
-#include "button.h" // for mouse_button_state
+#include "mouse_button_state.h" // for mouse_button_state
#include "timers.h" // for Timer
#include "fontlib.h"
#include "font.h"
Index: server/asobj/ASSound.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/ASSound.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/asobj/ASSound.cpp 24 Jul 2006 18:59:40 -0000 1.2
+++ server/asobj/ASSound.cpp 26 Aug 2006 22:58:12 -0000 1.3
@@ -22,6 +22,7 @@
#include "log.h"
#include "ASSound.h"
+#include "sound.h" // for sound_sample_impl
#include "movie_definition.h"
#include "sprite_instance.h"
#include "fn_call.h"
Index: server/asobj/MovieClipLoader.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/MovieClipLoader.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/asobj/MovieClipLoader.h 26 Aug 2006 13:09:53 -0000 1.3
+++ server/asobj/MovieClipLoader.h 26 Aug 2006 22:58:12 -0000 1.4
@@ -41,9 +41,9 @@
#ifndef GNASH_MOVIECLIPLOADER_H
#define GNASH_MOVIECLIPLOADER_H
-#include "button.h"
+#include "button_character_instance.h" // for mouse_state enum
#include "action.h"
-#include "impl.h"
+//#include "impl.h"
namespace gnash {
Index: server/parser/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/parser/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/parser/Makefile.am 26 Aug 2006 10:14:51 -0000 1.3
+++ server/parser/Makefile.am 26 Aug 2006 22:58:12 -0000 1.4
@@ -68,6 +68,7 @@
libgnashparser_la_SOURCES = \
action_buffer.cpp \
+ button_character_def.cpp \
character_def.cpp \
edit_text_character_def.cpp \
text_character_def.cpp \
@@ -78,6 +79,7 @@
noinst_HEADERS = \
action_buffer.h \
+ button_character_def.h \
character_def.h \
bitmap_character_def.h \
edit_text_character_def.h \
Index: server/parser/movie_def_impl.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/movie_def_impl.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- server/parser/movie_def_impl.h 26 Aug 2006 02:08:32 -0000 1.2
+++ server/parser/movie_def_impl.h 26 Aug 2006 22:58:12 -0000 1.3
@@ -40,7 +40,7 @@
#include "container.h"
#include "smart_ptr.h"
-#include "button.h" // for mouse_button_state
+//#include "button.h" // for mouse_button_state
#include "timers.h" // for Timer
#include "fontlib.h"
#include "font.h"
Index: server/parser/movie_definition.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/movie_definition.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/parser/movie_definition.h 26 Aug 2006 02:08:32 -0000 1.3
+++ server/parser/movie_definition.h 26 Aug 2006 22:58:12 -0000 1.4
@@ -63,8 +63,9 @@
#ifndef GNASH_MOVIE_DEFINITION_H
#define GNASH_MOVIE_DEFINITION_H
+#include "character_def.h" // for inheritance
#include "container.h"
-#include "button.h" // for mouse_button_state
+//#include "button.h" // for mouse_button_state
#include "timers.h" // for Timer
#include "fontlib.h"
#include "font.h"
Index: server/swf/tag_loaders.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf/tag_loaders.cpp,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- server/swf/tag_loaders.cpp 26 Aug 2006 21:04:31 -0000 1.33
+++ server/swf/tag_loaders.cpp 26 Aug 2006 22:58:12 -0000 1.34
@@ -46,8 +46,8 @@
#include "utility.h"
#include "action.h"
#include "action_buffer.h"
-#include "button.h"
-#include "impl.h"
+#include "button_character_def.h"
+//#include "impl.h"
#include "font.h"
#include "fontlib.h"
#include "log.h"
Index: server/button_character_instance.cpp
===================================================================
RCS file: server/button_character_instance.cpp
diff -N server/button_character_instance.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/button_character_instance.cpp 26 Aug 2006 22:58:12 -0000
1.1
@@ -0,0 +1,713 @@
+// button.cpp -- Thatcher Ulrich <address@hidden> 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 "button_character_instance.h"
+#include "button_character_def.h"
+
+//#include "action.h"
+//#include "render.h"
+//#include "sound.h"
+//#include "stream.h"
+//#include "movie_definition.h"
+#include "sprite_instance.h"
+#include "movie_root.h"
+//#include "action_buffer.h"
+
+
+/** \page buttons Buttons and mouse behaviour
+
+Observations about button & mouse behavior
+
+Entities that receive mouse events: only buttons and sprites, AFAIK
+
+When the mouse button goes down, it becomes "captured" by whatever
+element is topmost, directly below the mouse at that moment. While
+the 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 mouse
+remains captured even if the element that captured it is removed from
+the display list.
+
+If the mouse isn't above a button or sprite when the mouse button goes
+down, then the mouse is captured by the background (i.e. mouse events
+just 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 to
+be an active entity, representing the background, and other objects that
+don't receive mouse events).
+
+When the mouse button is up, the active entity is the topmost element
+directly under the mouse pointer.
+
+When the mouse button is down, the active entity remains whatever it
+was when the button last went down.
+
+The active entity is the only object that receives mouse events.
+
+!!! The "trackAsMenu" property alters this behavior! If trackAsMenu
+is set on the active entity, then onReleaseOutside is filtered out,
+and onDragOver from another entity is allowed (from the background, or
+another trackAsMenu entity). !!!
+
+
+Pseudocode:
+
+active_entity = NULL
+mouse_button_state = UP
+mouse_inside_entity_state = false
+frame 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 gnash {
+
+button_character_instance::button_character_instance(
+ button_character_definition* def,
+ character* 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* movie_def =
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();
+ }
+
+ // check up presence KeyPress events
+ for (unsigned int i = 0; i < m_def->m_button_actions.size(); i++)
+ {
+ if (m_def->m_button_actions[i].m_conditions & 0xFE00) //
check up on CondKeyPress: UB[7]
+ {
+ get_root()->add_keypress_listener(this);
+ break;
+ }
+ }
+
+}
+
+button_character_instance::~button_character_instance()
+{
+ get_root()->remove_keypress_listener(this);
+}
+
+// called from keypress listener only
+bool
+button_character_instance::on_event(event_id id)
+{
+
+ if (id.m_id != event_id::KEY_PRESS)
+ {
+ return false;
+ }
+
+ bool called = false;
+
+ static const event_id s_key[32] =
+ {
+ event_id(),
+ event_id(event_id::KEY_PRESS, key::LEFT),
+ event_id(event_id::KEY_PRESS, key::RIGHT),
+ event_id(event_id::KEY_PRESS, key::HOME),
+ event_id(event_id::KEY_PRESS, key::END),
+ event_id(event_id::KEY_PRESS, key::INSERT),
+ event_id(event_id::KEY_PRESS, key::DELETEKEY),
+ event_id(),
+ event_id(event_id::KEY_PRESS, key::BACKSPACE), //8
+ event_id(),
+ event_id(),
+ event_id(),
+ event_id(),
+ event_id(event_id::KEY_PRESS, key::ENTER), //13
+ event_id(event_id::KEY_PRESS, key::UP),
+ event_id(event_id::KEY_PRESS, key::DOWN),
+ event_id(event_id::KEY_PRESS, key::PGUP),
+ event_id(event_id::KEY_PRESS, key::PGDN),
+ event_id(event_id::KEY_PRESS, key::TAB),
+ // 32-126 folows ASCII
+ };
+
+
+ // Add appropriate actions to the movie's execute list...
+ for (unsigned int i = 0; i < m_def->m_button_actions.size(); i++)
+ {
+ int keycode = (m_def->m_button_actions[i].m_conditions &
0xFE00) >> 9;
+ event_id key_event = keycode < 32 ? s_key[keycode] :
event_id(event_id::KEY_PRESS, (key::code) keycode);
+ if (key_event == id)
+ {
+ // Matching action.
+ for (unsigned int j = 0; j <
m_def->m_button_actions[i].m_actions.size(); j++)
+ {
+
get_parent()->add_action_buffer(m_def->m_button_actions[i].m_actions[j]);
+ }
+ called = true;
+ }
+ }
+
+ return called;
+}
+
+void
+button_character_instance::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();
+ }
+}
+
+void
+button_character_instance::advance(float delta_time)
+{
+// printf("%s:\n", __PRETTY_FUNCTION__); // FIXME:
+ // Implement mouse-drag.
+ character::do_mouse_drag();
+
+ matrix mat = get_world_matrix();
+
+ // Advance our relevant characters.
+ {for (unsigned 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
+button_character_instance::display()
+{
+// GNASH_REPORT_FUNCTION;
+ for (unsigned 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))
+ {
+ matrix mat = get_world_matrix();
+
+ m_record_character[i]->display();
+ }
+ }
+
+ do_display_callback();
+}
+
+
+movie*
+button_character_instance::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 (unsigned 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;
+}
+
+
+void
+button_character_instance::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)
+ {
+
s->stop_sound(bs.m_sam->m_sound_handler_id);
+ }
+ else
+ {
+
s->play_sound(bs.m_sam->m_sound_handler_id, bs.m_sound_style.m_loop_count, 0,
0);
+ }
+ }
+ }
+ }
+ }
+
+ // @@ eh, should just be a lookup table.
+ int c = 0;
+ if (event.m_id == event_id::ROLL_OVER) c |=
(button_action::IDLE_TO_OVER_UP);
+ else if (event.m_id == event_id::ROLL_OUT) c |=
(button_action::OVER_UP_TO_IDLE);
+ else if (event.m_id == event_id::PRESS) c |=
(button_action::OVER_UP_TO_OVER_DOWN);
+ else if (event.m_id == event_id::RELEASE) c |=
(button_action::OVER_DOWN_TO_OVER_UP);
+ else if (event.m_id == event_id::DRAG_OUT) c |=
(button_action::OVER_DOWN_TO_OUT_DOWN);
+ else if (event.m_id == event_id::DRAG_OVER) c |=
(button_action::OUT_DOWN_TO_OVER_DOWN);
+ else if (event.m_id == event_id::RELEASE_OUTSIDE) c |=
(button_action::OUT_DOWN_TO_IDLE);
+ //IDLE_TO_OVER_DOWN = 1 << 7,
+ //OVER_DOWN_TO_IDLE = 1 << 8,
+
+ // restart the characters of the new state.
+ restart_characters(c);
+
+ // Add appropriate actions to the movie's execute list...
+ {for (unsigned int i = 0; i < m_def->m_button_actions.size(); i++)
+ {
+ if (m_def->m_button_actions[i].m_conditions & c)
+ {
+ // Matching action.
+ for (unsigned int j = 0; j <
m_def->m_button_actions[i].m_actions.size(); j++)
+ {
+
get_parent()->add_action_buffer(m_def->m_button_actions[i].m_actions[j]);
+ }
+ }
+ }}
+
+ // Call conventional attached method.
+ // @@ TODO
+}
+
+
+void
+button_character_instance::restart_characters(int condition)
+{
+ // Restart our relevant characters
+ for (unsigned int i = 0; i < m_def->m_button_records.size(); i++)
+ {
+ bool restart = false;
+ button_record* rec = &m_def->m_button_records[i];
+
+ switch (m_mouse_state)
+ {
+ case OVER:
+ {
+ if ((rec->m_over) && (condition &
button_action::IDLE_TO_OVER_UP))
+ {
+ restart = true;
+ }
+ break;
+ }
+ // @@ Hm, are there other cases where we restart stuff?
+ default:
+ {
+ break;
+ }
+ }
+
+ if (restart == true)
+ {
+ m_record_character[i]->restart();
+ }
+ }
+}
+
+
+void
+button_character_instance::get_mouse_state(int* x, int* y, int* buttons)
+{
+ get_parent()->get_mouse_state(x, y, buttons);
+}
+
+
+//
+// ActionScript overrides
+//
+
+void
+button_character_instance::set_member(const tu_stringi& name,
+ const as_value& val)
+{
+ // TODO: pull these up into a base class, to
+ // share as much as possible with sprite_instance.
+ as_standard_member std_member = get_standard_member(name);
+ switch (std_member)
+ {
+ default:
+ case M_INVALID_MEMBER:
+ break;
+ case M_VISIBLE: // _visible
+ {
+ m_visible = val.to_bool();
+ return;
+ }
+ case M_ALPHA: // _alpha
+ {
+ // Set alpha modulate, in percent.
+ cxform cx = get_cxform();
+ cx.m_[3][0] = float(val.to_number()) / 100.f;
+ set_cxform(cx);
+ //m_accept_anim_moves = false;
+ return;
+ }
+ case M_X: // _x
+ {
+ matrix m = get_matrix(); // @@ get_world_matrix()???
+ m.m_[0][2] = float(PIXELS_TO_TWIPS(val.to_number()));
+ this->set_matrix(m);
+ return;
+ }
+ case M_Y: // _y
+ {
+ matrix m = get_matrix(); // @@ get_world_matrix()???
+ m.m_[1][2] = float(PIXELS_TO_TWIPS(val.to_number()));
+ this->set_matrix(m);
+ return;
+ }
+// evan : need set_width and set_height function for struct character
+#if 0
+ case M_WIDTH: // _width
+ {
+ 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]->set_width(val.to_number);
+ // @@ evan: should we return here?
+ return;
+ }
+ }
+
+ return;
+ }
+ else if (name == "enabled")
+ {
+ m_enabled = val.to_bool();
+ }
+ case M_HEIGHT: // _height
+ {
+ 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]->set_height(val.to_number);
+ // @@ evan: should we return here?
+ return;
+ }
+ }
+
+ return;
+ }
+#endif
+ }
+
+ log_error("error: button_character_instance::set_member('%s', '%s') not
implemented yet\n",
+ name.c_str(),
+ val.to_string());
+}
+
+bool
+button_character_instance::get_member(const tu_stringi& name, as_value* val)
+{
+ // TODO: pull these up into a base class, to
+ // share as much as possible with sprite_instance.
+ as_standard_member std_member = get_standard_member(name);
+ switch (std_member)
+ {
+ default:
+ case M_INVALID_MEMBER:
+ break;
+ case M_VISIBLE: // _visible
+ {
+ val->set_bool(this->get_visible());
+ return true;
+ }
+ case M_ALPHA: // _alpha
+ {
+ // @@ TODO this should be generic to struct character!
+ // Alpha units are in percent.
+ val->set_double(get_cxform().m_[3][0] * 100.f);
+ return true;
+ }
+ case M_X: // _x
+ {
+ matrix m = get_matrix(); // @@ get_world_matrix()???
+ val->set_double(TWIPS_TO_PIXELS(m.m_[0][2]));
+ return true;
+ }
+ case M_Y: // _y
+ {
+ matrix m = get_matrix(); // @@ get_world_matrix()???
+ val->set_double(TWIPS_TO_PIXELS(m.m_[1][2]));
+ return true;
+ }
+ case M_WIDTH: // _width
+ {
+ for (unsigned 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))
+ {
+
val->set_double(TWIPS_TO_PIXELS(m_record_character[i]->get_width()));
+ // @@ evan: should we return here?
+ return true;
+ }
+ }
+
+ // from the experiments with macromedia flash player
+ val->set_double(0);
+ return true;
+ }
+ case M_HEIGHT: // _height
+ {
+ for (unsigned 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))
+ {
+
val->set_double(TWIPS_TO_PIXELS(m_record_character[i]->get_height()));
+ // @@ evan: should we return here?
+ return true;
+ }
+ }
+
+ // from the experiments with macromedia flash player
+ val->set_double(0);
+ return true;
+ }
+ } // end of switch
+
+ return false;
+}
+
+} // end of namespace gnash
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: server/button_character_instance.h
===================================================================
RCS file: server/button_character_instance.h
diff -N server/button_character_instance.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/button_character_instance.h 26 Aug 2006 22:58:12 -0000 1.1
@@ -0,0 +1,130 @@
+// Thatcher Ulrich <address@hidden> 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.
+
+
+#ifndef GNASH_BUTTON_CHARACTER_INSTANCE_H
+#define GNASH_BUTTON_CHARACTER_INSTANCE_H
+
+
+//#include "impl.h" // should get rid of this
+#include "character.h" // for inheritance
+//#include "sound.h"
+
+// Forward declarations
+namespace gnash {
+ class sprite_instance;
+ class button_character_definition;
+}
+
+namespace gnash {
+
+
+//
+// button characters
+//
+
+enum mouse_state
+{
+ MOUSE_UP,
+ MOUSE_DOWN,
+ MOUSE_OVER
+};
+
+//
+// button_character_instance
+//
+
+class button_character_instance : public character
+{
+public:
+ button_character_definition* m_def;
+ std::vector< 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,
+ character* parent, int id);
+
+ ~button_character_instance();
+
+ bool can_handle_mouse_event() { return true; }
+
+ // called from keypress listener only
+ bool on_event(event_id id);
+
+ movie_root* get_root() { return get_parent()->get_root(); }
+
+ void restart();
+
+ virtual void advance(float delta_time);
+
+ void display();
+
+ /// Combine the flags to avoid a conditional.
+ // It would be faster with a macro.
+ inline int transition(int a, int b) const
+ {
+ return (a << 2) | b;
+ }
+
+
+ /// \brief
+ /// Return the topmost entity that the given point covers.
+ /// NULL if none.
+ //
+ /// I.e. check against ourself.
+ ///
+ virtual movie* get_topmost_mouse_entity(float x, float y);
+
+ virtual void on_button_event(event_id event);
+
+ void restart_characters(int condition);
+
+ virtual void get_mouse_state(int* x, int* y, int* buttons);
+
+ //
+ // ActionScript overrides
+ //
+
+ virtual void set_member(const tu_stringi& name, const as_value& val);
+
+ virtual bool get_member(const tu_stringi& name, as_value* val);
+
+ // not sure if we need to override this one.
+ //virtual const char* get_text_value() const { return NULL; } //
edit_text_character overrides this
+};
+
+} // end namespace gnash
+
+
+#endif // GNASH_BUTTON_CHARACTER_INSTANCE_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: server/mouse_button_state.h
===================================================================
RCS file: server/mouse_button_state.h
diff -N server/mouse_button_state.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/mouse_button_state.h 26 Aug 2006 22:58:12 -0000 1.1
@@ -0,0 +1,61 @@
+// Thatcher Ulrich <address@hidden> 2003
+
+// This source code has been donated to the Public Domain. Do
+// whatever you want with it.
+
+
+#ifndef GNASH_MOUSE_BUTTON_STATE_H
+#define GNASH_MOUSE_BUTTON_STATE_H
+
+
+//#include "impl.h" // should get rid of this
+#include "character_def.h"
+#include "sound.h"
+
+// Forward declarations
+namespace gnash {
+ class sprite_instance;
+}
+
+namespace gnash {
+
+//
+// Helper to generate mouse events, given mouse state & history.
+//
+
+
+//
+// Helper to generate mouse events, given mouse state & history.
+//
+class mouse_button_state
+{
+public:
+ weak_ptr<movie> m_active_entity; // entity that currently owns
the mouse pointer
+ weak_ptr<movie> m_topmost_entity; // what's underneath the mouse
right now
+
+ bool m_mouse_button_state_last; // previous state of
mouse button
+ bool m_mouse_button_state_current; // current state of
mouse button
+
+ bool m_mouse_inside_entity_last; // whether mouse was inside the
active_entity last frame
+
+ mouse_button_state()
+ :
+ m_mouse_button_state_last(0),
+ m_mouse_button_state_current(0),
+ m_mouse_inside_entity_last(false)
+ {
+ }
+};
+
+} // end namespace gnash
+
+
+#endif // GNASH_MOUSE_BUTTON_STATE_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: server/parser/button_character_def.cpp
===================================================================
RCS file: server/parser/button_character_def.cpp
diff -N server/parser/button_character_def.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/button_character_def.cpp 26 Aug 2006 22:58:12 -0000
1.1
@@ -0,0 +1,265 @@
+// -- Thatcher Ulrich <address@hidden> 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 "button_character_def.h"
+#include "button_character_instance.h" // for create_character_instance()
+
+//#include "action.h"
+//#include "render.h"
+//#include "sound.h"
+#include "stream.h" // for read()
+#include "movie_definition.h"
+//#include "sprite_instance.h"
+//#include "movie_root.h"
+#include "action_buffer.h"
+
+
+
+namespace gnash {
+
+//
+// button_action
+//
+
+
+button_action::~button_action()
+{
+ m_actions.clear();
+}
+
+void button_action::read(stream* in, int tag_type)
+{
+ // Read condition flags.
+ if (tag_type == 7)
+ {
+ m_conditions = OVER_DOWN_TO_OVER_UP;
+ }
+ else
+ {
+ assert(tag_type == 34);
+ m_conditions = in->read_u16();
+ }
+
+ IF_VERBOSE_PARSE (
+ log_parse("-- actions in button\n"); // @@ need more info about which
actions
+ );
+
+ // Read actions.
+ action_buffer* a = new action_buffer;
+ a->read(in);
+ m_actions.push_back(a);
+}
+
+//
+// button_record
+//
+
+// Return true if we read a record; false if this is a null record.
+bool
+button_record::read(stream* in, int tag_type,
+ movie_definition* /*m*/)
+{
+ int flags = in->read_u8();
+ if (flags == 0)
+ {
+ return false;
+ }
+ m_hit_test = flags & 8 ? true : false;
+ m_down = flags & 4 ? true : false;
+ m_over = flags & 2 ? true : false;
+ m_up = flags & 1 ? true : false;
+
+ m_character_id = in->read_u16();
+ m_character_def = NULL;
+ m_button_layer = in->read_u16();
+ m_button_matrix.read(in);
+
+ if (tag_type == 34)
+ {
+ m_button_cxform.read_rgba(in);
+ }
+
+ return true;
+}
+
+
+//
+// button_character_definition
+//
+
+button_character_definition::button_character_definition()
+ :
+ m_sound(NULL)
+// Constructor.
+{
+}
+
+button_character_definition::~button_character_definition()
+{
+ delete m_sound;
+}
+
+
+void button_character_definition::sound_info::read(stream* in)
+{
+ m_in_point = m_out_point = m_loop_count = 0;
+ in->read_uint(2); // skip reserved bits.
+ m_stop_playback = in->read_uint(1) ? true : false;
+ m_no_multiple = in->read_uint(1) ? true : false;
+ m_has_envelope = in->read_uint(1) ? true : false;
+ m_has_loops = in->read_uint(1) ? true : false;
+ m_has_out_point = in->read_uint(1) ? true : false;
+ m_has_in_point = in->read_uint(1) ? true : false;
+ if (m_has_in_point) m_in_point = in->read_u32();
+ if (m_has_out_point) m_out_point = in->read_u32();
+ if (m_has_loops) m_loop_count = in->read_u16();
+ if (m_has_envelope)
+ {
+ int nPoints = in->read_u8();
+ m_envelopes.resize(nPoints);
+ for (int i=0; i < nPoints; i++)
+ {
+ m_envelopes[i].m_mark44 = in->read_u32();
+ m_envelopes[i].m_level0 = in->read_u16();
+ m_envelopes[i].m_level1 = in->read_u16();
+ }
+ }
+ else
+ {
+ m_envelopes.resize(0);
+ }
+
+ IF_VERBOSE_PARSE(
+ log_parse(" has_envelope = %d", m_has_envelope);
+ log_parse(" has_loops = %d", m_has_loops);
+ log_parse(" has_out_point = %d", m_has_out_point);
+ log_parse(" has_in_point = %d", m_has_in_point);
+ log_parse(" in_point = %d", m_in_point);
+ log_parse(" out_point = %d", m_out_point);
+ log_parse(" loop_count = %d", m_loop_count);
+ log_parse(" envelope size = %u", m_envelopes.size());
+ );
+}
+
+
+
+void button_character_definition::read(stream* in, int tag_type,
movie_definition* m)
+// Initialize from the given stream.
+{
+ assert(tag_type == 7 || tag_type == 17 || tag_type == 34);
+
+ if (tag_type == 7)
+ {
+ // Old button tag.
+
+ // Read button character records.
+ for (;;)
+ {
+ button_record r;
+ if (r.read(in, tag_type, m) == false)
+ {
+ // Null record; marks the end of button records.
+ break;
+ }
+ m_button_records.push_back(r);
+ }
+
+ // Read actions.
+ m_button_actions.resize(m_button_actions.size() + 1);
+ m_button_actions.back().read(in, tag_type);
+ }
+ else if (tag_type == 17)
+ {
+ assert(m_sound == NULL); // redefinition button sound is
error
+ m_sound = new button_sound_def();
+ IF_VERBOSE_PARSE(
+ log_parse("button sound options: ");
+ );
+ for (int i = 0; i < 4; i++)
+ {
+ button_sound_info& bs = m_sound->m_button_sounds[i];
+ bs.m_sound_id = in->read_u16();
+ if (bs.m_sound_id > 0)
+ {
+ bs.m_sam = (sound_sample_impl*)
m->get_sound_sample(bs.m_sound_id);
+ if (bs.m_sam == NULL)
+ {
+// printf("sound tag not found,
sound_id=%d, button state #=%i", bs.sound_id, i);
+ }
+ IF_VERBOSE_PARSE(
+ log_parse("\n sound_id = %d", bs.m_sound_id);
+ );
+ bs.m_sound_style.read(in);
+ }
+ }
+ }
+ else if (tag_type == 34)
+ {
+ // Read the menu flag.
+ m_menu = in->read_u8() != 0;
+
+ int button_2_action_offset = in->read_u16();
+ int next_action_pos = in->get_position() +
button_2_action_offset - 2;
+
+ // Read button records.
+ for (;;)
+ {
+ button_record r;
+ if (r.read(in, tag_type, m) == false)
+ {
+ // Null record; marks the end of button records.
+ break;
+ }
+ m_button_records.push_back(r);
+ }
+
+ if (button_2_action_offset > 0)
+ {
+ in->set_position(next_action_pos);
+
+ // Read Button2ActionConditions
+ for (;;)
+ {
+ int next_action_offset = in->read_u16();
+ next_action_pos = in->get_position() +
next_action_offset - 2;
+
+ m_button_actions.resize(m_button_actions.size()
+ 1);
+ m_button_actions.back().read(in, tag_type);
+
+ if (next_action_offset == 0
+ || in->get_position() >=
in->get_tag_end_position())
+ {
+ // done.
+ break;
+ }
+
+ // seek to next action.
+ in->set_position(next_action_pos);
+ }
+ }
+ }
+}
+
+
+character*
+button_character_definition::create_character_instance(
+ character* parent, int id)
+{
+ character* ch = new button_character_instance(this, parent, id);
+ return ch;
+}
+
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: server/parser/button_character_def.h
===================================================================
RCS file: server/parser/button_character_def.h
diff -N server/parser/button_character_def.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ server/parser/button_character_def.h 26 Aug 2006 22:58:12 -0000
1.1
@@ -0,0 +1,128 @@
+// -- Thatcher Ulrich <address@hidden> 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.
+
+
+#ifndef GNASH_BUTTON_CHARACTER_DEF_H
+#define GNASH_BUTTON_CHARACTER_DEF_H
+
+
+//#include "impl.h" // should get rid of this
+#include "character_def.h"
+#include "sound.h"
+
+// Forward declarations
+namespace gnash {
+ class sprite_instance;
+}
+
+namespace gnash {
+
+class button_record
+{
+public:
+ bool m_hit_test;
+ bool m_down;
+ bool m_over;
+ bool m_up;
+ int m_character_id;
+ character_def* m_character_def;
+ int m_button_layer;
+ matrix m_button_matrix;
+ cxform m_button_cxform;
+
+ bool read(stream* in, int tag_type, movie_definition* m);
+};
+
+class button_action
+{
+public:
+ enum condition
+ {
+ IDLE_TO_OVER_UP = 1 << 0,
+ OVER_UP_TO_IDLE = 1 << 1,
+ OVER_UP_TO_OVER_DOWN = 1 << 2,
+ OVER_DOWN_TO_OVER_UP = 1 << 3,
+ OVER_DOWN_TO_OUT_DOWN = 1 << 4,
+ OUT_DOWN_TO_OVER_DOWN = 1 << 5,
+ OUT_DOWN_TO_IDLE = 1 << 6,
+ IDLE_TO_OVER_DOWN = 1 << 7,
+ OVER_DOWN_TO_IDLE = 1 << 8
+ };
+ int m_conditions;
+ std::vector<action_buffer*> m_actions;
+
+ ~button_action();
+ void read(stream* in, int tag_type);
+};
+
+
+class button_character_definition : public character_def
+{
+public:
+ struct sound_envelope
+ {
+ uint32_t m_mark44;
+ uint16_t m_level0;
+ uint16_t m_level1;
+ };
+
+ struct sound_info
+ {
+ void read(stream* in);
+
+ bool m_no_multiple;
+ bool m_stop_playback;
+ bool m_has_envelope;
+ bool m_has_loops;
+ bool m_has_out_point;
+ bool m_has_in_point;
+ uint32_t m_in_point;
+ uint32_t m_out_point;
+ uint16_t m_loop_count;
+ std::vector<sound_envelope> m_envelopes;
+ };
+
+ struct button_sound_info
+ {
+ uint16_t m_sound_id;
+ sound_sample_impl* m_sam;
+ sound_info m_sound_style;
+ };
+
+ struct button_sound_def
+ {
+ void read(stream* in, movie_definition* m);
+ button_sound_info m_button_sounds[4];
+ };
+
+
+ bool m_menu;
+ std::vector<button_record> m_button_records;
+ std::vector<button_action> m_button_actions;
+ button_sound_def* m_sound;
+
+ button_character_definition();
+ virtual ~button_character_definition();
+
+ /// Create a mutable instance of our definition.
+ character* create_character_instance(character* parent, int id);
+
+ void read(stream* in, int tag_type, movie_definition* m);
+};
+
+} // end namespace gnash
+
+
+#endif // GNASH_BUTTON_CHARACTER_DEF_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: server/button.cpp
===================================================================
RCS file: server/button.cpp
diff -N server/button.cpp
--- server/button.cpp 26 Aug 2006 02:08:31 -0000 1.29
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,1119 +0,0 @@
-// button.cpp -- Thatcher Ulrich <address@hidden> 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 "button.h"
-
-#include "action.h"
-#include "render.h"
-#include "sound.h"
-#include "stream.h"
-#include "movie_definition.h"
-#include "sprite_instance.h"
-#include "movie_root.h"
-#include "action_buffer.h"
-
-
-/** \page buttons Buttons and mouse behaviour
-
-Observations about button & mouse behavior
-
-Entities that receive mouse events: only buttons and sprites, AFAIK
-
-When the mouse button goes down, it becomes "captured" by whatever
-element is topmost, directly below the mouse at that moment. While
-the 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 mouse
-remains captured even if the element that captured it is removed from
-the display list.
-
-If the mouse isn't above a button or sprite when the mouse button goes
-down, then the mouse is captured by the background (i.e. mouse events
-just 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 to
-be an active entity, representing the background, and other objects that
-don't receive mouse events).
-
-When the mouse button is up, the active entity is the topmost element
-directly under the mouse pointer.
-
-When the mouse button is down, the active entity remains whatever it
-was when the button last went down.
-
-The active entity is the only object that receives mouse events.
-
-!!! The "trackAsMenu" property alters this behavior! If trackAsMenu
-is set on the active entity, then onReleaseOutside is filtered out,
-and onDragOver from another entity is allowed (from the background, or
-another trackAsMenu entity). !!!
-
-
-Pseudocode:
-
-active_entity = NULL
-mouse_button_state = UP
-mouse_inside_entity_state = false
-frame 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 gnash {
-
-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
-
- // set/kill focus for current root
- movie_root* mroot = (movie_root*) get_current_root();
- movie* current_active_entity =
mroot->get_active_entity();
-
- // It's another entity ?
- if (current_active_entity != active_entity.get_ptr())
- {
- // First to clean focus
- if (current_active_entity != NULL)
- {
-
current_active_entity->on_event(event_id::KILLFOCUS);
- mroot->set_active_entity(NULL);
- }
-
- // Then to set focus
- if (active_entity != NULL)
- {
- if
(active_entity->on_event(event_id::SETFOCUS))
- {
-
mroot->set_active_entity(active_entity.get_ptr());
- }
- }
- }
-
- 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;
-}
-
-
-class button_character_instance : public character
-{
-public:
- button_character_definition* m_def;
- std::vector< 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,
- character* 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* movie_def =
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();
- }
-
- // check up presence KeyPress events
- for (unsigned int i = 0; i < m_def->m_button_actions.size();
i++)
- {
- if (m_def->m_button_actions[i].m_conditions & 0xFE00)
// check up on CondKeyPress: UB[7]
- {
- get_root()->add_keypress_listener(this);
- break;
- }
- }
-
- }
-
- ~button_character_instance()
- {
- get_root()->remove_keypress_listener(this);
- }
-
- bool can_handle_mouse_event() { return true; }
-
- // called from keypress listener only
- bool on_event(event_id id)
- {
-
- if (id.m_id != event_id::KEY_PRESS)
- {
- return false;
- }
-
- bool called = false;
-
- static const event_id s_key[32] =
- {
- event_id(),
- event_id(event_id::KEY_PRESS, key::LEFT),
- event_id(event_id::KEY_PRESS, key::RIGHT),
- event_id(event_id::KEY_PRESS, key::HOME),
- event_id(event_id::KEY_PRESS, key::END),
- event_id(event_id::KEY_PRESS, key::INSERT),
- event_id(event_id::KEY_PRESS, key::DELETEKEY),
- event_id(),
- event_id(event_id::KEY_PRESS, key::BACKSPACE), //8
- event_id(),
- event_id(),
- event_id(),
- event_id(),
- event_id(event_id::KEY_PRESS, key::ENTER), //13
- event_id(event_id::KEY_PRESS, key::UP),
- event_id(event_id::KEY_PRESS, key::DOWN),
- event_id(event_id::KEY_PRESS, key::PGUP),
- event_id(event_id::KEY_PRESS, key::PGDN),
- event_id(event_id::KEY_PRESS, key::TAB),
- // 32-126 folows ASCII
- };
-
-
- // Add appropriate actions to the movie's execute list...
- for (unsigned int i = 0; i < m_def->m_button_actions.size();
i++)
- {
- int keycode = (m_def->m_button_actions[i].m_conditions
& 0xFE00) >> 9;
- event_id key_event = keycode < 32 ? s_key[keycode] :
event_id(event_id::KEY_PRESS, (key::code) keycode);
- if (key_event == id)
- {
- // Matching action.
- for (unsigned int j = 0; j <
m_def->m_button_actions[i].m_actions.size(); j++)
- {
-
get_parent()->add_action_buffer(m_def->m_button_actions[i].m_actions[j]);
- }
- called = true;
- }
- }
-
- return called;
- }
-
- movie_root* get_root() { return get_parent()->get_root(); }
-
- 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)
- {
-// printf("%s:\n", __PRETTY_FUNCTION__); // FIXME:
- // Implement mouse-drag.
- character::do_mouse_drag();
-
- matrix mat = get_world_matrix();
-
- // Advance our relevant characters.
- {for (unsigned 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()
- {
-// GNASH_REPORT_FUNCTION;
- for (unsigned 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))
- {
- matrix mat = get_world_matrix();
-
- 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 (unsigned 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)
- {
-
s->stop_sound(bs.m_sam->m_sound_handler_id);
- }
- else
- {
-
s->play_sound(bs.m_sam->m_sound_handler_id, bs.m_sound_style.m_loop_count, 0,
0);
- }
- }
- }
- }
- }
-
- // @@ eh, should just be a lookup table.
- int c = 0;
- if (event.m_id == event_id::ROLL_OVER) c |=
(button_action::IDLE_TO_OVER_UP);
- else if (event.m_id == event_id::ROLL_OUT) c |=
(button_action::OVER_UP_TO_IDLE);
- else if (event.m_id == event_id::PRESS) c |=
(button_action::OVER_UP_TO_OVER_DOWN);
- else if (event.m_id == event_id::RELEASE) c |=
(button_action::OVER_DOWN_TO_OVER_UP);
- else if (event.m_id == event_id::DRAG_OUT) c |=
(button_action::OVER_DOWN_TO_OUT_DOWN);
- else if (event.m_id == event_id::DRAG_OVER) c |=
(button_action::OUT_DOWN_TO_OVER_DOWN);
- else if (event.m_id == event_id::RELEASE_OUTSIDE) c |=
(button_action::OUT_DOWN_TO_IDLE);
- //IDLE_TO_OVER_DOWN = 1 << 7,
- //OVER_DOWN_TO_IDLE = 1 << 8,
-
- // restart the characters of the new state.
- restart_characters(c);
-
- // Add appropriate actions to the movie's execute list...
- {for (unsigned int i = 0; i < m_def->m_button_actions.size();
i++)
- {
- if (m_def->m_button_actions[i].m_conditions & c)
- {
- // Matching action.
- for (unsigned int j = 0; j <
m_def->m_button_actions[i].m_actions.size(); j++)
- {
-
get_parent()->add_action_buffer(m_def->m_button_actions[i].m_actions[j]);
- }
- }
- }}
-
- // Call conventional attached method.
- // @@ TODO
- }
-
-
- void restart_characters(int condition)
- {
- // Restart our relevant characters
- for (unsigned int i = 0; i < m_def->m_button_records.size();
i++)
- {
- bool restart = false;
- button_record* rec = &m_def->m_button_records[i];
-
- switch (m_mouse_state)
- {
- case OVER:
- {
- if ((rec->m_over) && (condition &
button_action::IDLE_TO_OVER_UP))
- {
- restart = true;
- }
- break;
- }
- // @@ Hm, are there other cases where we restart stuff?
- default:
- {
- break;
- }
- }
-
- if (restart == true)
- {
- m_record_character[i]->restart();
- }
- }
- }
-
-
- virtual void get_mouse_state(int* x, int* y, int* buttons)
- {
- get_parent()->get_mouse_state(x, y, buttons);
- }
-
-
- //
- // ActionScript overrides
- //
-
- virtual void set_member(const tu_stringi& name, const as_value& val)
- {
- // TODO: pull these up into a base class, to
- // share as much as possible with sprite_instance.
- as_standard_member std_member = get_standard_member(name);
- switch (std_member)
- {
- default:
- case M_INVALID_MEMBER:
- break;
- case M_VISIBLE: // _visible
- {
- m_visible = val.to_bool();
- return;
- }
- case M_ALPHA: // _alpha
- {
- // Set alpha modulate, in percent.
- cxform cx = get_cxform();
- cx.m_[3][0] = float(val.to_number()) / 100.f;
- set_cxform(cx);
- //m_accept_anim_moves = false;
- return;
- }
- case M_X: // _x
- {
- matrix m = get_matrix(); // @@
get_world_matrix()???
- m.m_[0][2] = float(PIXELS_TO_TWIPS(val.to_number()));
- this->set_matrix(m);
- return;
- }
- case M_Y: // _y
- {
- matrix m = get_matrix(); // @@
get_world_matrix()???
- m.m_[1][2] = float(PIXELS_TO_TWIPS(val.to_number()));
- this->set_matrix(m);
- return;
- }
-// evan : need set_width and set_height function for struct character
-#if 0
- case M_WIDTH: // _width
- {
- 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]->set_width(val.to_number);
- // @@ evan: should we return here?
- return;
- }
- }
-
- return;
- }
- else if (name == "enabled")
- {
- m_enabled = val.to_bool();
- }
- case M_HEIGHT: // _height
- {
- 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]->set_height(val.to_number);
- // @@ evan: should we return here?
- return;
- }
- }
-
- return;
- }
-#endif
- }
-
- log_error("error: button_character_instance::set_member('%s',
'%s') not implemented yet\n",
- name.c_str(),
- val.to_string());
- }
-
- virtual bool get_member(const tu_stringi& name, as_value* val)
- {
- // TODO: pull these up into a base class, to
- // share as much as possible with sprite_instance.
- as_standard_member std_member = get_standard_member(name);
- switch (std_member)
- {
- default:
- case M_INVALID_MEMBER:
- break;
- case M_VISIBLE: // _visible
- {
- val->set_bool(this->get_visible());
- return true;
- }
- case M_ALPHA: // _alpha
- {
- // @@ TODO this should be generic to struct character!
- // Alpha units are in percent.
- val->set_double(get_cxform().m_[3][0] * 100.f);
- return true;
- }
- case M_X: // _x
- {
- matrix m = get_matrix(); // @@
get_world_matrix()???
- val->set_double(TWIPS_TO_PIXELS(m.m_[0][2]));
- return true;
- }
- case M_Y: // _y
- {
- matrix m = get_matrix(); // @@
get_world_matrix()???
- val->set_double(TWIPS_TO_PIXELS(m.m_[1][2]));
- return true;
- }
- case M_WIDTH: // _width
- {
- for (unsigned 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))
- {
-
val->set_double(TWIPS_TO_PIXELS(m_record_character[i]->get_width()));
- // @@ evan: should we return here?
- return true;
- }
- }
-
- // from the experiments with macromedia flash player
- val->set_double(0);
- return true;
- }
- case M_HEIGHT: // _height
- {
- for (unsigned 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))
- {
-
val->set_double(TWIPS_TO_PIXELS(m_record_character[i]->get_height()));
- // @@ evan: should we return here?
- return true;
- }
- }
-
- // from the experiments with macromedia flash player
- val->set_double(0);
- return true;
- }
- }
-
- return false;
- }
-
- // not sure if we need to override this one.
- //virtual const char* get_text_value() const { return NULL; } //
edit_text_character overrides this
-};
-
-
- //
- // button_record
- //
-
- // Return true if we read a record; false if this is a null record.
- bool button_record::read(stream* in, int tag_type,
- movie_definition* /*m*/)
- {
- int flags = in->read_u8();
- if (flags == 0)
- {
- return false;
- }
- m_hit_test = flags & 8 ? true : false;
- m_down = flags & 4 ? true : false;
- m_over = flags & 2 ? true : false;
- m_up = flags & 1 ? true : false;
-
- m_character_id = in->read_u16();
- m_character_def = NULL;
- m_button_layer = in->read_u16();
- m_button_matrix.read(in);
-
- if (tag_type == 34)
- {
- m_button_cxform.read_rgba(in);
- }
-
- return true;
- }
-
-
- //
- // button_action
- //
-
-
- button_action::~button_action()
- {
- m_actions.clear();
- }
-
- void button_action::read(stream* in, int tag_type)
- {
- // Read condition flags.
- if (tag_type == 7)
- {
- m_conditions = OVER_DOWN_TO_OVER_UP;
- }
- else
- {
- assert(tag_type == 34);
- m_conditions = in->read_u16();
- }
-
- IF_VERBOSE_PARSE (
- log_parse("-- actions in button\n"); // @@ need more info about
which actions
- );
-
- // Read actions.
- action_buffer* a = new action_buffer;
- a->read(in);
- m_actions.push_back(a);
- }
-
-
- //
- // button_character_definition
- //
-
- button_character_definition::button_character_definition()
- :
- m_sound(NULL)
- // Constructor.
- {
- }
-
- button_character_definition::~button_character_definition()
- {
- delete m_sound;
- }
-
-
- void button_character_definition::sound_info::read(stream* in)
- {
- m_in_point = m_out_point = m_loop_count = 0;
- in->read_uint(2); // skip reserved bits.
- m_stop_playback = in->read_uint(1) ? true : false;
- m_no_multiple = in->read_uint(1) ? true : false;
- m_has_envelope = in->read_uint(1) ? true : false;
- m_has_loops = in->read_uint(1) ? true : false;
- m_has_out_point = in->read_uint(1) ? true : false;
- m_has_in_point = in->read_uint(1) ? true : false;
- if (m_has_in_point) m_in_point = in->read_u32();
- if (m_has_out_point) m_out_point = in->read_u32();
- if (m_has_loops) m_loop_count = in->read_u16();
- if (m_has_envelope)
- {
- int nPoints = in->read_u8();
- m_envelopes.resize(nPoints);
- for (int i=0; i < nPoints; i++)
- {
- m_envelopes[i].m_mark44 = in->read_u32();
- m_envelopes[i].m_level0 = in->read_u16();
- m_envelopes[i].m_level1 = in->read_u16();
- }
- }
- else
- {
- m_envelopes.resize(0);
- }
-
- IF_VERBOSE_PARSE(
- log_parse(" has_envelope = %d", m_has_envelope);
- log_parse(" has_loops = %d", m_has_loops);
- log_parse(" has_out_point = %d", m_has_out_point);
- log_parse(" has_in_point = %d", m_has_in_point);
- log_parse(" in_point = %d", m_in_point);
- log_parse(" out_point = %d", m_out_point);
- log_parse(" loop_count = %d", m_loop_count);
- log_parse(" envelope size = %u", m_envelopes.size());
- );
- }
-
-
-
- void button_character_definition::read(stream* in, int tag_type,
movie_definition* m)
- // Initialize from the given stream.
- {
- assert(tag_type == 7 || tag_type == 17 || tag_type == 34);
-
- if (tag_type == 7)
- {
- // Old button tag.
-
- // Read button character records.
- for (;;)
- {
- button_record r;
- if (r.read(in, tag_type, m) == false)
- {
- // Null record; marks the end of button
records.
- break;
- }
- m_button_records.push_back(r);
- }
-
- // Read actions.
- m_button_actions.resize(m_button_actions.size() + 1);
- m_button_actions.back().read(in, tag_type);
- }
- else if (tag_type == 17)
- {
- assert(m_sound == NULL); // redefinition button
sound is error
- m_sound = new button_sound_def();
- IF_VERBOSE_PARSE(
- log_parse("button sound options: ");
- );
- for (int i = 0; i < 4; i++)
- {
- button_sound_info& bs =
m_sound->m_button_sounds[i];
- bs.m_sound_id = in->read_u16();
- if (bs.m_sound_id > 0)
- {
- bs.m_sam = (sound_sample_impl*)
m->get_sound_sample(bs.m_sound_id);
- if (bs.m_sam == NULL)
- {
-// printf("sound tag not found,
sound_id=%d, button state #=%i", bs.sound_id, i);
- }
- IF_VERBOSE_PARSE(
- log_parse("\n sound_id = %d",
bs.m_sound_id);
- );
- bs.m_sound_style.read(in);
- }
- }
- }
- else if (tag_type == 34)
- {
- // Read the menu flag.
- m_menu = in->read_u8() != 0;
-
- int button_2_action_offset = in->read_u16();
- int next_action_pos = in->get_position() +
button_2_action_offset - 2;
-
- // Read button records.
- for (;;)
- {
- button_record r;
- if (r.read(in, tag_type, m) == false)
- {
- // Null record; marks the end of button
records.
- break;
- }
- m_button_records.push_back(r);
- }
-
- if (button_2_action_offset > 0)
- {
- in->set_position(next_action_pos);
-
- // Read Button2ActionConditions
- for (;;)
- {
- int next_action_offset =
in->read_u16();
- next_action_pos = in->get_position() +
next_action_offset - 2;
-
-
m_button_actions.resize(m_button_actions.size() + 1);
- m_button_actions.back().read(in,
tag_type);
-
- if (next_action_offset == 0
- || in->get_position() >=
in->get_tag_end_position())
- {
- // done.
- break;
- }
-
- // seek to next action.
- in->set_position(next_action_pos);
- }
- }
- }
- }
-
-
-character*
-button_character_definition::create_character_instance(
- character* parent, int id)
-{
- character* ch = new button_character_instance(this, parent, id);
- return ch;
-}
-
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
Index: server/button.h
===================================================================
RCS file: server/button.h
diff -N server/button.h
--- server/button.h 26 Aug 2006 02:08:31 -0000 1.10
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,166 +0,0 @@
-// button.h -- Thatcher Ulrich <address@hidden> 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.
-
-
-#ifndef GNASH_BUTTON_H
-#define GNASH_BUTTON_H
-
-
-#include "impl.h" // should get rid of this
-#include "character_def.h"
-#include "sound.h"
-
-// Forward declarations
-namespace gnash {
- class sprite_instance;
-}
-
-namespace gnash {
-
-//
-// Helper to generate mouse events, given mouse state & history.
-//
-
-class mouse_button_state
-{
-public:
- weak_ptr<movie> m_active_entity; // entity that currently owns
the mouse pointer
- weak_ptr<movie> m_topmost_entity; // what's underneath the mouse
right now
-
- bool m_mouse_button_state_last; // previous state of
mouse button
- bool m_mouse_button_state_current; // current state of
mouse button
-
- bool m_mouse_inside_entity_last; // whether mouse was inside the
active_entity last frame
-
- mouse_button_state()
- :
- m_mouse_button_state_last(0),
- m_mouse_button_state_current(0),
- m_mouse_inside_entity_last(false)
- {
- }
-};
-
-void generate_mouse_button_events(mouse_button_state* ms);
-
-
-//
-// button characters
-//
-enum mouse_state
-{
- MOUSE_UP,
- MOUSE_DOWN,
- MOUSE_OVER
-};
-
-class button_record
-{
-public:
- bool m_hit_test;
- bool m_down;
- bool m_over;
- bool m_up;
- int m_character_id;
- character_def* m_character_def;
- int m_button_layer;
- matrix m_button_matrix;
- cxform m_button_cxform;
-
- bool read(stream* in, int tag_type, movie_definition* m);
-};
-
-
-class button_action
-{
-public:
- enum condition
- {
- IDLE_TO_OVER_UP = 1 << 0,
- OVER_UP_TO_IDLE = 1 << 1,
- OVER_UP_TO_OVER_DOWN = 1 << 2,
- OVER_DOWN_TO_OVER_UP = 1 << 3,
- OVER_DOWN_TO_OUT_DOWN = 1 << 4,
- OUT_DOWN_TO_OVER_DOWN = 1 << 5,
- OUT_DOWN_TO_IDLE = 1 << 6,
- IDLE_TO_OVER_DOWN = 1 << 7,
- OVER_DOWN_TO_IDLE = 1 << 8
- };
- int m_conditions;
- std::vector<action_buffer*> m_actions;
-
- ~button_action();
- void read(stream* in, int tag_type);
-};
-
-
-class button_character_definition : public character_def
-{
-public:
- struct sound_envelope
- {
- uint32_t m_mark44;
- uint16_t m_level0;
- uint16_t m_level1;
- };
-
- struct sound_info
- {
- void read(stream* in);
-
- bool m_no_multiple;
- bool m_stop_playback;
- bool m_has_envelope;
- bool m_has_loops;
- bool m_has_out_point;
- bool m_has_in_point;
- uint32_t m_in_point;
- uint32_t m_out_point;
- uint16_t m_loop_count;
- std::vector<sound_envelope> m_envelopes;
- };
-
- struct button_sound_info
- {
- uint16_t m_sound_id;
- sound_sample_impl* m_sam;
- sound_info m_sound_style;
- };
-
- struct button_sound_def
- {
- void read(stream* in, movie_definition* m);
- button_sound_info m_button_sounds[4];
- };
-
-
- bool m_menu;
- std::vector<button_record> m_button_records;
- std::vector<button_action> m_button_actions;
- button_sound_def* m_sound;
-
- button_character_definition();
- virtual ~button_character_definition();
-
- /// Create a mutable instance of our definition.
- character* create_character_instance(character* parent, int id);
-
- void read(stream* in, int tag_type, movie_definition* m);
-};
-
-} // end namespace gnash
-
-
-#endif // GNASH_BUTTON_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ChangeLog libbase/image_filters.cpp libba...,
Sandro Santilli <=