use crate::event::Event;
use crate::render::{
adapter::{
wgpu::{WgpuRenderCore, WgpuRenderCoreBuilder},
winit_common::{
apply_cursor_to_window, check_border_area, input_events_from_winit,
load_custom_cursor, winit_init_common, winit_move_win, BorderArea, Drag,
WindowInitParams,
},
Adapter, AdapterBase, RtComposite,
},
buffer::Buffer,
graph::{UnifiedTransform, is_letterboxing_enabled, set_letterboxing_override},
sprite::Layer,
};
use log::info;
use std::any::Any;
use std::sync::Arc;
use std::time::Duration;
use winit::platform::pump_events::{EventLoopExtPumpEvents, PumpStatus};
pub use winit::{
application::ApplicationHandler,
dpi::LogicalSize,
event::{Event as WinitEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{Cursor, CustomCursor, Fullscreen, Window},
};
pub struct WinitWgpuAdapter {
pub base: AdapterBase,
pub window: Option<Arc<Window>>,
pub event_loop: Option<EventLoop<()>>,
pub window_init_params: Option<WindowInitParams>,
pub wgpu_instance: Option<wgpu::Instance>,
pub wgpu_surface: Option<wgpu::Surface<'static>>,
pub wgpu_surface_config: Option<wgpu::SurfaceConfiguration>,
pub render_core: Option<WgpuRenderCore>,
pub should_exit: bool,
pub app_handler: Option<WinitWgpuAppHandler>,
pub custom_cursor: Option<CustomCursor>,
pub cursor_set: bool,
drag: Drag,
original_ratio_x: f32,
original_ratio_y: f32,
ratio_overridden: bool,
logical_content_w: f32,
logical_content_h: f32,
}
pub struct WinitWgpuAppHandler {
pub pending_events: Vec<Event>,
pub cursor_position: (f64, f64),
pub ratio_x: f32,
pub ratio_y: f32,
pub use_tui_height: bool,
pub should_exit: bool,
pub adapter_ref: *mut WinitWgpuAdapter,
}
impl ApplicationHandler for WinitWgpuAppHandler {
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
if let Some(adapter) = unsafe { self.adapter_ref.as_mut() } {
if adapter.window.is_none() {
adapter.create_wgpu_window_and_resources(event_loop);
}
if !adapter.cursor_set {
adapter.clear_screen_wgpu();
adapter.set_mouse_cursor();
adapter.cursor_set = true;
}
}
}
fn window_event(
&mut self,
event_loop: &winit::event_loop::ActiveEventLoop,
_window_id: winit::window::WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::CloseRequested => {
self.should_exit = true;
event_loop.exit();
}
WindowEvent::KeyboardInput {
event: key_event, ..
} => {
if key_event.state == winit::event::ElementState::Pressed {
if let winit::keyboard::PhysicalKey::Code(keycode) = key_event.physical_key {
if keycode == winit::keyboard::KeyCode::KeyQ {
self.should_exit = true;
event_loop.exit();
return;
}
}
}
let winit_event = WinitEvent::WindowEvent {
window_id: _window_id,
event: WindowEvent::KeyboardInput {
device_id: winit::event::DeviceId::dummy(),
event: key_event,
is_synthetic: false,
},
};
if let Some(pixel_event) = input_events_from_winit(
&winit_event,
self.ratio_x,
self.ratio_y,
self.use_tui_height,
&mut self.cursor_position,
) {
self.pending_events.push(pixel_event);
}
}
WindowEvent::Resized(new_size) => {
if new_size.width > 0 && new_size.height > 0 {
unsafe {
let adapter = &mut *self.adapter_ref;
let is_max = adapter.window.as_ref()
.map(|w| w.is_maximized()).unwrap_or(false);
let is_fullscreen = adapter.window.as_ref()
.and_then(|w| w.fullscreen()).is_some();
if let (Some(surface), Some(config), Some(core)) = (
&adapter.wgpu_surface,
adapter.wgpu_surface_config.as_mut(),
&adapter.render_core,
) {
config.width = new_size.width;
config.height = new_size.height;
surface.configure(&core.device, config);
}
let should_override = (is_max || is_fullscreen)
&& !adapter.ratio_overridden
&& adapter.base.gr.ratio_x > 1.0;
if should_override {
adapter.original_ratio_x = adapter.base.gr.ratio_x;
adapter.original_ratio_y = adapter.base.gr.ratio_y;
adapter.base.gr.ratio_x = 1.0;
adapter.base.gr.ratio_y = 1.0;
adapter.base.gr.set_pixel_size(
adapter.base.cell_w, adapter.base.cell_h,
);
set_letterboxing_override(true);
adapter.rebuild_render_core();
adapter.ratio_overridden = true;
} else if !is_max && !is_fullscreen && adapter.ratio_overridden {
adapter.base.gr.ratio_x = adapter.original_ratio_x;
adapter.base.gr.ratio_y = adapter.original_ratio_y;
adapter.base.gr.set_pixel_size(
adapter.base.cell_w, adapter.base.cell_h,
);
set_letterboxing_override(false);
adapter.rebuild_render_core();
adapter.ratio_overridden = false;
}
}
}
}
WindowEvent::CursorMoved { position, .. } => {
unsafe {
let adapter = &*self.adapter_ref;
if let Some(window) = &adapter.window {
let actual_size = window.inner_size();
let expected_w = adapter.base.gr.pixel_w as f64;
let expected_h = adapter.base.gr.pixel_h as f64;
let phys_w = actual_size.width as f64;
let phys_h = actual_size.height as f64;
if is_letterboxing_enabled() {
let content_aspect = expected_w / expected_h;
let window_aspect = phys_w / phys_h;
if window_aspect > content_aspect {
let content_phys_w = phys_h * content_aspect;
let offset_x = (phys_w - content_phys_w) / 2.0;
self.cursor_position = (
(position.x - offset_x) / content_phys_w * expected_w,
position.y / phys_h * expected_h,
);
} else {
let content_phys_h = phys_w / content_aspect;
let offset_y = (phys_h - content_phys_h) / 2.0;
self.cursor_position = (
position.x / phys_w * expected_w,
(position.y - offset_y) / content_phys_h * expected_h,
);
}
} else {
self.cursor_position = (
position.x / phys_w * expected_w,
position.y / phys_h * expected_h,
);
}
} else {
self.cursor_position = (position.x, position.y);
}
}
unsafe {
let adapter = &mut *self.adapter_ref;
if adapter.drag.draging {
adapter.drag.need = true;
adapter.drag.dx = position.x - adapter.drag.mouse_x;
adapter.drag.dy = position.y - adapter.drag.mouse_y;
}
}
let logical_position = winit::dpi::PhysicalPosition::new(
self.cursor_position.0,
self.cursor_position.1,
);
let winit_event = WinitEvent::WindowEvent {
window_id: _window_id,
event: WindowEvent::CursorMoved {
device_id: winit::event::DeviceId::dummy(),
position: logical_position,
},
};
unsafe {
let adapter = &*self.adapter_ref;
if !adapter.drag.draging {
if let Some(pixel_event) = input_events_from_winit(
&winit_event,
self.ratio_x,
self.ratio_y,
self.use_tui_height,
&mut self.cursor_position,
) {
self.pending_events.push(pixel_event);
}
}
}
}
WindowEvent::MouseInput { state, button, .. } => {
match (state, button) {
(winit::event::ElementState::Pressed, winit::event::MouseButton::Left) |
(winit::event::ElementState::Released, winit::event::MouseButton::Left) => {
let winit_event = WinitEvent::WindowEvent {
window_id: _window_id,
event: WindowEvent::MouseInput {
device_id: winit::event::DeviceId::dummy(),
state,
button,
},
};
if let Some(pixel_event) = input_events_from_winit(
&winit_event,
self.ratio_x,
self.ratio_y,
self.use_tui_height,
&mut self.cursor_position,
) {
self.pending_events.push(pixel_event);
}
}
_ => {
let winit_event = WinitEvent::WindowEvent {
window_id: _window_id,
event: WindowEvent::MouseInput {
device_id: winit::event::DeviceId::dummy(),
state,
button,
},
};
if let Some(pixel_event) = input_events_from_winit(
&winit_event,
self.ratio_x,
self.ratio_y,
self.use_tui_height,
&mut self.cursor_position,
) {
self.pending_events.push(pixel_event);
}
}
}
}
_ => {
let winit_event = WinitEvent::WindowEvent {
window_id: _window_id,
event,
};
if let Some(pixel_event) = input_events_from_winit(
&winit_event,
self.ratio_x,
self.ratio_y,
self.use_tui_height,
&mut self.cursor_position,
) {
self.pending_events.push(pixel_event);
}
}
}
}
}
impl Default for WinitWgpuAdapter {
fn default() -> Self {
Self::new()
}
}
impl WinitWgpuAdapter {
pub fn new() -> Self {
Self {
base: AdapterBase::new(),
window: None,
event_loop: None,
window_init_params: None,
wgpu_instance: None,
wgpu_surface: None,
wgpu_surface_config: None,
render_core: None,
should_exit: false,
app_handler: None,
custom_cursor: None,
cursor_set: false,
drag: Default::default(),
original_ratio_x: 1.0,
original_ratio_y: 1.0,
ratio_overridden: false,
logical_content_w: 0.0,
logical_content_h: 0.0,
}
}
fn init_common(&mut self, w: u16, h: u16, rx: f32, ry: f32, title: String) -> String {
let (event_loop, window_init_params, texture_path) =
winit_init_common(self, w, h, rx, ry, title);
self.event_loop = Some(event_loop);
self.window_init_params = Some(window_init_params);
self.app_handler = Some(WinitWgpuAppHandler {
pending_events: Vec::new(),
cursor_position: (0.0, 0.0),
ratio_x: self.base.gr.ratio_x,
ratio_y: self.base.gr.ratio_y,
use_tui_height: self.base.gr.use_tui_height,
should_exit: false,
adapter_ref: self as *mut WinitWgpuAdapter,
});
texture_path
}
fn init_wgpu(&mut self, w: u16, h: u16, rx: f32, ry: f32, title: String) {
info!("Initializing Winit adapter with WGPU backend...");
let _texture_path = self.init_common(w, h, rx, ry, title);
}
fn create_wgpu_window_and_resources(
&mut self,
event_loop: &winit::event_loop::ActiveEventLoop,
) {
let params = self.window_init_params.as_ref().unwrap().clone();
info!("Creating WGPU window and resources...");
let window_size = LogicalSize::new(self.base.gr.pixel_w, self.base.gr.pixel_h);
let game_config = crate::get_game_config();
let fullscreen = if game_config.fullscreen {
Some(Fullscreen::Borderless(None))
} else {
None
};
let window_attributes = winit::window::Window::default_attributes()
.with_title(¶ms.title)
.with_inner_size(window_size)
.with_decorations(true)
.with_resizable(true)
.with_fullscreen(fullscreen.clone())
.with_visible(false);
let window = Arc::new(
event_loop
.create_window(window_attributes)
.expect("Failed to create window"),
);
let physical_size = window.inner_size();
let scale_factor = window.scale_factor();
info!(
"Window created - Logical: {}x{}, Physical: {}x{}, Scale factor: {:.2}",
self.base.gr.pixel_w, self.base.gr.pixel_h,
physical_size.width, physical_size.height,
scale_factor
);
self.logical_content_w = self.base.gr.pixel_w as f32;
self.logical_content_h = self.base.gr.pixel_h as f32;
let logical_w = self.base.gr.pixel_w as f32;
let logical_h = self.base.gr.pixel_h as f32;
let phys_w = physical_size.width as f32;
let phys_h = physical_size.height as f32;
let orig_ratio_x = self.base.gr.ratio_x;
let orig_ratio_y = self.base.gr.ratio_y;
log::info!("=== Window/Display Size Debug ===");
log::info!(" game_config.fullscreen = {}", game_config.fullscreen);
log::info!(" game_config.fullscreen_fit = {}", game_config.fullscreen_fit);
log::info!(" logical (pixel_w/h before override) = {}x{}", logical_w, logical_h);
log::info!(" physical (window inner_size) = {}x{}", phys_w, phys_h);
log::info!(" scale_factor = {:.2}", scale_factor);
log::info!(" original ratio_x={:.4}, ratio_y={:.4}", orig_ratio_x, orig_ratio_y);
log::info!(" logical_content saved = {}x{}", self.logical_content_w, self.logical_content_h);
let (canvas_w, canvas_h, ratio_x, ratio_y, render_scale) = if game_config.fullscreen {
if game_config.fullscreen_fit {
let logical_aspect = logical_w / logical_h;
let phys_aspect = phys_w / phys_h;
let (cw, ch) = if phys_aspect > logical_aspect {
let ch = phys_h as u32;
let cw = (phys_h * logical_aspect) as u32;
(cw, ch)
} else {
let cw = phys_w as u32;
let ch = (phys_w / logical_aspect) as u32;
(cw, ch)
};
let uniform_ratio = logical_w / cw as f32;
log::info!(" [Fullscreen-FIT] logical_aspect={:.4}, phys_aspect={:.4}", logical_aspect, phys_aspect);
log::info!(" [Fullscreen-FIT] canvas={}x{}, uniform_ratio={:.6}", cw, ch, uniform_ratio);
log::info!(" [Fullscreen-FIT] render_scale=1.0");
self.base.gr.ratio_x = uniform_ratio;
self.base.gr.ratio_y = uniform_ratio;
self.base.gr.pixel_w = cw;
self.base.gr.pixel_h = ch;
if let Some(ref mut handler) = self.app_handler {
handler.ratio_x = uniform_ratio;
handler.ratio_y = uniform_ratio;
}
(cw, ch, uniform_ratio, uniform_ratio, 1.0)
} else {
let new_ratio_x = logical_w / phys_w;
let new_ratio_y = logical_h / phys_h;
log::info!(" [Fullscreen-STRETCH] ratio_x={:.6}, ratio_y={:.6}", new_ratio_x, new_ratio_y);
log::info!(" [Fullscreen-STRETCH] canvas={}x{} (=physical)", physical_size.width, physical_size.height);
log::info!(" [Fullscreen-STRETCH] render_scale=1.0");
self.base.gr.ratio_x = new_ratio_x;
self.base.gr.ratio_y = new_ratio_y;
self.base.gr.pixel_w = physical_size.width;
self.base.gr.pixel_h = physical_size.height;
if let Some(ref mut handler) = self.app_handler {
handler.ratio_x = new_ratio_x;
handler.ratio_y = new_ratio_y;
}
(physical_size.width, physical_size.height, new_ratio_x, new_ratio_y, 1.0)
}
} else {
let render_scale = phys_h / logical_h;
log::info!(" [Windowed] canvas={}x{} (=physical)", physical_size.width, physical_size.height);
log::info!(" [Windowed] ratio_x={:.6}, ratio_y={:.6} (unchanged)", self.base.gr.ratio_x, self.base.gr.ratio_y);
log::info!(" [Windowed] render_scale={:.4}", render_scale);
(physical_size.width, physical_size.height, self.base.gr.ratio_x, self.base.gr.ratio_y, render_scale)
};
log::info!(" --- Final Settings ---");
log::info!(" canvas (RT) = {}x{}", canvas_w, canvas_h);
log::info!(" surface (physical) = {}x{}", physical_size.width, physical_size.height);
log::info!(" ratio = ({:.6}, {:.6}), render_scale = {:.4}", ratio_x, ratio_y, render_scale);
log::info!(" pixel_w/h (after override) = {}x{}", self.base.gr.pixel_w, self.base.gr.pixel_h);
log::info!(" isotropic = {}", (ratio_x - ratio_y).abs() < 0.0001);
log::info!("================================");
let wgpu_instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
});
self.window = Some(window.clone());
let wgpu_surface = unsafe {
wgpu_instance
.create_surface_unsafe(
wgpu::SurfaceTargetUnsafe::from_window(&**self.window.as_ref().unwrap())
.unwrap(),
)
.expect("Failed to create surface")
};
let (device, queue, wgpu_surface_config) = pollster::block_on(async {
let adapter = wgpu_instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: Some(&wgpu_surface),
force_fallback_adapter: false,
})
.await
.expect("Failed to find suitable WGPU adapter");
info!("WGPU adapter found: {:?}", adapter.get_info());
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: Some("RustPixel WGPU Device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::Performance,
..Default::default()
},
)
.await
.expect("Failed to create WGPU device");
let surface_caps = wgpu_surface.get_capabilities(&adapter);
let surface_format = surface_caps
.formats
.iter()
.copied()
.find(|f| !f.is_srgb())
.unwrap_or(surface_caps.formats[0]);
let surface_config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: physical_size.width,
height: physical_size.height,
present_mode: surface_caps.present_modes[0],
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 2,
};
wgpu_surface.configure(&device, &surface_config);
info!(
"WGPU surface configured: {}x{}, format: {:?}",
surface_config.width, surface_config.height, surface_config.format
);
(device, queue, surface_config)
});
let builder = WgpuRenderCoreBuilder::new(
canvas_w,
canvas_h,
wgpu_surface_config.format,
)
.with_ratio(ratio_x, ratio_y)
.with_render_scale(render_scale);
let layer_data = crate::get_pixel_layer_data()
.expect("Layer data not loaded");
let layer_refs: Vec<&[u8]> = layer_data.layers.iter().map(|v| v.as_slice()).collect();
let render_core = builder
.build_layered(device, queue, layer_data.layer_size, &layer_refs)
.expect("Failed to build render core");
self.wgpu_instance = Some(wgpu_instance);
self.wgpu_surface = Some(wgpu_surface);
self.wgpu_surface_config = Some(wgpu_surface_config);
self.render_core = Some(render_core);
}
fn clear_screen_wgpu(&mut self) {
let mut cleared = false;
if let (Some(surface), Some(core)) = (&self.wgpu_surface, &self.render_core) {
if let Ok(output) = surface.get_current_texture() {
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = core.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Cursor Clear Screen Encoder"),
});
{
let _clear_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Cursor Clear Screen Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
store: wgpu::StoreOp::Store,
},
depth_slice: None,
})],
depth_stencil_attachment: None,
occlusion_query_set: None,
timestamp_writes: None,
});
}
core.queue.submit(std::iter::once(encoder.finish()));
output.present();
cleared = true;
}
}
if let Some(window) = &self.window {
window.set_visible(true);
}
let _ = cleared; }
fn set_mouse_cursor(&mut self) {
if let (Some(window), Some(event_loop)) = (&self.window, &self.event_loop) {
if let Some(cursor) = load_custom_cursor(event_loop) {
self.custom_cursor = Some(cursor.clone());
apply_cursor_to_window(window, &cursor);
}
}
}
fn rebuild_render_core(&mut self) {
if let Some(old_core) = self.render_core.take() {
let device = old_core.device;
let queue = old_core.queue;
let format = self.wgpu_surface_config.as_ref().unwrap().format;
let builder = WgpuRenderCoreBuilder::new(
self.base.gr.pixel_w,
self.base.gr.pixel_h,
format,
)
.with_ratio(self.base.gr.ratio_x, self.base.gr.ratio_y);
let layer_data = crate::get_pixel_layer_data()
.expect("Layer data not loaded");
let layer_refs: Vec<&[u8]> = layer_data.layers.iter().map(|v| v.as_slice()).collect();
let new_core = builder
.build_layered(device, queue, layer_data.layer_size, &layer_refs)
.expect("Failed to rebuild render core");
info!(
"Render core rebuilt: {}x{}, ratio: ({}, {})",
self.base.gr.pixel_w, self.base.gr.pixel_h,
self.base.gr.ratio_x, self.base.gr.ratio_y
);
self.render_core = Some(new_core);
}
}
#[allow(dead_code)]
fn in_border(&self, x: f64, y: f64) -> BorderArea {
check_border_area(x, y, &self.base)
}
fn draw_render_textures_to_screen_wgpu(&mut self) -> Result<(), String> {
let (cw, ch) = if let Some(core) = &self.render_core {
core.canvas_size()
} else {
return Err("render_core not initialized".to_string());
};
let (phys_w, phys_h) = if let Some(window) = &self.window {
let size = window.inner_size();
(size.width as f32, size.height as f32)
} else {
(cw as f32, ch as f32)
};
let (content_w, content_h) = if self.logical_content_w > 0.0 && self.logical_content_h > 0.0 {
(self.logical_content_w, self.logical_content_h)
} else {
(cw as f32, ch as f32)
};
let letterboxing = is_letterboxing_enabled();
let (scale_x, scale_y) = if letterboxing {
let content_aspect = content_w / content_h;
let window_aspect = phys_w / phys_h;
if window_aspect > content_aspect {
let scale = phys_h / content_h;
let scaled_w = content_w * scale;
(scaled_w / phys_w, 1.0)
} else {
let scale = phys_w / content_w;
let scaled_h = content_h * scale;
(1.0, scaled_h / phys_h)
}
} else {
(1.0, 1.0)
};
use std::sync::atomic::{AtomicBool, Ordering};
static LOGGED: AtomicBool = AtomicBool::new(false);
if !LOGGED.swap(true, Ordering::Relaxed) {
println!("=== Composition Debug (first frame) ===");
println!(" canvas (RT) = {}x{}", cw, ch);
println!(" physical (window) = {}x{}", phys_w, phys_h);
println!(" content_w/h (for letterbox) = {}x{}", content_w, content_h);
println!(" letterboxing = {}", letterboxing);
println!(" composition scale = ({:.4}, {:.4})", scale_x, scale_y);
println!("=======================================");
}
let mut rt2_transform = UnifiedTransform::new();
rt2_transform.scale(scale_x, scale_y);
let composites = vec![
RtComposite::fullscreen(2).transform(rt2_transform),
];
self.present_wgpu(&composites)
}
fn present_wgpu(&mut self, composites: &[RtComposite]) -> Result<(), String> {
if let (Some(surface), Some(core)) = (&self.wgpu_surface, &mut self.render_core) {
let output = surface
.get_current_texture()
.map_err(|e| format!("Failed to acquire next swap chain texture: {}", e))?;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
core.present(&view, composites);
output.present();
} else {
return Err("WGPU components not initialized".to_string());
}
Ok(())
}
}
impl Drop for WinitWgpuAdapter {
fn drop(&mut self) {
self.render_core.take();
self.wgpu_surface_config.take();
self.wgpu_surface.take();
self.wgpu_instance.take();
}
}
impl Adapter for WinitWgpuAdapter {
fn init(&mut self, w: u16, h: u16, rx: f32, ry: f32, title: String) {
info!("Initializing WinitWgpu adapter with WGPU backend...");
self.init_wgpu(w, h, rx, ry, title);
}
fn get_base(&mut self) -> &mut AdapterBase {
&mut self.base
}
fn get_canvas_size(&self) -> (u32, u32) {
if let Some(core) = &self.render_core {
core.canvas_size()
} else {
(self.base.gr.pixel_w, self.base.gr.pixel_h)
}
}
fn reset(&mut self) {}
fn poll_event(&mut self, timeout: Duration, es: &mut Vec<Event>) -> bool {
if let (Some(event_loop), Some(app_handler)) =
(self.event_loop.as_mut(), self.app_handler.as_mut())
{
let pump_timeout = Some(timeout);
let status = event_loop.pump_app_events(pump_timeout, app_handler);
for event in app_handler.pending_events.drain(..) {
if !self.drag.draging {
es.push(event);
}
}
if app_handler.should_exit {
return true;
}
if let PumpStatus::Exit(_) = status {
return true;
}
} else {
std::thread::sleep(timeout);
}
self.should_exit
}
fn draw_all(
&mut self,
current_buffer: &Buffer,
previous_buffer: &Buffer,
pixel_sprites: &mut Vec<Layer>,
stage: u32,
) -> Result<(), String> {
winit_move_win(
&mut self.drag.need,
self.window.as_deref(),
self.drag.dx,
self.drag.dy,
);
self.draw_all_graph(current_buffer, previous_buffer, pixel_sprites, stage);
self.post_draw();
Ok(())
}
fn post_draw(&mut self) {
if let Some(window) = &self.window {
window.as_ref().request_redraw();
}
}
fn hide_cursor(&mut self) -> Result<(), String> {
Ok(())
}
fn show_cursor(&mut self) -> Result<(), String> {
if let Some(window) = &self.window {
window.set_cursor_visible(true);
}
Ok(())
}
fn set_cursor(&mut self, _x: u16, _y: u16) -> Result<(), String> {
Ok(())
}
fn get_cursor(&mut self) -> Result<(u16, u16), String> {
Ok((0, 0))
}
fn as_any(&mut self) -> &mut dyn Any {
self
}
fn rbuf2rt(
&mut self,
rbuf: &[crate::render::adapter::RenderCell],
rtidx: usize,
debug: bool,
) where
Self: Sized,
{
let viewport_scale = if let (Some(window), Some(core)) = (&self.window, &self.render_core) {
let phys_h = window.inner_size().height as f32;
let (_, canvas_h) = core.canvas_size();
if canvas_h > 0 { phys_h / canvas_h as f32 } else { 1.0 }
} else {
1.0
};
if let Some(core) = &mut self.render_core {
core.set_viewport_scale(viewport_scale);
core.rbuf2rt(rbuf, rtidx, debug);
} else {
eprintln!("WinitWgpuAdapter: render core not initialized");
}
}
fn set_rt_visible(&mut self, texture_index: usize, visible: bool) {
if let Some(core) = &mut self.render_core {
core.set_rt_visible(texture_index, visible);
}
}
fn blend_rts(
&mut self,
src_texture1: usize,
src_texture2: usize,
dst_texture: usize,
effect_type: usize,
progress: f32,
) {
if let Some(core) = &mut self.render_core {
core.blend_rts(src_texture1, src_texture2, dst_texture, effect_type, progress);
}
}
fn setup_buffer_transition(&mut self, target_texture: usize) {
if let Some(core) = &mut self.render_core {
core.set_rt_visible(target_texture, false);
}
}
fn copy_rt(&mut self, src_index: usize, dst_index: usize) {
if let Some(core) = &mut self.render_core {
core.copy_rt(src_index, dst_index);
}
}
fn present(&mut self, composites: &[RtComposite]) {
if let Err(e) = self.present_wgpu(composites) {
eprintln!("WinitWgpuAdapter: Failed to present: {}", e);
}
}
fn present_default(&mut self) {
if let Err(e) = self.draw_render_textures_to_screen_wgpu() {
eprintln!("WinitWgpuAdapter: Failed to present_default: {}", e);
}
}
fn set_sharpness(&mut self, sharpness: f32) {
if let Some(core) = &mut self.render_core {
core.set_sharpness(sharpness);
}
}
fn set_msdf_enabled(&mut self, _enabled: bool) {
}
}