From f3f4fa61793fac931410c0bd98b9f2d937d9548e Mon Sep 17 00:00:00 2001 From: Mike Welsh Date: Mon, 19 Aug 2019 18:17:29 -0700 Subject: [PATCH] web: Add mouse up/down/move handlers --- core/src/movie_clip.rs | 5 ++- web/Cargo.toml | 2 +- web/src/audio.rs | 9 ++++- web/src/lib.rs | 90 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/core/src/movie_clip.rs b/core/src/movie_clip.rs index d42fc5e7b..bfdb46aca 100644 --- a/core/src/movie_clip.rs +++ b/core/src/movie_clip.rs @@ -366,7 +366,7 @@ impl<'gc> DisplayObject<'gc> for MovieClip<'gc> { TagCode::SoundStreamHead2 => { self.preload_sound_stream_head(context, reader, &mut static_data, 2) } - TagCode::SoundStreamBlock => self.preload_sound_stream_block(context, reader, tag_len), + TagCode::SoundStreamBlock => self.preload_sound_stream_block(context, reader, &mut static_data, tag_len), _ => Ok(()), }; let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End); @@ -549,9 +549,10 @@ impl<'gc, 'a> MovieClip<'gc> { &mut self, context: &mut UpdateContext<'_, 'gc, '_>, reader: &mut SwfStream<&'a [u8]>, + static_data: &mut MovieClipStatic, tag_len: usize, ) -> DecodeResult { - if self.static_data.audio_stream_info.is_some() { + if static_data.audio_stream_info.is_some() { let pos = reader.get_ref().position() as usize; let data = reader.get_ref().get_ref(); let data = &data[pos..pos + tag_len]; diff --git a/web/Cargo.toml b/web/Cargo.toml index 8b9cfef06..3daddb779 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -39,7 +39,7 @@ version = "0.3.25" features = [ "AudioBuffer", "AudioBufferSourceNode", "AudioProcessingEvent", "AudioContext", "AudioDestinationNode", "AudioNode", "CanvasRenderingContext2d", "CssStyleDeclaration", "Document", "Element", "Event", "EventTarget", "HtmlCanvasElement", - "HtmlElement", "HtmlImageElement", "Node", "Performance", "ScriptProcessorNode", "Window"] + "HtmlElement", "HtmlImageElement", "MouseEvent", "Node", "Performance", "ScriptProcessorNode", "Window"] [dev-dependencies] wasm-bindgen-test = "0.2.48" diff --git a/web/src/audio.rs b/web/src/audio.rs index 937656464..3e5fbc5d7 100644 --- a/web/src/audio.rs +++ b/web/src/audio.rs @@ -366,8 +366,13 @@ impl AudioBackend for WebAudioBackend { _clip_data: ruffle_core::tag_utils::SwfSlice, _stream_info: &swf::SoundStreamHead, ) -> AudioStreamHandle { - let handle = *self.id_to_sound.get(&clip_id).unwrap(); - self.play_sound_internal(handle) + if let Some(&handle) = self.id_to_sound.get(&clip_id) { + self.play_sound_internal(handle) + } else { + log::error!("Missing stream for clip {}", clip_id); + // TODO: Return dummy sound. + panic!(); + } } fn is_loading_complete(&self) -> bool { diff --git a/web/src/lib.rs b/web/src/lib.rs index ce92a7d84..9ca5af4b0 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -5,9 +5,10 @@ mod render; use crate::{audio::WebAudioBackend, render::WebCanvasRenderBackend}; use generational_arena::{Arena, Index}; use js_sys::Uint8Array; +use ruffle_core::{swf::Twips, PlayerEvent}; use std::{cell::RefCell, error::Error, num::NonZeroI32}; use wasm_bindgen::{prelude::*, JsCast, JsValue}; -use web_sys::{Event, EventTarget, HtmlCanvasElement}; +use web_sys::{Event, EventTarget, HtmlCanvasElement, MouseEvent}; thread_local! { /// We store the actual instances of the ruffle core in a static pool. @@ -25,6 +26,9 @@ struct RuffleInstance { animation_handler_id: Option, // requestAnimationFrame id #[allow(dead_code)] click_callback: Option>, + mouse_move_callback: Option>, + mouse_down_callback: Option>, + mouse_up_callback: Option>, } /// An opaque handle to a `RuffleInstance` inside the pool. @@ -95,6 +99,9 @@ impl Ruffle { animation_handler: None, animation_handler_id: None, click_callback: None, + mouse_move_callback: None, + mouse_down_callback: None, + mouse_up_callback: None, timestamp, }; @@ -114,6 +121,84 @@ impl Ruffle { as Box)); } + // Create mouse move handler. + { + let mouse_move_callback = Closure::wrap(Box::new(move |js_event: MouseEvent| { + INSTANCES.with(move |instances| { + let mut instances = instances.borrow_mut(); + if let Some(instance) = instances.get_mut(index) { + let event = PlayerEvent::MouseMove { + x: Twips::from_pixels(js_event.client_x().into()), + y: Twips::from_pixels(js_event.client_y().into()), + }; + instance.core.handle_event(event); + } + }); + }) + as Box); + let canvas_events: &EventTarget = canvas.as_ref(); + canvas_events + .add_event_listener_with_callback( + "mousemove", + mouse_move_callback.as_ref().unchecked_ref(), + ) + .unwrap(); + let instance = instances.get_mut(index).unwrap(); + instance.mouse_move_callback = Some(mouse_move_callback); + } + + // Create mouse down handler. + { + let mouse_down_callback = Closure::wrap(Box::new(move |js_event: MouseEvent| { + INSTANCES.with(move |instances| { + let mut instances = instances.borrow_mut(); + if let Some(instance) = instances.get_mut(index) { + let event = PlayerEvent::MouseDown { + x: Twips::from_pixels(js_event.client_x().into()), + y: Twips::from_pixels(js_event.client_y().into()), + }; + instance.core.handle_event(event); + } + }); + }) + as Box); + let canvas_events: &EventTarget = canvas.as_ref(); + canvas_events + .add_event_listener_with_callback( + "mousedown", + mouse_down_callback.as_ref().unchecked_ref(), + ) + .unwrap(); + let instance = instances.get_mut(index).unwrap(); + instance.mouse_down_callback = Some(mouse_down_callback); + } + + // Create mouse up handler. + { + let mouse_up_callback = Closure::wrap(Box::new(move |js_event: MouseEvent| { + INSTANCES.with(move |instances| { + let mut instances = instances.borrow_mut(); + if let Some(instance) = instances.get_mut(index) { + let event = PlayerEvent::MouseUp { + x: Twips::from_pixels(js_event.client_x().into()), + y: Twips::from_pixels(js_event.client_y().into()), + }; + instance.core.handle_event(event); + } + }); + }) + as Box); + let canvas_events: &EventTarget = canvas.as_ref(); + canvas_events + .add_event_listener_with_callback( + "mouseup", + mouse_up_callback.as_ref().unchecked_ref(), + ) + .unwrap(); + let instance = instances.get_mut(index).unwrap(); + instance.mouse_up_callback = Some(mouse_up_callback); + } + // Create click event handler. { let click_callback = Closure::wrap(Box::new(move |_| { @@ -134,8 +219,7 @@ impl Ruffle { canvas.style().set_property("cursor", "pointer").unwrap(); let instance = instances.get_mut(index).unwrap(); instance.click_callback = Some(click_callback); - - // Do an initial render for the pause overlay. + // Do initial render to render "click-to-play". instance.core.render(); }