2023-05-31 09:32:58 +00:00
|
|
|
mod display_object;
|
|
|
|
mod handle;
|
|
|
|
|
2023-06-01 22:28:27 +00:00
|
|
|
use crate::context::{RenderContext, UpdateContext};
|
2023-05-31 09:32:58 +00:00
|
|
|
use crate::debug_ui::display_object::DisplayObjectWindow;
|
|
|
|
use crate::debug_ui::handle::DisplayObjectHandle;
|
2023-06-01 22:28:27 +00:00
|
|
|
use crate::display_object::TDisplayObject;
|
|
|
|
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;
|
|
|
|
use swf::Twips;
|
|
|
|
|
|
|
|
const DEBUG_RECT_THICKNESS_PIXELS: f32 = 3.0;
|
|
|
|
const DEBUG_RECT_THICKNESS_TWIPS: Twips = Twips::from_pixels_i32(3);
|
2023-05-31 09:32:58 +00:00
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct DebugUi {
|
|
|
|
display_objects: HashMap<DisplayObjectHandle, DisplayObjectWindow>,
|
|
|
|
queued_messages: Vec<Message>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Message {
|
|
|
|
TrackDisplayObject(DisplayObjectHandle),
|
|
|
|
TrackStage,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DebugUi {
|
|
|
|
pub fn show(&mut self, egui_ctx: &egui::Context, context: &mut UpdateContext) {
|
|
|
|
let mut messages = std::mem::take(&mut self.queued_messages);
|
|
|
|
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)
|
|
|
|
});
|
|
|
|
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))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
let width = bounds.width().to_pixels() as f32;
|
|
|
|
let height = bounds.height().to_pixels() as f32;
|
|
|
|
|
|
|
|
// Top
|
|
|
|
context.commands.draw_rect(
|
|
|
|
color.clone(),
|
|
|
|
Matrix::create_box(
|
|
|
|
width,
|
|
|
|
DEBUG_RECT_THICKNESS_PIXELS,
|
|
|
|
0.0,
|
|
|
|
bounds.x_min,
|
|
|
|
bounds.y_min - DEBUG_RECT_THICKNESS_TWIPS,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
// Bottom
|
|
|
|
context.commands.draw_rect(
|
|
|
|
color.clone(),
|
|
|
|
Matrix::create_box(
|
|
|
|
width,
|
|
|
|
DEBUG_RECT_THICKNESS_PIXELS,
|
|
|
|
0.0,
|
|
|
|
bounds.x_min,
|
|
|
|
bounds.y_max,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
// Left
|
|
|
|
context.commands.draw_rect(
|
|
|
|
color.clone(),
|
|
|
|
Matrix::create_box(
|
|
|
|
DEBUG_RECT_THICKNESS_PIXELS,
|
|
|
|
height,
|
|
|
|
0.0,
|
|
|
|
bounds.x_min - DEBUG_RECT_THICKNESS_TWIPS,
|
|
|
|
bounds.y_min,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
// Right
|
|
|
|
context.commands.draw_rect(
|
|
|
|
color,
|
|
|
|
Matrix::create_box(
|
|
|
|
DEBUG_RECT_THICKNESS_PIXELS,
|
|
|
|
height,
|
|
|
|
0.0,
|
|
|
|
bounds.x_max,
|
|
|
|
bounds.y_min,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-05-31 09:32:58 +00:00
|
|
|
}
|