core: Re-enable AVM1
This commit is contained in:
parent
5bba546a53
commit
ce606cece8
213
core/src/avm1.rs
213
core/src/avm1.rs
|
@ -4,7 +4,8 @@ use std::collections::HashMap;
|
|||
use std::io::Cursor;
|
||||
use swf::avm1::read::Reader;
|
||||
|
||||
pub struct ActionContext<'a, 'gc> {
|
||||
pub struct ActionContext<'a, 'gc, 'gc_context> {
|
||||
pub gc_context: gc_arena::MutationContext<'gc, 'gc_context>,
|
||||
pub global_time: u64,
|
||||
pub root: DisplayNode<'gc>,
|
||||
pub start_clip: DisplayNode<'gc>,
|
||||
|
@ -147,7 +148,7 @@ impl Avm1 {
|
|||
num_actions_to_skip,
|
||||
} => self.action_wait_for_frame_2(context, num_actions_to_skip, &mut reader)?,
|
||||
Action::With { .. } => self.action_with(context)?,
|
||||
_ => self.unknown_op(context)?,
|
||||
_ => self.unknown_op(context, action)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,32 +156,31 @@ impl Avm1 {
|
|||
}
|
||||
|
||||
pub fn resolve_slash_path<'gc>(
|
||||
_start: DisplayNode<'gc>,
|
||||
_root: DisplayNode<'gc>,
|
||||
_path: &str,
|
||||
start: DisplayNode<'gc>,
|
||||
root: DisplayNode<'gc>,
|
||||
mut path: &str,
|
||||
) -> Option<DisplayNode<'gc>> {
|
||||
// let mut cur_clip = if path.bytes().nth(0).unwrap_or(0) == b'/' {
|
||||
// path = &path[1..];
|
||||
// root.clone()
|
||||
// } else {
|
||||
// start.clone()
|
||||
// };
|
||||
// if !path.is_empty() {
|
||||
// for name in path.split('/') {
|
||||
// let next_clip = if let Some(clip) = cur_clip.borrow().as_movie_clip() {
|
||||
// if let Some(child) = clip.get_child_by_name(name) {
|
||||
// child.clone()
|
||||
// } else {
|
||||
// return None;
|
||||
// }
|
||||
// } else {
|
||||
// return None;
|
||||
// };
|
||||
// cur_clip = next_clip;
|
||||
// }
|
||||
// }
|
||||
// Some(cur_clip)
|
||||
None
|
||||
let mut cur_clip = if path.bytes().nth(0).unwrap_or(0) == b'/' {
|
||||
path = &path[1..];
|
||||
root
|
||||
} else {
|
||||
start
|
||||
};
|
||||
if !path.is_empty() {
|
||||
for name in path.split('/') {
|
||||
let next_clip = if let Some(clip) = cur_clip.read().as_movie_clip() {
|
||||
if let Some(child) = clip.get_child_by_name(name) {
|
||||
*child
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
cur_clip = next_clip;
|
||||
}
|
||||
}
|
||||
Some(cur_clip)
|
||||
}
|
||||
|
||||
fn push(&mut self, value: impl Into<Value>) {
|
||||
|
@ -191,7 +191,12 @@ impl Avm1 {
|
|||
self.stack.pop().ok_or_else(|| "Stack underflow".into())
|
||||
}
|
||||
|
||||
fn unknown_op(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||
fn unknown_op(
|
||||
&mut self,
|
||||
_context: &mut ActionContext,
|
||||
action: swf::avm1::types::Action,
|
||||
) -> Result<(), Error> {
|
||||
log::error!("Unknown AVM1 opcode: {:?}", action);
|
||||
Err("Unknown op".into())
|
||||
}
|
||||
|
||||
|
@ -439,30 +444,30 @@ impl Avm1 {
|
|||
unimplemented!();
|
||||
}
|
||||
|
||||
fn action_get_property(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||
// let prop_index = self.pop()?.as_u32()? as usize;
|
||||
// let clip_path = self.pop()?.as_string()?;
|
||||
// let ret = if let Some(clip) =
|
||||
// Avm1::resolve_slash_path(&context.active_clip, &context.root, &clip_path)
|
||||
// {
|
||||
// if let Some(clip) = clip.borrow().as_movie_clip() {
|
||||
// match prop_index {
|
||||
// 0 => Value::Number(f64::from(clip.x())),
|
||||
// 1 => Value::Number(f64::from(clip.y())),
|
||||
// 2 => Value::Number(f64::from(clip.x_scale())),
|
||||
// 3 => Value::Number(f64::from(clip.y_scale())),
|
||||
// 4 => Value::Number(f64::from(clip.current_frame())),
|
||||
// 5 => Value::Number(f64::from(clip.total_frames())),
|
||||
// 12 => Value::Number(f64::from(clip.frames_loaded())),
|
||||
// _ => unimplemented!(),
|
||||
// }
|
||||
// } else {
|
||||
// Value::Undefined
|
||||
// }
|
||||
// } else {
|
||||
// Value::Undefined
|
||||
// };
|
||||
// self.push(ret);
|
||||
fn action_get_property(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||
let prop_index = self.pop()?.as_u32()? as usize;
|
||||
let clip_path = self.pop()?;
|
||||
let ret = if let Some(clip) =
|
||||
Avm1::resolve_slash_path(context.active_clip, context.root, clip_path.as_string()?)
|
||||
{
|
||||
if let Some(clip) = clip.read().as_movie_clip() {
|
||||
match prop_index {
|
||||
0 => Value::Number(f64::from(clip.x())),
|
||||
1 => Value::Number(f64::from(clip.y())),
|
||||
2 => Value::Number(f64::from(clip.x_scale())),
|
||||
3 => Value::Number(f64::from(clip.y_scale())),
|
||||
4 => Value::Number(f64::from(clip.current_frame())),
|
||||
5 => Value::Number(f64::from(clip.total_frames())),
|
||||
12 => Value::Number(f64::from(clip.frames_loaded())),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
} else {
|
||||
Value::Undefined
|
||||
}
|
||||
} else {
|
||||
Value::Undefined
|
||||
};
|
||||
self.push(ret);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -496,43 +501,39 @@ impl Avm1 {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn action_goto_frame(
|
||||
&mut self,
|
||||
_context: &mut ActionContext,
|
||||
_frame: u16,
|
||||
) -> Result<(), Error> {
|
||||
// let mut display_object = context.active_clip.borrow_mut();
|
||||
// let mut clip = display_object.as_movie_clip_mut().unwrap();
|
||||
// if clip.playing() {
|
||||
// clip.goto_frame(frame + 1, false);
|
||||
// } else {
|
||||
// clip.goto_frame(frame + 1, true);
|
||||
// }
|
||||
fn action_goto_frame(&mut self, context: &mut ActionContext, frame: u16) -> Result<(), Error> {
|
||||
let mut display_object = context.active_clip.write(context.gc_context);
|
||||
let clip = display_object.as_movie_clip_mut().unwrap();
|
||||
if clip.playing() {
|
||||
clip.goto_frame(frame + 1, false);
|
||||
} else {
|
||||
clip.goto_frame(frame + 1, true);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_goto_frame_2(
|
||||
&mut self,
|
||||
_context: &mut ActionContext,
|
||||
_set_playing: bool,
|
||||
_scene_offset: u16,
|
||||
context: &mut ActionContext,
|
||||
set_playing: bool,
|
||||
scene_offset: u16,
|
||||
) -> Result<(), Error> {
|
||||
// Version 4+ gotoAndPlay/gotoAndStop
|
||||
// Param can either be a frame number or a frame label.
|
||||
// TODO(Herschel): Slash notation
|
||||
// let mut display_object = context.active_clip.borrow_mut();
|
||||
// let mut clip = display_object.as_movie_clip_mut().unwrap();
|
||||
// match self.pop()? {
|
||||
// Value::Number(frame) => {
|
||||
// clip.goto_frame(scene_offset + (frame as u16) + 1, !set_playing)
|
||||
// }
|
||||
// Value::String(frame_label) => {
|
||||
// //if let Some(frame) = clip.frame_label_to_number(&frame_label, context) {
|
||||
// // clip.goto_frame(scene_offset + frame, !set_playing)
|
||||
// //}
|
||||
// }
|
||||
// _ => return Err("Expected frame number or label".into()),
|
||||
// }
|
||||
let mut display_object = context.active_clip.write(context.gc_context);
|
||||
let clip = display_object.as_movie_clip_mut().unwrap();
|
||||
match self.pop()? {
|
||||
Value::Number(frame) => {
|
||||
clip.goto_frame(scene_offset + (frame as u16) + 1, !set_playing)
|
||||
}
|
||||
Value::String(_frame_label) => {
|
||||
unimplemented!()
|
||||
//if let Some(frame) = clip.frame_label_to_number(&frame_label, context) {
|
||||
// clip.goto_frame(scene_offset + frame, !set_playing)
|
||||
//}
|
||||
}
|
||||
_ => return Err("Expected frame number or label".into()),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -686,10 +687,10 @@ impl Avm1 {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn action_next_frame(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||
// let mut display_object = context.active_clip.borrow_mut();
|
||||
// let mut clip = display_object.as_movie_clip_mut().unwrap();
|
||||
// clip.next_frame();
|
||||
fn action_next_frame(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||
let mut display_object = context.active_clip.write(context.gc_context);
|
||||
let clip = display_object.as_movie_clip_mut().unwrap();
|
||||
clip.next_frame();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -722,17 +723,17 @@ impl Avm1 {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn play(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||
// let mut display_object = context.active_clip.borrow_mut();
|
||||
// let mut clip = display_object.as_movie_clip_mut().unwrap();
|
||||
// clip.play();
|
||||
fn play(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||
let mut display_object = context.active_clip.write(context.gc_context);
|
||||
let clip = display_object.as_movie_clip_mut().unwrap();
|
||||
clip.play();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prev_frame(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||
// let mut display_object = context.active_clip.borrow_mut();
|
||||
// let mut clip = display_object.as_movie_clip_mut().unwrap();
|
||||
// clip.prev_frame();
|
||||
fn prev_frame(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||
let mut display_object = context.active_clip.write(context.gc_context);
|
||||
let clip = display_object.as_movie_clip_mut().unwrap();
|
||||
clip.prev_frame();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -799,18 +800,16 @@ impl Avm1 {
|
|||
|
||||
fn action_set_target(
|
||||
&mut self,
|
||||
_context: &mut ActionContext,
|
||||
context: &mut ActionContext,
|
||||
target: &str,
|
||||
) -> Result<(), Error> {
|
||||
log::info!("SetTarget: {}", target);
|
||||
// if target.is_empty() {
|
||||
// context.active_clip = context.start_clip.clone();
|
||||
// } else {
|
||||
// if let Some(clip) = Avm1::resolve_slash_path(&context.start_clip, &context.root, target)
|
||||
// {
|
||||
// context.active_clip = clip;
|
||||
// }
|
||||
// }
|
||||
if target.is_empty() {
|
||||
context.active_clip = context.start_clip.clone();
|
||||
} else {
|
||||
if let Some(clip) = Avm1::resolve_slash_path(context.start_clip, context.root, target) {
|
||||
context.active_clip = clip;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -827,10 +826,10 @@ impl Avm1 {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn action_stop(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||
// let mut display_object = context.active_clip.borrow_mut();
|
||||
// let mut clip = display_object.as_movie_clip_mut().unwrap();
|
||||
// clip.stop();
|
||||
fn action_stop(&mut self, context: &mut ActionContext) -> Result<(), Error> {
|
||||
let mut display_object = context.active_clip.write(context.gc_context);
|
||||
let clip = display_object.as_movie_clip_mut().unwrap();
|
||||
clip.stop();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@ impl BoundingBox {
|
|||
|
||||
x_min <= x_max && y_min <= y_max
|
||||
}
|
||||
|
||||
pub fn contains(&self, (x, y): (Twips, Twips)) -> bool {
|
||||
self.valid && x >= self.x_min && x <= self.x_max && y >= self.y_min && y <= self.y_max
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BoundingBox {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::display_object::{DisplayObject, DisplayObjectBase};
|
||||
use crate::event::PlayerEvent;
|
||||
use crate::player::{RenderContext, UpdateContext};
|
||||
use crate::prelude::*;
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -65,7 +66,10 @@ impl<'gc> Button<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
fn children_in_state(&self, state: ButtonState) -> impl Iterator<Item = &DisplayNode<'gc>> {
|
||||
fn children_in_state(
|
||||
&self,
|
||||
state: ButtonState,
|
||||
) -> impl std::iter::DoubleEndedIterator<Item = &DisplayNode<'gc>> {
|
||||
let i = match state {
|
||||
ButtonState::Up => 0,
|
||||
ButtonState::Over => 1,
|
||||
|
@ -77,7 +81,7 @@ impl<'gc> Button<'gc> {
|
|||
fn children_in_state_mut(
|
||||
&mut self,
|
||||
state: ButtonState,
|
||||
) -> impl Iterator<Item = &mut DisplayNode<'gc>> {
|
||||
) -> impl std::iter::DoubleEndedIterator<Item = &mut DisplayNode<'gc>> {
|
||||
let i = match state {
|
||||
ButtonState::Up => 0,
|
||||
ButtonState::Over => 1,
|
||||
|
@ -91,33 +95,18 @@ impl<'gc> DisplayObject<'gc> for Button<'gc> {
|
|||
impl_display_object!(base);
|
||||
|
||||
fn run_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
if self.state == ButtonState::Down {
|
||||
// let mut action_context = crate::avm1::ActionContext {
|
||||
// global_time: context.global_time,
|
||||
// active_clip: &mut crate::movie_clip::MovieClip::new(),
|
||||
// audio: context.audio,
|
||||
// };
|
||||
// context
|
||||
// .avm1
|
||||
// .do_action(&mut action_context, &self.release_actions[..]);
|
||||
self.state = ButtonState::Up;
|
||||
} else if self.state == ButtonState::Up {
|
||||
let dx = self.matrix().tx - context.mouse_pos.0;
|
||||
let dy = self.matrix().ty - context.mouse_pos.1;
|
||||
let len = f32::sqrt(dx * dx + dy * dy);
|
||||
self.state = if len > 20.0 {
|
||||
ButtonState::Up
|
||||
} else {
|
||||
ButtonState::Over
|
||||
};
|
||||
}
|
||||
for child in self.children_in_state_mut(self.state) {
|
||||
child
|
||||
.write(context.gc_context)
|
||||
.set_parent(Some(context.active_clip));
|
||||
context.active_clip = *child;
|
||||
child.write(context.gc_context).run_frame(context);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_post_frame(&mut self, context: &mut UpdateContext<'_, 'gc, '_>) {
|
||||
for child in self.children_in_state_mut(self.state) {
|
||||
context.active_clip = *child;
|
||||
child.write(context.gc_context).run_post_frame(context);
|
||||
}
|
||||
}
|
||||
|
@ -131,9 +120,33 @@ impl<'gc> DisplayObject<'gc> for Button<'gc> {
|
|||
context.transform_stack.pop();
|
||||
}
|
||||
|
||||
fn handle_click(&mut self, _pos: (f32, f32)) {
|
||||
if self.state == ButtonState::Over {
|
||||
self.state = ButtonState::Down;
|
||||
fn hit_test(&self, point: (Twips, Twips)) -> bool {
|
||||
//if self.world_bounds().contains(point) {
|
||||
for child in self.children_in_state(self.state).rev() {
|
||||
if child.read().hit_test(point) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
context: &mut crate::player::UpdateContext<'_, 'gc, '_>,
|
||||
event: PlayerEvent,
|
||||
) {
|
||||
match event {
|
||||
PlayerEvent::RollOver => self.state = ButtonState::Over,
|
||||
PlayerEvent::Click => {
|
||||
let slice = crate::tag_utils::SwfSlice {
|
||||
data: std::sync::Arc::new(self.release_actions.clone()),
|
||||
start: 0,
|
||||
end: self.release_actions.len(),
|
||||
};
|
||||
context.actions.push((self.parent().unwrap(), slice));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,21 @@ pub trait DisplayObject<'gc>: 'gc + Collect {
|
|||
None
|
||||
}
|
||||
fn box_clone(&self) -> Box<dyn DisplayObject<'gc>>;
|
||||
|
||||
fn pick(&self, _: (Twips, Twips)) -> Option<DisplayNode<'gc>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn hit_test(&self, _: (Twips, Twips)) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
_context: &mut crate::player::UpdateContext<'_, 'gc, '_>,
|
||||
_event: crate::event::PlayerEvent,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Clone for Box<dyn DisplayObject<'gc>> {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
use swf::Twips;
|
||||
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
MouseMove { x: Twips, y: Twips },
|
||||
MouseUp { x: Twips, y: Twips },
|
||||
MouseDown { x: Twips, y: Twips },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PlayerEvent {
|
||||
RollOver,
|
||||
Click,
|
||||
}
|
|
@ -41,6 +41,10 @@ impl<'gc> DisplayObject<'gc> for Graphic<'gc> {
|
|||
bounds
|
||||
}
|
||||
|
||||
fn hit_test(&self, point: (Twips, Twips)) -> bool {
|
||||
self.world_bounds().contains(point)
|
||||
}
|
||||
|
||||
fn run_frame(&mut self, _context: &mut UpdateContext) {
|
||||
// Noop
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ mod bounding_box;
|
|||
mod button;
|
||||
mod character;
|
||||
mod color_transform;
|
||||
mod event;
|
||||
mod font;
|
||||
mod graphic;
|
||||
mod library;
|
||||
|
@ -21,5 +22,7 @@ mod transform;
|
|||
|
||||
pub mod backend;
|
||||
|
||||
pub use event::Event;
|
||||
pub use player::Player;
|
||||
pub use swf;pub use swf::Color;
|
||||
pub use swf;
|
||||
pub use swf::Color;
|
||||
|
|
|
@ -336,11 +336,30 @@ impl<'gc> DisplayObject<'gc> for MovieClip<'gc> {
|
|||
context.transform_stack.pop();
|
||||
}
|
||||
|
||||
fn handle_click(&mut self, _pos: (f32, f32)) {
|
||||
// for child in self.children.values_mut() {
|
||||
// child.handle_click(pos);
|
||||
// }
|
||||
fn pick(&self, point: (Twips, Twips)) -> Option<DisplayNode<'gc>> {
|
||||
//if self.world_bounds().contains(point) {
|
||||
for child in self.children.values().rev() {
|
||||
if child.read().hit_test(point) {
|
||||
return Some(*child);
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn hit_test(&self, point: (Twips, Twips)) -> bool {
|
||||
//if self.world_bounds().contains(point) {
|
||||
for child in self.children.values().rev() {
|
||||
if child.read().hit_test(point) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn as_movie_clip(&self) -> Option<&crate::movie_clip::MovieClip<'gc>> {
|
||||
Some(self)
|
||||
}
|
||||
|
@ -804,12 +823,16 @@ impl<'gc, 'a> MovieClip<'gc> {
|
|||
tag_len: usize,
|
||||
) -> DecodeResult {
|
||||
// Queue the actions.
|
||||
// TODO: The reader is actually reading the tag slice at this point (tag_stream.take()),
|
||||
// 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 end = start + tag_len;
|
||||
let slice = crate::tag_utils::SwfSlice {
|
||||
data: std::sync::Arc::clone(context.swf_data),
|
||||
start: reader.get_ref().position() as usize,
|
||||
end: reader.get_ref().position() as usize + tag_len,
|
||||
start,
|
||||
end,
|
||||
};
|
||||
context.actions.push(slice);
|
||||
context.actions.push((context.active_clip, slice));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -839,7 +862,9 @@ impl<'gc, 'a> MovieClip<'gc> {
|
|||
};
|
||||
|
||||
// TODO(Herschel): Behavior when depth is occupied? (I think it replaces)
|
||||
character.write(context.gc_context).set_parent(Some(context.active_clip));
|
||||
character
|
||||
.write(context.gc_context)
|
||||
.set_parent(Some(context.active_clip));
|
||||
self.children.insert(place_object.depth, character);
|
||||
self.children.get_mut(&place_object.depth).unwrap()
|
||||
}
|
||||
|
@ -860,7 +885,9 @@ impl<'gc, 'a> MovieClip<'gc> {
|
|||
return Ok(());
|
||||
};
|
||||
|
||||
character.write(context.gc_context).set_parent(Some(context.active_clip));
|
||||
character
|
||||
.write(context.gc_context)
|
||||
.set_parent(Some(context.active_clip));
|
||||
let prev_character = self.children.insert(place_object.depth, character);
|
||||
let character = self.children.get_mut(&place_object.depth).unwrap();
|
||||
if let Some(prev_character) = prev_character {
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::library::Library;
|
|||
use crate::movie_clip::MovieClip;
|
||||
use crate::prelude::*;
|
||||
use crate::transform::TransformStack;
|
||||
use crate::Event;
|
||||
use gc_arena::{make_arena, ArenaParameters, Collect, GcCell, MutationContext};
|
||||
use log::info;
|
||||
use std::sync::Arc;
|
||||
|
@ -37,8 +38,6 @@ pub struct Player<Audio: AudioBackend, Renderer: RenderBackend> {
|
|||
|
||||
movie_width: u32,
|
||||
movie_height: u32,
|
||||
|
||||
mouse_pos: (f32, f32),
|
||||
}
|
||||
|
||||
impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
||||
|
@ -91,8 +90,6 @@ impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
|||
|
||||
movie_width,
|
||||
movie_height,
|
||||
|
||||
mouse_pos: (0.0, 0.0),
|
||||
};
|
||||
|
||||
player.preload();
|
||||
|
@ -144,20 +141,78 @@ impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
|||
self.movie_height
|
||||
}
|
||||
|
||||
pub fn mouse_move(&mut self, pos: (f32, f32)) {
|
||||
self.mouse_pos = pos;
|
||||
}
|
||||
pub fn handle_event(&mut self, event: Event) {
|
||||
let (global_time, swf_data, swf_version, background_color, renderer, audio, avm) = (
|
||||
self.global_time,
|
||||
&mut self.swf_data,
|
||||
self.swf_version,
|
||||
&mut self.background_color,
|
||||
&mut self.renderer,
|
||||
&mut self.audio,
|
||||
&mut self.avm,
|
||||
);
|
||||
|
||||
pub fn mouse_down(&mut self) {}
|
||||
self.gc_arena.mutate(move |gc_context, gc_root| {
|
||||
let actions = {
|
||||
let mut update_context = UpdateContext {
|
||||
global_time,
|
||||
swf_data,
|
||||
swf_version,
|
||||
library: gc_root.library.write(gc_context),
|
||||
background_color,
|
||||
avm,
|
||||
renderer,
|
||||
audio,
|
||||
actions: vec![],
|
||||
gc_context,
|
||||
active_clip: gc_root.root,
|
||||
};
|
||||
|
||||
pub fn mouse_up(&mut self) {
|
||||
//self.stage.handle_click(self.mouse_pos);
|
||||
match event {
|
||||
Event::MouseMove { x, y } => {
|
||||
if let Some(node) = gc_root.root.read().pick((x, y)) {
|
||||
update_context.active_clip = node;
|
||||
node.write(gc_context).handle_event(
|
||||
&mut update_context,
|
||||
crate::event::PlayerEvent::RollOver,
|
||||
);
|
||||
};
|
||||
}
|
||||
Event::MouseDown { x, y } => {
|
||||
if let Some(node) = gc_root.root.read().pick((x, y)) {
|
||||
update_context.active_clip = node;
|
||||
node.write(gc_context).handle_event(
|
||||
&mut update_context,
|
||||
crate::event::PlayerEvent::Click,
|
||||
);
|
||||
};
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
update_context.actions
|
||||
};
|
||||
|
||||
if !actions.is_empty() {
|
||||
let mut action_context = crate::avm1::ActionContext {
|
||||
gc_context,
|
||||
global_time,
|
||||
root: gc_root.root,
|
||||
start_clip: gc_root.root,
|
||||
active_clip: gc_root.root,
|
||||
audio,
|
||||
};
|
||||
for (active_clip, action) in actions {
|
||||
action_context.start_clip = active_clip;
|
||||
action_context.active_clip = active_clip;
|
||||
let _ = avm.do_action(&mut action_context, action.as_ref());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn preload(&mut self) {
|
||||
let (global_time, mouse_pos, swf_data, swf_version, background_color, renderer, audio, avm) = (
|
||||
let (global_time, swf_data, swf_version, background_color, renderer, audio, avm) = (
|
||||
self.global_time,
|
||||
self.mouse_pos,
|
||||
&mut self.swf_data,
|
||||
self.swf_version,
|
||||
&mut self.background_color,
|
||||
|
@ -169,7 +224,6 @@ impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
|||
self.gc_arena.mutate(|gc_context, gc_root| {
|
||||
let mut update_context = UpdateContext {
|
||||
global_time,
|
||||
mouse_pos,
|
||||
swf_data,
|
||||
swf_version,
|
||||
library: gc_root.library.write(gc_context),
|
||||
|
@ -187,9 +241,8 @@ impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
|||
}
|
||||
|
||||
fn run_frame(&mut self) {
|
||||
let (global_time, mouse_pos, swf_data, swf_version, background_color, renderer, audio, avm) = (
|
||||
let (global_time, swf_data, swf_version, background_color, renderer, audio, avm) = (
|
||||
self.global_time,
|
||||
self.mouse_pos,
|
||||
&mut self.swf_data,
|
||||
self.swf_version,
|
||||
&mut self.background_color,
|
||||
|
@ -199,29 +252,63 @@ impl<Audio: AudioBackend, Renderer: RenderBackend> Player<Audio, Renderer> {
|
|||
);
|
||||
|
||||
self.gc_arena.mutate(|gc_context, gc_root| {
|
||||
let mut update_context = UpdateContext {
|
||||
global_time,
|
||||
mouse_pos,
|
||||
swf_data,
|
||||
swf_version,
|
||||
library: gc_root.library.write(gc_context),
|
||||
background_color,
|
||||
avm,
|
||||
renderer,
|
||||
audio,
|
||||
actions: vec![],
|
||||
gc_context,
|
||||
active_clip: gc_root.root,
|
||||
};
|
||||
let actions = {
|
||||
let mut update_context = UpdateContext {
|
||||
global_time,
|
||||
swf_data,
|
||||
swf_version,
|
||||
library: gc_root.library.write(gc_context),
|
||||
background_color,
|
||||
avm,
|
||||
renderer,
|
||||
audio,
|
||||
actions: vec![],
|
||||
gc_context,
|
||||
active_clip: gc_root.root,
|
||||
};
|
||||
|
||||
gc_root
|
||||
.root
|
||||
.write(gc_context)
|
||||
.run_frame(&mut update_context);
|
||||
gc_root
|
||||
.root
|
||||
.write(gc_context)
|
||||
.run_post_frame(&mut update_context)
|
||||
gc_root
|
||||
.root
|
||||
.write(gc_context)
|
||||
.run_frame(&mut update_context);
|
||||
update_context.actions
|
||||
};
|
||||
{
|
||||
let mut action_context = crate::avm1::ActionContext {
|
||||
gc_context,
|
||||
global_time,
|
||||
root: gc_root.root,
|
||||
start_clip: gc_root.root,
|
||||
active_clip: gc_root.root,
|
||||
audio,
|
||||
};
|
||||
for (active_clip, action) in actions {
|
||||
action_context.start_clip = active_clip;
|
||||
action_context.active_clip = active_clip;
|
||||
let _ = avm.do_action(&mut action_context, action.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut update_context = UpdateContext {
|
||||
global_time,
|
||||
swf_data,
|
||||
swf_version,
|
||||
library: gc_root.library.write(gc_context),
|
||||
background_color,
|
||||
avm,
|
||||
renderer,
|
||||
audio,
|
||||
actions: vec![],
|
||||
gc_context,
|
||||
active_clip: gc_root.root,
|
||||
};
|
||||
|
||||
gc_root
|
||||
.root
|
||||
.write(gc_context)
|
||||
.run_post_frame(&mut update_context)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -269,14 +356,13 @@ pub struct UpdateContext<'a, 'gc, 'gc_context> {
|
|||
pub swf_version: u8,
|
||||
pub swf_data: &'a Arc<Vec<u8>>,
|
||||
pub global_time: u64,
|
||||
pub mouse_pos: (f32, f32),
|
||||
pub library: std::cell::RefMut<'a, Library<'gc>>,
|
||||
pub gc_context: MutationContext<'gc, 'gc_context>,
|
||||
pub background_color: &'a mut Color,
|
||||
pub avm: &'a mut Avm1,
|
||||
pub renderer: &'a mut dyn RenderBackend,
|
||||
pub audio: &'a mut dyn AudioBackend,
|
||||
pub actions: Vec<crate::tag_utils::SwfSlice>,
|
||||
pub actions: Vec<(DisplayNode<'gc>, crate::tag_utils::SwfSlice)>,
|
||||
pub active_clip: DisplayNode<'gc>,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ mod render;
|
|||
use crate::render::GliumRenderBackend;
|
||||
use glutin::{
|
||||
dpi::{LogicalPosition, LogicalSize},
|
||||
ContextBuilder, ElementState, Event, EventsLoop, MouseButton, WindowBuilder, WindowEvent,
|
||||
ContextBuilder, ElementState, EventsLoop, MouseButton, WindowBuilder, WindowEvent,
|
||||
};
|
||||
use ruffle_core::{backend::render::RenderBackend, Player};
|
||||
use ruffle_core::{backend::render::RenderBackend, swf::Twips, Player};
|
||||
use std::path::PathBuf;
|
||||
use std::time::{Duration, Instant};
|
||||
use structopt::StructOpt;
|
||||
|
@ -64,7 +64,7 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
// Poll UI events
|
||||
let mut request_close = false;
|
||||
events_loop.poll_events(|event| {
|
||||
if let Event::WindowEvent { event, .. } = event {
|
||||
if let glutin::Event::WindowEvent { event, .. } = event {
|
||||
match event {
|
||||
WindowEvent::Resized(logical_size) => {
|
||||
let size = logical_size.to_physical(hidpi_factor);
|
||||
|
@ -75,18 +75,22 @@ fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
mouse_pos = position;
|
||||
player.mouse_move((position.x as f32, position.y as f32));
|
||||
let event = ruffle_core::Event::MouseMove {x: Twips::from_pixels(position.x), y: Twips::from_pixels(position.y)};
|
||||
player.handle_event(event)
|
||||
}
|
||||
WindowEvent::MouseInput {
|
||||
button: MouseButton::Left,
|
||||
state: ElementState::Pressed,
|
||||
..
|
||||
} => player.mouse_down(),
|
||||
} => {
|
||||
let event = ruffle_core::Event::MouseDown {x: Twips::from_pixels(mouse_pos.x), y: Twips::from_pixels(mouse_pos.y)};
|
||||
player.handle_event(event)
|
||||
}
|
||||
WindowEvent::MouseInput {
|
||||
button: MouseButton::Left,
|
||||
state: ElementState::Released,
|
||||
..
|
||||
} => player.mouse_up(),
|
||||
} => {}
|
||||
WindowEvent::CloseRequested => request_close = true,
|
||||
_ => (),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue