core: Re-enable AVM1

This commit is contained in:
Mike Welsh 2019-08-14 12:39:26 -07:00
parent 5bba546a53
commit ce606cece8
10 changed files with 357 additions and 187 deletions

View File

@ -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(())
}

View File

@ -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 {

View File

@ -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));
}
}
}
}

View File

@ -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>> {

15
core/src/event.rs Normal file
View File

@ -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,
}

View File

@ -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
}

View File

@ -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;

View File

@ -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 {

View File

@ -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>,
}

View File

@ -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,
_ => (),
}