[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ./ChangeLog server/dlist.cpp server/dlist...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ./ChangeLog server/dlist.cpp server/dlist... |
Date: |
Mon, 29 May 2006 12:49:34 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Branch:
Changes by: Sandro Santilli <address@hidden> 06/05/29 12:49:34
Modified files:
. : ChangeLog
server : dlist.cpp dlist.h sprite_instance.cpp
sprite_instance.h
Log message:
* server/dlist.h, server/dlist.cpp: renamed display_list
to DisplayList and made a real class, many functions moved
to private space, abstracted underlying container to allow
for future modifications aimed at performance improvements;
current implementation done with std::list.
* server/sprite_instance.h, server/sprite_instance.cpp:
updated to use the new DisplayList class interface.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/ChangeLog.diff?tr1=1.384&tr2=1.385&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/dlist.cpp.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/dlist.h.diff?tr1=1.5&tr2=1.6&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/sprite_instance.cpp.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/sprite_instance.h.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
Patches:
Index: gnash/ChangeLog
diff -u gnash/ChangeLog:1.384 gnash/ChangeLog:1.385
--- gnash/ChangeLog:1.384 Sat May 27 18:46:09 2006
+++ gnash/ChangeLog Mon May 29 12:49:34 2006
@@ -1,4 +1,15 @@
+2006-05-29 Sandro Santilli <address@hidden>
+
+ * server/dlist.h, server/dlist.cpp: renamed display_list
+ to DisplayList and made a real class, many functions moved
+ to private space, abstracted underlying container to allow
+ for future modifications aimed at performance improvements;
+ current implementation done with std::list.
+ * server/sprite_instance.h, server/sprite_instance.cpp:
+ updated to use the new DisplayList class interface.
+
2006-05-27 Vitaly Alexeev <address@hidden>
+
* server/action.h: updated forward declaration.
* server/resource.h: updated forward declaration.
* server/fn_call.h: updated forward declaration.
Index: gnash/server/dlist.cpp
diff -u gnash/server/dlist.cpp:1.9 gnash/server/dlist.cpp:1.10
--- gnash/server/dlist.cpp:1.9 Mon May 8 21:12:24 2006
+++ gnash/server/dlist.cpp Mon May 29 12:49:34 2006
@@ -1,598 +1,531 @@
-// dlist.cpp -- Thatcher Ulrich <address@hidden> 2003
-
-// This source code has been donated to the Public Domain. Do
-// whatever you want with it.
-
-// A list of active characters.
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
#include "dlist.h"
#include "log.h"
#include "render.h"
#include "gnash.h"
+
#include <typeinfo>
+#include <iostream>
+#include <algorithm>
namespace gnash {
- /*static*/ int display_object_info::compare(const void* _a, const
void* _b)
- {
- const display_object_info* a = (const
display_object_info*) _a;
- const display_object_info* b = (const
display_object_info*) _b;
- if (a->m_character->get_depth() < b->m_character->get_depth())
- {
- return -1;
- }
- else if (a->m_character->get_depth() ==
b->m_character->get_depth())
- {
- return 0;
- }
- else
- {
- return 1;
- }
- }
+struct DepthEquals {
-
- int display_list::find_display_index(int depth)
- // Find the index in the display list of the first object
- // matching the given depth. Failing that, return the index
- // of the first object with a larger depth.
- {
- int size = m_display_object_array.size();
- if (size == 0)
- {
- return 0;
- }
-
- // Binary search.
- int jump = size >> 1;
- int index = jump;
- for (;;)
- {
- jump >>= 1;
- if (jump < 1) jump = 1;
-
- if (depth >
m_display_object_array[index].m_character->get_depth())
- {
- if (index == size - 1)
- {
- index = size;
- break;
- }
- index += jump;
- }
- else if (depth <
m_display_object_array[index].m_character->get_depth())
- {
- if (index == 0
- || depth > m_display_object_array[index -
1].m_character->get_depth())
- {
- break;
- }
- index -= jump;
- }
- else
- {
- // match -- scan backward to make sure this is
the first entry with this depth.
- //
- // Linear. But multiple objects with the same
depth are only allowed for
- // very old SWF's, so we don't really care.
- for (;;)
- {
- if (index == 0
- || m_display_object_array[index -
1].m_character->get_depth() < depth)
- {
- break;
- }
- index--;
- }
-
assert(m_display_object_array[index].m_character->get_depth() == depth);
- assert(index == 0 ||
m_display_object_array[index - 1].m_character->get_depth() < depth);
- break;
- }
- }
-
- assert(index >= 0 && index <= size);
-
- return index;
- }
-
+ int _depth;
- int display_list::get_display_index(int depth)
- // Like the above, but looks for an exact match, and returns -1
if failed.
- {
- int index = find_display_index(depth);
- if (index >= (int) m_display_object_array.size()
- || get_display_object(index).m_character->get_depth()
!= depth)
- {
- // No object at that depth.
- return -1;
- }
- return index;
+ DepthEquals(int depth)
+ :
+ _depth(depth)
+ {}
+
+ bool operator() (const DisplayItem& item) {
+ if ( ! item.get_ptr() ) return false;
+ return item->get_depth() == _depth;
}
+};
+struct DepthGreaterOrEqual {
- character* display_list::get_character_at_depth(int depth)
- {
- int index = get_display_index(depth);
- if (index != -1)
- {
- character* ch =
m_display_object_array[index].m_character.get_ptr();
- if (ch->get_depth() == depth)
- {
- return ch;
- }
- }
+ int _depth;
+
+ DepthGreaterOrEqual(int depth)
+ :
+ _depth(depth)
+ {}
- return NULL;
+ bool operator() (const DisplayItem& item) {
+ if ( ! item.get_ptr() ) return false;
+ return item->get_depth() >= _depth;
}
+};
+struct NameEquals {
- character* display_list::get_character_by_name(const tu_string&
name)
- {
- // See if we have a match on the display list.
- for (int i = 0, n = get_character_count(); i < n; i++)
- {
- character* ch = get_character(i);
- if (ch->get_name() == name.c_str())
- {
- // Found it.
- return ch;
- }
- }
- return NULL;
+ const tu_string& _name;
+
+ NameEquals(const tu_string& name)
+ :
+ _name(name)
+ {}
+
+ bool operator() (const DisplayItem& item) {
+ if ( ! item.get_ptr() ) return false;
+ return item->get_name() == _name;
}
+};
- character* display_list::get_character_by_name_i(const tu_stringi&
name)
- // Return first character with matching (case insensitive) name, if any.
- {
- // Search through dlist for a match.
- for (int i = 0, n = get_character_count(); i < n; i++)
- {
- character* ch = get_character(i);
- if (name == ch->get_name().c_str())
- {
- // Found it.
- return ch;
- }
- }
+struct NameEqualsNoCase {
- return NULL;
+ const tu_stringi& _name;
+
+ NameEqualsNoCase(const tu_stringi& name)
+ :
+ _name(name)
+ {}
+
+ bool operator() (const DisplayItem& item) {
+ if ( ! item.get_ptr() ) return false;
+ return item->get_name() == _name;
}
+};
+character*
+DisplayList::get_character_at_depth(int depth)
+{
+ //GNASH_REPORT_FUNCTION;
+ //dump(std::cout);
- void display_list::add_display_object(
- character* ch,
- uint16_t depth,
- bool replace_if_depth_is_occupied,
- const cxform& color_xform,
- const matrix& mat,
- float ratio,
- uint16_t clip_depth)
+ for (iterator it = _characters.begin(),
+ itEnd = _characters.end();
+ it != itEnd; ++it)
{
-// GNASH_REPORT_FUNCTION;
-// IF_VERBOSE_DEBUG(log_msg("dl::add(%d, '%s')\n", depth,
ch->get_name()));//xxxxx
+ character* ch = it->get_ptr();
+ assert(ch); // is this really needed ?
- assert(ch);
-
- int size = m_display_object_array.size();
- int index = find_display_index(depth);
+ // found
+ if ( ch->get_depth() == depth ) return ch;
- if (replace_if_depth_is_occupied)
- {
- // Eliminate an existing object if it's in the way.
- if (index >= 0 && index < size)
- {
- display_object_info & dobj =
m_display_object_array[index];
+ // non-existent (chars are ordered by depth)
+ if ( ch->get_depth() > depth ) return NULL;
+ }
- if (dobj.m_character->get_depth() == depth)
- {
- dobj.set_character(NULL);
-
m_display_object_array.erase(m_display_object_array.begin() + index);
- }
- }
- }
- else
- {
- // Caller wants us to allow multiple objects
- // with the same depth. find_display_index()
- // returns the first matching depth, if there
- // are any, so the new character will get
- // inserted before all the others with the
- // same depth. This matches the semantics
- // described by Alexi's SWF ref. (This is all
- // for legacy SWF compatibility anyway.)
- }
+ return NULL;
- ch->set_depth(depth);
+}
- display_object_info di;
- di.m_ref = true;
- di.set_character(ch);
- di.m_character->set_depth(depth);
- di.m_character->set_cxform(color_xform);
- di.m_character->set_matrix(mat);
- di.m_character->set_ratio(ratio);
- di.m_character->set_clip_depth(clip_depth);
- // Insert into the display list...
- assert(index == find_display_index(depth));
-
- m_display_object_array.insert(m_display_object_array.begin() +
index, di);
+character*
+DisplayList::get_character_by_name(const tu_string& name)
+{
+ container_type::iterator it = find_if(
+ _characters.begin(),
+ _characters.end(),
+ NameEquals(name));
- // do the frame1 actions (if applicable) and the "onClipEvent
(load)" event.
- ch->on_event_load();
- }
-
-
- void display_list::move_display_object(
- uint16_t depth,
- bool use_cxform,
- const cxform& color_xform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- uint16_t clip_depth)
- // Updates the transform properties of the object at
- // the specified depth.
- {
-// IF_VERBOSE_DEBUG(log_msg("dl::move(%d)\n", depth));//xxxxx
+ if ( it == _characters.end() ) return NULL;
+ else return it->get_ptr();
- int size = m_display_object_array.size();
- if (size <= 0)
- {
- // error.
- log_error("error: move_display_object() -- no objects
on display list\n");
- // assert(0);
- return;
- }
-
- int index = find_display_index(depth);
- if (index < 0 || index >= size)
- {
- // error.
- log_error("error: move_display_object() -- can't find
object at depth %d\n", depth);
- // assert(0);
- return;
- }
-
- display_object_info& di = m_display_object_array[index];
- character* ch = di.m_character.get_ptr();
- if (ch->get_depth() != depth)
- {
- // error
- log_error("error: move_display_object() -- no object at
depth %d\n", depth);
- // assert(0);
- return;
- }
+}
- di.m_ref = true;
+character*
+DisplayList::get_character_by_name_i(const tu_stringi& name)
+{
+ container_type::iterator it = find_if(
+ _characters.begin(),
+ _characters.end(),
+ NameEqualsNoCase(name));
- if (ch->get_accept_anim_moves() == false)
- {
- // This character is rejecting anim moves. This
happens after it
- // has been manipulated by ActionScript.
- return;
- }
+ if ( it == _characters.end() ) return NULL;
+ else return it->get_ptr();
+}
- if (use_cxform)
- {
- ch->set_cxform(color_xform);
- }
- if (use_matrix)
- {
- ch->set_matrix(mat);
- }
- ch->set_ratio(ratio);
- // move_display_object apparently does not change clip depth!
Thanks to Alexeev Vitaly.
- // ch->set_clip_depth(clip_depth);
- }
-
-
- void display_list::replace_display_object(
- character* ch,
- uint16_t depth,
- bool use_cxform,
- const cxform& color_xform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- uint16_t clip_depth)
- // Puts a new character at the specified depth, replacing any
- // existing character. If use_cxform or use_matrix are false,
- // then keep those respective properties from the existing
- // character.
- {
-// IF_VERBOSE_DEBUG(log_msg("dl::replace(%d)\n", depth));//xxxxx
-
- int size = m_display_object_array.size();
- int index = find_display_index(depth);
- if (index < 0 || index >= size)
- {
- // Error, no existing object found at depth.
-// IF_VERBOSE_DEBUG(log_msg("dl::replace_display_object()
no obj at depth %d\n", depth));
- // Fallback -- add the object.
- add_display_object(ch, depth, true, color_xform, mat,
ratio, clip_depth);
- return;
- }
-
- display_object_info& di = m_display_object_array[index];
- if (di.m_character->get_depth() != depth)
- {
- // error
-// IF_VERBOSE_DEBUG(log_msg("warning:
replace_display_object() -- no object at depth %d\n", depth));
- return;
- }
-
- smart_ptr<character> old_ch = di.m_character;
- // Put the new character in its place.
- assert(ch);
- ch->set_depth(depth);
- ch->restart();
-
- // Set the display properties.
- di.m_ref = true;
- di.set_character(ch);
+void
+DisplayList::place_character(
+ character* ch,
+ uint16_t depth,
+ const cxform& color_xform,
+ const matrix& mat,
+ float ratio,
+ uint16_t clip_depth)
+{
+ GNASH_REPORT_FUNCTION;
+ //IF_VERBOSE_DEBUG(log_msg("dl::add(%d, '%s')\n", depth,
ch->get_name()));//xxxxx
+
+ //log_msg("Before adding, list is:");
+ //dump(std::cout);
+
+ assert(ch);
+
+ ch->set_depth(depth);
+ ch->set_cxform(color_xform);
+ ch->set_matrix(mat);
+ ch->set_ratio(ratio);
+ ch->set_clip_depth(clip_depth);
+
+ container_type::iterator it = find_if(
+ _characters.begin(), _characters.end(),
+ DepthGreaterOrEqual(depth));
+
+ if ( it == _characters.end() || (*it)->get_depth() != depth )
+ {
+ //IF_VERBOSE_DEBUG(dbglogfile << "This is a new character" <<
std::endl );
+ // add the new char
+ _characters.insert(it, DisplayItem(ch));
+ }
+ else
+ {
+ //IF_VERBOSE_DEBUG(dbglogfile << "Replacing existing character"
<< std::endl );
+ // replace existing char
+ *it = DisplayItem(ch);
+ }
+
+ // do the frame1 actions (if applicable) and the "onClipEvent (load)"
+ // event.
+ ch->on_event_load();
- if (use_cxform)
- {
- ch->set_cxform(color_xform);
- }
- else
+ //log_msg("After adding, list is:");
+ //dump(std::cout);
+}
+
+void
+DisplayList::replace_character(
+ character* ch,
+ uint16_t depth,
+ bool use_cxform,
+ const cxform& color_xform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ uint16_t clip_depth)
+{
+ GNASH_REPORT_FUNCTION;
+
+ ch->set_depth(depth);
+ ch->set_cxform(color_xform);
+ ch->set_matrix(mat);
+ ch->set_ratio(ratio);
+ ch->set_clip_depth(clip_depth);
+ ch->restart();
+
+ container_type::iterator it = find_if(
+ _characters.begin(), _characters.end(),
+ DepthGreaterOrEqual(depth));
+
+ DisplayItem di(ch);
+
+ if ( it == _characters.end() || (*it)->get_depth() != depth )
+ {
+
+ // Error, no existing object found at depth.
+// IF_VERBOSE_DEBUG(
+// log_msg("dl::replace_display_object()"
+// " no obj at depth %d\n", depth)
+// );
+
+ // add the new char
+ _characters.insert(it, di);
+
+ // do the frame1 actions (if applicable) and the
+ // "onClipEvent (load)" event.
+ ch->on_event_load();
+ }
+ else
+ {
+ if (!use_cxform)
{
// Use the cxform from the old character.
- ch->set_cxform(old_ch->get_cxform());
+ ch->set_cxform((*it)->get_cxform());
}
- if (use_matrix)
- {
- ch->set_matrix(mat);
- }
- else
+ if (!use_matrix)
{
// Use the matrix from the old character.
- ch->set_matrix(old_ch->get_matrix());
+ ch->set_matrix((*it)->get_matrix());
}
- ch->set_ratio(ratio);
- ch->set_clip_depth(clip_depth);
+ // replace existing char
+ *it = di;
}
+
+}
- void display_list::remove_display_object(uint16_t depth, int id)
- // Removes the object at the specified depth.
- {
-// IF_VERBOSE_DEBUG(log_msg("dl::remove(%d)\n", depth));//xxxxx
+// Updates the transform properties of the object at
+// the specified depth.
+void
+DisplayList::move_display_object(
+ uint16_t depth,
+ bool use_cxform,
+ const cxform& color_xform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ uint16_t clip_depth)
+{
+ //GNASH_REPORT_FUNCTION;
+ //IF_VERBOSE_DEBUG(log_msg("dl::move(%d)\n", depth));//xxxxx
- int size = m_display_object_array.size();
- if (size <= 0)
- {
- // error.
- log_error("remove_display_object: no characters in
display list\n");
- return;
- }
-
- int index = find_display_index(depth);
- if (index < 0
- || index >= size
- || get_character(index)->get_depth() != depth)
- {
- // error -- no character at the given depth.
- log_error("remove_display_object: no character at depth
%d\n", depth);
- return;
- }
-
- assert(get_character(index)->get_depth() == depth);
-
- if (id != -1)
- {
- // Caller specifies a specific id; scan forward til we
find it.
- for (;;)
- {
- if (get_character(index)->get_id() == id)
- {
- break;
- }
- if (index + 1 >= size
- || get_character(index + 1)->get_depth() !=
depth)
- {
- // Didn't find a match!
- log_error("remove_display_object: no
character at depth %d with id %d\n", depth, id);
- return;
- }
- index++;
- }
- assert(index < size);
- assert(get_character(index)->get_depth() == depth);
- assert(get_character(index)->get_id() == id);
- }
+ character* ch = get_character_at_depth(depth);
+ if ( ! ch )
+ {
+ log_error("error: move_display_object() -- "
+ "can't find object at depth %d\n",
+ depth);
+ return;
+ }
- // Removing the character at get_display_object(index).
- display_object_info& di = m_display_object_array[index];
-
- // Remove reference only.
- di.m_ref = false;
+ if (ch->get_accept_anim_moves() == false)
+ {
+ // This character is rejecting anim moves. This happens after
it
+ // has been manipulated by ActionScript.
+ return;
}
-
-
- void display_list::clear()
- // clear the display list.
+
+ if (use_cxform)
{
- int i, n = m_display_object_array.size();
- for (i = 0; i < n; i++)
- {
- display_object_info& di = m_display_object_array[i];
- //character* ch =
m_display_object_array[i].m_character;
- di.m_character->on_event(event_id::UNLOAD);
- }
-
- m_display_object_array.clear();
+ ch->set_cxform(color_xform);
}
-
-
- void display_list::reset()
- // reset the references to the display list.
+ if (use_matrix)
{
- //printf("### reset the display list!\n");
- int i, n = m_display_object_array.size();
- for (i = 0; i < n; i++)
- {
- m_display_object_array[i].m_ref = false;
- }
+ ch->set_matrix(mat);
}
+ ch->set_ratio(ratio);
+ // move_display_object apparently does not change clip depth! Thanks
to Alexeev Vitaly.
+ // ch->set_clip_depth(clip_depth);
+}
- void display_list::update()
- // remove unreferenced objects.
- {
- //printf("### update the display list!\n");
-
- int r = 0;
- int i, n = m_display_object_array.size();
- for (i = n-1; i >= 0; i--)
- {
- display_object_info & dobj = m_display_object_array[i];
-
- if (dobj.m_ref == false)
- {
- dobj.set_character(NULL);
+// Removes the object at the specified depth.
+void
+DisplayList::remove_display_object(uint16_t depth)
+{
+ GNASH_REPORT_FUNCTION;
+
+ //log_msg("Before removing, list is:");
+ //dump(std::cout);
+
+#ifndef NDEBUG
+ container_type::size_type size = _characters.size();
+#endif
+
+ // TODO: optimize to take by-depth order into account
+ container_type::iterator new_end = remove_if(
+ _characters.begin(),
+ _characters.end(),
+ DepthEquals(depth));
+
+ if ( new_end != _characters.end() ) {
+ _characters.erase(new_end, _characters.end());
+ }
+
+#ifndef NDEBUG
+ assert(size >= _characters.size());
+#endif
-
m_display_object_array.erase(m_display_object_array.begin() + i);
- r++;
- }
- }
-
- //printf("### removed characters: %4d active characters:
%4d\n", r, m_display_object_array.size());
+ //log_msg("Done removing, list is:");
+ //dump(std::cout);
+}
+
+
+// clear the display list.
+void
+DisplayList::clear()
+{
+ GNASH_REPORT_FUNCTION;
+ for (iterator it = _characters.begin(),
+ itEnd = _characters.end();
+ it != itEnd; ++it)
+ {
+ DisplayItem& di = *it;
+ if ( ! it->get_ptr() ) continue;
+ di->on_event(event_id::UNLOAD);
}
+
+ _characters.clear();
+}
- void display_list::advance(float delta_time)
- // advance referenced characters.
- {
-// GNASH_REPORT_FUNCTION;
+// reset the references to the display list.
+void
+DisplayList::reset()
+{
+ GNASH_REPORT_FUNCTION;
+
+ // We just clear the container, but
+ // might eventually keep it allocated
+ // to reduce allocation costs.
+ _characters.clear();
+}
+
+void
+DisplayList::advance(float delta_time)
+// advance referenced characters.
+{
+ //GNASH_REPORT_FUNCTION;
+
+ container_type::size_type size = _characters.size();
+
+ for (iterator it = _characters.begin(),
+ itEnd = _characters.end();
+ it != itEnd; ++it)
+ {
+ // @@@@ TODO FIX: If array changes size due to
+ // character actions, the iteration may not be
+ // correct!
+ //
+ // What's the correct thing to do here? Options:
+ //
+ // * copy the display list at the beginning,
+ // iterate through the copy
+ //
+ // * use (or emulate) a linked list instead of
+ // an array (still has problems; e.g. what
+ // happens if the next or current object gets
+ // removed from the dlist?)
+ //
+ // * iterate through current array in depth
+ // order. Always find the next object using a
+ // search of current array (but optimize the
+ // common case where nothing has changed).
+ //
+ // * ???
+ //
+ // Need to test to see what Flash does.
- int n = m_display_object_array.size();
- for (int i = 0; i < n; i++)
+ if (_characters.size() != size)
{
- // @@@@ TODO FIX: If array changes size due to
- // character actions, the iteration may not be
- // correct!
- //
- // What's the correct thing to do here? Options:
- //
- // * copy the display list at the beginning,
- // iterate through the copy
- //
- // * use (or emulate) a linked list instead of
- // an array (still has problems; e.g. what
- // happens if the next or current object gets
- // removed from the dlist?)
- //
- // * iterate through current array in depth
- // order. Always find the next object using a
- // search of current array (but optimize the
- // common case where nothing has changed).
- //
- // * ???
- //
- // Need to test to see what Flash does.
- if (n != (int) m_display_object_array.size())
- {
- log_error("gnash bug: dlist size changed due to
character actions, bailing on update!\n");
- break;
- }
+ log_error("gnash bug: dlist size changed due to
character actions, bailing on update!\n");
+ break;
+ }
- display_object_info & dobj = m_display_object_array[i];
-
- if (dobj.m_ref == true)
- {
- character* ch = dobj.m_character.get_ptr();
- assert(ch);
+ character* ch = it->get_ptr();
+ assert(ch);
- ch->advance(delta_time);
- }
- }
+ ch->advance(delta_time);
}
+
+}
- void display_list::display()
- // Display the referenced characters. Lower depths
- // are obscured by higher depths.
- {
-// GNASH_REPORT_FUNCTION;
-
+// Display the referenced characters. Lower depths
+// are obscured by higher depths.
+void
+DisplayList::display()
+{
+ //GNASH_REPORT_FUNCTION;
+
// printf(".");
- bool masked = false;
- int highest_masked_layer = 0;
-
- //log_msg("number of objects to be drawn %i\n",
m_display_object_array.size());
-
- for (unsigned int i = 0; i < m_display_object_array.size(); i++)
- {
- display_object_info& dobj =
m_display_object_array[i];
+ bool masked = false;
+ int highest_masked_layer = 0;
+
+ //log_msg("number of objects to be drawn %i\n",
m_display_object_array.size());
+
+ for( iterator it = _characters.begin(),
+ endIt = _characters.end();
+ it != endIt; ++it)
+ {
+ DisplayItem& dobj = *it;
- character* ch = dobj.m_character.get_ptr();
- assert(ch);
+ //character* ch = dobj.m_character.get_ptr();
+ character* ch = dobj.get_ptr();
- if (ch->get_visible() == false)
- {
- // Don't display.
- continue;
- }
+ assert(ch);
- if (ch->get_clip_depth() > 0)
- {
+ if (ch->get_visible() == false)
+ {
+ // Don't display.
+ continue;
+ }
+
+ if (ch->get_clip_depth() > 0)
+ {
// log_msg("depth %i, clip_depth %i\n",
dobj.m_depth, dobj.m_clip_depth);
- }
+ }
- // check whether a previous mask should be disabled
- if (masked)
+ // check whether a previous mask should be disabled
+ if (masked)
+ {
+ if (ch->get_depth() > highest_masked_layer)
{
- if (ch->get_depth() > highest_masked_layer)
- {
// log_msg("disabled mask before drawing
depth %i\n", ch->get_depth());
- masked = false;
- // turn off mask
- render::disable_mask();
- }
+ masked = false;
+ // turn off mask
+ render::disable_mask();
}
+ }
- // check whether this object should become mask
- if (ch->get_clip_depth() > 0)
- {
- //log_msg("begin submit mask\n");
- render::begin_submit_mask();
- }
-
- ch->display();
+ // check whether this object should become mask
+ if (ch->get_clip_depth() > 0)
+ {
+ //log_msg("begin submit mask\n");
+ render::begin_submit_mask();
+ }
+
+ ch->display();
- if (ch->get_clip_depth() > 0)
- {
+ if (ch->get_clip_depth() > 0)
+ {
// log_msg("object drawn\n");
- }
-
- // if this object should have become a mask,
- // inform the renderer that it now has all
- // information about it
- if (ch->get_clip_depth() > 0)
- {
- //log_msg("end submit mask\n");
- render::end_submit_mask();
- highest_masked_layer = ch->get_clip_depth();
- masked = true;
- }
}
- if (masked)
+ // if this object should have become a mask,
+ // inform the renderer that it now has all
+ // information about it
+ if (ch->get_clip_depth() > 0)
{
- // If a mask masks the scene all the way up to the
highest
- // layer, it will not be disabled at the end of drawing
- // the display list, so disable it manually.
- render::disable_mask();
+ //log_msg("end submit mask\n");
+ render::end_submit_mask();
+ highest_masked_layer = ch->get_clip_depth();
+ masked = true;
}
}
+
+ if (masked)
+ {
+ // If a mask masks the scene all the way up to the highest
+ // layer, it will not be disabled at the end of drawing
+ // the display list, so disable it manually.
+ render::disable_mask();
+ }
+}
+
+/*private*/
+void
+DisplayList::dump(std::ostream& os)
+{
+ int num=0;
+ for( iterator it = _characters.begin(),
+ endIt = _characters.end();
+ it != endIt; ++it)
+ {
+ DisplayItem& dobj = *it;
+ os << "Item " << num << " at depth " << dobj->get_depth()
+ << " (char id " << dobj->get_id() << ")" << std::endl;
+ num++;
+ }
}
+} // namespace gnash
+
// Local Variables:
// mode: C++
Index: gnash/server/dlist.h
diff -u gnash/server/dlist.h:1.5 gnash/server/dlist.h:1.6
--- gnash/server/dlist.h:1.5 Mon May 8 21:12:24 2006
+++ gnash/server/dlist.h Mon May 29 12:49:34 2006
@@ -1,9 +1,40 @@
-// dlist.h -- Thatcher Ulrich <address@hidden> 2003
+//
+// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+// Linking Gnash statically or dynamically with other modules is making a
+// combined work based on Gnash. Thus, the terms and conditions of the GNU
+// General Public License cover the whole combination.
+//
+// As a special exception, the copyright holders of Gnash give you
+// permission to combine Gnash with free software programs or libraries
+// that are released under the GNU LGPL and with code included in any
+// release of Talkback distributed by the Mozilla Foundation. You may
+// copy and distribute such a system following the terms of the GNU GPL
+// for all but the LGPL-covered parts and Talkback, and following the
+// LGPL for the LGPL-covered parts.
+//
+// Note that people who make modified versions of Gnash are not obligated
+// to grant this special exception for their modified versions; it is their
+// choice whether to do so. The GNU General Public License gives permission
+// to release a modified version without this exception; this exception
+// also makes it possible to release a modified version which carries
+// forward this exception.
+//
+//
-// This source code has been donated to the Public Domain. Do
-// whatever you want with it.
-
-// A list of active characters.
#ifndef GNASH_DLIST_H
@@ -14,175 +45,202 @@
#include "types.h"
#include "impl.h"
+#include <list>
+#include <iosfwd>
+
namespace gnash {
-
- /// A struct to serve as an entry in the display list.
- struct display_object_info {
- bool m_ref;
-
- /// state is held in here
- smart_ptr<character> m_character;
-
- display_object_info()
- :
- m_ref(false)
- {
- }
-
- display_object_info(const display_object_info& di)
- :
- m_ref(false)
- {
- *this = di;
- }
-
- ~display_object_info()
- {
- }
-
- void operator=(const display_object_info& di)
- {
- m_ref = di.m_ref;
- m_character = di.m_character;
- }
-
- void set_character(character* ch)
- {
- m_character = ch;
- }
-
- /// For qsort().
- static int compare(const void* _a, const void* _b);
- };
-
-
- /// A list of active characters.
- struct display_list {
- // TODO use better names!
- int find_display_index(int depth);
- int get_display_index(int depth);
-
- /// Add a new character in this display list.
- //
- /// If applicable, the event_id::LOAD event
- /// associated with the given character
- /// is called as last step of addition.
- ///
- /// @param ch
- /// the character to be added into the list
- ///
- /// @param depth
- /// depth to be assign to the character
- /// using character::set_depth
- ///
- /// @param replace_if_depth_is_occupied
- /// If this is false, caller wants to allow multiple
- /// objects with the same depth.
- /// find_display_index() returns the first matching
- /// depth, if there are any, so the new character
- /// will get inserted before all the others with the
- /// same depth. This matches the semantics
- /// described by Alexi's SWF ref. (This is all
- /// for legacy SWF compatibility anyway.)
- ///
- /// @param color_xform
- /// Color transform to be applied to the character
- /// using character::set_cxform
- ///
- /// @param mat
- /// matrix to be assigned to the character
- /// using character::set_matrix
- ///
- /// @param ratio
- /// ratio (scale?) to be assigned to the character
- /// using character::set_ratio
- ///
- /// @param clip_depth
- /// clip_depth (?) to be assigned to the character
- /// using character::set_clip_depth
- ///
- void add_display_object(
- character* ch,
- uint16_t depth,
- bool replace_if_depth_is_occupied,
- const cxform& color_xform,
- const matrix& mat,
- float ratio,
- uint16_t clip_depth);
-
- /// Updates the transform properties of the object at
- /// the specified depth.
- void move_display_object(
- uint16_t depth,
- bool use_cxform,
- const cxform& color_xform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- uint16_t clip_depth);
-
- /// Puts a new character at the specified depth, replacing any
- /// existing character. If use_cxform or use_matrix are false,
- /// then keep those respective properties from the existing
- /// character.
- void replace_display_object(
- character* ch,
- uint16_t depth,
- bool use_cxform,
- const cxform& color_xform,
- bool use_matrix,
- const matrix& mat,
- float ratio,
- uint16_t clip_depth);
-
- /// Removes the object at the specified depth.
- void remove_display_object(uint16_t depth, int id);
-
- /// clear the display list.
- void clear();
-
- /// reset the references to the display list.
- void reset();
-
- /// remove unreferenced objects.
- void update();
-
- /// advance referenced characters.
- void advance(float delta_time);
-
- /// Display the referenced characters.
- /// Lower depths are obscured by higher depths.
- void display();
-
- // unused
- //void display(const display_info& di);
-
- int get_character_count() { return
m_display_object_array.size(); }
- character* get_character(int index) { return
m_display_object_array[index].m_character.get_ptr(); }
-
- // May return NULL.
- character* get_character_at_depth(int depth);
-
- // May return NULL.
- // If there are multiples, returns the *first* match only!
- character* get_character_by_name(const tu_string& name);
-
- // May return NULL.
- // If there are multiples, returns the *first* match only!
- character* get_character_by_name_i(const tu_stringi& name);
- inline const display_object_info& get_display_object(int
idx) const
- // get the display object at the given position.
+/// A DisplayItem is simply a character object
+typedef smart_ptr<character> DisplayItem;
+
+/// A list of on-stage characters, ordered by depth
+//
+/// Any sprite_instance has an associated DisplayList
+/// that may change from frame to frame due to control
+/// tags instructing when to add or remove characthers
+/// from the stage.
+///
+class DisplayList {
+
+public:
+
+ /// \brief
+ /// Place a new character in this display list
+ /// replacing any other char at the same depth.
+ //
+ /// If applicable, the event_id::LOAD event
+ /// associated with the given character
+ /// is called as last step of addition.
+ ///
+ /// @param ch
+ /// the character to be added into the list
+ ///
+ /// @param depth
+ /// depth to be assign to the character
+ /// using character::set_depth
+ ///
+ /// @param color_xform
+ /// Color transform to be applied to the character
+ /// using character::set_cxform
+ ///
+ /// @param mat
+ /// matrix to be assigned to the character
+ /// using character::set_matrix
+ ///
+ /// @param ratio
+ /// ratio (scale?) to be assigned to the character
+ /// using character::set_ratio
+ ///
+ /// @param clip_depth
+ /// clip_depth (?) to be assigned to the character
+ /// using character::set_clip_depth
+ ///
+ void place_character(
+ character* ch,
+ uint16_t depth,
+ const cxform& color_xform,
+ const matrix& mat,
+ float ratio,
+ uint16_t clip_depth);
+
+ /// \brief
+ /// Puts a new character at the specified depth, replacing any
+ /// existing character.
+ //
+ /// If use_cxform or use_matrix are false, and a character is
+ /// present at the given depth, then keep those respective
+ /// properties from the existing character.
+ ///
+ /// TODO: use pointers for matrix and cxform, and use NULL
+ /// instead of the two bool arguments
+ ///
+ void replace_character(
+ character* ch,
+ uint16_t depth,
+ bool use_cxform,
+ const cxform& color_xform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ uint16_t clip_depth);
+
+
+ /// Updates the transform properties of the object at
+ /// the specified depth.
+ void move_display_object(
+ uint16_t depth,
+ bool use_cxform,
+ const cxform& color_xform,
+ bool use_matrix,
+ const matrix& mat,
+ float ratio,
+ uint16_t clip_depth);
+
+ /// Removes the object at the specified depth.
+ void remove_display_object(uint16_t depth);
+
+ /// \brief
+ /// Clear the display list, calling the UNLOAD event
+ /// on each item still present
+ void clear();
+
+ /// \brief
+ /// Clear the display list, w/out calling the UNLOAD event
+ /// on the items.
+ void reset();
+
+ /// advance referenced characters.
+ void advance(float delta_time);
+
+ /// \brief
+ /// Display the referenced characters.
+ /// Lower depths are obscured by higher depths.
+ void display();
+
+ /// May return NULL.
+ character* get_character_at_depth(int depth);
+
+ /// \brief
+ /// May return NULL.
+ /// If there are multiples, returns the *first* match only!
+ character* get_character_by_name(const tu_string& name);
+
+ /// \brief
+ /// May return NULL.
+ /// If there are multiples, returns the *first* match only!
+ character* get_character_by_name_i(const tu_stringi& name);
+
+ /// \brief
+ /// Visit each character in the list in depth order
+ /// (lower depth first).
+ //
+ /// The visitor functor will
+ /// receive a character pointer; must return true if
+ /// it wants next item or false to exit the loop.
+ template <class V>
+ inline void visitForward(V& visitor);
+
+ /// \brief
+ /// Visit each character in the list in reverse depth
+ /// order (higher depth first).
+ //
+ /// The visitor functor
+ /// will receive a character pointer; must return true if
+ /// it wants next item or false
+ /// to exit the loop.
+ template <class V>
+ inline void visitBackward(V& visitor);
+
+private:
+
+ typedef std::list<DisplayItem> container_type;
+ typedef container_type::iterator iterator;
+ typedef container_type::reverse_iterator reverse_iterator;
+
+ container_type _characters;
+
+ /// dump list to given output stream (debugging)
+ void dump(std::ostream& os);
+
+};
+
+template <class V>
+void
+DisplayList::visitForward(V& visitor)
+{
+ for (iterator it = _characters.begin(),
+ itEnd = _characters.end();
+ it != itEnd; ++it)
+ {
+ DisplayItem& di = *it;
+
+ //if ( ! di.get_ptr() ) continue;
+
+ if ( ! visitor(di.get_ptr()) )
{
- return m_display_object_array[idx];
+ break;
}
+ }
+}
+template <class V>
+void
+DisplayList::visitBackward(V& visitor)
+{
+ for (reverse_iterator it = _characters.rbegin(),
+ itEnd = _characters.rend();
+ it != itEnd; ++it)
+ {
+ DisplayItem& di = *it;
-// void set_character_position(character* ch, float x, float y);
+ //if ( ! di.get_ptr() ) continue;
- private:
- std::vector<display_object_info> m_display_object_array;
- };
+ if ( ! visitor(di.get_ptr()) )
+ {
+ break;
+ }
+ }
+}
}
Index: gnash/server/sprite_instance.cpp
diff -u gnash/server/sprite_instance.cpp:1.6
gnash/server/sprite_instance.cpp:1.7
--- gnash/server/sprite_instance.cpp:1.6 Sat May 20 23:49:33 2006
+++ gnash/server/sprite_instance.cpp Mon May 29 12:49:34 2006
@@ -314,6 +314,38 @@
}
+struct HeightFinder {
+ float _h;
+ HeightFinder(): _h(0) {}
+ bool operator() (character* ch)
+ {
+ float ch_h = ch->get_height();
+ if (ch_h > _h) {
+ _h = ch_h;
+ }
+ return true; // keep scanning
+ }
+ float getHeight() {
+ return _h;
+ }
+};
+
+struct WidthFinder {
+ float _w;
+ WidthFinder(): _w(0) {}
+ bool operator() (character* ch)
+ {
+ float ch_w = ch->get_width();
+ if (ch_w > _w) {
+ _w = ch_w;
+ }
+ return true; // keep scanning
+ }
+ float getWidth() {
+ return _w;
+ }
+};
+
//------------------------------------------------
// sprite_instance
//------------------------------------------------
@@ -733,7 +765,7 @@
newname.c_str(),
dummy_event_handlers,
depth,
- true, // replace if depth is occupied
+ true, // replace if depth is occupied (to drop)
ch->get_cxform(),
ch->get_matrix(),
ch->get_ratio(),
@@ -743,6 +775,7 @@
}
}
+#if 0
void sprite_instance::remove_display_object(const tu_string& name)
{
// GNASH_REPORT_FUNCTION;
@@ -754,6 +787,7 @@
remove_display_object(ch->get_depth(), ch->get_id());
}
}
+#endif
bool sprite_instance::on_event(event_id id)
{
@@ -819,9 +853,9 @@
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)
- {
+ as_standard_member std_member = get_standard_member(name);
+ switch (std_member)
+ {
default:
case M_INVALID_MEMBER:
break;
@@ -962,15 +996,26 @@
// val->set(0.0);
return;
}
- } // end switch
+ } // 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
+ // 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)
- {
+ if (text_val)
+ {
+ // CASE INSENSITIVE compare.
+ // In ActionScript 2.0, this must change
+ // to CASE SENSITIVE!!!
+ character* ch = m_display_list.get_character_by_name_i(
name);
+ if ( ch ) // item found
+ {
+ const char* text = val.to_string();
+ ch->set_text_value(text);
+ return;
+ }
+#if 0 // avoid use of DisplayList method taking indexes (moved to private)
bool success = false;
for (int i = 0, n = m_display_list.get_character_count(); i
< n; i++)
{
@@ -985,10 +1030,11 @@
}
}
if (success) return;
- }
+#endif // 0
+ }
- // If that didn't work, set a variable within this environment.
- m_as_environment.set_member(name, val);
+ // 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
@@ -1059,7 +1105,7 @@
void sprite_instance::advance(float delta_time)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
// Keep this (particularly m_as_environment) alive during execution!
smart_ptr<as_object> this_ptr(this);
@@ -1079,28 +1125,34 @@
// Check for the end of frame
if (m_time_remainder >= frame_time)
{
- m_time_remainder -= frame_time;
+ m_time_remainder -= frame_time;
- // Update current and next frames.
- if (m_play_state == PLAY)
+ // Update current and next frames.
+ if (m_play_state == PLAY)
+ {
+ int frame_count = m_def->get_frame_count();
+ if ( m_current_frame == frame_count && frame_count > 1 )
{
- int current_frame0 = m_current_frame;
- increment_frame_and_check_for_loop();
+ m_display_list.reset();
+ }
- // Execute the current frame's tags.
- if (m_current_frame != current_frame0)
- {
- execute_frame_tags(m_current_frame);
- }
+ 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);
+ // Dispatch onEnterFrame event.
+ on_event(event_id::ENTER_FRAME);
- do_actions();
+ do_actions();
- // Clean up display list (remove dead objects).
- m_display_list.update();
+ //we don't have the concept of a DisplayList update anymore
+ //m_display_list.update();
}
// Skip excess time. TODO root caller should
@@ -1111,9 +1163,11 @@
m_time_remainder = fmod(m_time_remainder, frame_time);
}
+/* virtual public, reimplemented from gnash::movie */
void sprite_instance::execute_frame_tags(int frame,
bool state_only)
{
+
// Keep this (particularly m_as_environment) alive during execution!
smart_ptr<as_object> this_ptr(this);
@@ -1223,7 +1277,8 @@
}
execute_frame_tags(target_frame_number, false);
- m_display_list.update();
+ //we don't have the concept of a DisplayList update anymore
+ //m_display_list.update();
}
else if (target_frame_number > m_current_frame)
{
@@ -1233,7 +1288,8 @@
}
execute_frame_tags(target_frame_number, false);
- m_display_list.update();
+ //we don't have the concept of a DisplayList update anymore
+ //m_display_list.update();
}
m_current_frame = target_frame_number;
@@ -1273,14 +1329,16 @@
}
character*
-sprite_instance::add_display_object(uint16_t character_id,
+sprite_instance::add_display_object(
+ uint16_t character_id,
const char* name,
const std::vector<swf_event*>& event_handlers,
- uint16_t depth, bool replace_if_depth_is_occupied,
+ uint16_t depth,
+ bool replace_if_depth_is_occupied,
const cxform& color_transform, const matrix& matrix,
float ratio, uint16_t clip_depth)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
assert(m_def != NULL);
character_def* cdef = m_def->get_character_def(character_id);
@@ -1306,8 +1364,9 @@
//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);
+ smart_ptr<character> ch = cdef->create_character_instance(this,
+ character_id);
+ assert(ch.get_ptr() != NULL);
if (name != NULL && name[0] != 0)
{
ch->set_name(name);
@@ -1319,10 +1378,9 @@
event_handlers[i]->attach_to(ch.get_ptr());
}}
- m_display_list.add_display_object(
+ m_display_list.place_character(
ch.get_ptr(),
depth,
- replace_if_depth_is_occupied,
color_transform,
matrix,
ratio,
@@ -1344,34 +1402,26 @@
float ratio,
uint16_t 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);
+ assert(m_def != NULL);
+ // printf("%s: character %s, id is %d\n", __FUNCTION__, name,
character_id); // FIXME: debugging crap
- smart_ptr<character> ch =
cdef->create_character_instance(this, character_id);
- assert(ch != NULL);
+ 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);
- if (name != NULL && name[0] != 0)
- {
- ch->set_name(name);
- }
+ smart_ptr<character> ch = cdef->create_character_instance(this,
+ character_id);
- m_display_list.replace_display_object(
- ch.get_ptr(),
- depth,
- use_cxform,
- color_transform,
- use_matrix,
- mat,
- ratio,
- clip_depth);
+ replace_display_object(
+ ch.get_ptr(), name, depth,
+ use_cxform, color_transform,
+ use_matrix, mat,
+ ratio, clip_depth);
}
void sprite_instance::replace_display_object(
@@ -1385,7 +1435,7 @@
float ratio,
uint16_t clip_depth)
{
- printf("%s: character %s, id is %d\n", __FUNCTION__, name, ch->get_id());
// FIXME:
+ //printf("%s: character %s, id is %d\n", __FUNCTION__, name,
ch->get_id()); // FIXME:
assert(ch != NULL);
@@ -1394,7 +1444,7 @@
ch->set_name(name);
}
- m_display_list.replace_display_object(
+ m_display_list.replace_character(
ch,
depth,
use_cxform,
@@ -1407,44 +1457,102 @@
int sprite_instance::get_id_at_depth(int depth)
{
+#if 0 // don't mess with DisplayList indexes
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();
+#endif
+ character* ch = m_display_list.get_character_at_depth(depth);
+ if ( ! ch ) return -1;
+ else return ch->get_id();
}
void sprite_instance::increment_frame_and_check_for_loop()
{
- m_current_frame++;
+ //GNASH_REPORT_FUNCTION;
- int frame_count = m_def->get_frame_count();
- if (m_current_frame >= frame_count)
+ 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)
+ // Loop.
+ m_current_frame = 0;
+ m_has_looped = true;
+ if (frame_count > 1)
{
- m_display_list.reset();
+ //m_display_list.reset();
}
}
+
+ //log_msg("Frame %d/%d", m_current_frame, frame_count);
}
+/// Find a character hit by the given coordinates.
+class MouseEntityFinder {
+
+ movie* _m;
+
+ float _x;
+
+ float _y;
+
+public:
+
+ MouseEntityFinder(float x, float y)
+ :
+ _m(NULL),
+ _x(x),
+ _y(y)
+ {}
+
+ bool operator() (character* ch)
+ {
+ if ( ! ch->get_visible() ) return true;
+
+ movie* te = ch->get_topmost_mouse_entity(_x, _y);
+ if ( te )
+ {
+ _m = te;
+ return false; // done
+ }
+
+ return true; // haven't found it yet
+ }
+
+ movie* getEntity() { return _m; }
+
+};
+
movie*
sprite_instance::get_topmost_mouse_entity(float x, float y)
{
- if (get_visible() == false) {
- return NULL;
- }
+ //GNASH_REPORT_FUNCTION;
- matrix m = get_matrix();
- point p;
- m.transform_by_inverse(&p, point(x, y));
+ if (get_visible() == false)
+ {
+ return NULL;
+ }
+
+ matrix m = get_matrix();
+ point p;
+ m.transform_by_inverse(&p, point(x, y));
+
+ MouseEntityFinder finder(p.m_x, p.m_y);
+ m_display_list.visitBackward(finder);
+ movie* ch = finder.getEntity();
+
+ if ( ch && can_handle_mouse_event() )
+ {
+ return this;
+ }
+ else
+ {
+ return ch; // might be NULL
+ }
+#if 0 // rewritten to use the visitor pattern
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);
@@ -1466,6 +1574,9 @@
}
return NULL;
+
+#endif // 0
+
}
bool
@@ -1519,12 +1630,18 @@
m_play_state = PLAY;
execute_frame_tags(m_current_frame);
- m_display_list.update();
+ //we don't have the concept of a DisplayList update anymore
+ //m_display_list.update();
}
-float sprite_instance::get_height()
+float sprite_instance::get_height()
{
- float h = 0;
+ HeightFinder f;
+ m_display_list.visitForward(f);
+ return f.getHeight();
+
+#if 0 // rewritten to use the visitor pattern
+
int i, n = m_display_list.get_character_count();
character* ch;
for (i=0; i < n; i++)
@@ -1540,11 +1657,17 @@
}
}
return h;
+
+#endif // 0
}
-float sprite_instance::get_width()
+float sprite_instance::get_width()
{
- float w = 0;
+ WidthFinder f;
+ m_display_list.visitForward(f);
+ return f.getWidth();
+
+#if 0 // rewritten to use visitor pattern
int i, n = m_display_list.get_character_count();
character* ch;
for (i = 0; i < n; i++)
@@ -1561,6 +1684,7 @@
}
return w;
+#endif
}
void sprite_instance::do_something(void *timer)
Index: gnash/server/sprite_instance.h
diff -u gnash/server/sprite_instance.h:1.4 gnash/server/sprite_instance.h:1.5
--- gnash/server/sprite_instance.h:1.4 Sat May 20 23:49:33 2006
+++ gnash/server/sprite_instance.h Mon May 29 12:49:34 2006
@@ -49,7 +49,7 @@
#include "movie_definition.h"
#include "movie_root.h"
-#include "dlist.h" // display_list
+#include "dlist.h" // DisplayList
#include "stream.h"
#include "log.h"
#include "as_environment.h" // for composition
@@ -112,7 +112,7 @@
float get_width();
- float get_height();
+ float get_height();
int get_current_frame() const
{
@@ -182,14 +182,12 @@
/// Return true if we have any mouse event handlers.
bool can_handle_mouse_event();
+ /// \brief
/// 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.
@@ -236,8 +234,12 @@
/// Display (render?) this Sprite/MovieClip, unless invisible
void display();
- /// Add an object to the DisplayList.
- character* add_display_object(
+ /// Add an object to the DisplayList.
+ //
+ /// @param replace_if_dept_is_occupied
+ /// unused, always true
+ ///
+ character* add_display_object(
uint16_t character_id,
const char* name,
const std::vector<swf_event*>& event_handlers,
@@ -288,12 +290,15 @@
uint16_t clip_depth);
+ /// \brief
/// Remove the object at the specified depth.
- /// If id != -1, then only remove the object
- /// at depth with matching id.
+ //
+ /// NOTE: the id parameter is unused, but currently
+ /// required to avoid break of inheritance from movie.h
+ ///
void remove_display_object(uint16_t depth, int id)
{
- m_display_list.remove_display_object(depth, id);
+ m_display_list.remove_display_object(depth);
}
@@ -393,7 +398,10 @@
const tu_string& newname, uint16_t depth);
/// Remove the object with the specified name.
- void remove_display_object(const tu_string& name);
+ //
+ /// @@ what happens if the we have multiple objects
+ /// with the same name ?
+ //void remove_display_object(const tu_string& name);
/// Dispatch event handler(s), if any.
virtual bool on_event(event_id id);
@@ -474,7 +482,7 @@
smart_ptr<movie_definition> m_def;
movie_root* m_root;
- display_list m_display_list;
+ DisplayList m_display_list;
//std::vector<action_buffer*> m_action_list;
std::vector<action_buffer*> m_action_list;
@@ -498,6 +506,9 @@
static as_object as_builtins;
static void init_builtins();
+ /// Increment m_current_frame, and take care of looping.
+ void increment_frame_and_check_for_loop();
+
};
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash ./ChangeLog server/dlist.cpp server/dlist...,
Sandro Santilli <=