[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash/server MovieClipLoader.cpp Sprite.cpp Spr...
From: |
strk |
Subject: |
[Gnash-commit] gnash/server MovieClipLoader.cpp Sprite.cpp Spr... |
Date: |
Fri, 27 Jan 2006 00:54:38 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Branch:
Changes by: strk <address@hidden> 06/01/27 00:54:38
Modified files:
server : MovieClipLoader.cpp Sprite.cpp Sprite.h
action.cpp action.h gnash.h impl.cpp impl.h
sound.cpp text.cpp
Log message:
More separation in Sprite.{cpp,h}.
General Doxygen dox (it's a long way...)
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/MovieClipLoader.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/Sprite.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/Sprite.h.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/action.cpp.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/action.h.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/gnash.h.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/impl.cpp.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/impl.h.diff?tr1=1.5&tr2=1.6&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/sound.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/text.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
Patches:
Index: gnash/server/MovieClipLoader.cpp
diff -u gnash/server/MovieClipLoader.cpp:1.1
gnash/server/MovieClipLoader.cpp:1.2
--- gnash/server/MovieClipLoader.cpp:1.1 Tue Jan 24 10:12:00 2006
+++ gnash/server/MovieClipLoader.cpp Fri Jan 27 00:54:38 2006
@@ -21,6 +21,7 @@
#include "tu_config.h"
#include <sys/types.h>
#include <sys/stat.h>
+#include <typeinfo>
#ifdef HAVE_LIBXML
// TODO: http and sockets and such ought to be factored out into an
@@ -202,12 +203,36 @@
moviecliploader_as_object* ptr = (moviecliploader_as_object*) (as_object*)
fn.this_ptr;
- tu_string url = fn.arg(0).to_string();
- as_object *target = (as_object *)fn.arg(1).to_object();
+ tu_string url = fn.arg(0).to_string();
+ as_object *target = (as_object *)fn.arg(1).to_object();
- log_msg("load clip: %s, target is: %p\n", url.c_str(), target);
+ log_msg("load clip: %s, target is: %p (%s)\n", url.c_str(),
+ target, typeid(*target).name());
+
+ //
+ // Extract root movie URL
+ // @@ could be cached somewhere...
+ //
+ as_value target_url;
+ if ( ! target->get_member("_url", &target_url) )
+ {
+ log_msg("FIXME: no _url member in target!");
+ }
+
+ log_msg(" target._url: %s\n", target_url.to_string());
+
+#if 0
+ as_value root_url;
+ if ( ! target->get_member("_url", &root_url) )
+ {
+ log_msg("FIXME: no _url member in target!");
+ }
- xmlNanoHTTPInit(); // This doesn't do much for now, but in the
+ log_msg(" root._url: type:%d to_string:%s rtty:%s\n",
+ root_url.m_type, root_url.to_string(), typeid(root_url).name());
+#endif
+
+ xmlNanoHTTPInit(); // This doesn't do much for now, but in the
// future it might, so here it is...
if (target == NULL)
@@ -217,19 +242,18 @@
return;
}
+ //
+ // Resolve relative urls
+ // @@ todo
+
+
// local file path
// this is either fetched from http or local in origin
tu_string filespec;
- bool filespec_copied = true;
+ bool filespec_copied = false;
- if (url.utf8_substring(0, 7) == "file://")
+ if (url.utf8_substring(0, 7) == "http://")
{
- filespec = url.utf8_substring(7, url.length());
- filespec_copied = false;
- }
- else
- {
-
// Grab the filename off the end of the URL, and use the same
name
// as the disk file when something is fetched. Store files in
/tmp/.
// If the file exists, libxml properly replaces it.
@@ -242,8 +266,19 @@
xmlNanoHTTPCleanup();
// FIXME: check for success or failure
+ filespec_copied = true;
}
+ else if (url.utf8_substring(0, 7) == "file://")
+ {
+ filespec = url.utf8_substring(7, url.length());
+ }
+ else
+ {
+ // @@ should never happen if we resolve relative urls
+ log_msg("FIXME: unresolved relative url\n");
+ filespec = url;
+ }
// If the file doesn't exist, don't try to do anything.
if (stat(filespec.c_str(), &stats) < 0)
Index: gnash/server/Sprite.cpp
diff -u gnash/server/Sprite.cpp:1.1 gnash/server/Sprite.cpp:1.2
--- gnash/server/Sprite.cpp:1.1 Wed Jan 25 18:03:25 2006
+++ gnash/server/Sprite.cpp Fri Jan 27 00:54:38 2006
@@ -21,16 +21,17 @@
#include "gnash.h"
#include "Sprite.h"
#include "MovieClipLoader.h" // @@ temp hack for loading tests
+#include <vector>
namespace gnash {
// Execute the actions in the action list, in the given
// environment.
static void
- execute_actions(as_environment* env, const array<action_buffer*>&
- action_list)
+ execute_actions(as_environment* env,
+ const std::vector<action_buffer*>& action_list)
{
- for (int i = 0; i < action_list.size(); i++)
+ for (unsigned int i=0, n=action_list.size(); i<n; ++i)
{
action_list[i]->execute(env);
}
@@ -165,10 +166,20 @@
static void sprite_load_movie(const fn_call& fn)
{
- log_error("Not implemented yet");
+ log_error("FIXME: %s not implemented yet", __PRETTY_FUNCTION__);
//moviecliploader_loadclip(fn);
}
+ static void sprite_create_text_field(const fn_call& fn)
+ {
+ log_error("FIXME: %s not implemented yet", __PRETTY_FUNCTION__);
+ //moviecliploader_loadclip(fn);
+ }
+
+ //------------------------------------------------
+ // sprite_instance
+ //------------------------------------------------
+
//
// Initialize the Sprite/MovieClip builtin class
//
@@ -187,6 +198,7 @@
as_builtins.set_member("getBytesLoaded",
&sprite_get_bytes_loaded);
as_builtins.set_member("getBytesTotal",
&sprite_get_bytes_total);
as_builtins.set_member("loadMovie", &sprite_load_movie);
+ as_builtins.set_member("createTextField",
&sprite_create_text_field);
// @TODO
//as_builtins.set_member("startDrag", &sprite_start_drag);
@@ -308,6 +320,8 @@
val->set_double(angle);
return true;
}
+
+ /// FIXME: use a contextual 'target' member
case M_TARGET:
//else if (name == "_target")
{
@@ -335,6 +349,14 @@
val->set_string("/_root");
return true;
}
+
+ ///
+ /// FIXME: add a valid 'url' member. Currently
+ /// the verbatim "gnash" value is assigned to it.
+ /// The 'url' member should be inherited by
+ /// parent *unless* we loaded an external resource
+ /// into this movieclip.
+ ///
case M_URL:
//else if (name == "_url")
{
@@ -450,4 +472,934 @@
m_action_list.resize(0);
}
+ /// Execute the actions for the specified frame.
+ //
+ /// The frame_spec could be an integer or a string.
+ ///
+ void sprite_instance::call_frame_actions(const as_value& frame_spec)
+ {
+ int frame_number = -1;
+
+ // Figure out what frame to call.
+ if (frame_spec.get_type() == as_value::STRING)
+ {
+ if (m_def->get_labeled_frame(frame_spec.to_string(),
&frame_number) == false)
+ {
+ // Try converting to integer.
+ frame_number = (int) frame_spec.to_number();
+ }
+ }
+ else
+ {
+ // convert from 1-based to 0-based
+ frame_number = (int) frame_spec.to_number() - 1;
+ }
+
+ if (frame_number < 0 || frame_number >=
m_def->get_frame_count())
+ {
+ // No dice.
+ log_error("error: call_frame('%s') -- unknown
frame\n", frame_spec.to_string());
+ return;
+ }
+
+ unsigned int top_action = m_action_list.size();
+
+ // Execute the execute_tag actions
+
+ const array<execute_tag*>&playlist =
m_def->get_playlist(frame_number);
+ for (int i=0, n=playlist.size(); i<n; ++i)
+ {
+ execute_tag* e = playlist[i];
+ if (e->is_action_tag())
+ {
+ e->execute(this);
+ }
+ }
+
+ // Execute any new actions triggered by the tag,
+ // leaving existing actions to be executed.
+
+ while (m_action_list.size() > top_action)
+ {
+ m_action_list[top_action]->execute(&m_as_environment);
+ //m_action_list.remove(top_action);
+ m_action_list.erase(m_action_list.begin()+top_action);
+ }
+
+ assert(m_action_list.size() == top_action);
+ }
+
+ void sprite_instance::clone_display_object(const tu_string& name,
+ const tu_string& newname, Uint16 depth)
+ {
+ character* ch = m_display_list.get_character_by_name(name);
+ if (ch)
+ {
+ array<swf_event*> dummy_event_handlers;
+
+ add_display_object(
+ ch->get_id(),
+ newname.c_str(),
+ dummy_event_handlers,
+ depth,
+ true, // replace if depth is occupied
+ ch->get_cxform(),
+ ch->get_matrix(),
+ ch->get_ratio(),
+ ch->get_clip_depth());
+ // @@ TODO need to duplicate ch's event handlers, and
presumably other members?
+ // Probably should make a character::clone() function to
handle this.
+ }
+ }
+
+ void sprite_instance::remove_display_object(const tu_string& name)
+ {
+ character* ch = m_display_list.get_character_by_name(name);
+ if (ch)
+ {
+ // @@ TODO: should only remove movies that were created via
clone_display_object --
+ // apparently original movies, placed by anim events, are
immune to this.
+ remove_display_object(ch->get_depth(), ch->get_id());
+ }
+ }
+
+ bool sprite_instance::on_event(event_id id)
+ {
+ // Keep m_as_environment alive during any method calls!
+ smart_ptr<as_object_interface> this_ptr(this);
+
+ bool called = false;
+
+ // First, check for built-in event handler.
+ {
+ as_value method;
+ if (get_event_handler(id, &method))
+ {
+ // Dispatch.
+ call_method0(method, &m_as_environment, this);
+
+ called = true;
+ // Fall through and call the function also, if
it's defined!
+ // (@@ Seems to be the behavior for mouse
events; not tested & verified for
+ // every event type.)
+ }
+ }
+
+ // Check for member function.
+ {
+ // In ActionScript 2.0, event method names are CASE
SENSITIVE.
+ // In ActionScript 1.0, event method names are CASE
INSENSITIVE.
+ const tu_stringi& method_name =
id.get_function_name().to_tu_stringi();
+ if (method_name.length() > 0)
+ {
+ as_value method;
+ if (get_member(method_name, &method))
+ {
+ call_method0(method, &m_as_environment,
this);
+ called = true;
+ }
+ }
+ }
+
+ return called;
+ }
+
+ movie* sprite_instance::get_relative_target(const tu_string& name)
+ {
+ if (name == "." || name == "this")
+ {
+ return this;
+ }
+ else if (name == "..")
+ {
+ return get_parent();
+ }
+ else if (name == "_level0"
+ || name == "_root")
+ {
+ return m_root->m_movie.get_ptr();
+ }
+
+ // See if we have a match on the display list.
+ return m_display_list.get_character_by_name(name);
+ }
+
+ void sprite_instance::set_member(const tu_stringi& name,
+ const as_value& val)
+ {
+ as_standard_member std_member = get_standard_member(name);
+ switch (std_member)
+ {
+ default:
+ case M_INVALID_MEMBER:
+ break;
+ case M_X:
+ //if (name == "_x")
+ {
+ matrix m = get_matrix();
+ m.m_[0][2] = (float)
PIXELS_TO_TWIPS(val.to_number());
+ set_matrix(m);
+
+ m_accept_anim_moves = false;
+
+ return;
+ }
+ case M_Y:
+ //else if (name == "_y")
+ {
+ matrix m = get_matrix();
+ m.m_[1][2] = (float)
PIXELS_TO_TWIPS(val.to_number());
+ set_matrix(m);
+
+ m_accept_anim_moves = false;
+
+ return;
+ }
+ case M_XSCALE:
+ //else if (name == "_xscale")
+ {
+ matrix m = get_matrix();
+
+ // Decompose matrix and insert the desired value.
+ float x_scale = (float) val.to_number() /
100.f; // input is in percent
+ float y_scale = m.get_y_scale();
+ float rotation = m.get_rotation();
+ m.set_scale_rotation(x_scale, y_scale, rotation);
+
+ set_matrix(m);
+ m_accept_anim_moves = false;
+ return;
+ }
+ case M_YSCALE:
+ //else if (name == "_yscale")
+ {
+ matrix m = get_matrix();
+
+ // Decompose matrix and insert the desired value.
+ float x_scale = m.get_x_scale();
+ float y_scale = (float) val.to_number() /
100.f; // input is in percent
+ float rotation = m.get_rotation();
+ m.set_scale_rotation(x_scale, y_scale, rotation);
+
+ set_matrix(m);
+ m_accept_anim_moves = false;
+ return;
+ }
+ case M_ALPHA:
+ //else if (name == "_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_VISIBLE:
+ //else if (name == "_visible")
+ {
+ set_visible(val.to_bool());
+ m_accept_anim_moves = false;
+ return;
+ }
+ case M_WIDTH:
+ //else if (name == "_width")
+ {
+ // @@ tulrich: is parameter in world-coords or
local-coords?
+ matrix m = get_matrix();
+ m.m_[0][0] =
float(PIXELS_TO_TWIPS(val.to_number()));
+ float w = get_width();
+ if (fabsf(w) > 1e-6f)
+ {
+ m.m_[0][0] /= w;
+ }
+ set_matrix(m);
+ m_accept_anim_moves = false;
+ return;
+ }
+ case M_HEIGHT:
+ //else if (name == "_height")
+ {
+ // @@ tulrich: is parameter in world-coords or
local-coords?
+ matrix m = get_matrix();
+ m.m_[1][1] =
float(PIXELS_TO_TWIPS(val.to_number()));
+ float h = get_width();
+ if (fabsf(h) > 1e-6f)
+ {
+ m.m_[1][1] /= h;
+ }
+ set_matrix(m);
+ m_accept_anim_moves = false;
+ return;
+ }
+ case M_ROTATION:
+ //else if (name == "_rotation")
+ {
+ matrix m = get_matrix();
+
+ // Decompose matrix and insert the desired value.
+ float x_scale = m.get_x_scale();
+ float y_scale = m.get_y_scale();
+ float rotation = (float) val.to_number() *
float(M_PI) / 180.f; // input is in degrees
+ m.set_scale_rotation(x_scale, y_scale, rotation);
+
+ set_matrix(m);
+ m_accept_anim_moves = false;
+ return;
+ }
+ case M_HIGHQUALITY:
+ //else if (name == "_highquality")
+ {
+ // @@ global { 0, 1, 2 }
+ // // Whether we're in high quality mode
or not.
+ // val->set(true);
+ return;
+ }
+ case M_FOCUSRECT:
+ //else if (name == "_focusrect")
+ {
+ // // Is a yellow rectangle visible around
a focused movie clip (?)
+ // val->set(false);
+ return;
+ }
+ case M_SOUNDBUFTIME:
+ //else if (name == "_soundbuftime")
+ {
+ // @@ global
+ // // Number of seconds before sound
starts to stream.
+ // val->set(0.0);
+ return;
+ }
+ } // end switch
+
+ // Not a built-in property. See if we have a
+ // matching edit_text character in our display
+ // list.
+ bool text_val = val.get_type() == as_value::STRING
+ || val.get_type() == as_value::NUMBER;
+ if (text_val)
+ {
+ bool success = false;
+ for (int i = 0, n =
m_display_list.get_character_count(); i < n; i++)
+ {
+ character* ch =
m_display_list.get_character(i);
+ // CASE INSENSITIVE compare. In
ActionScript 2.0, this
+ // changes to CASE SENSITIVE!!!
+ if (name == ch->get_text_name())
+ {
+ const char* text = val.to_string();
+ ch->set_text_value(text);
+ success = true;
+ }
+ }
+ if (success) return;
+ }
+
+ // If that didn't work, set a variable within this
environment.
+ m_as_environment.set_member(name, val);
+ }
+
+ const char* sprite_instance::get_variable(const char* path_to_var) const
+ {
+ assert(m_parent == NULL); // should only be called on the root
movie.
+
+ array<with_stack_entry> empty_with_stack;
+ tu_string path(path_to_var);
+
+ // NOTE: this is static so that the string
+ // value won't go away after we return!!!
+ // It'll go away during the next call to this
+ // function though!!! NOT THREAD SAFE!
+ static as_value val;
+
+ val = m_as_environment.get_variable(path, empty_with_stack);
+
+ return val.to_string(); // ack!
+ }
+
+ void sprite_instance::set_variable(const char* path_to_var,
+ const wchar_t* new_value)
+ {
+ if (path_to_var == NULL)
+ {
+ log_error("error: NULL path_to_var passed to
set_variable()\n");
+ return;
+ }
+ if (new_value == NULL)
+ {
+ log_error("error: NULL passed to set_variable('%s',"
+ " NULL)\n", path_to_var);
+ return;
+ }
+
+ // should only be called on the root movie.
+ assert(m_parent == NULL);
+
+ array<with_stack_entry> empty_with_stack;
+ tu_string path(path_to_var);
+ as_value val(new_value);
+
+ m_as_environment.set_variable(path, val, empty_with_stack);
+ }
+
+ void sprite_instance::set_variable(const char* path_to_var,
+ const char* new_value)
+ {
+ assert(m_parent == NULL); // should only be called on the
root movie.
+
+ if (path_to_var == NULL)
+ {
+ log_error("error: NULL path_to_var passed to
set_variable()\n");
+ return;
+ }
+ if (new_value == NULL)
+ {
+ log_error("error: NULL passed to set_variable('%s',
NULL)\n", path_to_var);
+ return;
+ }
+
+ array<with_stack_entry> empty_with_stack;
+ tu_string path(path_to_var);
+ as_value val(new_value);
+
+ m_as_environment.set_variable(path, val, empty_with_stack);
+ }
+
+ void sprite_instance::advance(float delta_time)
+ {
+ // printf("%s:\n", __PRETTY_FUNCTION__); // FIXME:
+
+ // Keep this (particularly m_as_environment) alive during execution!
+ smart_ptr<as_object_interface> this_ptr(this);
+
+ assert(m_def != NULL && m_root != NULL);
+
+ // Advance everything in the display list.
+ m_display_list.advance(delta_time);
+
+ // mouse drag.
+ character::do_mouse_drag();
+
+ m_time_remainder += delta_time;
+
+ const float frame_time = 1.0f / m_root->get_frame_rate();
// @@ cache this
+
+ // Check for the end of frame
+ if (m_time_remainder >= frame_time)
+ {
+ m_time_remainder -= frame_time;
+
+ // Update current and next frames.
+ if (m_play_state == PLAY)
+ {
+ int current_frame0 = m_current_frame;
+ increment_frame_and_check_for_loop();
+
+ // Execute the current frame's tags.
+ if (m_current_frame != current_frame0)
+ {
+ execute_frame_tags(m_current_frame);
+ }
+ }
+
+ // Dispatch onEnterFrame event.
+ on_event(event_id::ENTER_FRAME);
+
+ do_actions();
+
+ // Clean up display list (remove dead objects).
+ m_display_list.update();
+ }
+
+ // Skip excess time. TODO root caller should
+ // loop to prevent this happening; probably
+ // only root should keep m_time_remainder, and
+ // advance(dt) should be a discrete tick()
+ // with no dt.
+ m_time_remainder = fmod(m_time_remainder, frame_time);
+ }
+
+ void sprite_instance::execute_frame_tags(int frame,
+ bool state_only)
+ {
+ // Keep this (particularly m_as_environment) alive during execution!
+ smart_ptr<as_object_interface> this_ptr(this);
+
+ assert(frame >= 0);
+ assert(frame < m_def->get_frame_count());
+
+ // Execute this frame's init actions, if necessary.
+ if (m_init_actions_executed[frame] == false)
+ {
+ const array<execute_tag*>* init_actions =
m_def->get_init_actions(frame);
+ if (init_actions && init_actions->size() > 0)
+ {
+ // Need to execute these actions.
+ for (int i= 0; i < init_actions->size(); i++)
+ {
+ execute_tag* e = (*init_actions)[i];
+ e->execute(this);
+ }
+
+ // Mark this frame done, so we never execute these
init actions
+ // again.
+ m_init_actions_executed[frame] = true;
+ }
+ }
+
+ const array<execute_tag*>& playlist = m_def->get_playlist(frame);
+ for (int i = 0; i < playlist.size(); i++)
+ {
+ execute_tag* e = playlist[i];
+ if (state_only)
+ {
+ e->execute_state(this);
+ }
+ else
+ {
+ e->execute(this);
+ }
+ }
+ }
+
+ void sprite_instance::execute_frame_tags_reverse(int frame)
+ {
+ // Keep this (particularly m_as_environment) alive during execution!
+ smart_ptr<as_object_interface> this_ptr(this);
+
+ assert(frame >= 0);
+ assert(frame < m_def->get_frame_count());
+
+ const array<execute_tag*>& playlist = m_def->get_playlist(frame);
+ for (int i = 0; i < playlist.size(); i++)
+ {
+ execute_tag* e = playlist[i];
+ e->execute_state_reverse(this, frame);
+ }
+ }
+
+ void sprite_instance::execute_remove_tags(int frame)
+ {
+ assert(frame >= 0);
+ assert(frame < m_def->get_frame_count());
+
+ const array<execute_tag*>& playlist =
m_def->get_playlist(frame);
+ for (int i = 0; i < playlist.size(); i++)
+ {
+ execute_tag* e = playlist[i];
+ if (e->is_remove_tag())
+ {
+ e->execute_state(this);
+ }
+ }
+ }
+
+ execute_tag*
+ sprite_instance::find_previous_replace_or_add_tag(int frame,
+ int depth, int id)
+ {
+ uint32 depth_id = ((depth & 0x0FFFF) << 16) | (id & 0x0FFFF);
+
+ for (int f = frame - 1; f >= 0; f--)
+ {
+ const array<execute_tag*>& playlist =
m_def->get_playlist(f);
+ for (int i = playlist.size() - 1; i >= 0; i--)
+ {
+ execute_tag* e = playlist[i];
+ if (e->get_depth_id_of_replace_or_add_tag() ==
depth_id)
+ {
+ return e;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ void
+ sprite_instance::goto_frame(int target_frame_number)
+ {
+ //
IF_VERBOSE_DEBUG(log_msg("sprite::goto_frame(%d)\n",
target_frame_number));//xxxxx
+
+ target_frame_number = iclamp(target_frame_number, 0,
m_def->get_frame_count() - 1);
+
+ if (target_frame_number < m_current_frame)
+ {
+ for (int f = m_current_frame; f >
target_frame_number; f--)
+ {
+ execute_frame_tags_reverse(f);
+ }
+
+ execute_frame_tags(target_frame_number, false);
+ m_display_list.update();
+ }
+ else if (target_frame_number > m_current_frame)
+ {
+ for (int f = m_current_frame + 1; f <
target_frame_number; f++)
+ {
+ execute_frame_tags(f, true);
+ }
+
+ execute_frame_tags(target_frame_number, false);
+ m_display_list.update();
+ }
+
+ m_current_frame = target_frame_number;
+
+ // goto_frame stops by default.
+ m_play_state = STOP;
+ }
+
+ bool sprite_instance::goto_labeled_frame(const char* label)
+ {
+ int target_frame = -1;
+ if (m_def->get_labeled_frame(label, &target_frame))
+ {
+ goto_frame(target_frame);
+ return true;
+ }
+ else
+ {
+ IF_VERBOSE_ACTION(
+ log_error("error: movie_impl::goto_labeled_frame('%s')
unknown label\n", label));
+ return false;
+ }
+ }
+
+ void sprite_instance::display()
+ {
+ if (get_visible() == false)
+ {
+ // We're invisible, so don't display!
+ return;
+ }
+
+ m_display_list.display();
+
+ do_display_callback();
+ }
+
+ character*
+ sprite_instance::add_display_object(Uint16 character_id,
+ const char* name,
+ const array<swf_event*>& event_handlers,
+ Uint16 depth, bool replace_if_depth_is_occupied,
+ const cxform& color_transform, const matrix& matrix,
+ float ratio, Uint16 clip_depth)
+ {
+ assert(m_def != NULL);
+
+ character_def* cdef =
m_def->get_character_def(character_id);
+ if (cdef == NULL)
+ {
+ log_error("sprite::add_display_object(): unknown
cid = %d\n", character_id);
+ return NULL;
+ }
+
+ // If we already have this object on this
+ // plane, then move it instead of replacing
+ // it.
+ character* existing_char =
m_display_list.get_character_at_depth(depth);
+ if (existing_char
+ && existing_char->get_id() == character_id
+ && ((name == NULL && existing_char->get_name().length()
== 0)
+ || (name && existing_char->get_name() == name)))
+ {
+ // IF_VERBOSE_DEBUG(log_msg("add changed
to move on depth %d\n", depth));//xxxxxx
+ move_display_object(depth, true, color_transform,
true, matrix, ratio, clip_depth);
+ return NULL;
+ }
+ //printf("%s: character %s, id is %d, count is %d\n",
__FUNCTION__, existing_char->get_name(),
character_id,m_display_list.get_character_count()); // FIXME:
+
+ assert(cdef);
+ smart_ptr<character> ch =
cdef->create_character_instance(this, character_id);
+ assert(ch != NULL);
+ if (name != NULL && name[0] != 0)
+ {
+ ch->set_name(name);
+ }
+
+ // Attach event handlers (if any).
+ {for (int i = 0, n = event_handlers.size(); i < n; i++)
+ {
+ event_handlers[i]->attach_to(ch.get_ptr());
+ }}
+
+ m_display_list.add_display_object(
+ ch.get_ptr(),
+ depth,
+ replace_if_depth_is_occupied,
+ color_transform,
+ matrix,
+ ratio,
+ clip_depth);
+
+ assert(ch == NULL || ch->get_ref_count() > 1);
+ return ch.get_ptr();
+ }
+
+ void
+ sprite_instance::replace_display_object(
+ Uint16 character_id,
+ const char* name,
+ Uint16 depth,
+ bool use_cxform,
+ const cxform& color_transform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ Uint16 clip_depth)
+ {
+ assert(m_def != NULL);
+ // printf("%s: character %s, id is %d\n", __FUNCTION__,
name, character_id); // FIXME: debugging crap
+
+ character_def* cdef =
m_def->get_character_def(character_id);
+ if (cdef == NULL)
+ {
+ log_error("sprite::replace_display_object():
unknown cid = %d\n", character_id);
+ return;
+ }
+ assert(cdef);
+
+ smart_ptr<character> ch =
cdef->create_character_instance(this, character_id);
+ assert(ch != NULL);
+
+ if (name != NULL && name[0] != 0)
+ {
+ ch->set_name(name);
+ }
+
+ m_display_list.replace_display_object(
+ ch.get_ptr(),
+ depth,
+ use_cxform,
+ color_transform,
+ use_matrix,
+ mat,
+ ratio,
+ clip_depth);
+ }
+
+ void sprite_instance::replace_display_object(
+ character* ch,
+ const char* name,
+ Uint16 depth,
+ bool use_cxform,
+ const cxform& color_transform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ Uint16 clip_depth)
+ {
+ printf("%s: character %s, id is %d\n", __FUNCTION__, name,
ch->get_id()); // FIXME:
+
+ assert(ch != NULL);
+
+ if (name != NULL && name[0] != 0)
+ {
+ ch->set_name(name);
+ }
+
+ m_display_list.replace_display_object(
+ ch,
+ depth,
+ use_cxform,
+ color_transform,
+ use_matrix,
+ mat,
+ ratio,
+ clip_depth);
+ }
+
+ int sprite_instance::get_id_at_depth(int depth)
+ {
+ int index = m_display_list.get_display_index(depth);
+ if (index == -1) return -1;
+
+ character* ch =
m_display_list.get_display_object(index).m_character.get_ptr();
+
+ return ch->get_id();
+ }
+
+ void sprite_instance::increment_frame_and_check_for_loop()
+ {
+ m_current_frame++;
+
+ int frame_count = m_def->get_frame_count();
+ if (m_current_frame >= frame_count)
+ {
+ // Loop.
+ m_current_frame = 0;
+ m_has_looped = true;
+ if (frame_count > 1)
+ {
+ m_display_list.reset();
+ }
+ }
+ }
+
+ movie*
+ sprite_instance::get_topmost_mouse_entity(float x, float y)
+ {
+ if (get_visible() == false) {
+ return NULL;
+ }
+
+ matrix m = get_matrix();
+ point p;
+ m.transform_by_inverse(&p, point(x, y));
+
+ int i, n = m_display_list.get_character_count();
+ // Go backwards, to check higher objects first.
+ for (i = n - 1; i >= 0; i--)
+ {
+ character* ch = m_display_list.get_character(i);
+
+ if (ch != NULL && ch->get_visible())
+ {
+ movie* te =
ch->get_topmost_mouse_entity(p.m_x, p.m_y);
+ if (te)
+ {
+ // The containing entity that 1) is closest
to root and 2) can
+ // handle mouse events takes precedence.
+ if (can_handle_mouse_event()) {
+ return this;
+ } else {
+ return te;
+ }
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ bool
+ sprite_instance::can_handle_mouse_event()
+ {
+ // We should cache this!
+ as_value dummy;
+
+ // Functions that qualify as mouse event handlers.
+ const char* FN_NAMES[] = {
+ "onKeyPress",
+ "onRelease",
+ "onDragOver",
+ "onDragOut",
+ "onPress",
+ "onReleaseOutside",
+ "onRollout",
+ "onRollover",
+ };
+ for (unsigned int i = 0; i < ARRAYSIZE(FN_NAMES); i++) {
+ if (get_member(FN_NAMES[i], &dummy)) {
+ return true;
+ }
+ }
+
+ // Event handlers that qualify as mouse event handlers.
+ const event_id::id_code EH_IDS[] = {
+ event_id::PRESS,
+ event_id::RELEASE,
+ event_id::RELEASE_OUTSIDE,
+ event_id::ROLL_OVER,
+ event_id::ROLL_OUT,
+ event_id::DRAG_OVER,
+ event_id::DRAG_OUT,
+ };
+ {for (unsigned int i = 0; i < ARRAYSIZE(EH_IDS); i++) {
+ if (get_event_handler(EH_IDS[i], &dummy)) {
+ return true;
+ }
+ }}
+
+ return false;
+ }
+
+ void sprite_instance::restart()
+ {
+ m_current_frame = 0;
+ m_time_remainder = 0;
+ m_update_frame = true;
+ m_has_looped = false;
+ m_play_state = PLAY;
+
+ execute_frame_tags(m_current_frame);
+ m_display_list.update();
+ }
+
+ float sprite_instance::get_height()
+ {
+ float h = 0;
+ int i, n = m_display_list.get_character_count();
+ character* ch;
+ for (i=0; i < n; i++)
+ {
+ ch = m_display_list.get_character(i);
+ if (ch != NULL)
+ {
+ float ch_h = ch->get_height();
+ if (ch_h > h)
+ {
+ h = ch_h;
+ }
+ }
+ }
+ return h;
+ }
+
+ float sprite_instance::get_width()
+ {
+ float w = 0;
+ int i, n = m_display_list.get_character_count();
+ character* ch;
+ for (i = 0; i < n; i++)
+ {
+ ch = m_display_list.get_character(i);
+ if (ch != NULL)
+ {
+ float ch_w = ch->get_width();
+ if (ch_w > w)
+ {
+ w = ch_w;
+ }
+ }
+ }
+
+ return w;
+ }
+
+ void sprite_instance::do_something(void *timer)
+ {
+ as_value val;
+ as_object *obj, *this_ptr;
+ as_environment *as_env;
+
+ //printf("FIXME: %s:\n", __FUNCTION__);
+ Timer *ptr = (Timer *)timer;
+ //log_msg("INTERVAL ID is %d\n", ptr->getIntervalID());
+
+ const as_value& timer_method = ptr->getASFunction();
+ as_env = ptr->getASEnvironment();
+ this_ptr = ptr->getASObject();
+ obj = ptr->getObject();
+ //m_as_environment.push(obj);
+
+ as_c_function_ptr cfunc = timer_method.to_c_function();
+ if (cfunc) {
+ // It's a C function. Call it.
+ //log_msg("Calling C function for interval timer\n");
+ //(*cfunc)(&val, obj, as_env, 0, 0);
+ (*cfunc)(fn_call(&val, obj, &m_as_environment, 0, 0));
+
+ } else if (as_as_function* as_func = timer_method.to_as_function())
{
+ // It's an ActionScript function. Call it.
+ as_value method;
+ //log_msg("Calling ActionScript function for interval timer\n");
+ (*as_func)(fn_call(&val, (as_object_interface *)this_ptr,
as_env, 0, 0));
+ //(*as_func)(&val, (as_object_interface *)this_ptr,
&m_as_environment, 1, 1);
+ } else {
+ log_error("error in call_method(): method is not a function\n");
+ }
+ }
} // namespace gnash
Index: gnash/server/Sprite.h
diff -u gnash/server/Sprite.h:1.2 gnash/server/Sprite.h:1.3
--- gnash/server/Sprite.h:1.2 Thu Jan 26 00:15:57 2006
+++ gnash/server/Sprite.h Fri Jan 27 00:54:38 2006
@@ -17,18 +17,24 @@
// Implementation for ActionScript MovieClip object.
-// A sprite, or MovieClip, is a mini movie-within-a-movie.
-// It doesn't define its own characters;
-// it uses the characters from the parent
-// movie, but it has its own frame counter, display list, etc.
-//
-// @@ are we sure it doesn't define its own chars ?
-//
-// The sprite implementation is divided into a
-// sprite_definition and a sprite_instance. The _definition
-// holds the immutable data for a sprite, while the _instance
-// contains the state for a specific instance being updated
-// and displayed in the parent movie's display list.
+/// \page Sprite Sprites and MovieClips
+///
+/// A Sprite, or MovieClip, is a mini movie-within-a-movie.
+///
+/// It doesn't define its own characters;
+/// it uses the characters from the parent
+/// movie, but it has its own frame counter, display list, etc.
+///
+/// @@ are we sure it doesn't define its own chars ?
+///
+/// The sprite implementation is divided into
+/// gnash::sprite_definition and gnash::sprite_instance.
+///
+/// The _definition holds the immutable data for a sprite, while the _instance
+/// contains the state for a specific instance being updated
+/// and displayed in the parent movie's display list.
+///
+/// @@ QUESTION: why isn't sprite_definition a bunch of statics ?
#ifndef GNASH_SPRITE_H
#define GNASH_SPRITE_H
@@ -36,6 +42,7 @@
#include "Movie.h"
#include "dlist.h" // display_list
#include "stream.h"
+#include <vector>
namespace gnash
{
@@ -244,17 +251,16 @@
};
- /// Sprite instance
- //
/// Stateful Sprite object. Also known as a MovieClip.
- ///
struct sprite_instance : public character
{
smart_ptr<movie_definition_sub> m_def;
movie_root* m_root;
display_list m_display_list;
- array<action_buffer*> m_action_list;
+
+ //array<action_buffer*> m_action_list;
+ std::vector<action_buffer*> m_action_list;
play_state m_play_state;
int m_current_frame;
@@ -286,17 +292,17 @@
sprite_instance(movie_definition_sub* def,
movie_root* r, movie* parent, int id)
- :
- character(parent, id),
- m_def(def),
- m_root(r),
- m_play_state(PLAY),
- m_current_frame(0),
- m_time_remainder(0),
- m_update_frame(true),
- m_has_looped(false),
- m_accept_anim_moves(true),
- m_mouse_state(UP)
+ :
+ character(parent, id),
+ m_def(def),
+ m_root(r),
+ m_play_state(PLAY),
+ m_current_frame(0),
+ m_time_remainder(0),
+ m_update_frame(true),
+ m_has_looped(false),
+ m_accept_anim_moves(true),
+ m_mouse_state(UP)
{
assert(m_def != NULL);
assert(m_root != NULL);
@@ -319,772 +325,262 @@
return m_root->add_interval_timer(timer);
}
- virtual void clear_interval_timer(int x)
+ virtual void clear_interval_timer(int x)
{
// log_msg("FIXME: %s:\n", __FUNCTION__);
m_root->clear_interval_timer(x);
}
- /* sprite_instance */
- virtual void do_something(void *timer)
- {
- as_value val;
- as_object *obj, *this_ptr;
- as_environment *as_env;
-
- //printf("FIXME: %s:\n", __FUNCTION__);
- Timer *ptr = (Timer *)timer;
- //log_msg("INTERVAL ID is %d\n", ptr->getIntervalID());
-
- const as_value& timer_method = ptr->getASFunction();
- as_env = ptr->getASEnvironment();
- this_ptr = ptr->getASObject();
- obj = ptr->getObject();
- //m_as_environment.push(obj);
-
- as_c_function_ptr cfunc = timer_method.to_c_function();
- if (cfunc) {
- // It's a C function. Call it.
- //log_msg("Calling C function for interval timer\n");
- //(*cfunc)(&val, obj, as_env, 0, 0);
- (*cfunc)(fn_call(&val, obj, &m_as_environment, 0, 0));
-
- } else if (as_as_function* as_func =
timer_method.to_as_function()) {
- // It's an ActionScript function. Call it.
- as_value method;
- //log_msg("Calling ActionScript function for interval
timer\n");
- (*as_func)(fn_call(&val, (as_object_interface
*)this_ptr, as_env, 0, 0));
- //(*as_func)(&val, (as_object_interface *)this_ptr,
&m_as_environment, 1, 1);
- } else {
- log_error("error in call_method(): method is not a
function\n");
- }
- }
+ /// Interval timer timeout executor
+ virtual void do_something(void *timer);
- virtual ~sprite_instance()
+ virtual ~sprite_instance()
{
m_display_list.clear();
//m_root->drop_ref();
}
- movie_interface* get_root_interface() { return m_root; }
- movie_root* get_root() { return m_root; }
- movie* get_root_movie() { return m_root->get_root_movie(); }
-
- movie_definition* get_movie_definition() { return
m_def.get_ptr(); }
-
- float get_width()
- {
- float w = 0;
- int i, n = m_display_list.get_character_count();
- character* ch;
- for (i = 0; i < n; i++)
- {
- ch = m_display_list.get_character(i);
- if (ch != NULL)
- {
- float ch_w = ch->get_width();
- if (ch_w > w)
- {
- w = ch_w;
- }
- }
- }
-
- return w;
+ movie_interface* get_root_interface() {
+ return m_root;
}
-
- float get_height()
- {
- float h = 0;
- int i, n = m_display_list.get_character_count();
- character* ch;
- for (i=0; i < n; i++)
- {
- ch = m_display_list.get_character(i);
- if (ch != NULL)
- {
- float ch_h = ch->get_height();
- if (ch_h > h)
- {
- h = ch_h;
- }
- }
- }
- return h;
+ movie_root* get_root() {
+ return m_root;
}
- int get_current_frame() const { return m_current_frame; }
- int get_frame_count() const { return m_def->get_frame_count(); }
-
- void set_play_state(play_state s)
- // Stop or play the sprite.
- {
- if (m_play_state != s)
- {
- m_time_remainder = 0;
- }
-
- m_play_state = s;
+ movie* get_root_movie() {
+ return m_root->get_root_movie();
}
- play_state get_play_state() const { return m_play_state; }
-
- character* get_character(int character_id)
- {
- // return m_def->get_character_def(character_id);
- // @@ TODO -- look through our dlist for a match
- return NULL;
+ movie_definition* get_movie_definition() {
+ return m_def.get_ptr();
}
- float get_background_alpha() const
- {
- // @@ this doesn't seem right...
- return m_root->get_background_alpha();
- }
+ float get_width();
- float get_pixel_scale() const { return
m_root->get_pixel_scale(); }
+ float get_height();
- virtual void get_mouse_state(int* x, int* y, int* buttons)
+ int get_current_frame() const
{
- m_root->get_mouse_state(x, y, buttons);
+ return m_current_frame;
}
- void set_background_color(const rgba& color)
+ int get_frame_count() const
{
- m_root->set_background_color(color);
+ return m_def->get_frame_count();
}
- float get_timer() const { return m_root->get_timer(); }
-
- void restart()
+ /// Stop or play the sprite.
+ void set_play_state(play_state s)
{
- m_current_frame = 0;
- m_time_remainder = 0;
- m_update_frame = true;
- m_has_looped = false;
- m_play_state = PLAY;
-
- execute_frame_tags(m_current_frame);
- m_display_list.update();
+ if (m_play_state != s) m_time_remainder = 0;
+ m_play_state = s;
}
+ play_state get_play_state() const { return m_play_state; }
- virtual bool has_looped() const { return m_has_looped; }
-
- virtual bool get_accept_anim_moves() const { return
m_accept_anim_moves; }
-
- inline int transition(int a, int b) const
- // Combine the flags to avoid a conditional. It would be faster
with a macro.
+ character* get_character(int character_id)
{
- return (a << 2) | b;
+ //return m_def->get_character_def(character_id);
+ // @@ TODO -- look through our dlist for a match
+ log_msg("FIXME: %s doesn't even check for a char",
+ __PRETTY_FUNCTION__);
+ return NULL;
}
-
- bool can_handle_mouse_event()
- // Return true if we have any mouse event handlers.
+ float get_background_alpha() const
{
- // We should cache this!
- as_value dummy;
-
- // Functions that qualify as mouse event handlers.
- const char* FN_NAMES[] = {
- "onKeyPress",
- "onRelease",
- "onDragOver",
- "onDragOut",
- "onPress",
- "onReleaseOutside",
- "onRollout",
- "onRollover",
- };
- for (unsigned int i = 0; i < ARRAYSIZE(FN_NAMES); i++) {
- if (get_member(FN_NAMES[i], &dummy)) {
- return true;
- }
- }
-
- // Event handlers that qualify as mouse event handlers.
- const event_id::id_code EH_IDS[] = {
- event_id::PRESS,
- event_id::RELEASE,
- event_id::RELEASE_OUTSIDE,
- event_id::ROLL_OVER,
- event_id::ROLL_OUT,
- event_id::DRAG_OVER,
- event_id::DRAG_OUT,
- };
- {for (unsigned int i = 0; i < ARRAYSIZE(EH_IDS); i++) {
- if (get_event_handler(EH_IDS[i], &dummy)) {
- return true;
- }
- }}
-
- return false;
+ // @@ this doesn't seem right...
+ return m_root->get_background_alpha();
}
-
- /* sprite_instance */
- virtual movie* get_topmost_mouse_entity(float x, float y)
- // Return the topmost entity that the given point
- // covers that can receive mouse events. NULL if
- // none. Coords are in parent's frame.
+ float get_pixel_scale() const
{
- if (get_visible() == false) {
- return NULL;
- }
-
- matrix m = get_matrix();
- point p;
- m.transform_by_inverse(&p, point(x, y));
-
- int i, n = m_display_list.get_character_count();
- // Go backwards, to check higher objects first.
- for (i = n - 1; i >= 0; i--)
- {
- character* ch = m_display_list.get_character(i);
-
- if (ch != NULL && ch->get_visible())
- {
- movie* te =
ch->get_topmost_mouse_entity(p.m_x, p.m_y);
- if (te)
- {
- // The containing entity that 1) is
closest to root and 2) can
- // handle mouse events takes
precedence.
- if (can_handle_mouse_event()) {
- return this;
- } else {
- return te;
- }
- }
- }
- }
-
- return NULL;
+ return m_root->get_pixel_scale();
}
-
- /* sprite_instance */
- void increment_frame_and_check_for_loop()
- // Increment m_current_frame, and take care of looping.
+ virtual void get_mouse_state(int* x, int* y, int* buttons)
{
- m_current_frame++;
-
- int frame_count = m_def->get_frame_count();
- if (m_current_frame >= frame_count)
- {
- // Loop.
- m_current_frame = 0;
- m_has_looped = true;
- if (frame_count > 1)
- {
- m_display_list.reset();
- }
- }
+ m_root->get_mouse_state(x, y, buttons);
}
- /* sprite_instance */
- virtual void advance(float delta_time)
+ void set_background_color(const rgba& color)
{
- // printf("%s:\n", __PRETTY_FUNCTION__); // FIXME:
-
- // Keep this (particularly m_as_environment) alive during
execution!
- smart_ptr<as_object_interface> this_ptr(this);
-
- assert(m_def != NULL && m_root != NULL);
-
- // Advance everything in the display list.
- m_display_list.advance(delta_time);
-
- // mouse drag.
- character::do_mouse_drag();
-
- m_time_remainder += delta_time;
-
- const float frame_time = 1.0f / m_root->get_frame_rate();
// @@ cache this
-
- // Check for the end of frame
- if (m_time_remainder >= frame_time)
- {
- m_time_remainder -= frame_time;
-
- // Update current and next frames.
- if (m_play_state == PLAY)
- {
- int current_frame0 = m_current_frame;
- increment_frame_and_check_for_loop();
-
- // Execute the current frame's tags.
- if (m_current_frame != current_frame0)
- {
- execute_frame_tags(m_current_frame);
- }
- }
-
- // Dispatch onEnterFrame event.
- on_event(event_id::ENTER_FRAME);
-
- do_actions();
-
- // Clean up display list (remove dead objects).
- m_display_list.update();
- }
-
- // Skip excess time. TODO root caller should
- // loop to prevent this happening; probably
- // only root should keep m_time_remainder, and
- // advance(dt) should be a discrete tick()
- // with no dt.
- m_time_remainder = fmod(m_time_remainder, frame_time);
+ m_root->set_background_color(color);
}
- /*sprite_instance*/
- void execute_frame_tags(int frame, bool state_only = false)
- // Execute the tags associated with the specified frame.
- // frame is 0-based
- {
- // Keep this (particularly m_as_environment) alive during
execution!
- smart_ptr<as_object_interface> this_ptr(this);
-
- assert(frame >= 0);
- assert(frame < m_def->get_frame_count());
-
- // Execute this frame's init actions, if necessary.
- if (m_init_actions_executed[frame] == false)
- {
- const array<execute_tag*>* init_actions =
m_def->get_init_actions(frame);
- if (init_actions && init_actions->size() > 0)
- {
- // Need to execute these actions.
- for (int i= 0; i < init_actions->size();
i++)
- {
- execute_tag* e =
(*init_actions)[i];
- e->execute(this);
- }
-
- // Mark this frame done, so we never
execute these init actions
- // again.
- m_init_actions_executed[frame] = true;
- }
- }
+ float get_timer() const { return m_root->get_timer(); }
- const array<execute_tag*>& playlist =
m_def->get_playlist(frame);
- for (int i = 0; i < playlist.size(); i++)
- {
- execute_tag* e = playlist[i];
- if (state_only)
- {
- e->execute_state(this);
- }
- else
- {
- e->execute(this);
- }
- }
- }
+ void restart();
- /*sprite_instance*/
- void execute_frame_tags_reverse(int frame)
- // Execute the tags associated with the specified frame, IN
REVERSE.
- // I.e. if it's an "add" tag, then we do a "remove" instead.
- // Only relevant to the display-list manipulation tags: add,
move, remove, replace.
- //
- // frame is 0-based
+ virtual bool has_looped() const
{
- // Keep this (particularly m_as_environment) alive during
execution!
- smart_ptr<as_object_interface> this_ptr(this);
-
- assert(frame >= 0);
- assert(frame < m_def->get_frame_count());
-
- const array<execute_tag*>& playlist =
m_def->get_playlist(frame);
- for (int i = 0; i < playlist.size(); i++)
- {
- execute_tag* e = playlist[i];
- e->execute_state_reverse(this, frame);
- }
+ return m_has_looped;
}
-
- /*sprite_instance*/
- execute_tag* find_previous_replace_or_add_tag(int frame, int
depth, int id)
+ virtual bool get_accept_anim_moves() const
{
- uint32 depth_id = ((depth & 0x0FFFF) << 16) | (id &
0x0FFFF);
-
- for (int f = frame - 1; f >= 0; f--)
- {
- const array<execute_tag*>& playlist =
m_def->get_playlist(f);
- for (int i = playlist.size() - 1; i >= 0; i--)
- {
- execute_tag* e = playlist[i];
- if (e->get_depth_id_of_replace_or_add_tag()
== depth_id)
- {
- return e;
- }
- }
- }
-
- return NULL;
+ return m_accept_anim_moves;
}
-
- /*sprite_instance*/
- void execute_remove_tags(int frame)
- // Execute any remove-object tags associated with the specified
frame.
- // frame is 0-based
+ /// Combine the flags to avoid a conditional.
+ /// It would be faster with a macro.
+ inline int transition(int a, int b) const
{
- assert(frame >= 0);
- assert(frame < m_def->get_frame_count());
-
- const array<execute_tag*>& playlist =
m_def->get_playlist(frame);
- for (int i = 0; i < playlist.size(); i++)
- {
- execute_tag* e = playlist[i];
- if (e->is_remove_tag())
- {
- e->execute_state(this);
- }
- }
+ return (a << 2) | b;
}
- // Take care of this frame's actions.
- void do_actions();
-
-
- /*sprite_instance*/
- void goto_frame(int target_frame_number)
- // Set the sprite state at the specified frame number.
- // 0-based frame numbers!! (in contrast to ActionScript and
Flash MX)
- {
- //
IF_VERBOSE_DEBUG(log_msg("sprite::goto_frame(%d)\n",
target_frame_number));//xxxxx
-
- target_frame_number = iclamp(target_frame_number, 0,
m_def->get_frame_count() - 1);
-
- if (target_frame_number < m_current_frame)
- {
- for (int f = m_current_frame; f >
target_frame_number; f--)
- {
- execute_frame_tags_reverse(f);
- }
-
- execute_frame_tags(target_frame_number, false);
- m_display_list.update();
- }
- else if (target_frame_number > m_current_frame)
- {
- for (int f = m_current_frame + 1; f <
target_frame_number; f++)
- {
- execute_frame_tags(f, true);
- }
-
- execute_frame_tags(target_frame_number, false);
- m_display_list.update();
- }
-
- m_current_frame = target_frame_number;
-
- // goto_frame stops by default.
- m_play_state = STOP;
- }
+ /// Return true if we have any mouse event handlers.
+ bool can_handle_mouse_event();
-
- bool goto_labeled_frame(const char* label)
- // Look up the labeled frame, and jump to it.
- {
- int target_frame = -1;
- if (m_def->get_labeled_frame(label, &target_frame))
- {
- goto_frame(target_frame);
- return true;
- }
- else
- {
- IF_VERBOSE_ACTION(
- log_error("error:
movie_impl::goto_labeled_frame('%s') unknown label\n", label));
- return false;
- }
- }
+ /// Return the topmost entity that the given point
+ /// covers that can receive mouse events. NULL if
+ /// none. Coords are in parent's frame.
+ virtual movie* get_topmost_mouse_entity(float x, float y);
+
+ /// Increment m_current_frame, and take care of looping.
+ void increment_frame_and_check_for_loop();
+
+ virtual void advance(float delta_time);
+
+ /// Execute the tags associated with the specified frame.
+ /// frame is 0-based
+ void execute_frame_tags(int frame, bool state_only = false);
+
+
+ /// Execute the tags associated with the specified frame,
+ /// IN REVERSE.
+ /// I.e. if it's an "add" tag, then we do a "remove" instead.
+ /// Only relevant to the display-list manipulation tags:
+ /// add, move, remove, replace.
+ ///
+ /// frame is 0-based
+ void execute_frame_tags_reverse(int frame);
- /*sprite_instance*/
- void display()
- {
- if (get_visible() == false)
- {
- // We're invisible, so don't display!
- return;
- }
+ execute_tag* find_previous_replace_or_add_tag(int frame,
+ int depth, int id);
- m_display_list.display();
- do_display_callback();
- }
+ /// Execute any remove-object tags associated with
+ /// the specified frame.
+ /// frame is 0-based
+ void execute_remove_tags(int frame);
- /*sprite_instance*/
- character* add_display_object(
- Uint16 character_id,
- const char* name,
- const array<swf_event*>& event_handlers,
- Uint16 depth,
- bool replace_if_depth_is_occupied,
- const cxform& color_transform,
- const matrix& matrix,
- float ratio,
- Uint16 clip_depth)
- // Add an object to the display list.
- {
- assert(m_def != NULL);
- character_def* cdef =
m_def->get_character_def(character_id);
- if (cdef == NULL)
- {
- log_error("sprite::add_display_object(): unknown
cid = %d\n", character_id);
- return NULL;
- }
+ /// Take care of this frame's actions.
+ void do_actions();
- // If we already have this object on this
- // plane, then move it instead of replacing
- // it.
- character* existing_char =
m_display_list.get_character_at_depth(depth);
- if (existing_char
- && existing_char->get_id() == character_id
- && ((name == NULL && existing_char->get_name().length()
== 0)
- || (name && existing_char->get_name() == name)))
- {
- // IF_VERBOSE_DEBUG(log_msg("add changed
to move on depth %d\n", depth));//xxxxxx
- move_display_object(depth, true, color_transform,
true, matrix, ratio, clip_depth);
- return NULL;
- }
- //printf("%s: character %s, id is %d, count is %d\n",
__FUNCTION__, existing_char->get_name(),
character_id,m_display_list.get_character_count()); // FIXME:
- assert(cdef);
- smart_ptr<character> ch =
cdef->create_character_instance(this, character_id);
- assert(ch != NULL);
- if (name != NULL && name[0] != 0)
- {
- ch->set_name(name);
- }
+ /// Set the sprite state at the specified frame number.
+ //
+ /// 0-based frame numbers!!
+ ///(in contrast to ActionScript and Flash MX)
+ ///
+ void goto_frame(int target_frame_number);
- // Attach event handlers (if any).
- {for (int i = 0, n = event_handlers.size(); i < n; i++)
- {
- event_handlers[i]->attach_to(ch.get_ptr());
- }}
- m_display_list.add_display_object(
- ch.get_ptr(),
- depth,
- replace_if_depth_is_occupied,
- color_transform,
- matrix,
- ratio,
- clip_depth);
-
- assert(ch == NULL || ch->get_ref_count() > 1);
- return ch.get_ptr();
- }
+ /// Look up the labeled frame, and jump to it.
+ bool goto_labeled_frame(const char* label);
+
+ /// Display (render?) this Sprite/MovieClip, unless invisible
+ void display();
- /*sprite_instance*/
- void move_display_object(
- Uint16 depth,
- bool use_cxform,
- const cxform& color_xform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- Uint16 clip_depth)
- // Updates the transform properties of the object at
- // the specified depth.
+ /// Add an object to the DisplayList.
+ character* add_display_object(
+ Uint16 character_id,
+ const char* name,
+ const array<swf_event*>& event_handlers,
+ Uint16 depth,
+ bool replace_if_depth_is_occupied,
+ const cxform& color_transform,
+ const matrix& matrix,
+ float ratio,
+ Uint16 clip_depth);
+
+
+ /// Updates the transform properties of the object at
+ /// the specified depth.
+ void move_display_object(
+ Uint16 depth,
+ bool use_cxform,
+ const cxform& color_xform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ Uint16 clip_depth)
{
m_display_list.move_display_object(depth, use_cxform,
color_xform, use_matrix, mat, ratio, clip_depth);
}
- /*sprite_instance*/
- void replace_display_object(
- Uint16 character_id,
- const char* name,
- Uint16 depth,
- bool use_cxform,
- const cxform& color_transform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- Uint16 clip_depth)
- {
- assert(m_def != NULL);
- // printf("%s: character %s, id is %d\n", __FUNCTION__,
name, character_id); // FIXME: debugging crap
-
- character_def* cdef =
m_def->get_character_def(character_id);
- if (cdef == NULL)
- {
- log_error("sprite::replace_display_object():
unknown cid = %d\n", character_id);
- return;
- }
- assert(cdef);
-
- smart_ptr<character> ch =
cdef->create_character_instance(this, character_id);
- assert(ch != NULL);
-
- if (name != NULL && name[0] != 0)
- {
- ch->set_name(name);
- }
-
- m_display_list.replace_display_object(
- ch.get_ptr(),
- depth,
- use_cxform,
- color_transform,
- use_matrix,
- mat,
- ratio,
- clip_depth);
- }
-
-
- /*sprite_instance*/
- void replace_display_object(
- character* ch,
- const char* name,
- Uint16 depth,
- bool use_cxform,
- const cxform& color_transform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- Uint16 clip_depth)
- {
- printf("%s: character %s, id is %d\n", __FUNCTION__, name,
ch->get_id()); // FIXME:
-
- assert(ch != NULL);
-
- if (name != NULL && name[0] != 0)
- {
- ch->set_name(name);
- }
-
- m_display_list.replace_display_object(
- ch,
- depth,
- use_cxform,
- color_transform,
- use_matrix,
- mat,
- ratio,
- clip_depth);
- }
-
-
- /*sprite_instance*/
- void remove_display_object(Uint16 depth, int id)
- // Remove the object at the specified depth.
- // If id != -1, then only remove the object at depth with
matching id.
+ void replace_display_object(
+ Uint16 character_id,
+ const char* name,
+ Uint16 depth,
+ bool use_cxform,
+ const cxform& color_transform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ Uint16 clip_depth);
+
+
+ void replace_display_object(
+ character* ch,
+ const char* name,
+ Uint16 depth,
+ bool use_cxform,
+ const cxform& color_transform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ Uint16 clip_depth);
+
+
+ /// Remove the object at the specified depth.
+ /// If id != -1, then only remove the object
+ /// at depth with matching id.
+ void remove_display_object(Uint16 depth, int id)
{
m_display_list.remove_display_object(depth, id);
}
- /*sprite_instance*/
- void add_action_buffer(action_buffer* a)
- // Add the given action buffer to the list of action
- // buffers to be processed at the end of the next
- // frame advance.
+ /// Add the given action buffer to the list of action
+ /// buffers to be processed at the end of the next
+ /// frame advance.
+ void add_action_buffer(action_buffer* a)
{
m_action_list.push_back(a);
}
- /*sprite_instance*/
- int get_id_at_depth(int depth)
- // For debugging -- return the id of the character at the
specified depth.
- // Return -1 if nobody's home.
- {
- int index = m_display_list.get_display_index(depth);
- if (index == -1)
- {
- return -1;
- }
-
- character* ch =
m_display_list.get_display_object(index).m_character.get_ptr();
-
- return ch->get_id();
- }
-
-
- //
- // ActionScript support
- //
-
-
- /* sprite_instance */
- virtual void set_variable(const char* path_to_var, const
char* new_value)
- {
- assert(m_parent == NULL); // should only be called on the
root movie.
-
- if (path_to_var == NULL)
- {
- log_error("error: NULL path_to_var passed to
set_variable()\n");
- return;
- }
- if (new_value == NULL)
- {
- log_error("error: NULL passed to set_variable('%s',
NULL)\n", path_to_var);
- return;
- }
-
- array<with_stack_entry> empty_with_stack;
- tu_string path(path_to_var);
- as_value val(new_value);
-
- m_as_environment.set_variable(path, val, empty_with_stack);
- }
-
- /* sprite_instance */
- virtual void set_variable(const char* path_to_var, const
wchar_t* new_value)
- {
- if (path_to_var == NULL)
- {
- log_error("error: NULL path_to_var passed to
set_variable()\n");
- return;
- }
- if (new_value == NULL)
- {
- log_error("error: NULL passed to set_variable('%s',
NULL)\n", path_to_var);
- return;
- }
-
- assert(m_parent == NULL); // should only be called on the
root movie.
-
- array<with_stack_entry> empty_with_stack;
- tu_string path(path_to_var);
- as_value val(new_value);
+ /// For debugging -- return the id of the character
+ /// at the specified depth.
+ /// Return -1 if nobody's home.
+ int get_id_at_depth(int depth);
- m_as_environment.set_variable(path, val, empty_with_stack);
- }
-
- /* sprite_instance */
- virtual const char* get_variable(const char* path_to_var) const
- {
- assert(m_parent == NULL); // should only be called on the
root movie.
- array<with_stack_entry> empty_with_stack;
- tu_string path(path_to_var);
+ //
+ // ActionScript support
+ //
- // NOTE: this is static so that the string
- // value won't go away after we return!!!
- // It'll go away during the next call to this
- // function though!!! NOT THREAD SAFE!
- static as_value val;
- val = m_as_environment.get_variable(path, empty_with_stack);
+ /// Set the named variable to the value
+ virtual void set_variable(const char* path_to_var,
+ const char* new_value);
+
+ /// Set the named variable to the wide value
+ virtual void set_variable(const char* path_to_var,
+ const wchar_t* new_value);
- return val.to_string(); // ack!
- }
+ /// Returns address to static buffer. NOT THREAD SAFE!
+ virtual const char* get_variable(const char* path_to_var) const;
// Set *val to the value of the named member and
// return true, if we have the named member.
@@ -1092,438 +588,133 @@
bool get_member(const tu_stringi& name, as_value* val);
- /* sprite_instance */
- virtual void set_member(const tu_stringi& name, const
as_value& val)
- // Set the named member to the value. Return true if we have
- // that member; false otherwise.
- {
- as_standard_member std_member = get_standard_member(name);
- switch (std_member)
- {
- default:
- case M_INVALID_MEMBER:
- break;
- case M_X:
- //if (name == "_x")
- {
- matrix m = get_matrix();
- m.m_[0][2] = (float)
PIXELS_TO_TWIPS(val.to_number());
- set_matrix(m);
-
- m_accept_anim_moves = false;
-
- return;
- }
- case M_Y:
- //else if (name == "_y")
- {
- matrix m = get_matrix();
- m.m_[1][2] = (float)
PIXELS_TO_TWIPS(val.to_number());
- set_matrix(m);
-
- m_accept_anim_moves = false;
-
- return;
- }
- case M_XSCALE:
- //else if (name == "_xscale")
- {
- matrix m = get_matrix();
-
- // Decompose matrix and insert the desired value.
- float x_scale = (float) val.to_number() /
100.f; // input is in percent
- float y_scale = m.get_y_scale();
- float rotation = m.get_rotation();
- m.set_scale_rotation(x_scale, y_scale, rotation);
-
- set_matrix(m);
- m_accept_anim_moves = false;
- return;
- }
- case M_YSCALE:
- //else if (name == "_yscale")
- {
- matrix m = get_matrix();
-
- // Decompose matrix and insert the desired value.
- float x_scale = m.get_x_scale();
- float y_scale = (float) val.to_number() /
100.f; // input is in percent
- float rotation = m.get_rotation();
- m.set_scale_rotation(x_scale, y_scale, rotation);
-
- set_matrix(m);
- m_accept_anim_moves = false;
- return;
- }
- case M_ALPHA:
- //else if (name == "_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_VISIBLE:
- //else if (name == "_visible")
- {
- set_visible(val.to_bool());
- m_accept_anim_moves = false;
- return;
- }
- case M_WIDTH:
- //else if (name == "_width")
- {
- // @@ tulrich: is parameter in world-coords or
local-coords?
- matrix m = get_matrix();
- m.m_[0][0] =
float(PIXELS_TO_TWIPS(val.to_number()));
- float w = get_width();
- if (fabsf(w) > 1e-6f)
- {
- m.m_[0][0] /= w;
- }
- set_matrix(m);
- m_accept_anim_moves = false;
- return;
- }
- case M_HEIGHT:
- //else if (name == "_height")
- {
- // @@ tulrich: is parameter in world-coords or
local-coords?
- matrix m = get_matrix();
- m.m_[1][1] =
float(PIXELS_TO_TWIPS(val.to_number()));
- float h = get_width();
- if (fabsf(h) > 1e-6f)
- {
- m.m_[1][1] /= h;
- }
- set_matrix(m);
- m_accept_anim_moves = false;
- return;
- }
- case M_ROTATION:
- //else if (name == "_rotation")
- {
- matrix m = get_matrix();
-
- // Decompose matrix and insert the desired value.
- float x_scale = m.get_x_scale();
- float y_scale = m.get_y_scale();
- float rotation = (float) val.to_number() *
float(M_PI) / 180.f; // input is in degrees
- m.set_scale_rotation(x_scale, y_scale, rotation);
-
- set_matrix(m);
- m_accept_anim_moves = false;
- return;
- }
- case M_HIGHQUALITY:
- //else if (name == "_highquality")
- {
- // @@ global { 0, 1, 2 }
- // // Whether we're in high quality mode
or not.
- // val->set(true);
- return;
- }
- case M_FOCUSRECT:
- //else if (name == "_focusrect")
- {
- // // Is a yellow rectangle visible around
a focused movie clip (?)
- // val->set(false);
- return;
- }
- case M_SOUNDBUFTIME:
- //else if (name == "_soundbuftime")
- {
- // @@ global
- // // Number of seconds before sound
starts to stream.
- // val->set(0.0);
- return;
- }
- } // end switch
-
- // Not a built-in property. See if we have a
- // matching edit_text character in our display
- // list.
- bool text_val = val.get_type() == as_value::STRING
- || val.get_type() == as_value::NUMBER;
- if (text_val)
- {
- bool success = false;
- for (int i = 0, n =
m_display_list.get_character_count(); i < n; i++)
- {
- character* ch =
m_display_list.get_character(i);
- // CASE INSENSITIVE compare. In
ActionScript 2.0, this
- // changes to CASE SENSITIVE!!!
- if (name == ch->get_text_name())
- {
- const char* text = val.to_string();
- ch->set_text_value(text);
- success = true;
- }
- }
- if (success) return;
- }
-
- // If that didn't work, set a variable within this
environment.
- m_as_environment.set_member(name, val);
- }
-
-
- /* sprite_instance */
- virtual movie* get_relative_target(const tu_string& name)
- // Find the movie which is one degree removed from us,
- // given the relative pathname.
- //
- // If the pathname is "..", then return our parent.
- // If the pathname is ".", then return ourself. If
- // the pathname is "_level0" or "_root", then return
- // the root movie.
- //
- // Otherwise, the name should refer to one our our
- // named characters, so we return it.
- //
- // NOTE: In ActionScript 2.0, top level names (like
- // "_root" and "_level0") are CASE SENSITIVE.
- // Character names in a display list are CASE
- // SENSITIVE. Member names are CASE INSENSITIVE. Gah.
+ /// Set the named member to the value.
//
- // In ActionScript 1.0, everything seems to be CASE
- // INSENSITIVE.
- {
- if (name == "." || name == "this")
- {
- return this;
- }
- else if (name == "..")
- {
- return get_parent();
- }
- else if (name == "_level0"
- || name == "_root")
- {
- return m_root->m_movie.get_ptr();
- }
-
- // See if we have a match on the display list.
- return m_display_list.get_character_by_name(name);
- }
-
-
- /* sprite_instance */
- virtual void call_frame_actions(const as_value& frame_spec)
- // Execute the actions for the specified frame. The
- // frame_spec could be an integer or a string.
- {
- int frame_number = -1;
-
- // Figure out what frame to call.
- if (frame_spec.get_type() == as_value::STRING)
- {
- if
(m_def->get_labeled_frame(frame_spec.to_string(), &frame_number) == false)
- {
- // Try converting to integer.
- frame_number = (int) frame_spec.to_number();
- }
- }
- else
- {
- // convert from 1-based to 0-based
- frame_number = (int) frame_spec.to_number() - 1;
- }
-
- if (frame_number < 0 || frame_number >=
m_def->get_frame_count())
- {
- // No dice.
- log_error("error: call_frame('%s') -- unknown
frame\n", frame_spec.to_string());
- return;
- }
-
- int top_action = m_action_list.size();
+ /// Return true if we have
+ /// that member; false otherwise.
+ virtual void set_member(const tu_stringi& name,
+ const as_value& val);
+
+
+ /// Find the movie which is one degree removed from us,
+ /// given the relative pathname.
+ ///
+ /// If the pathname is "..", then return our parent.
+ /// If the pathname is ".", then return ourself. If
+ /// the pathname is "_level0" or "_root", then return
+ /// the root movie.
+ ///
+ /// Otherwise, the name should refer to one our our
+ /// named characters, so we return it.
+ ///
+ /// NOTE: In ActionScript 2.0, top level names (like
+ /// "_root" and "_level0") are CASE SENSITIVE.
+ /// Character names in a display list are CASE
+ /// SENSITIVE. Member names are CASE INSENSITIVE. Gah.
+ ///
+ /// In ActionScript 1.0, everything seems to be CASE
+ /// INSENSITIVE.
+ virtual movie* get_relative_target(const tu_string& name);
- // Execute the actions.
- const array<execute_tag*>& playlist =
m_def->get_playlist(frame_number);
- for (int i = 0; i < playlist.size(); i++)
- {
- execute_tag* e = playlist[i];
- if (e->is_action_tag())
- {
- e->execute(this);
- }
- }
- // Execute any new actions triggered by the tag,
- // leaving existing actions to be executed.
- while (m_action_list.size() > top_action)
- {
-
m_action_list[top_action]->execute(&m_as_environment);
- m_action_list.remove(top_action);
- }
- assert(m_action_list.size() == top_action);
- }
+ /// Execute the actions for the specified frame.
+ //
+ /// The frame_spec could be an integer or a string.
+ ///
+ virtual void call_frame_actions(const as_value& frame_spec);
- /* sprite_instance */
- virtual void set_drag_state(const drag_state& st)
- {
+ virtual void set_drag_state(const drag_state& st) {
m_root->m_drag_state = st;
}
- /* sprite_instance */
- virtual void stop_drag()
- {
+ virtual void stop_drag() {
assert(m_parent == NULL); // we must be the root movie!!!
m_root->stop_drag();
}
-
- /* sprite_instance */
- virtual void get_drag_state(drag_state* st)
+ /* sprite_instance */
+ virtual void get_drag_state(drag_state* st)
{
*st = m_root->m_drag_state;
}
- void clone_display_object(const tu_string& name, const
tu_string& newname, Uint16 depth)
- // Duplicate the object with the specified name and add it with
a new name
- // at a new depth.
- {
- character* ch = m_display_list.get_character_by_name(name);
- if (ch)
- {
- array<swf_event*> dummy_event_handlers;
-
- add_display_object(
- ch->get_id(),
- newname.c_str(),
- dummy_event_handlers,
- depth,
- true, // replace if depth is occupied
- ch->get_cxform(),
- ch->get_matrix(),
- ch->get_ratio(),
- ch->get_clip_depth());
- // @@ TODO need to duplicate ch's event handlers,
and presumably other members?
- // Probably should make a character::clone()
function to handle this.
- }
- }
-
-
- void remove_display_object(const tu_string& name)
- // Remove the object with the specified name.
- {
- character* ch = m_display_list.get_character_by_name(name);
- if (ch)
- {
- // @@ TODO: should only remove movies that were
created via clone_display_object --
- // apparently original movies, placed by anim
events, are immune to this.
- remove_display_object(ch->get_depth(),
ch->get_id());
- }
- }
-
-
- /* sprite_instance */
- virtual bool on_event(event_id id)
- // Dispatch event handler(s), if any.
- {
- // Keep m_as_environment alive during any method calls!
- smart_ptr<as_object_interface> this_ptr(this);
-
- bool called = false;
-
- // First, check for built-in event handler.
- {
- as_value method;
- if (get_event_handler(id, &method))
- {
- // Dispatch.
- call_method0(method, &m_as_environment, this);
-
- called = true;
- // Fall through and call the function also, if
it's defined!
- // (@@ Seems to be the behavior for mouse
events; not tested & verified for
- // every event type.)
- }
- }
-
- // Check for member function.
- {
- // In ActionScript 2.0, event method names are CASE
SENSITIVE.
- // In ActionScript 1.0, event method names are CASE
INSENSITIVE.
- const tu_stringi& method_name =
id.get_function_name().to_tu_stringi();
- if (method_name.length() > 0)
- {
- as_value method;
- if (get_member(method_name, &method))
- {
- call_method0(method, &m_as_environment,
this);
- called = true;
- }
- }
- }
-
- return called;
- }
-
-
- /*sprite_instance*/
- virtual void on_event_load()
- // Do the events that (appear to) happen as the movie
- // loads. frame1 tags and actions are executed (even
- // before advance() is called). Then the onLoad event
- // is triggered.
+ /// Duplicate the object with the specified name
+ /// and add it with a new name at a new depth.
+ void clone_display_object(const tu_string& name,
+ const tu_string& newname, Uint16 depth);
+
+ /// Remove the object with the specified name.
+ void remove_display_object(const tu_string& name);
+
+ /// Dispatch event handler(s), if any.
+ virtual bool on_event(event_id id);
+
+
+ /// Do the events that (appear to) happen as the movie
+ /// loads. frame1 tags and actions are executed (even
+ /// before advance() is called). Then the onLoad event
+ /// is triggered.
+ virtual void on_event_load()
{
execute_frame_tags(0);
do_actions();
on_event(event_id::LOAD);
}
- // Do the events that happen when there is XML data waiting
- // on the XML socket connection.
- virtual void on_event_xmlsocket_onxml()
+ /// Do the events that happen when there is XML data waiting
+ /// on the XML socket connection.
+ /// FIXME: unimplemented
+ virtual void on_event_xmlsocket_onxml()
{
log_msg("FIXME: %s: unimplemented\n", __FUNCTION__);
on_event(event_id::SOCK_XML);
}
- // Do the events that (appear to) happen on a specified interval.
- virtual void on_event_interval_timer()
+ /// Do the events that (appear to) happen on a
+ /// specified interval.
+ virtual void on_event_interval_timer()
{
log_msg("FIXME: %s: unimplemented\n", __FUNCTION__);
on_event(event_id::TIMER);
}
- // Do the events that happen as a MovieClip (swf 7 only) loads.
- virtual void on_event_load_progress()
+ /// Do the events that happen as a MovieClip (swf 7 only) loads.
+ virtual void on_event_load_progress()
{
log_msg("FIXME: %s: unimplemented\n", __FUNCTION__);
on_event(event_id::LOAD_PROGRESS);
}
- /*sprite_instance*/
- virtual const char* call_method_args(const char* method_name, const
char* method_arg_fmt, va_list args)
+ /// Call a method with a list of arguments
+ virtual const char* call_method_args(const char* method_name,
+ const char* method_arg_fmt, va_list args)
{
// Keep m_as_environment alive during any method calls!
smart_ptr<as_object_interface> this_ptr(this);
- return call_method_parsed(&m_as_environment, this,
method_name, method_arg_fmt, args);
+ return call_method_parsed(&m_as_environment, this,
+ method_name, method_arg_fmt, args);
}
- /* sprite_instance */
- virtual void attach_display_callback(const char*
path_to_object, void (*callback)(void*), void* user_ptr)
+ virtual void attach_display_callback(
+ const char* path_to_object,
+ void (*callback)(void*), void* user_ptr)
{
- assert(m_parent == NULL); // should only be called on the
root movie.
+ // should only be called on the root movie.
+ assert(m_parent == NULL);
- array<with_stack_entry> dummy;
- as_value obj =
m_as_environment.get_variable(tu_string(path_to_object), dummy);
- as_object_interface* as_obj = obj.to_object();
- if (as_obj)
+ array<with_stack_entry> dummy;
+ as_value obj =
m_as_environment.get_variable(tu_string(path_to_object), dummy);
+ as_object_interface* as_obj = obj.to_object();
+ if (as_obj)
{
- movie* m = as_obj->to_movie();
- if (m)
+ movie* m = as_obj->to_movie();
+ if (m)
{
- m->set_display_callback(callback, user_ptr);
+ m->set_display_callback(callback, user_ptr);
}
}
}
@@ -1534,9 +725,9 @@
character* sprite_definition::create_character_instance(movie* parent,
int id)
{
- sprite_instance* si = new sprite_instance(this,
- parent->get_root(), parent, id);
- return si;
+ sprite_instance* si = new sprite_instance(this,
+ parent->get_root(), parent, id);
+ return si;
}
Index: gnash/server/action.cpp
diff -u gnash/server/action.cpp:1.6 gnash/server/action.cpp:1.7
--- gnash/server/action.cpp:1.6 Wed Jan 25 13:38:31 2006
+++ gnash/server/action.cpp Fri Jan 27 00:54:38 2006
@@ -1381,7 +1381,7 @@
//
- // Thin wrapper around action_buffer.
+ /// Thin wrapper around action_buffer.
struct do_action : public execute_tag
{
action_buffer m_buf;
Index: gnash/server/action.h
diff -u gnash/server/action.h:1.4 gnash/server/action.h:1.5
--- gnash/server/action.h:1.4 Thu Jan 26 00:15:57 2006
+++ gnash/server/action.h Fri Jan 27 00:54:38 2006
@@ -732,16 +732,17 @@
};
- // ActionScript "environment", essentially VM state?
+ /// ActionScript "environment", essentially VM state?
struct as_environment
{
array<as_value> m_stack;
as_value m_global_register[4];
- array<as_value> m_local_register; // function2 uses this
+ /// function2 uses this
+ array<as_value> m_local_register;
movie* m_target;
stringi_hash<as_value> m_variables;
- // For local vars. Use empty names to separate frames.
+ /// For local vars. Use empty names to separate frames.
struct frame_slot
{
tu_string m_name;
@@ -765,6 +766,7 @@
// stack access/manipulation
// @@ TODO do more checking on these
template<class T>
+ // stack access/manipulation
void push(T val) { push_val(as_value(val)); }
void push_val(const as_value& val) { m_stack.push_back(val);
}
as_value pop() { as_value result = m_stack.back();
m_stack.pop_back(); return result; }
@@ -775,16 +777,21 @@
int get_top_index() const { return m_stack.size() - 1; }
as_value get_variable(const tu_string& varname, const
array<with_stack_entry>& with_stack) const;
- // no path stuff:
+
+ /// no path stuff
as_value get_variable_raw(const tu_string& varname,
const array<with_stack_entry>& with_stack) const;
void set_variable(const tu_string& path, const as_value&
val, const array<with_stack_entry>& with_stack);
- // no path stuff:
+
+ /// no path stuff
void set_variable_raw(const tu_string& path, const as_value&
val, const array<with_stack_entry>& with_stack);
void set_local(const tu_string& varname, const as_value&
val);
- void add_local(const tu_string& varname, const as_value&
val); // when you know it doesn't exist.
- void declare_local(const tu_string& varname); //
Declare varname; undefined unless it already exists.
+ /// when you know it doesn't exist.
+ void add_local(const tu_string& varname, const as_value&
val);
+
+ /// Declare varname; undefined unless it already exists.
+ void declare_local(const tu_string& varname);
bool get_member(const tu_stringi& varname, as_value* val)
const;
void set_member(const tu_stringi& varname, const as_value&
val);
Index: gnash/server/gnash.h
diff -u gnash/server/gnash.h:1.3 gnash/server/gnash.h:1.4
--- gnash/server/gnash.h:1.3 Thu Jan 26 00:15:57 2006
+++ gnash/server/gnash.h Fri Jan 27 00:54:38 2006
@@ -139,7 +139,7 @@
sound_handler* create_sound_handler_sdl();
- // For stuff that's tricky to keep track of w/r/t ownership & cleanup.
+ /// For stuff that's tricky to keep track of w/r/t ownership & cleanup.
struct ref_counted
{
ref_counted();
@@ -159,8 +159,7 @@
struct character_def;
struct sound_sample;
- /// An interface for casting to different types of
- /// resources.
+ /// An interface for casting to different types of resources.
struct resource : public ref_counted
{
virtual ~resource() {}
@@ -174,8 +173,7 @@
/// This is the base class for all ActionScript-able objects
//
- /// ("as_" stands for ActionScript).
- ///
+ // ("as_" stands for ActionScript).
struct as_object_interface : public resource
{
virtual ~as_object_interface() {}
@@ -213,7 +211,6 @@
/// can be mixed into movie_definition, movie_definition_sub,
/// and sprite_definition, without using multiple inheritance.
///
- ///
struct character_def : public resource
{
private:
Index: gnash/server/impl.cpp
diff -u gnash/server/impl.cpp:1.9 gnash/server/impl.cpp:1.10
--- gnash/server/impl.cpp:1.9 Thu Jan 26 00:13:56 2006
+++ gnash/server/impl.cpp Fri Jan 27 00:54:38 2006
@@ -752,6 +752,7 @@
delete [] n;
}
+/// SWF Tag SetBackgroundColor (9)
struct set_background_color : public execute_tag
{
rgba m_color;
@@ -1434,10 +1435,7 @@
-//
-// place_object_2
-//
-
+/// SWF Tag PlaceObject2 (9)
struct place_object_2 : public execute_tag
{
int m_tag_type;
@@ -1782,11 +1780,7 @@
}
-//
-// remove_object_2
-//
-
-
+/// SWF Tag RemoveObject2 (28)
struct remove_object_2 : public execute_tag
{
int m_depth, m_id;
Index: gnash/server/impl.h
diff -u gnash/server/impl.h:1.5 gnash/server/impl.h:1.6
--- gnash/server/impl.h:1.5 Thu Jan 26 00:15:57 2006
+++ gnash/server/impl.h Fri Jan 27 00:54:38 2006
@@ -627,9 +627,10 @@
#endif
- // Execute tags include things that control the operation of
- // the movie. Essentially, these are the events associated
- // with a frame.
+ /// Execute tags include things that control the operation of the
movie.
+ //
+ /// Essentially, these are the events associated with a frame.
+ ///
struct execute_tag
{
virtual ~execute_tag() {}
Index: gnash/server/sound.cpp
diff -u gnash/server/sound.cpp:1.1 gnash/server/sound.cpp:1.2
--- gnash/server/sound.cpp:1.1 Tue Dec 20 21:01:18 2005
+++ gnash/server/sound.cpp Fri Jan 27 00:54:38 2006
@@ -122,6 +122,7 @@
}
+ /// SWF Tag StartSound (15)
struct start_sound_tag : public execute_tag
{
Uint16 m_handler_id;
Index: gnash/server/text.cpp
diff -u gnash/server/text.cpp:1.1 gnash/server/text.cpp:1.2
--- gnash/server/text.cpp:1.1 Tue Dec 20 21:01:18 2005
+++ gnash/server/text.cpp Fri Jan 27 00:54:38 2006
@@ -346,8 +346,8 @@
};
+ /// Read a DefineText tag.
void define_text_loader(stream* in, int tag_type,
movie_definition_sub* m)
- // Read a DefineText tag.
{
assert(tag_type == 11 || tag_type == 33);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash/server MovieClipLoader.cpp Sprite.cpp Spr...,
strk <=