ruffle/src/lib.rs

156 lines
4.4 KiB
Rust
Raw Normal View History

2019-04-25 17:52:22 +00:00
mod character;
2019-04-26 21:11:29 +00:00
mod color_transform;
2019-04-25 17:52:22 +00:00
mod display_object;
mod graphic;
mod library;
mod matrix;
mod movie_clip;
mod shape_utils;
2019-04-26 03:27:44 +00:00
mod stage;
2019-04-25 17:52:22 +00:00
2019-04-26 21:11:29 +00:00
use self::color_transform::{ColorTransform, ColorTransformStack};
2019-04-25 17:52:22 +00:00
use self::display_object::DisplayObject;
use self::library::Library;
use self::matrix::{Matrix, MatrixStack};
use self::movie_clip::MovieClip;
2019-04-26 03:27:44 +00:00
use self::stage::Stage;
2019-04-25 17:52:22 +00:00
use bacon_rajan_cc::Cc;
use js_sys::{ArrayBuffer, Uint8Array};
use log::{info, trace, warn};
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::Cursor;
use std::rc::Rc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlImageElement};
type CharacterId = swf::CharacterId;
#[wasm_bindgen]
pub struct Player {
tag_stream: swf::read::Reader<Cursor<Vec<u8>>>,
2019-04-26 03:27:44 +00:00
2019-04-25 17:52:22 +00:00
canvas: HtmlCanvasElement,
render_context: RenderContext,
library: Library,
2019-04-26 03:27:44 +00:00
stage: Cc<RefCell<Stage>>,
2019-04-25 17:52:22 +00:00
frame_rate: f64,
frame_accumulator: f64,
cur_timestamp: f64,
}
#[wasm_bindgen]
impl Player {
pub fn new(data: ArrayBuffer, canvas: HtmlCanvasElement) -> Player {
console_error_panic_hook::set_once();
console_log::init_with_level(log::Level::Trace).expect("error initializing log");
let data = Uint8Array::new(data.as_ref());
let mut swf_data = vec![0; data.byte_length() as usize];
data.copy_to(&mut swf_data[..]);
let (swf, tag_stream) = swf::read::read_swf_header_decompressed(&swf_data[..]).unwrap();
info!("{}x{}", swf.stage_size.x_max, swf.stage_size.y_max);
canvas.set_width(swf.stage_size.x_max as u32);
canvas.set_height(swf.stage_size.y_max as u32);
let context: CanvasRenderingContext2d = canvas
.get_context("2d")
.expect("Expected canvas")
.expect("Expected canvas")
.dyn_into()
.expect("Expected CanvasRenderingContext2d");
Player {
tag_stream,
canvas,
2019-04-26 03:27:44 +00:00
2019-04-25 17:52:22 +00:00
render_context: RenderContext {
context_2d: context,
matrix_stack: MatrixStack::new(),
2019-04-26 21:11:29 +00:00
color_transform_stack: ColorTransformStack::new(),
2019-04-25 17:52:22 +00:00
},
library: Library::new(),
2019-04-26 03:27:44 +00:00
stage: Stage::new(swf.num_frames),
2019-04-25 17:52:22 +00:00
frame_rate: swf.frame_rate.into(),
frame_accumulator: 0.0,
cur_timestamp: web_sys::window()
.expect("Expected window")
.performance()
.expect("Expected performance")
.now(),
}
}
pub fn tick(&mut self, timestamp: f64) {
let dt = timestamp - self.cur_timestamp;
self.cur_timestamp = timestamp;
self.frame_accumulator += dt;
let frame_time = 1000.0 / self.frame_rate;
let needs_render = self.frame_accumulator >= frame_time;
while self.frame_accumulator >= frame_time {
self.frame_accumulator -= frame_time;
self.run_frame();
}
if needs_render {
self.render();
}
}
}
impl Player {
fn run_frame(&mut self) {
2019-04-26 03:27:44 +00:00
let mut update_context = UpdateContext {
tag_stream: &mut self.tag_stream,
position_stack: vec![],
library: &mut self.library,
};
let mut stage = self.stage.borrow_mut();
stage.run_frame(&mut update_context);
stage.update_frame_number();
2019-04-25 17:52:22 +00:00
}
fn render(&mut self) {
2019-04-26 03:27:44 +00:00
let stage = self.stage.borrow_mut();
let background_color = stage.background_color();
let css_color = format!(
2019-04-25 17:52:22 +00:00
"rgb({}, {}, {})",
2019-04-26 03:27:44 +00:00
background_color.r, background_color.g, background_color.b
2019-04-25 17:52:22 +00:00
);
2019-04-26 03:27:44 +00:00
self.render_context.context_2d.reset_transform().unwrap();
2019-04-25 17:52:22 +00:00
self.render_context
.context_2d
2019-04-26 03:27:44 +00:00
.set_fill_style(&format!("{}", css_color).into());
2019-04-25 17:52:22 +00:00
let width: f64 = self.canvas.width().into();
let height: f64 = self.canvas.height().into();
self.render_context
.context_2d
.fill_rect(0.0, 0.0, width, height);
2019-04-26 03:27:44 +00:00
stage.render(&mut self.render_context);
2019-04-25 17:52:22 +00:00
}
}
2019-04-26 03:27:44 +00:00
pub struct UpdateContext<'a> {
tag_stream: &'a mut swf::read::Reader<Cursor<Vec<u8>>>,
position_stack: Vec<u64>,
library: &'a mut Library,
}
2019-04-25 17:52:22 +00:00
pub struct RenderContext {
context_2d: CanvasRenderingContext2d,
matrix_stack: MatrixStack,
2019-04-26 21:11:29 +00:00
color_transform_stack: ColorTransformStack,
2019-04-25 17:52:22 +00:00
}