2019-05-03 09:33:58 +00:00
|
|
|
mod audio;
|
2019-09-02 21:23:26 +00:00
|
|
|
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::{
|
2019-08-20 05:23:02 +00:00
|
|
|
dpi::{LogicalSize, PhysicalPosition},
|
2019-11-11 16:29:33 +00:00
|
|
|
event::{ElementState, MouseButton, WindowEvent},
|
|
|
|
event_loop::{ControlFlow, EventLoop},
|
|
|
|
window::WindowBuilder,
|
|
|
|
ContextBuilder,
|
2019-05-03 18:44:12 +00:00
|
|
|
};
|
2019-09-02 21:23:26 +00:00
|
|
|
use ruffle_core::{backend::render::RenderBackend, Player};
|
2019-04-28 06:08:59 +00:00
|
|
|
use std::path::PathBuf;
|
2019-10-29 03:35:26 +00:00
|
|
|
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
|
|
|
|
2019-08-15 20:48:51 +00:00
|
|
|
fn run_player(input_path: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
2019-04-28 06:08:59 +00:00
|
|
|
let swf_data = std::fs::read(input_path)?;
|
|
|
|
|
2019-11-11 16:29:33 +00:00
|
|
|
let event_loop = EventLoop::new();
|
2019-05-08 16:46:19 +00:00
|
|
|
let window_builder = WindowBuilder::new().with_title("Ruffle");
|
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)
|
2019-11-11 16:29:33 +00:00
|
|
|
.build_windowed(window_builder, &event_loop)?;
|
2019-09-19 00:55:07 +00:00
|
|
|
let audio = audio::CpalAudioBackend::new()?;
|
2019-04-28 06:08:59 +00:00
|
|
|
let renderer = GliumRenderBackend::new(windowed_context)?;
|
2019-09-02 21:23:26 +00:00
|
|
|
let navigator = navigator::ExternalNavigatorBackend::new(); //TODO: actually implement this backend type
|
2019-05-01 00:46:32 +00:00
|
|
|
let display = renderer.display().clone();
|
2019-09-01 19:24:04 +00:00
|
|
|
let mut player = Player::new(renderer, audio, navigator, swf_data)?;
|
2019-08-09 21:50:20 +00:00
|
|
|
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();
|
2019-11-11 16:29:33 +00:00
|
|
|
let hidpi_factor = display.gl_window().window().hidpi_factor();
|
2019-05-01 00:46:32 +00:00
|
|
|
|
|
|
|
display
|
|
|
|
.gl_window()
|
|
|
|
.resize(logical_size.to_physical(hidpi_factor));
|
|
|
|
|
2019-08-20 05:23:02 +00:00
|
|
|
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
|
2019-11-11 16:29:33 +00:00
|
|
|
event_loop.run(move |event, _window_target, control_flow| {
|
|
|
|
*control_flow = ControlFlow::Poll;
|
|
|
|
match event {
|
|
|
|
glutin::event::Event::LoopDestroyed => return,
|
|
|
|
glutin::event::Event::WindowEvent { event, .. } => match event {
|
2019-08-10 17:18:32 +00:00
|
|
|
WindowEvent::Resized(logical_size) => {
|
|
|
|
let size = logical_size.to_physical(hidpi_factor);
|
2019-08-20 01:40:55 +00:00
|
|
|
player.set_viewport_dimensions(
|
|
|
|
size.width.ceil() as u32,
|
|
|
|
size.height.ceil() as u32,
|
|
|
|
);
|
2019-08-10 17:18:32 +00:00
|
|
|
player.renderer_mut().set_viewport_dimensions(
|
|
|
|
size.width.ceil() as u32,
|
|
|
|
size.height.ceil() as u32,
|
2019-08-20 01:40:55 +00:00
|
|
|
);
|
2019-08-10 17:18:32 +00:00
|
|
|
}
|
2019-05-03 18:44:12 +00:00
|
|
|
WindowEvent::CursorMoved { position, .. } => {
|
2019-08-20 05:23:02 +00:00
|
|
|
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 {
|
2019-08-20 05:23:02 +00:00
|
|
|
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 {
|
2019-08-20 05:23:02 +00:00
|
|
|
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 {
|
2019-08-20 05:23:02 +00:00
|
|
|
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
|
|
|
}
|
2019-11-11 16:29:33 +00:00
|
|
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
2019-05-03 18:44:12 +00:00
|
|
|
_ => (),
|
2019-11-11 16:29:33 +00:00
|
|
|
},
|
|
|
|
_ => (),
|
2019-05-03 18:44:12 +00:00
|
|
|
}
|
2019-04-28 06:08:59 +00:00
|
|
|
|
2019-11-11 16:29:33 +00:00
|
|
|
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
|
|
|
|
2019-11-11 16:29:33 +00:00
|
|
|
std::thread::sleep(player.time_til_next_frame());
|
|
|
|
});
|
2019-04-28 06:08:59 +00:00
|
|
|
}
|
2019-04-25 17:52:22 +00:00
|
|
|
}
|