1
// dlist.h: Display list definitions, for Gnash.
3
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 3 of the License, or
8
// (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
#include "snappingrange.h"
26
#include "character.h"
32
#include <set> // for testInvariant
35
// GNASH_PARANOIA_LEVEL:
36
// 0 : (not unimplemented)
37
// 1 : quick assertions
38
// 2 : add testInvariant
40
#ifndef GNASH_PARANOIA_LEVEL
41
# define GNASH_PARANOIA_LEVEL 1
50
/// A DisplayItem is simply a character object
51
typedef boost::intrusive_ptr<character> DisplayItem;
53
/// A list of on-stage characters, ordered by depth
55
/// Any sprite_instance has an associated DisplayList
56
/// that may change from frame to frame due to control
57
/// tags instructing when to add or remove characters
64
void testInvariant() const
66
#if GNASH_PARANOIA_LEVEL > 1
68
DisplayList sorted = *this;
69
// check no duplicated depths above non-removed zone.
71
for (const_iterator it=beginNonRemoved(_charsByDepth), itEnd=_charsByDepth.end(); it!=itEnd; ++it)
73
boost::intrusive_ptr<character> ch = *it;
74
int depth = ch->get_depth();
75
if ( ! depths.insert(depth).second )
77
log_debug("Depth %d is duplicated in DisplayList %p", depth, (const void*)this);
81
assert(isSorted()); // check we didn't screw up ordering
83
#endif // GNASH_PARANOIA_LEVEL > 1
87
friend std::ostream& operator<< (std::ostream&, const DisplayList&);
90
/// Place a new character at the specified depth,
91
/// replacing any existing character at the same depth.
93
/// If a character is replaced, it's unload() method
96
/// If applicable, the event_id::LOAD event
97
/// associated with the given character
98
/// is called as last step of addition.
101
/// the new character to be added into the list.
104
/// depth at which the new character is placed.
106
void place_character(character* ch, int depth);
109
/// Replace the old character at the specified depth with
110
/// the given new character.
112
/// Calls unload on the removed character.
115
/// the new character to be put
118
/// depth to be replaced
120
/// @param use_old_cxform
121
/// true: set the new character's cxform to the old one.
122
/// false: keep the new character's cxform.
124
/// @param use_old_matrix
125
/// true: set the new character's transformation matrix to the old one.
126
/// false: keep the new character's transformation matrix.
128
void replace_character(character* ch, int depth,
130
bool use_old_matrix);
133
/// Change depth of the given characters in the list,
134
/// swapping with any existing character at target depth.
136
/// List ordering will be maintained by this function.
138
/// Any character affected by this operation (none on invalid call,
139
/// 1 if new depth is not occupied, 2 otherwise) will be:
140
/// - bounds invalidated (see character::set_invalidated)
141
/// - marked as script-transformed (see character::transformedByScript)
144
/// The character to apply depth swapping to.
145
/// If not found in the list, an error is raised
146
/// and no other action is taken.
149
/// The new depth to assign to the given character.
150
/// If occupied by another character, the target character
151
/// will get the current depth of the first.
152
/// If target depth equals the current depth of character, an
153
/// assertion fails, as I think the caller should check this instead.
155
void swapDepths(character* ch, int depth);
158
/// Updates the transform properties of the object at the
159
/// specified depth, unless its get_accept_anim_moves() returns false.
161
/// See character::get_accept_anim_moves()
163
/// @param color_xform
164
/// The color tranform to assign to the character at the given depth.
165
/// If NULL the orignial color transform will be kept.
168
/// The matrix tranform to assign to the character at the given depth.
169
/// If NULL the orignial matrix will be kept.
172
/// The new ratio value to assign to the character at the given depth.
173
/// If NULL the original ratio will be kept.
176
/// Not used at the moment.
180
const cxform* color_xform,
185
/// Removes the object at the specified depth.
187
/// Calls unload on the removed character.
189
void remove_character(int depth);
191
/// Remove all unloaded character from the list
193
/// Removed characters still in the list are those
194
/// on which onUnload event handlers were defined..
196
/// NOTE: we don't call the function recursively in the
197
/// contained elements, as that should not be needed
198
/// (ie: any inned thing will not be accessible anyway)
200
void removeUnloaded();
202
/// Unload the characters in this DisplayList removing
203
/// all but the ones with on onUnload event defined
204
/// (checked by calling ::unload on them) and keeping
205
/// the others, w/out depth-shifting them.
207
/// Return true if any child was kept (as they had onUnload defined)
211
/// destroy all characters in this DisplayList
214
/// Add all characters in the list, maintaining depth-order
217
/// The characters to add
220
/// If true the given characters would replace any
221
/// pre-existing character at the same depth.
223
void addAll(std::vector<character*>& chars, bool replace);
225
/// Add a character in the list, maintaining depth-order
229
/// The character to add
232
/// If true the given character would replace any
233
/// pre-existing character at the same depth.
235
void add(character* ch, bool replace);
238
/// Display the referenced characters.
239
/// Lower depths are obscured by higher depths.
245
character* get_character_at_depth(int depth);
247
const character* get_character_at_depth(int depth) const {
248
return const_cast<DisplayList*>(this)->get_character_at_depth(depth);
253
/// If there are multiples, returns the *first* match only!
254
character* get_character_by_name(const std::string& name);
256
const character* get_character_by_name(const std::string& name) const
258
return const_cast<DisplayList*>(this)->get_character_by_name(name);
263
/// If there are multiples, returns the *first* match only!
264
character* get_character_by_name_i(const std::string& name);
267
/// Visit each character in the list in depth order
268
/// (lower depth first).
270
/// The visitor functor will
271
/// receive a character pointer; must return true if
272
/// it wants next item or false to exit the loop.
274
/// NOTE: all elements in the list are visited, even
275
/// the removed ones (unloaded)
276
/// TODO: inspect if worth providing an arg to skip removed
279
inline void visitForward(V& visitor);
282
/// Visit each character in the list in reverse depth
283
/// order (higher depth first).
285
/// The visitor functor
286
/// will receive a character pointer; must return true if
287
/// it wants next item or false
288
/// to exit the loop.
290
/// NOTE: all elements in the list are visited, even
291
/// the removed ones (unloaded)
292
/// TODO: inspect if worth providing an arg to skip removed
295
inline void visitBackward(V& visitor);
297
inline void visitBackward(V& visitor) const;
300
/// Visit each and all character in the list.
302
/// Scan happens in arbitrary order, if order is
303
/// important use visitBackward or visitForward
305
/// The visitor functor will receive a character pointer,
306
/// it's return value is not used so can return void.
308
/// NOTE: all elements in the list are visited, even
309
/// the removed ones (unloaded)
310
/// TODO: inspect if worth providing an arg to skip removed
313
inline void visitAll(V& visitor);
316
inline void visitAll(V& visitor) const;
318
/// dump list to logfile/stderr
321
/// Like character_instance::add_invalidated_bounds() this method calls the
322
/// method with the same name of all childs.
323
void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
325
void dump_character_tree(const std::string prefix) const;
328
/// Return number of elements in the list
331
return _charsByDepth.size();
334
/// Return true if the list contains no elements
337
return _charsByDepth.empty();
340
/// Return the next highest available depth
342
/// Placing an object at the depth returned by
343
/// this function should result in a character
344
/// that is displayd above all others
346
int getNextHighestDepth() const;
348
/// Sort list by depth (lower depths first)
350
/// You only need calling this method if depth
351
/// of characters on the list has been externally
352
/// changed. Usually it is DisplayList itself
353
/// assigning depths, so won't need to call it.
355
/// A notable use for this is backing up a specific
356
/// state and restoring it later. Restore step would
362
/// merge the given display list
363
void mergeDisplayList(DisplayList& newList);
365
bool operator==(const DisplayList& other) const { return _charsByDepth == other._charsByDepth; }
367
bool operator!=(const DisplayList& other) const { return _charsByDepth != other._charsByDepth; }
371
typedef std::list<DisplayItem> container_type;
372
typedef container_type::iterator iterator;
373
typedef container_type::const_iterator const_iterator;
374
typedef container_type::reverse_iterator reverse_iterator;
375
typedef container_type::const_reverse_iterator const_reverse_iterator;
377
/// Return an iterator to the first element of the container NOT in the "removed" depth zone
378
static iterator beginNonRemoved(container_type& c);
380
/// Return an constant iterator to the first element of the container NOT in the "removed" depth zone
381
static const_iterator beginNonRemoved(const container_type& c);
383
/// Return an iterator succeeding the last element in zone (-16384, 0xffff-16384)
384
static iterator dlistTagsEffectivZoneEnd(container_type& c);
386
/// Return an constant iterator succeeding the last element in (-16384, 0xffff-16384)
387
static const_iterator dlistTagsEffectivZoneEnd(const container_type& c);
390
/// Re-insert a removed-from-stage character after appropriately
391
/// shifting its depth based on the character::removedDepthOffset
395
/// - ch::isUnloaded() returns true (assertion fails otherwise)
396
/// - ch is not already in the list (assertion fails otherwise)
398
/// TODO: inspect what should happen if the target depth is already occupied
400
void reinsertRemovedCharacter(boost::intrusive_ptr<character> ch);
402
container_type _charsByDepth;
404
/// Check that the list is sorted by depth
405
bool isSorted() const;
410
DisplayList::visitForward(V& visitor)
412
for (iterator it = _charsByDepth.begin(),
413
itEnd = _charsByDepth.end();
416
DisplayItem& di = *it;
417
if ( ! visitor(di.get()) ) break;
423
DisplayList::visitBackward(V& visitor)
425
for (reverse_iterator it = _charsByDepth.rbegin(),
426
itEnd = _charsByDepth.rend();
429
DisplayItem& di = *it;
430
if ( ! visitor(di.get()) ) break;
436
DisplayList::visitBackward(V& visitor) const
438
for (const_reverse_iterator it = _charsByDepth.rbegin(),
439
itEnd = _charsByDepth.rend();
442
const DisplayItem& di = *it;
443
if ( ! visitor(di.get()) ) break;
449
DisplayList::visitAll(V& visitor)
451
for (iterator it = _charsByDepth.begin(),
452
itEnd = _charsByDepth.end();
461
DisplayList::visitAll(V& visitor) const
463
for (const_iterator it = _charsByDepth.begin(),
464
itEnd = _charsByDepth.end();
471
std::ostream& operator<< (std::ostream&, const DisplayList&);
476
#endif // GNASH_DLIST_H
484
// indent-tabs-mode: t