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:
parent
d16e9e1511
commit
8cbd527e4c
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Reference in New Issue