Work
This commit is contained in:
parent
3a2b11c511
commit
ba6843cf55
20
Cargo.toml
20
Cargo.toml
|
@ -6,6 +6,12 @@ edition = "2018"
|
|||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
name = "fluster"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fluster"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook", "console_log"]
|
||||
|
@ -15,7 +21,14 @@ bacon_rajan_cc = "0.2"
|
|||
log = "0.4"
|
||||
url = "1.7.2"
|
||||
svg = "0.5.12"
|
||||
swf = { path = "../swf-rs", version = "*" }
|
||||
swf = { git = "https://github.com/Herschel/swf-rs", version = "*" }
|
||||
|
||||
# Desktop dependencies
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
structopt = "0.2.15"
|
||||
glium = "0.24"
|
||||
glutin = "0.20"
|
||||
winit = "0.19.1"
|
||||
|
||||
# Wasm32 dependencies
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
|
@ -32,4 +45,7 @@ version = "0.3.19"
|
|||
features = ["CanvasRenderingContext2d", "HtmlCanvasElement", "Performance", "HtmlImageElement", "Window"]
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.2"
|
||||
wasm-bindgen-test = "0.2"
|
||||
|
||||
[patch.'https://github.com/Herschel/swf-rs']
|
||||
swf = { path = "../swf-rs" }
|
|
@ -0,0 +1,11 @@
|
|||
pub mod render;
|
||||
pub mod ui;
|
||||
|
||||
use render::RenderBackend;
|
||||
use ui::UiBackend;
|
||||
|
||||
pub fn build() -> Result<(Box<UiBackend>, Box<RenderBackend>), Box<std::error::Error>> {
|
||||
let mut ui = ui::glutin::GlutinBackend::new(500, 500)?;
|
||||
let renderer = render::glium::GliumRenderBackend::new(&mut ui)?;
|
||||
Ok((Box::new(ui), Box::new(renderer)))
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
pub mod glium;
|
||||
|
||||
use swf::Shape;
|
||||
|
||||
pub trait RenderBackend {
|
||||
//fn register_shape(shape: &Shape) {}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
use super::RenderBackend;
|
||||
use crate::backend::ui::glutin::GlutinBackend;
|
||||
use glium::Display;
|
||||
use glutin::Context;
|
||||
|
||||
pub struct GliumRenderBackend {
|
||||
display: Display,
|
||||
}
|
||||
|
||||
impl GliumRenderBackend {
|
||||
pub fn new(ui: &mut GlutinBackend) -> Result<GliumRenderBackend, Box<std::error::Error>> {
|
||||
let display = Display::from_gl_window(ui.take_context())?;
|
||||
Ok(GliumRenderBackend { display })
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderBackend for GliumRenderBackend {}
|
|
@ -0,0 +1,5 @@
|
|||
pub mod glutin;
|
||||
|
||||
pub trait UiBackend {
|
||||
fn poll_events(&mut self) -> bool;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
use super::UiBackend;
|
||||
use glutin::{ContextBuilder, Event, EventsLoop, WindowBuilder, WindowEvent, WindowedContext};
|
||||
|
||||
pub struct GlutinBackend {
|
||||
context: Option<WindowedContext>,
|
||||
events_loop: EventsLoop,
|
||||
}
|
||||
|
||||
impl GlutinBackend {
|
||||
pub fn new(width: u32, height: u32) -> Result<GlutinBackend, Box<std::error::Error>> {
|
||||
let events_loop = EventsLoop::new();
|
||||
let window_builder = WindowBuilder::new().with_dimensions((width, height).into());
|
||||
let context = ContextBuilder::new().build_windowed(window_builder, &events_loop)?;
|
||||
Ok(GlutinBackend {
|
||||
context: Some(context),
|
||||
events_loop,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn take_context(&mut self) -> WindowedContext {
|
||||
self.context.take().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl UiBackend for GlutinBackend {
|
||||
fn poll_events(&mut self) -> bool {
|
||||
let mut request_close = false;
|
||||
self.events_loop.poll_events(|event| match event {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => request_close = true,
|
||||
_ => (),
|
||||
});
|
||||
|
||||
!request_close
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
use web_sys::HtmlImageElement;
|
||||
|
||||
pub enum Character {
|
||||
Graphic {
|
||||
image: HtmlImageElement,
|
||||
//image: HtmlImageElement,
|
||||
x_min: f32,
|
||||
y_min: f32,
|
||||
},
|
||||
|
|
|
@ -26,6 +26,7 @@ impl From<swf::ColorTransform> for ColorTransform {
|
|||
}
|
||||
|
||||
impl ColorTransform {
|
||||
#[allow(clippy::float_cmp)]
|
||||
pub fn is_identity(&self) -> bool {
|
||||
self.r_mult == 1.0
|
||||
&& self.g_mult == 1.0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::ColorTransform;
|
||||
use crate::Matrix;
|
||||
use crate::{graphic::Graphic, MovieClip, Stage};
|
||||
use crate::{RenderContext, UpdateContext};
|
||||
use crate::color_transform::ColorTransform;
|
||||
use crate::matrix::Matrix;
|
||||
use crate::player::{RenderContext, UpdateContext};
|
||||
use crate::{graphic::Graphic, movie_clip::MovieClip, stage::Stage};
|
||||
use bacon_rajan_cc::{Trace, Tracer};
|
||||
|
||||
pub trait DisplayObject {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::color_transform::ColorTransform;
|
||||
use crate::display_object::DisplayObject;
|
||||
use crate::library::Library;
|
||||
use crate::Matrix;
|
||||
use crate::{RenderContext, UpdateContext};
|
||||
use crate::matrix::Matrix;
|
||||
use crate::player::{RenderContext, UpdateContext};
|
||||
use bacon_rajan_cc::{Trace, Tracer};
|
||||
use log::{info, trace, warn};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use web_sys::HtmlImageElement;
|
||||
|
||||
pub struct Graphic {
|
||||
|
@ -12,13 +11,11 @@ pub struct Graphic {
|
|||
color_transform: ColorTransform,
|
||||
x_min: f32,
|
||||
y_min: f32,
|
||||
image: HtmlImageElement,
|
||||
}
|
||||
|
||||
impl Graphic {
|
||||
pub fn new(image: HtmlImageElement, x_min: f32, y_min: f32) -> Graphic {
|
||||
pub fn new(x_min: f32, y_min: f32) -> Graphic {
|
||||
Graphic {
|
||||
image,
|
||||
color_transform: Default::default(),
|
||||
x_min,
|
||||
y_min,
|
||||
|
@ -39,32 +36,32 @@ impl DisplayObject for Graphic {
|
|||
let world_matrix = context.matrix_stack.matrix();
|
||||
let color_transform = context.color_transform_stack.color_transform();
|
||||
|
||||
if !color_transform.is_identity() {
|
||||
context
|
||||
.context_2d
|
||||
.set_global_alpha(color_transform.a_mult.into());
|
||||
}
|
||||
// if !color_transform.is_identity() {
|
||||
// context
|
||||
// .context_2d
|
||||
// .set_global_alpha(color_transform.a_mult.into());
|
||||
// }
|
||||
|
||||
context
|
||||
.context_2d
|
||||
.set_transform(
|
||||
world_matrix.a.into(),
|
||||
world_matrix.b.into(),
|
||||
world_matrix.c.into(),
|
||||
world_matrix.d.into(),
|
||||
world_matrix.tx.into(),
|
||||
world_matrix.ty.into(),
|
||||
)
|
||||
.unwrap();
|
||||
// context
|
||||
// .context_2d
|
||||
// .set_transform(
|
||||
// world_matrix.a.into(),
|
||||
// world_matrix.b.into(),
|
||||
// world_matrix.c.into(),
|
||||
// world_matrix.d.into(),
|
||||
// world_matrix.tx.into(),
|
||||
// world_matrix.ty.into(),
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
if !color_transform.is_identity() {
|
||||
context.context_2d.set_global_alpha(1.0);
|
||||
}
|
||||
// if !color_transform.is_identity() {
|
||||
// context.context_2d.set_global_alpha(1.0);
|
||||
// }
|
||||
|
||||
context
|
||||
.context_2d
|
||||
.draw_image_with_html_image_element(&self.image, self.x_min.into(), self.y_min.into())
|
||||
.expect("Couldn't render image");
|
||||
// context
|
||||
// .context_2d
|
||||
// .draw_image_with_html_image_element(&self.image, self.x_min.into(), self.y_min.into())
|
||||
// .expect("Couldn't render image");
|
||||
|
||||
context.matrix_stack.pop();
|
||||
context.color_transform_stack.push(&self.color_transform);
|
||||
|
|
156
src/lib.rs
156
src/lib.rs
|
@ -1,3 +1,4 @@
|
|||
mod backend;
|
||||
mod character;
|
||||
mod color_transform;
|
||||
mod display_object;
|
||||
|
@ -5,151 +6,28 @@ mod graphic;
|
|||
mod library;
|
||||
mod matrix;
|
||||
mod movie_clip;
|
||||
mod player;
|
||||
mod shape_utils;
|
||||
mod stage;
|
||||
|
||||
use self::color_transform::{ColorTransform, ColorTransformStack};
|
||||
use self::display_object::DisplayObject;
|
||||
use self::library::Library;
|
||||
use self::matrix::{Matrix, MatrixStack};
|
||||
use self::movie_clip::MovieClip;
|
||||
use self::stage::Stage;
|
||||
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};
|
||||
pub use player::Player;
|
||||
|
||||
type CharacterId = swf::CharacterId;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[allow(dead_code)]
|
||||
fn main() {
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Player {
|
||||
tag_stream: swf::read::Reader<Cursor<Vec<u8>>>,
|
||||
|
||||
canvas: HtmlCanvasElement,
|
||||
render_context: RenderContext,
|
||||
|
||||
library: Library,
|
||||
stage: Cc<RefCell<Stage>>,
|
||||
|
||||
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,
|
||||
|
||||
render_context: RenderContext {
|
||||
context_2d: context,
|
||||
matrix_stack: MatrixStack::new(),
|
||||
color_transform_stack: ColorTransformStack::new(),
|
||||
},
|
||||
|
||||
library: Library::new(),
|
||||
stage: Stage::new(swf.num_frames),
|
||||
|
||||
frame_rate: swf.frame_rate.into(),
|
||||
frame_accumulator: 0.0,
|
||||
cur_timestamp: web_sys::window()
|
||||
.expect("Expected window")
|
||||
.performance()
|
||||
.expect("Expected performance")
|
||||
.now(),
|
||||
}
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(name = "basic")]
|
||||
struct Opt {
|
||||
#[structopt(name = "FILE", parse(from_os_str))]
|
||||
input_path: PathBuf,
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, timestamp: f64) {
|
||||
let dt = timestamp - self.cur_timestamp;
|
||||
self.cur_timestamp = timestamp;
|
||||
let opt = Opt::from_args();
|
||||
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
||||
fn render(&mut self) {
|
||||
let stage = self.stage.borrow_mut();
|
||||
let background_color = stage.background_color();
|
||||
let css_color = format!(
|
||||
"rgb({}, {}, {})",
|
||||
background_color.r, background_color.g, background_color.b
|
||||
);
|
||||
self.render_context.context_2d.reset_transform().unwrap();
|
||||
self.render_context
|
||||
.context_2d
|
||||
.set_fill_style(&format!("{}", css_color).into());
|
||||
|
||||
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);
|
||||
|
||||
stage.render(&mut self.render_context);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UpdateContext<'a> {
|
||||
tag_stream: &'a mut swf::read::Reader<Cursor<Vec<u8>>>,
|
||||
position_stack: Vec<u64>,
|
||||
library: &'a mut Library,
|
||||
}
|
||||
|
||||
pub struct RenderContext {
|
||||
context_2d: CanvasRenderingContext2d,
|
||||
matrix_stack: MatrixStack,
|
||||
color_transform_stack: ColorTransformStack,
|
||||
let swf_data = std::fs::read(opt.input_path).unwrap();
|
||||
let mut player = Player::new(swf_data).unwrap();
|
||||
player.play();
|
||||
}
|
||||
|
|
|
@ -31,13 +31,12 @@ impl Library {
|
|||
) -> Result<DisplayObjectNode, Box<std::error::Error>> {
|
||||
match self.characters.get(&id) {
|
||||
Some(Character::Graphic {
|
||||
image,
|
||||
//image,
|
||||
x_min,
|
||||
y_min,
|
||||
}) => Ok(DisplayObjectNode::Graphic(Graphic::new(
|
||||
image.clone(),
|
||||
*x_min,
|
||||
*y_min,
|
||||
//image.clone(),
|
||||
*x_min, *y_min,
|
||||
))),
|
||||
Some(Character::MovieClip {
|
||||
tag_stream_start,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use crate::color_transform::ColorTransform;
|
||||
use crate::display_object::{DisplayObject, DisplayObjectNode};
|
||||
use crate::matrix::Matrix;
|
||||
use crate::Library;
|
||||
use crate::{RenderContext, UpdateContext};
|
||||
use crate::player::{RenderContext, UpdateContext};
|
||||
use bacon_rajan_cc::{Cc, Trace, Tracer};
|
||||
use log::{info, trace, warn};
|
||||
use log::info;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
|
||||
type Depth = i16;
|
||||
type FrameNumber = u16;
|
||||
|
@ -65,7 +63,7 @@ impl MovieClip {
|
|||
PlaceObjectAction::Place(id) => {
|
||||
// TODO(Herschel): Behavior when character doesn't exist/isn't a DisplayObject?
|
||||
let character =
|
||||
if let Ok(mut character) = context.library.instantiate_display_object(id) {
|
||||
if let Ok(character) = context.library.instantiate_display_object(id) {
|
||||
Cc::new(RefCell::new(character))
|
||||
} else {
|
||||
return;
|
||||
|
@ -84,7 +82,7 @@ impl MovieClip {
|
|||
}
|
||||
PlaceObjectAction::Replace(id) => {
|
||||
let character =
|
||||
if let Ok(mut character) = context.library.instantiate_display_object(id) {
|
||||
if let Ok(character) = context.library.instantiate_display_object(id) {
|
||||
Cc::new(RefCell::new(character))
|
||||
} else {
|
||||
return;
|
||||
|
@ -122,10 +120,7 @@ impl DisplayObject for MovieClip {
|
|||
Tag::PlaceObject(place_object) => {
|
||||
MovieClip::run_place_object(&mut self.children, &*place_object, context)
|
||||
}
|
||||
Tag::RemoveObject {
|
||||
depth,
|
||||
character_id,
|
||||
} => {
|
||||
Tag::RemoveObject { depth, .. } => {
|
||||
// TODO(Herschel): How does the character ID work for RemoveObject?
|
||||
self.children.remove(&depth);
|
||||
info!("REMOVE {} {}", depth, self.children.len());
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
use crate::backend::{render::RenderBackend, ui::UiBackend};
|
||||
use crate::color_transform::ColorTransformStack;
|
||||
use crate::display_object::DisplayObject;
|
||||
use crate::library::Library;
|
||||
use crate::matrix::MatrixStack;
|
||||
use crate::stage::Stage;
|
||||
use bacon_rajan_cc::Cc;
|
||||
use log::info;
|
||||
use std::cell::RefCell;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use js_sys::{ArrayBuffer, Uint8Array};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::JsCast;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlImageElement};
|
||||
|
||||
type CharacterId = swf::CharacterId;
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
|
||||
pub struct Player {
|
||||
tag_stream: swf::read::Reader<Cursor<Vec<u8>>>,
|
||||
|
||||
render_context: RenderContext,
|
||||
|
||||
ui: Box<UiBackend>,
|
||||
renderer: Box<RenderBackend>,
|
||||
|
||||
library: Library,
|
||||
stage: Cc<RefCell<Stage>>,
|
||||
|
||||
frame_rate: f64,
|
||||
frame_accumulator: f64,
|
||||
//cur_timestamp: f64,
|
||||
}
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
|
||||
impl Player {
|
||||
pub fn new(swf_data: Vec<u8>) -> Result<Player, Box<std::error::Error>> {
|
||||
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);
|
||||
|
||||
let (ui, renderer) = crate::backend::build()?;
|
||||
|
||||
Ok(Player {
|
||||
tag_stream,
|
||||
|
||||
ui,
|
||||
renderer,
|
||||
|
||||
render_context: RenderContext {
|
||||
matrix_stack: MatrixStack::new(),
|
||||
color_transform_stack: ColorTransformStack::new(),
|
||||
},
|
||||
|
||||
library: Library::new(),
|
||||
stage: Stage::new(swf.num_frames),
|
||||
|
||||
frame_rate: swf.frame_rate.into(),
|
||||
frame_accumulator: 0.0,
|
||||
//cur_timestamp: std::time::Instant::now(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn play(&mut self) {
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
let mut time = Instant::now();
|
||||
|
||||
while self.ui.poll_events() {
|
||||
let new_time = Instant::now();
|
||||
let dt = new_time.duration_since(time).as_millis();
|
||||
time = new_time;
|
||||
|
||||
self.tick(dt as f64);
|
||||
|
||||
std::thread::sleep(Duration::from_millis(1000 / 60));
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
||||
fn render(&mut self) {
|
||||
let stage = self.stage.borrow_mut();
|
||||
|
||||
/*
|
||||
let background_color = stage.background_color();
|
||||
let css_color = format!(
|
||||
"rgb({}, {}, {})",
|
||||
background_color.r, background_color.g, background_color.b
|
||||
);
|
||||
self.render_context.context_2d.reset_transform().unwrap();
|
||||
self.render_context
|
||||
.context_2d
|
||||
.set_fill_style(&format!("{}", css_color).into());
|
||||
|
||||
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);
|
||||
*/
|
||||
|
||||
stage.render(&mut self.render_context);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UpdateContext<'a> {
|
||||
pub tag_stream: &'a mut swf::read::Reader<Cursor<Vec<u8>>>,
|
||||
pub position_stack: Vec<u64>,
|
||||
pub library: &'a mut Library,
|
||||
}
|
||||
|
||||
pub struct RenderContext {
|
||||
//pub context_2d: CanvasRenderingContext2d,
|
||||
pub matrix_stack: MatrixStack,
|
||||
pub color_transform_stack: ColorTransformStack,
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
use crate::Matrix;
|
||||
use log::{info, trace, warn};
|
||||
use crate::matrix::Matrix;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use svg::node::element::{
|
||||
path::Data, Definitions, Image, LinearGradient, Path as SvgPath, Pattern, RadialGradient, Stop,
|
||||
|
@ -179,12 +178,7 @@ pub fn swf_shape_to_svg(shape: &Shape) -> String {
|
|||
num_defs += 1;
|
||||
fill_id
|
||||
}
|
||||
FillStyle::Bitmap {
|
||||
id,
|
||||
matrix,
|
||||
is_smoothed,
|
||||
is_repeating,
|
||||
} => {
|
||||
FillStyle::Bitmap { .. } => {
|
||||
let svg_image = Image::new(); // TODO: .set("xlink:href", "");
|
||||
|
||||
let svg_pattern = Pattern::new()
|
||||
|
@ -283,7 +277,6 @@ fn swf_shape_to_paths(shape: &Shape) -> (Vec<Path>, Vec<Path>) {
|
|||
let mut fill_style_0 = 0;
|
||||
let mut fill_style_1 = 0;
|
||||
let mut line_style = 0;
|
||||
let mut i = 0;
|
||||
let mut fill_styles = &shape.styles.fill_styles;
|
||||
let mut line_styles = &shape.styles.line_styles;
|
||||
for record in &shape.shape {
|
||||
|
|
31
src/stage.rs
31
src/stage.rs
|
@ -3,15 +3,12 @@ use crate::color_transform::ColorTransform;
|
|||
use crate::display_object::{DisplayObject, DisplayObjectNode};
|
||||
use crate::matrix::Matrix;
|
||||
use crate::movie_clip::MovieClip;
|
||||
use crate::Library;
|
||||
use crate::{RenderContext, UpdateContext};
|
||||
use crate::player::{RenderContext, UpdateContext};
|
||||
use bacon_rajan_cc::{Cc, Trace, Tracer};
|
||||
use log::{info, trace, warn};
|
||||
use log::info;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use swf::Color;
|
||||
use web_sys::HtmlImageElement;
|
||||
|
||||
type Depth = i16;
|
||||
type FrameNumber = u16;
|
||||
|
@ -78,26 +75,16 @@ impl DisplayObject for Stage {
|
|||
|
||||
Tag::ShowFrame => break,
|
||||
|
||||
Tag::DefineSceneAndFrameLabelData {
|
||||
scenes,
|
||||
frame_labels,
|
||||
} => (), // TODO(Herschel)
|
||||
Tag::DefineSceneAndFrameLabelData { .. } => (), // TODO(Herschel)
|
||||
|
||||
Tag::DefineShape(shape) => {
|
||||
if !context.library.contains_character(shape.id) {
|
||||
let svg = crate::shape_utils::swf_shape_to_svg(&shape);
|
||||
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||
let url_encoded_svg = format!(
|
||||
"data:image/svg+xml,{}",
|
||||
utf8_percent_encode(&svg, DEFAULT_ENCODE_SET)
|
||||
);
|
||||
|
||||
let mut image = HtmlImageElement::new().unwrap();
|
||||
image.set_src(&url_encoded_svg);
|
||||
//let mut image = HtmlImageElement::new().unwrap();
|
||||
//image.set_src(&url_encoded_svg);
|
||||
context.library.register_character(
|
||||
shape.id,
|
||||
Character::Graphic {
|
||||
image,
|
||||
//image,
|
||||
x_min: shape.shape_bounds.x_min,
|
||||
y_min: shape.shape_bounds.y_min,
|
||||
},
|
||||
|
@ -122,14 +109,10 @@ impl DisplayObject for Stage {
|
|||
}
|
||||
}
|
||||
|
||||
Tag::ShowFrame => break,
|
||||
Tag::PlaceObject(place_object) => {
|
||||
MovieClip::run_place_object(&mut self.children, &*place_object, context)
|
||||
}
|
||||
Tag::RemoveObject {
|
||||
depth,
|
||||
character_id,
|
||||
} => {
|
||||
Tag::RemoveObject { depth, .. } => {
|
||||
// TODO(Herschel): How does the character ID work for RemoveObject?
|
||||
self.children.remove(&depth).is_some();
|
||||
info!("REMOVE {} {}", depth, self.children.len());
|
||||
|
|
Loading…
Reference in New Issue