core: Move `ClipAction` into crate::events
This commit is contained in:
parent
1fe170400c
commit
eb3aa1c878
|
@ -657,7 +657,17 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug {
|
||||||
}
|
}
|
||||||
// Clip events only apply to movie clips.
|
// Clip events only apply to movie clips.
|
||||||
if let Some(clip) = self.as_movie_clip() {
|
if let Some(clip) = self.as_movie_clip() {
|
||||||
clip.set_clip_actions(gc_context, &place_object.clip_actions[..]);
|
// Convert from `swf::ClipAction` to Ruffle's `ClipAction`.
|
||||||
|
use crate::display_object::movie_clip::ClipAction;
|
||||||
|
clip.set_clip_actions(
|
||||||
|
gc_context,
|
||||||
|
place_object
|
||||||
|
.clip_actions
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(ClipAction::from)
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// TODO: Others will go here eventually.
|
// TODO: Others will go here eventually.
|
||||||
}
|
}
|
||||||
|
@ -677,7 +687,7 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug {
|
||||||
}
|
}
|
||||||
// onEnterFrame actions only apply to movie clips.
|
// onEnterFrame actions only apply to movie clips.
|
||||||
if let (Some(me), Some(other)) = (self.as_movie_clip(), other.as_movie_clip()) {
|
if let (Some(me), Some(other)) = (self.as_movie_clip(), other.as_movie_clip()) {
|
||||||
me.set_clip_actions(gc_context, &*other.clip_actions());
|
me.set_clip_actions(gc_context, other.clip_actions().iter().cloned().collect());
|
||||||
}
|
}
|
||||||
// TODO: More in here eventually.
|
// TODO: More in here eventually.
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,16 @@ use crate::context::{ActionType, RenderContext, UpdateContext};
|
||||||
use crate::display_object::{
|
use crate::display_object::{
|
||||||
Bitmap, Button, DisplayObjectBase, EditText, Graphic, MorphShapeStatic, TDisplayObject, Text,
|
Bitmap, Button, DisplayObjectBase, EditText, Graphic, MorphShapeStatic, TDisplayObject, Text,
|
||||||
};
|
};
|
||||||
|
use crate::events::ClipEvent;
|
||||||
use crate::font::Font;
|
use crate::font::Font;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::tag_utils::{self, DecodeResult, SwfStream};
|
use crate::tag_utils::{self, DecodeResult, SwfSlice, SwfStream};
|
||||||
use enumset::{EnumSet, EnumSetType};
|
use enumset::{EnumSet, EnumSetType};
|
||||||
use gc_arena::{Collect, Gc, GcCell, MutationContext};
|
use gc_arena::{Collect, Gc, GcCell, MutationContext};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use std::cell::Ref;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use swf::{read::SwfRead, ClipAction, ClipEventFlag};
|
use swf::read::SwfRead;
|
||||||
|
|
||||||
type Depth = i16;
|
type Depth = i16;
|
||||||
type FrameNumber = u16;
|
type FrameNumber = u16;
|
||||||
|
@ -166,14 +168,18 @@ impl<'gc> MovieClip<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the clip events for this movieclip.
|
/// Gets the clip events for this movieclip.
|
||||||
pub fn clip_actions(&self) -> std::cell::Ref<[ClipAction]> {
|
pub fn clip_actions(&self) -> Ref<[ClipAction]> {
|
||||||
std::cell::Ref::map(self.0.read(), |mc| mc.clip_actions())
|
Ref::map(self.0.read(), |mc| mc.clip_actions())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the clip actions (a.k.a. clip events) for this movieclip.
|
/// Sets the clip actions (a.k.a. clip events) for this movieclip.
|
||||||
/// Clip actions are created in the Flash IDE by using the `onEnterFrame`
|
/// Clip actions are created in the Flash IDE by using the `onEnterFrame`
|
||||||
/// tag on a movieclip instance.
|
/// tag on a movieclip instance.
|
||||||
pub fn set_clip_actions(&self, gc_context: MutationContext<'gc, '_>, actions: &[ClipAction]) {
|
pub fn set_clip_actions(
|
||||||
|
self,
|
||||||
|
gc_context: MutationContext<'gc, '_>,
|
||||||
|
actions: SmallVec<[ClipAction; 2]>,
|
||||||
|
) {
|
||||||
self.0.write(gc_context).set_clip_actions(actions);
|
self.0.write(gc_context).set_clip_actions(actions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,9 +252,11 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unload(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
fn unload(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||||
self.0
|
self.0.write(context.gc_context).run_clip_action(
|
||||||
.write(context.gc_context)
|
(*self).into(),
|
||||||
.run_clip_action(context, ClipEventFlag::Unload, None);
|
context,
|
||||||
|
ClipEvent::Unload,
|
||||||
|
);
|
||||||
self.set_removed(context.gc_context, true);
|
self.set_removed(context.gc_context, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,10 +387,10 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
|
|
||||||
// Run my load/enterFrame clip event.
|
// Run my load/enterFrame clip event.
|
||||||
if !self.initialized() {
|
if !self.initialized() {
|
||||||
self.run_clip_action(context, ClipEventFlag::Load, None);
|
self.run_clip_action(self_display_object, context, ClipEvent::Load);
|
||||||
self.set_initialized(true);
|
self.set_initialized(true);
|
||||||
} else {
|
} else {
|
||||||
self.run_clip_action(context, ClipEventFlag::EnterFrame, None);
|
self.run_clip_action(self_display_object, context, ClipEvent::EnterFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _tag_pos = self.tag_stream_pos;
|
let _tag_pos = self.tag_stream_pos;
|
||||||
|
@ -709,37 +717,34 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
/// Run all actions for the given clip event.
|
/// Run all actions for the given clip event.
|
||||||
fn run_clip_action(
|
fn run_clip_action(
|
||||||
&self,
|
&self,
|
||||||
|
self_display_object: DisplayObject<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
event: ClipEventFlag,
|
event: ClipEvent,
|
||||||
key_code: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
for clip_action in self
|
for clip_action in self
|
||||||
.clip_actions
|
.clip_actions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|action| action.events.contains(event) && action.key_code == key_code)
|
.filter(|action| action.events.contains(&event))
|
||||||
{
|
{
|
||||||
let slice = crate::tag_utils::SwfSlice {
|
let action_type = if event == ClipEvent::Unload {
|
||||||
data: std::sync::Arc::new(clip_action.action_data.clone()),
|
|
||||||
start: 0,
|
|
||||||
end: clip_action.action_data.len(),
|
|
||||||
};
|
|
||||||
let action_type = if event == ClipEventFlag::Unload {
|
|
||||||
ActionType::Unload
|
ActionType::Unload
|
||||||
} else {
|
} else {
|
||||||
ActionType::Normal
|
ActionType::Normal
|
||||||
};
|
};
|
||||||
context
|
context.action_queue.queue_actions(
|
||||||
.action_queue
|
self_display_object,
|
||||||
.queue_actions(context.active_clip, slice, action_type);
|
clip_action.action_data.clone(),
|
||||||
|
action_type,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clip_actions(&self) -> &[ClipAction] {
|
pub fn clip_actions(&self) -> &[ClipAction] {
|
||||||
&self.clip_actions[..]
|
&self.clip_actions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clip_actions(&mut self, actions: &[ClipAction]) {
|
pub fn set_clip_actions(&mut self, actions: SmallVec<[ClipAction; 2]>) {
|
||||||
self.clip_actions = actions.iter().cloned().collect();
|
self.clip_actions = actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialized(&self) -> bool {
|
fn initialized(&self) -> bool {
|
||||||
|
@ -1369,7 +1374,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
// so make sure to get the proper offsets. This feels kind of bad.
|
// so make sure to get the proper offsets. This feels kind of bad.
|
||||||
let start = (self.tag_stream_start() + reader.get_ref().position()) as usize;
|
let start = (self.tag_stream_start() + reader.get_ref().position()) as usize;
|
||||||
let end = start + tag_len;
|
let end = start + tag_len;
|
||||||
let slice = crate::tag_utils::SwfSlice {
|
let slice = SwfSlice {
|
||||||
data: std::sync::Arc::clone(context.swf_data),
|
data: std::sync::Arc::clone(context.swf_data),
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
|
@ -1399,7 +1404,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
// so make sure to get the proper offsets. This feels kind of bad.
|
// so make sure to get the proper offsets. This feels kind of bad.
|
||||||
let start = (self.tag_stream_start() + reader.get_ref().position()) as usize;
|
let start = (self.tag_stream_start() + reader.get_ref().position()) as usize;
|
||||||
let end = start + tag_len;
|
let end = start + tag_len;
|
||||||
let slice = crate::tag_utils::SwfSlice {
|
let slice = SwfSlice {
|
||||||
data: std::sync::Arc::clone(context.swf_data),
|
data: std::sync::Arc::clone(context.swf_data),
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
|
@ -1494,7 +1499,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
if let (Some(stream_info), None) = (&self.static_data.audio_stream_info, self.audio_stream)
|
if let (Some(stream_info), None) = (&self.static_data.audio_stream_info, self.audio_stream)
|
||||||
{
|
{
|
||||||
let pos = self.tag_stream_start() + self.tag_stream_pos;
|
let pos = self.tag_stream_start() + self.tag_stream_pos;
|
||||||
let slice = crate::tag_utils::SwfSlice {
|
let slice = SwfSlice {
|
||||||
data: std::sync::Arc::clone(context.swf_data),
|
data: std::sync::Arc::clone(context.swf_data),
|
||||||
start: pos as usize,
|
start: pos as usize,
|
||||||
end: self.tag_stream_start() as usize + self.tag_stream_len(),
|
end: self.tag_stream_start() as usize + self.tag_stream_len(),
|
||||||
|
@ -1646,3 +1651,54 @@ enum MovieClipFlags {
|
||||||
/// Whether this `MovieClip` is playing or stopped.
|
/// Whether this `MovieClip` is playing or stopped.
|
||||||
Playing,
|
Playing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Actions that are attached to a `MovieClip` event in
|
||||||
|
/// an `onClipEvent`/`on` handler.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ClipAction {
|
||||||
|
/// The events that trigger this handler.
|
||||||
|
events: SmallVec<[ClipEvent; 1]>,
|
||||||
|
|
||||||
|
/// The actions to run.
|
||||||
|
action_data: SwfSlice,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<swf::ClipAction> for ClipAction {
|
||||||
|
fn from(other: swf::ClipAction) -> Self {
|
||||||
|
use swf::ClipEventFlag;
|
||||||
|
Self {
|
||||||
|
events: other
|
||||||
|
.events
|
||||||
|
.into_iter()
|
||||||
|
.map(|event| match event {
|
||||||
|
ClipEventFlag::Construct => ClipEvent::Construct,
|
||||||
|
ClipEventFlag::Data => ClipEvent::Data,
|
||||||
|
ClipEventFlag::DragOut => ClipEvent::DragOut,
|
||||||
|
ClipEventFlag::DragOver => ClipEvent::DragOver,
|
||||||
|
ClipEventFlag::EnterFrame => ClipEvent::EnterFrame,
|
||||||
|
ClipEventFlag::Initialize => ClipEvent::Initialize,
|
||||||
|
ClipEventFlag::KeyUp => ClipEvent::KeyUp,
|
||||||
|
ClipEventFlag::KeyDown => ClipEvent::KeyDown,
|
||||||
|
ClipEventFlag::KeyPress => ClipEvent::KeyPress {
|
||||||
|
key_code: other.key_code.unwrap_or(0),
|
||||||
|
},
|
||||||
|
ClipEventFlag::Load => ClipEvent::Load,
|
||||||
|
ClipEventFlag::MouseUp => ClipEvent::MouseUp,
|
||||||
|
ClipEventFlag::MouseDown => ClipEvent::MouseDown,
|
||||||
|
ClipEventFlag::MouseMove => ClipEvent::MouseMove,
|
||||||
|
ClipEventFlag::Press => ClipEvent::Press,
|
||||||
|
ClipEventFlag::RollOut => ClipEvent::RollOut,
|
||||||
|
ClipEventFlag::RollOver => ClipEvent::RollOver,
|
||||||
|
ClipEventFlag::Release => ClipEvent::Release,
|
||||||
|
ClipEventFlag::ReleaseOutside => ClipEvent::ReleaseOutside,
|
||||||
|
ClipEventFlag::Unload => ClipEvent::Unload,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
action_data: SwfSlice {
|
||||||
|
data: std::sync::Arc::new(other.action_data.clone()),
|
||||||
|
start: 0,
|
||||||
|
end: other.action_data.len(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,32 @@ pub enum ButtonEvent {
|
||||||
KeyPress(KeyCode),
|
KeyPress(KeyCode),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An event type that can be handled by a movie clip
|
||||||
|
/// instance.
|
||||||
|
/// TODO: Move this representation in the swf crate?
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum ClipEvent {
|
||||||
|
Construct,
|
||||||
|
Data,
|
||||||
|
DragOut,
|
||||||
|
DragOver,
|
||||||
|
EnterFrame,
|
||||||
|
Initialize,
|
||||||
|
KeyUp,
|
||||||
|
KeyDown,
|
||||||
|
KeyPress { key_code: KeyCode },
|
||||||
|
Load,
|
||||||
|
MouseUp,
|
||||||
|
MouseDown,
|
||||||
|
MouseMove,
|
||||||
|
Press,
|
||||||
|
RollOut,
|
||||||
|
RollOver,
|
||||||
|
Release,
|
||||||
|
ReleaseOutside,
|
||||||
|
Unload,
|
||||||
|
}
|
||||||
|
|
||||||
/// Flash virtual keycode.
|
/// Flash virtual keycode.
|
||||||
/// TODO: This will eventually move to a separate module.
|
/// TODO: This will eventually move to a separate module.
|
||||||
pub type KeyCode = u8;
|
pub type KeyCode = swf::KeyCode;
|
||||||
|
|
Loading…
Reference in New Issue