ruffle/desktop/src/main.rs

157 lines
5.7 KiB
Rust
Raw Normal View History

#![allow(clippy::unneeded_field_pattern)]
2019-05-03 09:33:58 +00:00
mod audio;
mod input;
mod navigator;
2019-09-17 03:37:11 +00:00
mod render;
2019-05-03 02:11:47 +00:00
use crate::render::GliumRenderBackend;
2019-05-03 18:44:12 +00:00
use glutin::{
dpi::{LogicalSize, PhysicalPosition},
event::{ElementState, MouseButton, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
ContextBuilder,
2019-05-03 18:44:12 +00:00
};
use ruffle_core::{
backend::audio::{AudioBackend, NullAudioBackend},
backend::render::RenderBackend,
Player,
};
2019-04-28 06:08:59 +00:00
use std::path::PathBuf;
use std::time::Instant;
2019-04-28 06:08:59 +00:00
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(name = "basic")]
struct Opt {
#[structopt(name = "FILE", parse(from_os_str))]
input_path: PathBuf,
}
2019-04-25 17:52:22 +00:00
2019-04-27 01:55:06 +00:00
fn main() {
2019-05-02 00:46:49 +00:00
env_logger::init();
2019-04-28 06:08:59 +00:00
let opt = Opt::from_args();
let ret = run_player(opt.input_path);
if let Err(e) = ret {
eprintln!("Fatal error:\n{}", e);
std::process::exit(-1);
2019-04-25 17:52:22 +00:00
}
2019-04-28 06:08:59 +00:00
}
2019-04-25 17:52:22 +00:00
fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
let swf_data = std::fs::read(&input_path)?;
2019-04-28 06:08:59 +00:00
let event_loop = EventLoop::new();
let window_builder = WindowBuilder::new().with_title(format!(
"Ruffle - {}",
input_path.file_name().unwrap_or_default().to_string_lossy()
));
2019-05-01 06:05:16 +00:00
let windowed_context = ContextBuilder::new()
.with_vsync(true)
.with_multisampling(4)
.with_srgb(true)
2019-09-08 02:33:06 +00:00
.with_stencil_buffer(8)
.build_windowed(window_builder, &event_loop)?;
let audio: Box<dyn AudioBackend> = match audio::CpalAudioBackend::new() {
Ok(audio) => Box::new(audio),
Err(e) => {
log::error!("Unable to create audio device: {}", e);
Box::new(NullAudioBackend::new())
}
};
2019-04-28 06:08:59 +00:00
let renderer = GliumRenderBackend::new(windowed_context)?;
let navigator = navigator::ExternalNavigatorBackend::new(); //TODO: actually implement this backend type
2019-05-01 00:46:32 +00:00
let display = renderer.display().clone();
let input = input::WinitInputBackend::new(display.clone());
let mut player = Player::new(renderer, audio, navigator, input, swf_data)?;
player.set_is_playing(true); // Desktop player will auto-play.
2019-04-26 03:27:44 +00:00
2019-05-01 00:46:32 +00:00
let logical_size: LogicalSize = (player.movie_width(), player.movie_height()).into();
let hidpi_factor = display.gl_window().window().hidpi_factor();
2019-05-01 00:46:32 +00:00
// Set initial size to movie dimensions.
display.gl_window().window().set_inner_size(logical_size);
2019-05-01 00:46:32 +00:00
display
.gl_window()
.resize(logical_size.to_physical(hidpi_factor));
let mut mouse_pos = PhysicalPosition::new(0.0, 0.0);
2019-04-28 06:08:59 +00:00
let mut time = Instant::now();
loop {
// Poll UI events
event_loop.run(move |event, _window_target, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
glutin::event::Event::LoopDestroyed => return,
glutin::event::Event::WindowEvent { event, .. } => match event {
WindowEvent::Resized(logical_size) => {
let size = logical_size.to_physical(hidpi_factor);
player.set_viewport_dimensions(
size.width.ceil() as u32,
size.height.ceil() as u32,
);
player.renderer_mut().set_viewport_dimensions(
size.width.ceil() as u32,
size.height.ceil() as u32,
);
}
2019-05-03 18:44:12 +00:00
WindowEvent::CursorMoved { position, .. } => {
let position = position.to_physical(hidpi_factor);
2019-05-03 18:44:12 +00:00
mouse_pos = position;
2019-08-19 14:53:12 +00:00
let event = ruffle_core::PlayerEvent::MouseMove {
x: position.x,
y: position.y,
2019-08-17 01:04:26 +00:00
};
player.handle_event(event);
2019-05-03 18:44:12 +00:00
}
WindowEvent::MouseInput {
button: MouseButton::Left,
2019-08-17 01:04:26 +00:00
state: pressed,
2019-05-03 18:44:12 +00:00
..
2019-08-14 19:39:26 +00:00
} => {
2019-08-17 01:04:26 +00:00
let event = if pressed == ElementState::Pressed {
2019-08-19 14:53:12 +00:00
ruffle_core::PlayerEvent::MouseDown {
x: mouse_pos.x,
y: mouse_pos.y,
2019-08-17 01:04:26 +00:00
}
} else {
2019-08-19 14:53:12 +00:00
ruffle_core::PlayerEvent::MouseUp {
x: mouse_pos.x,
y: mouse_pos.y,
2019-08-17 01:04:26 +00:00
}
};
player.handle_event(event);
}
WindowEvent::CursorLeft { .. } => {
2019-08-19 14:53:12 +00:00
player.handle_event(ruffle_core::PlayerEvent::MouseLeft)
2019-08-14 19:39:26 +00:00
}
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
2019-12-24 10:41:35 +00:00
WindowEvent::KeyboardInput { .. } | WindowEvent::ReceivedCharacter(_) => {
if let Some(event) = player.input_mut().handle_event(event) {
player.handle_event(event);
}
}
2019-05-03 18:44:12 +00:00
_ => (),
},
_ => (),
2019-05-03 18:44:12 +00:00
}
2019-04-28 06:08:59 +00:00
// After polling events, sleep the event loop until the next event or the next frame.
if *control_flow == ControlFlow::Wait {
let new_time = Instant::now();
let dt = new_time.duration_since(time).as_micros();
if dt > 0 {
time = new_time;
player.tick(dt as f64 / 1000.0);
}
2019-04-28 06:08:59 +00:00
*control_flow = ControlFlow::WaitUntil(new_time + player.time_til_next_frame());
}
});
2019-04-28 06:08:59 +00:00
}
2019-04-25 17:52:22 +00:00
}