ruffle/core/src/display_object.rs

195 lines
5.8 KiB
Rust
Raw Normal View History

2019-04-27 01:55:06 +00:00
use crate::player::{RenderContext, UpdateContext};
2019-04-29 05:55:44 +00:00
use crate::prelude::*;
use crate::transform::Transform;
2019-05-07 06:31:34 +00:00
use bacon_rajan_cc::{Cc, Trace, Tracer};
2019-04-25 17:52:22 +00:00
2019-05-04 18:45:11 +00:00
#[derive(Clone)]
2019-04-29 05:55:44 +00:00
pub struct DisplayObjectBase {
depth: Depth,
transform: Transform,
name: String,
2019-04-25 17:52:22 +00:00
}
2019-04-29 05:55:44 +00:00
impl Default for DisplayObjectBase {
fn default() -> Self {
Self {
depth: Default::default(),
transform: Default::default(),
name: Default::default(),
2019-04-26 03:27:44 +00:00
}
}
2019-04-29 05:55:44 +00:00
}
2019-04-26 03:27:44 +00:00
2019-04-29 05:55:44 +00:00
impl DisplayObjectImpl for DisplayObjectBase {
2019-05-01 16:55:54 +00:00
fn transform(&self) -> &Transform {
&self.transform
}
2019-04-29 05:55:44 +00:00
fn get_matrix(&self) -> &Matrix {
&self.transform.matrix
2019-04-25 17:52:22 +00:00
}
2019-04-29 05:55:44 +00:00
fn set_matrix(&mut self, matrix: &Matrix) {
2019-05-03 18:44:12 +00:00
self.transform.matrix = *matrix;
2019-04-26 03:27:44 +00:00
}
2019-04-29 05:55:44 +00:00
fn get_color_transform(&self) -> &ColorTransform {
&self.transform.color_transform
}
fn set_color_transform(&mut self, color_transform: &ColorTransform) {
2019-05-03 18:44:12 +00:00
self.transform.color_transform = *color_transform;
2019-04-25 17:52:22 +00:00
}
fn name(&self) -> &str {
&self.name
}
fn set_name(&mut self, name: &str) {
self.name = name.to_string();
}
2019-04-29 05:55:44 +00:00
}
impl Trace for DisplayObjectBase {
fn trace(&mut self, _tracer: &mut Tracer) {}
}
2019-05-07 10:34:17 +00:00
pub trait DisplayObjectImpl: Trace {
2019-05-01 16:55:54 +00:00
fn transform(&self) -> &Transform;
2019-04-29 05:55:44 +00:00
fn get_matrix(&self) -> &Matrix;
fn set_matrix(&mut self, matrix: &Matrix);
fn get_color_transform(&self) -> &ColorTransform;
fn set_color_transform(&mut self, color_transform: &ColorTransform);
fn name(&self) -> &str;
fn set_name(&mut self, name: &str);
2019-04-26 21:11:29 +00:00
fn preload(&self, _context: &mut UpdateContext) {}
2019-04-29 05:55:44 +00:00
fn run_frame(&mut self, _context: &mut UpdateContext) {}
2019-05-02 00:46:49 +00:00
fn run_post_frame(&mut self, _context: &mut UpdateContext) {}
2019-04-29 05:55:44 +00:00
fn render(&self, _context: &mut RenderContext) {}
2019-05-03 18:44:12 +00:00
fn handle_click(&mut self, _pos: (f32, f32)) {}
2019-05-07 06:31:34 +00:00
fn visit_children(&self, queue: &mut VecDeque<Cc<RefCell<DisplayObject>>>) {}
fn as_movie_clip(&self) -> Option<&crate::movie_clip::MovieClip> {
None
}
fn as_movie_clip_mut(&mut self) -> Option<&mut crate::movie_clip::MovieClip> {
None
}
2019-04-29 05:55:44 +00:00
}
macro_rules! impl_display_object {
2019-05-07 10:34:17 +00:00
($field:ident) => {
2019-05-01 16:55:54 +00:00
fn transform(&self) -> &crate::transform::Transform {
self.$field.transform()
}
2019-04-29 05:55:44 +00:00
fn get_matrix(&self) -> &Matrix {
self.$field.get_matrix()
}
fn set_matrix(&mut self, matrix: &Matrix) {
self.$field.set_matrix(matrix)
}
fn get_color_transform(&self) -> &ColorTransform {
self.$field.get_color_transform()
}
fn set_color_transform(&mut self, color_transform: &ColorTransform) {
self.$field.set_color_transform(color_transform)
2019-04-26 21:11:29 +00:00
}
fn name(&self) -> &str {
self.$field.name()
}
fn set_name(&mut self, name: &str) {
self.$field.set_name(name)
}
2019-04-29 05:55:44 +00:00
};
}
// TODO(Herschel): We wrap in a box because using a trait object
// directly with Cc gets hairy.
// Extra heap allocation, though.
// Revisit this eventually, some possibilities:
// - Just use a dumb enum.
// - Some DST magic if we remove the Box below and mark this !Sized?
pub struct DisplayObject {
inner: Box<DisplayObjectImpl>,
}
impl DisplayObject {
pub fn new(inner: Box<DisplayObjectImpl>) -> DisplayObject {
DisplayObject { inner }
2019-04-26 21:11:29 +00:00
}
2019-04-25 17:52:22 +00:00
}
2019-05-07 10:34:17 +00:00
impl DisplayObjectImpl for DisplayObject {
impl_display_object!(inner);
2019-04-29 05:55:44 +00:00
fn preload(&self, context: &mut UpdateContext) {
self.inner.preload(context);
}
2019-04-29 05:55:44 +00:00
fn run_frame(&mut self, context: &mut UpdateContext) {
self.inner.run_frame(context)
}
2019-05-02 00:46:49 +00:00
fn run_post_frame(&mut self, context: &mut UpdateContext) {
self.inner.run_post_frame(context)
2019-04-29 05:55:44 +00:00
}
2019-05-02 00:46:49 +00:00
2019-04-29 05:55:44 +00:00
fn render(&self, context: &mut RenderContext) {
self.inner.render(context)
}
2019-05-03 18:44:12 +00:00
fn handle_click(&mut self, pos: (f32, f32)) {
self.inner.handle_click(pos)
}
2019-05-07 06:31:34 +00:00
fn visit_children(&self, queue: &mut VecDeque<Cc<RefCell<DisplayObject>>>) {
self.inner.visit_children(queue);
}
fn as_movie_clip(&self) -> Option<&crate::movie_clip::MovieClip> {
self.inner.as_movie_clip()
}
fn as_movie_clip_mut(&mut self) -> Option<&mut crate::movie_clip::MovieClip> {
self.inner.as_movie_clip_mut()
}
2019-04-29 05:55:44 +00:00
}
impl Trace for DisplayObject {
2019-04-25 17:52:22 +00:00
fn trace(&mut self, tracer: &mut Tracer) {
2019-04-29 05:55:44 +00:00
self.inner.trace(tracer)
2019-04-25 17:52:22 +00:00
}
}
2019-05-07 06:31:34 +00:00
use std::cell::RefCell;
use std::collections::VecDeque;
pub struct DisplayObjectVisitor {
pub open: VecDeque<Cc<RefCell<DisplayObject>>>,
}
impl DisplayObjectVisitor {
pub fn run(&mut self, context: &mut crate::player::UpdateContext) {
let root = self.open[0].clone();
while let Some(node) = self.open.pop_front() {
// {
// let mut node = node.borrow_mut();
// node.run_frame(context);
// }
let mut action = None;
if let Some(clip) = node.borrow().as_movie_clip() {
action = clip.action();
}
if let Some((pos, len)) = action {
let mut action_context = crate::avm1::ActionContext {
global_time: context.global_time,
start_clip: node.clone(),
active_clip: node.clone(),
root: root.clone(),
audio: context.audio,
};
let data = &context.tag_stream.get_ref().get_ref()[pos..pos + len];
if let Err(e) = context.avm1.do_action(&mut action_context, &data[..]) {}
}
node.borrow_mut().run_post_frame(context);
node.borrow().visit_children(&mut self.open);
}
}
}