use crate::config::WindowConfig;
use crate::{
App, Backend, BackendSystem, CursorIcon, EventIterator, FrameState, InitializeFn, WindowBackend,
};
use notan_graphics::prelude::*;
use std::any::Any;
#[cfg(feature = "audio")]
use std::cell::RefCell;
#[cfg(feature = "audio")]
use std::rc::Rc;
#[cfg(feature = "audio")]
use notan_audio::AudioBackend;
#[derive(Default)]
pub struct EmptyWindowBackend {
title: String,
size: (u32, u32),
position: (i32, i32),
is_fullscreen: bool,
is_focused: bool,
is_always_on_top: bool,
lazy: bool,
captured: bool,
visible: bool,
mouse_passthrough: bool,
touch_as_mouse: bool,
}
impl WindowBackend for EmptyWindowBackend {
fn capture_cursor(&self) -> bool {
self.captured
}
fn cursor(&self) -> CursorIcon {
CursorIcon::Default
}
fn dpi(&self) -> f64 {
1.0
}
fn id(&self) -> u64 {
0
}
fn is_always_on_top(&self) -> bool {
self.is_always_on_top
}
fn is_fullscreen(&self) -> bool {
self.is_fullscreen
}
fn is_focused(&self) -> bool {
self.is_focused
}
fn lazy_loop(&self) -> bool {
self.lazy
}
fn mouse_passthrough(&mut self) -> bool {
self.mouse_passthrough
}
fn position(&self) -> (i32, i32) {
self.position
}
fn request_frame(&mut self) {
}
fn screen_size(&self) -> (i32, i32) {
(0, 0)
}
fn set_always_on_top(&mut self, enabled: bool) {
self.is_always_on_top = enabled;
}
fn set_capture_cursor(&mut self, capture: bool) {
self.captured = capture;
}
fn set_cursor(&mut self, _cursor: CursorIcon) {}
fn set_cursor_position(&mut self, _x: f32, _y: f32) {}
fn set_fullscreen(&mut self, enabled: bool) {
self.is_fullscreen = enabled;
}
fn set_lazy_loop(&mut self, lazy: bool) {
self.lazy = lazy;
}
fn set_mouse_passthrough(&mut self, pass_through: bool) {
self.mouse_passthrough = pass_through;
}
fn set_position(&mut self, x: i32, y: i32) {
self.position = (x, y);
}
fn set_size(&mut self, width: u32, height: u32) {
self.size = (width, height);
}
fn set_visible(&mut self, visible: bool) {
self.visible = visible;
}
fn size(&self) -> (u32, u32) {
self.size
}
fn visible(&self) -> bool {
self.visible
}
fn set_title(&mut self, title: &str) {
self.title = title.to_string();
}
fn title(&self) -> &str {
&self.title
}
fn set_touch_as_mouse(&mut self, enable: bool) {
self.touch_as_mouse = enable;
}
fn touch_as_mouse(&self) -> bool {
self.touch_as_mouse
}
}
#[derive(Default)]
pub struct EmptyBackend {
window: EmptyWindowBackend,
}
impl EmptyBackend {
pub fn new() -> Result<Self, String> {
Ok(Default::default())
}
}
impl Backend for EmptyBackend {
fn window(&mut self) -> &mut dyn WindowBackend {
&mut self.window
}
fn set_clipboard_text(&mut self, _text: &str) {}
fn events_iter(&mut self) -> EventIterator {
Default::default()
}
fn exit(&mut self) {}
fn system_timestamp(&self) -> u64 {
0
}
fn open_link(&self, _url: &str, _new_tab: bool) {
}
}
impl BackendSystem for EmptyBackend {
fn initialize<S, R>(&mut self, _config: WindowConfig) -> Result<Box<InitializeFn<S, R>>, String>
where
S: 'static,
R: FnMut(&mut App, &mut S) -> Result<FrameState, String> + 'static,
{
Ok(Box::new(|mut app: App, mut state: S, mut cb: R| {
if let Err(e) = cb(&mut app, &mut state) {
log::error!("{}", e);
}
Ok(())
}))
}
fn get_graphics_backend(&self) -> Box<dyn DeviceBackend> {
Box::<EmptyDeviceBackend>::default()
}
#[cfg(feature = "audio")]
fn get_audio_backend(&self) -> Rc<RefCell<dyn AudioBackend>> {
Rc::new(RefCell::new(EmptyAudioBackend::default()))
}
}
#[derive(Default)]
struct EmptyDeviceBackend {
id_count: u64,
}
impl DeviceBackend for EmptyDeviceBackend {
fn api_name(&self) -> &str {
""
}
fn stats(&self) -> GpuStats {
GpuStats::default()
}
fn reset_stats(&mut self) {
}
fn create_pipeline(
&mut self,
_vertex_source: &[u8],
_fragment_source: &[u8],
_vertex_attrs: &[VertexAttr],
_texture_locations: &[(u32, String)],
_options: PipelineOptions,
) -> Result<u64, String> {
self.id_count += 1;
Ok(self.id_count)
}
fn create_vertex_buffer(
&mut self,
_attrs: &[VertexAttr],
_step_mode: VertexStepMode,
) -> Result<u64, String> {
self.id_count += 1;
Ok(self.id_count)
}
fn create_index_buffer(&mut self, _format: IndexFormat) -> Result<u64, String> {
self.id_count += 1;
Ok(self.id_count)
}
fn create_uniform_buffer(&mut self, _slot: u32, _name: &str) -> Result<u64, String> {
self.id_count += 1;
Ok(self.id_count)
}
fn set_buffer_data(&mut self, _id: u64, _data: &[u8]) {}
fn render(&mut self, commands: &[Commands], _target: Option<u64>) {
commands.iter().for_each(|cmd| log::info!("{:?}", cmd));
}
fn clean(&mut self, to_clean: &[ResourceId]) {
log::info!("{:?}", to_clean);
}
fn set_size(&mut self, _width: u32, _height: u32) {}
fn set_dpi(&mut self, _scale_factor: f64) {}
fn create_texture(
&mut self,
_source: TextureSourceKind,
info: TextureInfo,
) -> Result<(u64, TextureInfo), String> {
self.id_count += 1;
Ok((self.id_count, info))
}
fn create_render_texture(
&mut self,
_texture_id: u64,
_info: &TextureInfo,
) -> Result<u64, String> {
self.id_count += 1;
Ok(self.id_count)
}
fn update_texture(
&mut self,
_texture: u64,
_source: TextureUpdaterSourceKind,
_opts: TextureUpdate,
) -> Result<(), String> {
Ok(())
}
fn read_pixels(
&mut self,
_texture: u64,
_bytes: &mut [u8],
_opts: &TextureRead,
) -> Result<(), String> {
Ok(())
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
#[cfg(feature = "audio")]
#[derive(Default)]
pub struct EmptyAudioBackend {
id_count: u64,
volume: f32,
}
#[cfg(feature = "audio")]
impl AudioBackend for EmptyAudioBackend {
fn set_global_volume(&mut self, volume: f32) {
self.volume = volume;
}
fn global_volume(&self) -> f32 {
self.volume
}
fn create_source(&mut self, _bytes: &[u8]) -> Result<u64, String> {
let id = self.id_count;
self.id_count += 1;
Ok(id)
}
fn play_sound(&mut self, _source: u64, _volume: f32, _repeat: bool) -> Result<u64, String> {
let id = self.id_count;
self.id_count += 1;
Ok(id)
}
fn pause(&mut self, _sound: u64) {}
fn resume(&mut self, _sound: u64) {}
fn stop(&mut self, _sound: u64) {}
fn is_stopped(&mut self, _sound: u64) -> bool {
false
}
fn is_paused(&mut self, _sound: u64) -> bool {
false
}
fn set_volume(&mut self, _sound: u64, _volume: f32) {}
fn volume(&self, _sound: u64) -> f32 {
0.0
}
fn clean(&mut self, _sources: &[u64], _sounds: &[u64]) {}
}