rust/hwrunner/src/main.rs
changeset 15798 c4d931ce2659
parent 15777 2b3f8af6f647
child 15892 b3295f94e5e9
equal deleted inserted replaced
15797:655d0e0d612a 15798:c4d931ce2659
     1 use std::time::Duration;
     1 use std::time::Duration;
     2 
     2 
     3 use futures::executor::block_on;
     3 use futures::executor::block_on;
       
     4 use glutin::event_loop::ControlFlow;
     4 use glutin::{
     5 use glutin::{
     5     dpi, ContextTrait, DeviceEvent, ElementState, Event, EventsLoop, GlProfile, GlRequest,
     6     dpi,
     6     MouseButton, MouseScrollDelta, Window, WindowBuilder, WindowEvent, WindowedContext,
     7     event::{DeviceEvent, ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent},
       
     8     event_loop::EventLoop,
       
     9     window::{Window, WindowBuilder},
       
    10     ContextWrapper, GlProfile, GlRequest, NotCurrent, PossiblyCurrent, WindowedContext,
     7 };
    11 };
     8 use hedgewars_engine::instance::EngineInstance;
    12 use hedgewars_engine::instance::EngineInstance;
     9 use integral_geometry::Point;
    13 use integral_geometry::Point;
    10 use std::error::Error;
    14 use std::error::Error;
    11 use wgpu::{
    15 use wgpu::{
    13     LoadOp, Operations, PowerPreference, PresentMode, Queue, RenderPassColorAttachmentDescriptor,
    17     LoadOp, Operations, PowerPreference, PresentMode, Queue, RenderPassColorAttachmentDescriptor,
    14     RenderPassDescriptor, RequestAdapterOptions, Surface, SwapChain, SwapChainDescriptor,
    18     RenderPassDescriptor, RequestAdapterOptions, Surface, SwapChain, SwapChainDescriptor,
    15     TextureFormat, TextureUsage,
    19     TextureFormat, TextureUsage,
    16 };
    20 };
    17 
    21 
    18 type HwGlRendererContext = WindowedContext;
    22 type HwGlRendererContext = ContextWrapper<PossiblyCurrent, Window>;
    19 
    23 
    20 struct HwWgpuRenderingContext {
    24 struct HwWgpuRenderingContext {
    21     window: Window,
    25     window: Window,
    22     surface: Surface,
    26     surface: Surface,
    23     adapter: Adapter,
    27     adapter: Adapter,
    39     }
    43     }
    40 }
    44 }
    41 
    45 
    42 impl HwRendererContext {
    46 impl HwRendererContext {
    43     fn get_framebuffer_size(window: &Window) -> (u32, u32) {
    47     fn get_framebuffer_size(window: &Window) -> (u32, u32) {
    44         let size = window.get_inner_size().unwrap();
    48         window.inner_size().into()
    45         (size.to_physical(window.get_hidpi_factor())).into()
       
    46     }
    49     }
    47 
    50 
    48     fn create_wpgu_swap_chain(window: &Window, surface: &Surface, device: &Device) -> SwapChain {
    51     fn create_wpgu_swap_chain(window: &Window, surface: &Surface, device: &Device) -> SwapChain {
    49         let (width, height) = Self::get_framebuffer_size(window);
    52         let (width, height) = Self::get_framebuffer_size(window);
    50         device.create_swap_chain(
    53         device.create_swap_chain(
    57                 present_mode: PresentMode::Fifo,
    60                 present_mode: PresentMode::Fifo,
    58             },
    61             },
    59         )
    62         )
    60     }
    63     }
    61 
    64 
    62     fn init_wgpu(event_loop: &EventsLoop, size: dpi::LogicalSize) -> HwWgpuRenderingContext {
    65     fn init_wgpu(
       
    66         event_loop: &EventLoop<()>,
       
    67         size: dpi::LogicalSize<f64>,
       
    68     ) -> HwWgpuRenderingContext {
    63         let builder = WindowBuilder::new()
    69         let builder = WindowBuilder::new()
    64             .with_title("hwengine")
    70             .with_title("hwengine")
    65             .with_dimensions(size);
    71             .with_inner_size(size);
    66         let window = builder.build(event_loop).unwrap();
    72         let window = builder.build(event_loop).unwrap();
    67 
    73 
    68         let instance = wgpu::Instance::new(BackendBit::VULKAN);
    74         let instance = wgpu::Instance::new(BackendBit::PRIMARY);
    69 
    75 
    70         let surface = unsafe { instance.create_surface(&window) };
    76         let surface = unsafe { instance.create_surface(&window) };
    71 
    77 
    72         let adapter = block_on(instance.request_adapter(&RequestAdapterOptions {
    78         let adapter = block_on(instance.request_adapter(&RequestAdapterOptions {
    73             power_preference: PowerPreference::HighPerformance,
    79             power_preference: PowerPreference::HighPerformance,
    87             queue,
    93             queue,
    88             swap_chain,
    94             swap_chain,
    89         }
    95         }
    90     }
    96     }
    91 
    97 
    92     fn init_gl(event_loop: &EventsLoop, size: dpi::LogicalSize) -> HwGlRendererContext {
    98     fn init_gl(event_loop: &EventLoop<()>, size: dpi::LogicalSize<f64>) -> HwGlRendererContext {
    93         use glutin::ContextBuilder;
    99         use glutin::ContextBuilder;
    94 
   100 
    95         let builder = WindowBuilder::new()
   101         let builder = WindowBuilder::new()
    96             .with_title("hwengine")
   102             .with_title("hwengine")
    97             .with_dimensions(size);
   103             .with_inner_size(size);
    98 
   104 
    99         let context = ContextBuilder::new()
   105         let context = ContextBuilder::new()
   100             .with_gl(GlRequest::Latest)
   106             .with_gl(GlRequest::Latest)
   101             .with_gl_profile(GlProfile::Core)
   107             .with_gl_profile(GlProfile::Core)
   102             .build_windowed(builder, &event_loop)
   108             .build_windowed(builder, &event_loop)
   103             .ok()
   109             .ok()
   104             .unwrap();
   110             .unwrap();
   105 
   111 
   106         unsafe {
   112         unsafe {
   107             context.make_current().unwrap();
   113             let wrapper = context.make_current().unwrap();
   108             gl::load_with(|ptr| context.get_proc_address(ptr) as *const _);
   114             gl::load_with(|ptr| wrapper.get_proc_address(ptr) as *const _);
   109 
   115 
   110             if let Some(sz) = context.get_inner_size() {
   116             let (width, height) = Self::get_framebuffer_size(wrapper.window());
   111                 let (width, height) = Self::get_framebuffer_size(context.window());
   117             gl::Viewport(0, 0, width as i32, height as i32);
   112                 gl::Viewport(0, 0, width as i32, height as i32);
   118             wrapper
   113             }
   119         }
   114         }
   120     }
   115 
   121 
   116         context
   122     fn new(event_loop: &EventLoop<()>, size: dpi::LogicalSize<f64>, use_wgpu: bool) -> Self {
   117     }
       
   118 
       
   119     fn new(event_loop: &EventsLoop, size: dpi::LogicalSize, use_wgpu: bool) -> Self {
       
   120         if use_wgpu {
   123         if use_wgpu {
   121             Self::Wgpu(Self::init_wgpu(event_loop, size))
   124             Self::Wgpu(Self::init_wgpu(event_loop, size))
   122         } else {
   125         } else {
   123             Self::Gl(Self::init_gl(event_loop, size))
   126             Self::Gl(Self::init_gl(event_loop, size))
   124         }
   127         }
   182         Ok(())
   185         Ok(())
   183     }
   186     }
   184 }
   187 }
   185 
   188 
   186 fn main() {
   189 fn main() {
   187     let use_wgpu = true;
   190     let use_wgpu = false;
   188     let mut event_loop = EventsLoop::new();
   191     let mut event_loop = EventLoop::<()>::new();
   189     let (w, h) = (1024.0, 768.0);
   192     let (w, h) = (1024.0, 768.0);
   190 
   193 
   191     let mut context = HwRendererContext::new(&event_loop, dpi::LogicalSize::new(w, h), use_wgpu);
   194     let mut context = HwRendererContext::new(&event_loop, dpi::LogicalSize::new(w, h), use_wgpu);
   192 
   195 
   193     let mut engine = EngineInstance::new();
   196     let mut engine = EngineInstance::new();
   201 
   204 
   202     let mut now = Instant::now();
   205     let mut now = Instant::now();
   203     let mut update_time = Instant::now();
   206     let mut update_time = Instant::now();
   204     let mut render_time = Instant::now();
   207     let mut render_time = Instant::now();
   205 
   208 
   206     let mut is_running = true;
   209     let current_time = Instant::now();
   207 
   210     let delta = current_time - now;
   208     while is_running {
   211     now = current_time;
   209         let current_time = Instant::now();
   212     let ms = delta.as_secs() as f64 * 1000.0 + delta.subsec_millis() as f64;
   210         let delta = current_time - now;
   213     context.window().set_title(&format!("hwengine {:.3}ms", ms));
   211         now = current_time;
   214 
   212         let ms = delta.as_secs() as f64 * 1000.0 + delta.subsec_millis() as f64;
   215     event_loop.run(move |event, _, control_flow| {
   213         context.window().set_title(&format!("hwengine {:.3}ms", ms));
   216         *control_flow = ControlFlow::Poll;
   214 
   217         match event {
   215         if update_time.elapsed() > Duration::from_millis(10) {
       
   216             update_time = current_time;
       
   217             engine.world.step()
       
   218         }
       
   219 
       
   220         event_loop.poll_events(|event| match event {
       
   221             Event::WindowEvent { event, .. } => match event {
   218             Event::WindowEvent { event, .. } => match event {
   222                 WindowEvent::CloseRequested => {
   219                 WindowEvent::CloseRequested => {
   223                     is_running = false;
   220                     *control_flow = ControlFlow::Exit;
   224                 }
   221                 }
   225                 WindowEvent::Resized(_) | WindowEvent::HiDpiFactorChanged(_) => context.update(),
   222                 WindowEvent::Resized(_) | WindowEvent::ScaleFactorChanged { .. } => {
       
   223                     context.update()
       
   224                 }
   226 
   225 
   227                 WindowEvent::MouseInput { button, state, .. } => {
   226                 WindowEvent::MouseInput { button, state, .. } => {
   228                     if let MouseButton::Right = button {
   227                     if let MouseButton::Right = button {
   229                         dragging = state == ElementState::Pressed;
   228                         dragging = state == ElementState::Pressed;
   230                     }
   229                     }
   231                 }
   230                 }
   232 
   231 
   233                 WindowEvent::MouseWheel { delta, .. } => {
   232                 WindowEvent::MouseWheel { delta, .. } => {
   234                     let zoom_change = match delta {
   233                     let zoom_change = match delta {
   235                         MouseScrollDelta::LineDelta(x, y) => y as f32 * 0.1f32,
   234                         MouseScrollDelta::LineDelta(x, y) => y as f32 * 0.1f32,
   236                         MouseScrollDelta::PixelDelta(delta) => {
   235                         MouseScrollDelta::PixelDelta(delta) => delta.y as f32 * 0.1f32,
   237                             let physical = delta.to_physical(context.window().get_hidpi_factor());
       
   238                             physical.y as f32 * 0.1f32
       
   239                         }
       
   240                     };
   236                     };
   241                     engine.world.move_camera(Point::ZERO, zoom_change);
   237                     engine.world.move_camera(Point::ZERO, zoom_change);
   242                 }
   238                 }
   243                 _ => (),
   239                 _ => (),
   244             },
   240             },
   250                             .move_camera(Point::new(delta.0 as i32, delta.1 as i32), 0.0)
   246                             .move_camera(Point::new(delta.0 as i32, delta.1 as i32), 0.0)
   251                     }
   247                     }
   252                 }
   248                 }
   253                 _ => {}
   249                 _ => {}
   254             },
   250             },
       
   251 
   255             _ => (),
   252             _ => (),
   256         });
   253         }
       
   254 
       
   255         let current_time = Instant::now();
       
   256 
       
   257         if update_time.elapsed() > Duration::from_millis(10) {
       
   258             update_time = current_time;
       
   259             engine.world.step()
       
   260         }
   257 
   261 
   258         if render_time.elapsed() > Duration::from_millis(16) {
   262         if render_time.elapsed() > Duration::from_millis(16) {
   259             render_time = current_time;
   263             render_time = current_time;
   260             if !use_wgpu {
   264             if !use_wgpu {
   261                 engine.render();
   265                 engine.render();
   262             }
   266             }
   263             context.present().ok().unwrap();
   267             context.present().ok().unwrap();
   264         }
   268         }
   265     }
   269     });
   266 }
   270 }