core: Add flag for display objects which were placed by AS3.
In AS3. objects placed by scripts *cannot* be removed by `RemoveObject` tags. This enforces that in Ruffle.
This commit is contained in:
parent
8c9f8520b3
commit
f3ae65df93
|
@ -358,6 +358,18 @@ impl<'gc> DisplayObjectBase<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
fn placed_by_script(&self) -> bool {
|
||||
self.flags.contains(DisplayObjectFlags::PlacedByScript)
|
||||
}
|
||||
|
||||
fn set_placed_by_script(&mut self, value: bool) {
|
||||
if value {
|
||||
self.flags.insert(DisplayObjectFlags::PlacedByScript);
|
||||
} else {
|
||||
self.flags.remove(DisplayObjectFlags::PlacedByScript);
|
||||
}
|
||||
}
|
||||
|
||||
fn swf_version(&self) -> u8 {
|
||||
self.parent
|
||||
.map(|p| p.swf_version())
|
||||
|
@ -736,6 +748,16 @@ pub trait TDisplayObject<'gc>:
|
|||
false
|
||||
}
|
||||
|
||||
/// Whether this display object has been created by ActionScript 3.
|
||||
/// When this flag is set, changes from SWF `RemoveObject` tags are
|
||||
/// ignored.
|
||||
fn placed_by_script(&self) -> bool;
|
||||
|
||||
/// Sets whether this display object has been created by ActionScript 3.
|
||||
/// When this flag is set, changes from SWF `RemoveObject` tags are
|
||||
/// ignored.
|
||||
fn set_placed_by_script(&self, context: MutationContext<'gc, '_>, value: bool);
|
||||
|
||||
/// Executes and propagates the given clip event.
|
||||
/// Events execute inside-out; the deepest child will react first, followed by its parent, and
|
||||
/// so forth.
|
||||
|
@ -1123,6 +1145,12 @@ macro_rules! impl_display_object_sansbounds {
|
|||
.$field
|
||||
.set_transformed_by_script(value)
|
||||
}
|
||||
fn placed_by_script(&self) -> bool {
|
||||
self.0.read().$field.placed_by_script()
|
||||
}
|
||||
fn set_placed_by_script(&self, context: gc_arena::MutationContext<'gc, '_>, value: bool) {
|
||||
self.0.write(context).$field.set_placed_by_script(value)
|
||||
}
|
||||
fn instantiate(
|
||||
&self,
|
||||
gc_context: gc_arena::MutationContext<'gc, '_>,
|
||||
|
@ -1255,6 +1283,10 @@ enum DisplayObjectFlags {
|
|||
/// Whether this object has been transformed by ActionScript.
|
||||
/// When this flag is set, changes from SWF `PlaceObject` tags are ignored.
|
||||
TransformedByScript,
|
||||
|
||||
/// Whether this object has been placed on the timeline by ActionScript 3.
|
||||
/// When this flag is set, changes from SWF `RemoveObject` tags are ignored.
|
||||
PlacedByScript,
|
||||
}
|
||||
|
||||
pub struct ChildIter<'gc> {
|
||||
|
|
|
@ -1198,8 +1198,10 @@ impl<'gc> MovieClip<'gc> {
|
|||
.children
|
||||
.insert(depth, child);
|
||||
if let Some(prev_child) = prev_child {
|
||||
if !prev_child.placed_by_script() {
|
||||
self.remove_child_from_exec_list(context, prev_child);
|
||||
}
|
||||
}
|
||||
self.0
|
||||
.write(context.gc_context)
|
||||
.add_child_to_exec_list(context.gc_context, child);
|
||||
|
@ -1275,9 +1277,11 @@ impl<'gc> MovieClip<'gc> {
|
|||
})
|
||||
.collect();
|
||||
for (depth, child) in children {
|
||||
if !child.placed_by_script() {
|
||||
self.0.write(context.gc_context).children.remove(&depth);
|
||||
self.remove_child_from_exec_list(context, child);
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -1704,11 +1708,13 @@ impl<'gc> MovieClip<'gc> {
|
|||
// Don't do this for rewinds, because they conceptually
|
||||
// start from an empty display list, and we also want to examine
|
||||
// the old children to decide if they persist (place_frame <= goto_frame).
|
||||
let child = self.0.write(context.gc_context).children.remove(&depth);
|
||||
if let Some(child) = child {
|
||||
if let Some(child) = self.0.read().children.get(&depth).cloned() {
|
||||
if !child.placed_by_script() {
|
||||
self.0.write(context.gc_context).children.remove(&depth);
|
||||
self.remove_child_from_exec_list(context, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -2944,14 +2950,14 @@ impl<'gc, 'a> MovieClip<'gc> {
|
|||
} else {
|
||||
reader.read_remove_object_2()
|
||||
}?;
|
||||
let child = self
|
||||
.0
|
||||
.write(context.gc_context)
|
||||
.children
|
||||
.remove(&remove_object.depth.into());
|
||||
if let Some(child) = child {
|
||||
|
||||
if let Some(child) = self.0.read().children.get(&remove_object.depth.into()).cloned() {
|
||||
if !child.placed_by_script() {
|
||||
self.0.write(context.gc_context).children.remove(&remove_object.depth.into());
|
||||
self.remove_child_from_exec_list(context, child);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue