ruffle/core/src/debug_ui.rs

159 lines
4.9 KiB
Rust
Raw Normal View History

2023-06-05 10:36:55 +00:00
mod avm1;
2023-05-31 09:32:58 +00:00
mod display_object;
mod handle;
2023-06-04 20:38:43 +00:00
mod movie;
2023-05-31 09:32:58 +00:00
2023-06-01 22:28:27 +00:00
use crate::context::{RenderContext, UpdateContext};
2023-06-05 10:36:55 +00:00
use crate::debug_ui::avm1::Avm1ObjectWindow;
2023-05-31 09:32:58 +00:00
use crate::debug_ui::display_object::DisplayObjectWindow;
2023-06-05 10:36:55 +00:00
use crate::debug_ui::handle::{AVM1ObjectHandle, DisplayObjectHandle};
2023-06-04 20:38:43 +00:00
use crate::debug_ui::movie::MovieWindow;
2023-06-01 22:28:27 +00:00
use crate::display_object::TDisplayObject;
2023-06-04 20:38:43 +00:00
use crate::tag_utils::SwfMovie;
2023-06-01 22:28:27 +00:00
use gc_arena::DynamicRootSet;
2023-05-31 09:32:58 +00:00
use hashbrown::HashMap;
2023-06-01 22:28:27 +00:00
use ruffle_render::commands::CommandHandler;
use ruffle_render::matrix::Matrix;
2023-06-04 20:38:43 +00:00
use std::sync::{Arc, Weak};
use swf::{Color, Rectangle, Twips};
2023-06-04 20:38:43 +00:00
use weak_table::PtrWeakKeyHashMap;
2023-05-31 09:32:58 +00:00
#[derive(Default)]
pub struct DebugUi {
display_objects: HashMap<DisplayObjectHandle, DisplayObjectWindow>,
2023-06-04 20:38:43 +00:00
movies: PtrWeakKeyHashMap<Weak<SwfMovie>, MovieWindow>,
2023-06-05 10:36:55 +00:00
avm1_objects: HashMap<AVM1ObjectHandle, Avm1ObjectWindow>,
2023-05-31 09:32:58 +00:00
queued_messages: Vec<Message>,
}
#[derive(Debug)]
pub enum Message {
TrackDisplayObject(DisplayObjectHandle),
2023-06-04 20:38:43 +00:00
TrackMovie(Arc<SwfMovie>),
2023-06-05 10:36:55 +00:00
TrackAVM1Object(AVM1ObjectHandle),
2023-05-31 09:32:58 +00:00
TrackStage,
2023-06-04 20:38:43 +00:00
TrackTopLevelMovie,
2023-05-31 09:32:58 +00:00
}
impl DebugUi {
pub fn show(&mut self, egui_ctx: &egui::Context, context: &mut UpdateContext) {
let mut messages = std::mem::take(&mut self.queued_messages);
2023-06-04 20:38:43 +00:00
2023-05-31 09:32:58 +00:00
self.display_objects.retain(|object, window| {
2023-06-01 22:28:27 +00:00
let object = object.fetch(context.dynamic_root);
2023-05-31 09:32:58 +00:00
window.show(egui_ctx, context, object, &mut messages)
});
2023-06-04 20:38:43 +00:00
2023-06-05 10:36:55 +00:00
self.avm1_objects.retain(|object, window| {
let object = object.fetch(context.dynamic_root);
window.show(egui_ctx, context, object, &mut messages)
});
2023-06-04 20:38:43 +00:00
self.movies
.retain(|movie, window| window.show(egui_ctx, context, movie));
2023-05-31 09:32:58 +00:00
for message in messages {
match message {
Message::TrackDisplayObject(object) => self.track_display_object(object),
Message::TrackStage => {
self.track_display_object(DisplayObjectHandle::new(context, context.stage))
}
2023-06-04 20:38:43 +00:00
Message::TrackMovie(movie) => {
self.movies.insert(movie, Default::default());
}
Message::TrackTopLevelMovie => {
self.movies.insert(context.swf.clone(), Default::default());
}
2023-06-05 10:36:55 +00:00
Message::TrackAVM1Object(object) => {
self.avm1_objects.insert(object, Default::default());
}
2023-05-31 09:32:58 +00:00
}
}
}
pub fn queue_message(&mut self, message: Message) {
self.queued_messages.push(message);
}
pub fn track_display_object(&mut self, handle: DisplayObjectHandle) {
self.display_objects.insert(handle, Default::default());
}
2023-06-01 22:28:27 +00:00
pub fn draw_debug_rects<'gc>(
&self,
context: &mut RenderContext<'_, 'gc>,
dynamic_root_set: DynamicRootSet<'gc>,
) {
let world_matrix = context.stage.view_matrix() * *context.stage.base().matrix();
for (object, window) in self.display_objects.iter() {
if let Some(color) = window.debug_rect_color() {
let object = object.fetch(dynamic_root_set);
let bounds = world_matrix * object.world_bounds();
draw_debug_rect(context, color, bounds, 3.0);
}
if let Some(object) = window.hovered_debug_rect() {
let object = object.fetch(dynamic_root_set);
let bounds = world_matrix * object.world_bounds();
draw_debug_rect(context, swf::Color::RED, bounds, 5.0);
2023-06-01 22:28:27 +00:00
}
}
2023-06-05 10:36:55 +00:00
for (_object, window) in self.avm1_objects.iter() {
if let Some(object) = window.hovered_debug_rect() {
let object = object.fetch(dynamic_root_set);
let bounds = world_matrix * object.world_bounds();
draw_debug_rect(context, swf::Color::RED, bounds, 5.0);
}
}
2023-06-01 22:28:27 +00:00
}
2023-05-31 09:32:58 +00:00
}
fn draw_debug_rect(
context: &mut RenderContext,
color: Color,
bounds: Rectangle<Twips>,
thickness: f32,
) {
let width = bounds.width().to_pixels() as f32;
let height = bounds.height().to_pixels() as f32;
let thickness_twips = Twips::from_pixels(thickness as f64);
// Top
context.commands.draw_rect(
color.clone(),
Matrix::create_box(
width,
thickness,
0.0,
bounds.x_min,
bounds.y_min - thickness_twips,
),
);
// Bottom
context.commands.draw_rect(
color.clone(),
Matrix::create_box(width, thickness, 0.0, bounds.x_min, bounds.y_max),
);
// Left
context.commands.draw_rect(
color.clone(),
Matrix::create_box(
thickness,
height,
0.0,
bounds.x_min - thickness_twips,
bounds.y_min,
),
);
// Right
context.commands.draw_rect(
color,
Matrix::create_box(thickness, height, 0.0, bounds.x_max, bounds.y_min),
);
}