core: Add a method to fire common `InteractiveObject` events into AVM2.

This commit is contained in:
David Wendt 2021-12-04 14:50:10 -05:00 committed by Mike Welsh
parent 18b8b227a1
commit 6d02248ea5
5 changed files with 56 additions and 6 deletions

View File

@ -805,6 +805,8 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> {
self.set_state(context, new_state);
}
self.event_dispatch_to_avm2(context, event);
handled
}
}

View File

@ -1821,7 +1821,7 @@ impl<'gc> TInteractiveObject<'gc> for EditText<'gc> {
fn event_dispatch(
self,
context: &mut UpdateContext<'_, 'gc, '_>,
_event: ClipEvent,
event: ClipEvent,
) -> ClipEventResult {
let tracker = context.focus_tracker;
tracker.set(Some(self.into()), context);
@ -1835,6 +1835,8 @@ impl<'gc> TInteractiveObject<'gc> for EditText<'gc> {
Some(TextSelection::for_position(self.text_length()));
}
self.event_dispatch_to_avm2(context, event);
ClipEventResult::Handled
}
}

View File

@ -1,6 +1,6 @@
//! Interactive object enumtrait
use crate::avm2::Value;
use crate::avm2::{Avm2, Event as Avm2Event, EventData as Avm2EventData, Value as Avm2Value};
use crate::context::UpdateContext;
use crate::display_object::avm1_button::Avm1Button;
use crate::display_object::avm2_button::Avm2Button;
@ -36,7 +36,7 @@ bitflags! {
pub struct InteractiveObjectBase<'gc> {
pub base: DisplayObjectBase<'gc>,
flags: InteractiveObjectFlags,
context_menu: Value<'gc>,
context_menu: Avm2Value<'gc>,
}
impl<'gc> Default for InteractiveObjectBase<'gc> {
@ -44,7 +44,7 @@ impl<'gc> Default for InteractiveObjectBase<'gc> {
Self {
base: Default::default(),
flags: InteractiveObjectFlags::MOUSE_ENABLED,
context_menu: Value::Null,
context_menu: Avm2Value::Null,
}
}
}
@ -97,11 +97,11 @@ pub trait TInteractiveObject<'gc>:
.set(InteractiveObjectFlags::DOUBLE_CLICK_ENABLED, value)
}
fn context_menu(self) -> Value<'gc> {
fn context_menu(self) -> Avm2Value<'gc> {
self.ibase().context_menu
}
fn set_context_menu(self, mc: MutationContext<'gc, '_>, value: Value<'gc>) {
fn set_context_menu(self, mc: MutationContext<'gc, '_>, value: Avm2Value<'gc>) {
self.ibase_mut(mc).context_menu = value;
}
@ -150,6 +150,48 @@ pub trait TInteractiveObject<'gc>:
_event: ClipEvent,
) -> ClipEventResult;
/// Convert the clip event into an AVM2 event and dispatch it into the
/// AVM2 side of this object.
///
/// This is only intended to be called for events defined by
/// `InteractiveObject` itself. Display object impls that have their own
/// event types should dispatch them in `event_dispatch`.
fn event_dispatch_to_avm2(self, context: &mut UpdateContext<'_, 'gc, '_>, event: ClipEvent) {
let target = if let Avm2Value::Object(target) = self.as_displayobject().object2() {
target
} else {
return;
};
match event {
ClipEvent::MouseDown => {
let mut avm2_event = Avm2Event::new(
"mouseDown",
Avm2EventData::mouse_event(context, self.as_displayobject(), None, 0),
);
avm2_event.set_bubbles(true);
if let Err(e) = Avm2::dispatch_event(context, avm2_event, target) {
log::error!("Got error when dispatching {:?} to AVM2: {}", event, e);
}
}
ClipEvent::MouseUp => {
let mut avm2_event = Avm2Event::new(
"mouseUp",
Avm2EventData::mouse_event(context, self.as_displayobject(), None, 0),
);
avm2_event.set_bubbles(true);
if let Err(e) = Avm2::dispatch_event(context, avm2_event, target) {
log::error!("Got error when dispatching {:?} to AVM2: {}", event, e);
}
}
_ => {}
};
}
/// Executes and propagates the given clip event.
/// Events execute inside-out; the deepest child will react first, followed
/// by its parent, and so forth.

View File

@ -2179,6 +2179,8 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
}
}
}
} else {
self.event_dispatch_to_avm2(context, event);
}
handled

View File

@ -720,6 +720,8 @@ impl<'gc> TInteractiveObject<'gc> for Stage<'gc> {
_context: &mut UpdateContext<'_, 'gc, '_>,
_event: ClipEvent,
) -> ClipEventResult {
//NOTE: Stage does not appear to fire common InteractiveObject events
//within AVM2.
ClipEventResult::Handled
}
}