avm1: Small cleanups in ActionQueue (#8486)

- Use a fixed-size array instead of a Vec for the queues
- Remove unwanted plurals in methods and types names
This commit is contained in:
moulins 2022-11-06 06:39:11 +01:00 committed by GitHub
parent d16e9e1511
commit 8cbd527e4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 41 deletions

View File

@ -324,7 +324,7 @@ impl<'gc> AudioManager<'gc> {
object.set_position(gc_context, duration.round() as u32);
// Fire soundComplete event.
action_queue.queue_actions(
action_queue.queue_action(
root,
crate::context::ActionType::Method {
object: object.into(),
@ -340,7 +340,7 @@ impl<'gc> AudioManager<'gc> {
//TODO: AVM2 events are usually not queued, but we can't
//hold the update context in the audio manager yet.
action_queue.queue_actions(
action_queue.queue_action(
root,
crate::context::ActionType::Event2 {
event_type: "soundComplete",

View File

@ -355,7 +355,7 @@ impl<'a, 'gc, 'gc_context> UpdateContext<'a, 'gc, 'gc_context> {
/// A queued ActionScript call.
#[derive(Collect)]
#[collect(no_drop)]
pub struct QueuedActions<'gc> {
pub struct QueuedAction<'gc> {
/// The movie clip this ActionScript is running on.
pub clip: DisplayObject<'gc>,
@ -371,7 +371,7 @@ pub struct QueuedActions<'gc> {
#[collect(no_drop)]
pub struct ActionQueue<'gc> {
/// Each priority is kept in a separate bucket.
action_queue: Vec<VecDeque<QueuedActions<'gc>>>,
action_queue: [VecDeque<QueuedAction<'gc>>; ActionQueue::NUM_PRIORITIES],
}
impl<'gc> ActionQueue<'gc> {
@ -380,24 +380,20 @@ impl<'gc> ActionQueue<'gc> {
/// Crates a new `ActionQueue` with an empty queue.
pub fn new() -> Self {
let mut action_queue = Vec::with_capacity(Self::NUM_PRIORITIES);
for _ in 0..Self::NUM_PRIORITIES {
action_queue.push(VecDeque::with_capacity(Self::DEFAULT_CAPACITY))
}
let action_queue = std::array::from_fn(|_| VecDeque::with_capacity(Self::DEFAULT_CAPACITY));
Self { action_queue }
}
/// Queues ActionScript to run for the given movie clip.
/// `actions` is the slice of ActionScript bytecode to run.
/// The actions will be skipped if the clip is removed before the actions run.
pub fn queue_actions(
/// Queues an action to run for the given movie clip.
/// The action will be skipped if the clip is removed before the action runs.
pub fn queue_action(
&mut self,
clip: DisplayObject<'gc>,
action_type: ActionType<'gc>,
is_unload: bool,
) {
let priority = action_type.priority();
let action = QueuedActions {
let action = QueuedAction {
clip,
action_type,
is_unload,
@ -409,14 +405,11 @@ impl<'gc> ActionQueue<'gc> {
}
/// Sorts and drains the actions from the queue.
pub fn pop_action(&mut self) -> Option<QueuedActions<'gc>> {
for queue in self.action_queue.iter_mut().rev() {
let action = queue.pop_front();
if action.is_some() {
return action;
}
}
None
pub fn pop_action(&mut self) -> Option<QueuedAction<'gc>> {
self.action_queue
.iter_mut()
.rev()
.find_map(VecDeque::pop_front)
}
}

View File

@ -493,7 +493,7 @@ impl<'gc> TInteractiveObject<'gc> for Avm1Button<'gc> {
// (e.g., clip.onRelease = foo).
if context.swf.version() >= 6 {
if let Some(name) = event.method_name() {
context.action_queue.queue_actions(
context.action_queue.queue_action(
self_display_object,
ActionType::Method {
object: write.object.unwrap(),
@ -579,7 +579,7 @@ impl<'gc> Avm1ButtonData<'gc> {
{
// Note that AVM1 buttons run actions relative to their parent, not themselves.
handled = ClipEventResult::Handled;
context.action_queue.queue_actions(
context.action_queue.queue_action(
parent,
ActionType::Normal {
bytecode: action.action_data.clone(),

View File

@ -2002,7 +2002,7 @@ impl<'gc> MovieClip<'gc> {
.iter()
{
if event_handler.events.contains(ClipEventFlag::INITIALIZE) {
context.action_queue.queue_actions(
context.action_queue.queue_action(
self.into(),
ActionType::Initialize {
bytecode: event_handler.action_data.clone(),
@ -2015,7 +2015,7 @@ impl<'gc> MovieClip<'gc> {
}
}
context.action_queue.queue_actions(
context.action_queue.queue_action(
self.into(),
ActionType::Construct {
constructor: avm1_constructor,
@ -2719,7 +2719,7 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
}
}
context.action_queue.queue_actions(
context.action_queue.queue_action(
self.into(),
ActionType::Normal {
bytecode: event_handler.action_data.clone(),
@ -2735,7 +2735,7 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
if let Some(name) = event.method_name() {
// Keyboard events don't fire their methods unless the MovieClip has focus (#2120).
if !event.is_key_event() || read.has_focus {
context.action_queue.queue_actions(
context.action_queue.queue_action(
self.into(),
ActionType::Method {
object,
@ -3650,7 +3650,7 @@ impl<'gc, 'a> MovieClip<'gc> {
.swf
.resize_to_reader(reader, tag_len);
if !slice.is_empty() {
context.action_queue.queue_actions(
context.action_queue.queue_action(
self.into(),
ActionType::Normal { bytecode: slice },
false,

View File

@ -876,7 +876,7 @@ impl<'gc> Loader<'gc> {
// Fire the onData method and event.
if let Some(display_object) = that.as_display_object() {
if let Some(movie_clip) = display_object.as_movie_clip() {
activation.context.action_queue.queue_actions(
activation.context.action_queue.queue_action(
movie_clip.into(),
ActionType::Method {
object: that,
@ -1646,7 +1646,7 @@ impl<'gc> Loader<'gc> {
LoaderStatus::Succeeded => {
// AVM2 is handled separately
if let Some(MovieLoaderEventHandler::Avm1Broadcast(broadcaster)) = event_handler {
queue.queue_actions(
queue.queue_action(
clip,
ActionType::Method {
object: broadcaster,

View File

@ -1019,7 +1019,7 @@ impl Player {
// Fire event listener on appropriate object
if let Some((listener_type, event_name, args)) = listener {
context.action_queue.queue_actions(
context.action_queue.queue_action(
context.stage.root_clip(),
ActionType::NotifyListeners {
listener: listener_type,
@ -1514,16 +1514,16 @@ impl Player {
pub fn run_actions<'gc>(context: &mut UpdateContext<'_, 'gc, '_>) {
// Note that actions can queue further actions, so a while loop is necessary here.
while let Some(actions) = context.action_queue.pop_action() {
while let Some(action) = context.action_queue.pop_action() {
// We don't run frame actions if the clip was removed after it queued the action.
if !actions.is_unload && actions.clip.removed() {
if !action.is_unload && action.clip.removed() {
continue;
}
match actions.action_type {
match action.action_type {
// DoAction/clip event code.
ActionType::Normal { bytecode } | ActionType::Initialize { bytecode } => {
Avm1::run_stack_frame_for_action(actions.clip, "[Frame]", bytecode, context);
Avm1::run_stack_frame_for_action(action.clip, "[Frame]", bytecode, context);
}
// Change the prototype of a MovieClip and run constructor events.
ActionType::Construct {
@ -1536,10 +1536,10 @@ impl Player {
context.reborrow(),
ActivationIdentifier::root("[Construct]"),
globals,
actions.clip,
action.clip,
);
if let Ok(prototype) = constructor.get("prototype", &mut activation) {
if let Value::Object(object) = actions.clip.object() {
if let Value::Object(object) = action.clip.object() {
object.define_value(
activation.context.gc_context,
"__proto__",
@ -1549,7 +1549,7 @@ impl Player {
for event in events {
let _ = activation.run_child_frame_for_action(
"[Actions]",
actions.clip,
action.clip,
event,
);
}
@ -1565,7 +1565,7 @@ impl Player {
} => {
for event in events {
Avm1::run_stack_frame_for_action(
actions.clip,
action.clip,
"[Construct]",
event,
context,
@ -1575,7 +1575,7 @@ impl Player {
// Event handler method call (e.g. onEnterFrame).
ActionType::Method { object, name, args } => {
Avm1::run_stack_frame_for_method(
actions.clip,
action.clip,
object,
context,
name.into(),
@ -1592,7 +1592,7 @@ impl Player {
// A native function ends up resolving immediately,
// so this doesn't require any further execution.
Avm1::notify_system_listeners(
actions.clip,
action.clip,
context,
listener.into(),
method.into(),