web: Add mouse up/down/move handlers

This commit is contained in:
Mike Welsh 2019-08-19 18:17:29 -07:00
parent 8be9b9089b
commit f3f4fa6179
4 changed files with 98 additions and 8 deletions

View File

@ -366,7 +366,7 @@ impl<'gc> DisplayObject<'gc> for MovieClip<'gc> {
TagCode::SoundStreamHead2 => { TagCode::SoundStreamHead2 => {
self.preload_sound_stream_head(context, reader, &mut static_data, 2) 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(()), _ => Ok(()),
}; };
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End); let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End);
@ -549,9 +549,10 @@ impl<'gc, 'a> MovieClip<'gc> {
&mut self, &mut self,
context: &mut UpdateContext<'_, 'gc, '_>, context: &mut UpdateContext<'_, 'gc, '_>,
reader: &mut SwfStream<&'a [u8]>, reader: &mut SwfStream<&'a [u8]>,
static_data: &mut MovieClipStatic,
tag_len: usize, tag_len: usize,
) -> DecodeResult { ) -> 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 pos = reader.get_ref().position() as usize;
let data = reader.get_ref().get_ref(); let data = reader.get_ref().get_ref();
let data = &data[pos..pos + tag_len]; let data = &data[pos..pos + tag_len];

View File

@ -39,7 +39,7 @@ version = "0.3.25"
features = [ features = [
"AudioBuffer", "AudioBufferSourceNode", "AudioProcessingEvent", "AudioContext", "AudioDestinationNode", "AudioNode", "AudioBuffer", "AudioBufferSourceNode", "AudioProcessingEvent", "AudioContext", "AudioDestinationNode", "AudioNode",
"CanvasRenderingContext2d", "CssStyleDeclaration", "Document", "Element", "Event", "EventTarget", "HtmlCanvasElement", "CanvasRenderingContext2d", "CssStyleDeclaration", "Document", "Element", "Event", "EventTarget", "HtmlCanvasElement",
"HtmlElement", "HtmlImageElement", "Node", "Performance", "ScriptProcessorNode", "Window"] "HtmlElement", "HtmlImageElement", "MouseEvent", "Node", "Performance", "ScriptProcessorNode", "Window"]
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "0.2.48" wasm-bindgen-test = "0.2.48"

View File

@ -366,8 +366,13 @@ impl AudioBackend for WebAudioBackend {
_clip_data: ruffle_core::tag_utils::SwfSlice, _clip_data: ruffle_core::tag_utils::SwfSlice,
_stream_info: &swf::SoundStreamHead, _stream_info: &swf::SoundStreamHead,
) -> AudioStreamHandle { ) -> AudioStreamHandle {
let handle = *self.id_to_sound.get(&clip_id).unwrap(); if let Some(&handle) = self.id_to_sound.get(&clip_id) {
self.play_sound_internal(handle) 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 { fn is_loading_complete(&self) -> bool {

View File

@ -5,9 +5,10 @@ mod render;
use crate::{audio::WebAudioBackend, render::WebCanvasRenderBackend}; use crate::{audio::WebAudioBackend, render::WebCanvasRenderBackend};
use generational_arena::{Arena, Index}; use generational_arena::{Arena, Index};
use js_sys::Uint8Array; use js_sys::Uint8Array;
use ruffle_core::{swf::Twips, PlayerEvent};
use std::{cell::RefCell, error::Error, num::NonZeroI32}; use std::{cell::RefCell, error::Error, num::NonZeroI32};
use wasm_bindgen::{prelude::*, JsCast, JsValue}; use wasm_bindgen::{prelude::*, JsCast, JsValue};
use web_sys::{Event, EventTarget, HtmlCanvasElement}; use web_sys::{Event, EventTarget, HtmlCanvasElement, MouseEvent};
thread_local! { thread_local! {
/// We store the actual instances of the ruffle core in a static pool. /// We store the actual instances of the ruffle core in a static pool.
@ -25,6 +26,9 @@ struct RuffleInstance {
animation_handler_id: Option<NonZeroI32>, // requestAnimationFrame id animation_handler_id: Option<NonZeroI32>, // requestAnimationFrame id
#[allow(dead_code)] #[allow(dead_code)]
click_callback: Option<Closure<dyn FnMut(Event)>>, click_callback: Option<Closure<dyn FnMut(Event)>>,
mouse_move_callback: Option<Closure<dyn FnMut(MouseEvent)>>,
mouse_down_callback: Option<Closure<dyn FnMut(MouseEvent)>>,
mouse_up_callback: Option<Closure<dyn FnMut(MouseEvent)>>,
} }
/// An opaque handle to a `RuffleInstance` inside the pool. /// An opaque handle to a `RuffleInstance` inside the pool.
@ -95,6 +99,9 @@ impl Ruffle {
animation_handler: None, animation_handler: None,
animation_handler_id: None, animation_handler_id: None,
click_callback: None, click_callback: None,
mouse_move_callback: None,
mouse_down_callback: None,
mouse_up_callback: None,
timestamp, timestamp,
}; };
@ -114,6 +121,84 @@ impl Ruffle {
as Box<dyn FnMut(f64)>)); as Box<dyn FnMut(f64)>));
} }
// 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<dyn FnMut(MouseEvent)>);
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<dyn FnMut(MouseEvent)>);
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<dyn FnMut(MouseEvent)>);
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. // Create click event handler.
{ {
let click_callback = Closure::wrap(Box::new(move |_| { let click_callback = Closure::wrap(Box::new(move |_| {
@ -134,8 +219,7 @@ impl Ruffle {
canvas.style().set_property("cursor", "pointer").unwrap(); canvas.style().set_property("cursor", "pointer").unwrap();
let instance = instances.get_mut(index).unwrap(); let instance = instances.get_mut(index).unwrap();
instance.click_callback = Some(click_callback); instance.click_callback = Some(click_callback);
// Do initial render to render "click-to-play".
// Do an initial render for the pause overlay.
instance.core.render(); instance.core.render();
} }