Send Event to breakout main

This commit is contained in:
Richard Feldman 2022-04-10 10:13:33 -04:00
parent 5de57ef30a
commit 999dbfd9d1
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798
5 changed files with 131 additions and 77 deletions

View file

@ -5,47 +5,52 @@ app "breakout"
program = { render }
render = \state ->
numRows = 4
numCols = 8
numBlocks = numRows * numCols
render = \event ->
when event is
Resize size ->
numRows = 4
numCols = 8
numBlocks = numRows * numCols
blocks = List.map (List.range 0 numBlocks) \index ->
col =
Num.rem index numCols
|> Result.withDefault 0
|> Num.toF32
blocks = List.map (List.range 0 numBlocks) \index ->
col =
Num.rem index numCols
|> Result.withDefault 0
|> Num.toF32
row =
index // numCols
|> Result.withDefault 0
|> Num.toF32
row =
index // numCols
|> Result.withDefault 0
|> Num.toF32
red = (col / Num.toF32 numCols) |> Result.withDefault 0
green = ((row / Num.toF32 numRows) |> Result.withDefault 0)
blue = (Num.toF32 index / Num.toF32 numBlocks) |> Result.withDefault 0
red = (col / Num.toF32 numCols) |> Result.withDefault 0
green = ((row / Num.toF32 numRows) |> Result.withDefault 0)
blue = (Num.toF32 index / Num.toF32 numBlocks) |> Result.withDefault 0
color = { r: red * 0.8, g: 0.2 + green * 0.6, b: 0.2 + blue * 0.8, a: 1 }
color = { r: red * 0.8, g: 0.2 + green * 0.6, b: 0.2 + blue * 0.8, a: 1 }
{ row, col, color }
{ row, col, color }
blockWidth = state.width / numCols |> Result.withDefault 0
blockHeight = 80
blockWidth = size.width / numCols |> Result.withDefault 0
blockHeight = 80
rects =
List.map blocks \{ row, col, color } ->
left = Num.toF32 col * blockWidth
top = Num.toF32 (row * blockHeight)
rects =
List.map blocks \{ row, col, color } ->
left = Num.toF32 col * blockWidth
top = Num.toF32 (row * blockHeight)
Rect { left, top, width: blockWidth, height: blockHeight, color }
Rect { left, top, width: blockWidth, height: blockHeight, color }
paddle =
color = { r: 0.8, g: 0.8, b: 0.8, a: 1.0 }
width = state.width * 0.25
height = blockHeight
left = (state.width * 0.5) - (width * 0.5)
top = state.height - (height * 2)
paddle =
color = { r: 0.8, g: 0.8, b: 0.8, a: 1.0 }
width = size.width * 0.25
height = blockHeight
left = (size.width * 0.5) - (width * 0.5)
top = size.height - (height * 2)
Rect { left, top, width, height, color }
Rect { left, top, width, height, color }
List.append rects paddle
List.append rects paddle
_ ->
[ Text "TODO handle other events than Resize!" ]

View file

@ -9,8 +9,8 @@ Rgba : { r : F32, g : F32, b : F32, a : F32 }
Elem : [ Rect { color : Rgba, left : F32, top : F32, width : F32, height : F32 }, Text Str ]
State : { width : F32, height : F32 }
Event : [ Resize { width : F32, height : F32 }, KeyDown U32, KeyUp U32 ]
# TODO allow changing the window title - maybe via a Task, since that shouldn't happen all the time
programForHost : { render : (State -> List Elem) as Render }
programForHost : { render : (Event -> List Elem) as Render }
programForHost = program

View file

@ -9,7 +9,7 @@ use crate::{
text::build_glyph_brush,
},
},
roc::{self, RocElem, RocElemTag},
roc::{self, Bounds, RocElem, RocElemTag, RocEvent},
};
use cgmath::{Vector2, Vector4};
use glyph_brush::{GlyphCruncher, OwnedSection};
@ -23,7 +23,7 @@ use wgpu_glyph::GlyphBrush;
use winit::{
dpi::PhysicalSize,
event,
event::{Event, ModifiersState},
event::{ElementState, Event, ModifiersState},
event_loop::ControlFlow,
platform::run_return::EventLoopExtRunReturn,
};
@ -36,17 +36,17 @@ use winit::{
const TIME_BETWEEN_RENDERS: Duration = Duration::new(0, 1000 / 60);
pub fn run_event_loop(title: &str, state: roc::State) -> Result<(), Box<dyn Error>> {
pub fn run_event_loop(title: &str, window_bounds: Bounds) -> Result<(), Box<dyn Error>> {
// Open window and create a surface
let mut event_loop = winit::event_loop::EventLoop::new();
let window = winit::window::WindowBuilder::new()
.with_inner_size(PhysicalSize::new(state.width, state.height))
.with_inner_size(PhysicalSize::new(window_bounds.width, window_bounds.height))
.with_title(title)
.build(&event_loop)
.unwrap();
let mut elems = roc::app_render(state);
let mut elems = roc::app_render(RocEvent::resize(window_bounds));
let instance = wgpu::Instance::new(wgpu::Backends::all());
@ -150,10 +150,10 @@ pub fn run_event_loop(title: &str, state: roc::State) -> Result<(), Box<dyn Erro
&cmd_queue,
);
elems = roc::app_render(roc::State {
elems = roc::app_render(RocEvent::resize(Bounds {
height: size.height as f32,
width: size.width as f32,
});
}));
window.request_redraw();
}
@ -171,27 +171,14 @@ pub fn run_event_loop(title: &str, state: roc::State) -> Result<(), Box<dyn Erro
},
..
} => {
use event::ElementState::*;
use event::VirtualKeyCode::*;
match keycode {
Left => match input_state {
Pressed => println!("Left pressed!"),
Released => println!("Left released!"),
},
Right => match input_state {
Pressed => println!("Right pressed!"),
Released => println!("Right released!"),
},
_ => {
println!("Other!");
}
let roc_event = match input_state {
ElementState::Pressed => RocEvent::key_down(keycode),
ElementState::Released => RocEvent::key_up(keycode),
};
elems = roc::app_render(roc::State {
height: size.height as f32,
width: size.width as f32,
});
elems = roc::app_render(roc_event);
window.request_redraw();
}
//Modifiers Changed
Event::WindowEvent {
@ -318,12 +305,6 @@ fn begin_render_pass<'a>(
})
}
#[derive(Copy, Clone, Debug, Default)]
pub struct Bounds {
pub height: f32,
pub width: f32,
}
#[derive(Clone, Debug)]
struct Drawable {
pos: Vector2<f32>,

View file

@ -4,12 +4,12 @@ mod roc;
#[no_mangle]
pub extern "C" fn rust_main() -> i32 {
let state = roc::State {
let bounds = roc::Bounds {
width: 1900.0,
height: 1000.0,
};
gui::run_event_loop("RocOut!", state).expect("Error running event loop");
gui::run_event_loop("RocOut!", bounds).expect("Error running event loop");
// Exit code
0

View file

@ -7,13 +7,14 @@ use std::ffi::CStr;
use std::fmt::Debug;
use std::mem::MaybeUninit;
use std::os::raw::c_char;
use winit::event::VirtualKeyCode;
extern "C" {
#[link_name = "roc__programForHost_1_exposed_generic"]
fn roc_program() -> ();
#[link_name = "roc__programForHost_1_Render_caller"]
fn call_Render(state: *const State, closure_data: *const u8, output: *mut RocList<RocElem>);
fn call_Render(event: *const RocEvent, closure_data: *const u8, output: *mut RocList<RocElem>);
#[link_name = "roc__programForHost_size"]
fn roc_program_size() -> i64;
@ -23,11 +24,71 @@ extern "C" {
fn size_Render() -> i64;
}
#[derive(Debug)]
#[repr(C)]
pub struct State {
pub height: f32,
pub width: f32,
pub union RocEventEntry {
pub key_down: winit::event::VirtualKeyCode,
pub key_up: winit::event::VirtualKeyCode,
pub resize: Bounds,
}
#[repr(u8)]
#[allow(unused)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RocEventTag {
KeyDown = 0,
KeyUp = 1,
Resize = 2,
}
#[repr(C)]
#[cfg(target_pointer_width = "64")] // on a 64-bit system, the tag fits in this pointer's spare 3 bits
pub struct RocEvent {
entry: RocEventEntry,
tag: RocEventTag,
}
impl Debug for RocEvent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use RocEventTag::*;
match self.tag() {
KeyDown => unsafe { self.entry().key_down }.fmt(f),
KeyUp => unsafe { self.entry().key_up }.fmt(f),
Resize => unsafe { self.entry().resize }.fmt(f),
}
}
}
impl RocEvent {
#[cfg(target_pointer_width = "64")]
pub fn tag(&self) -> RocEventTag {
self.tag
}
pub fn entry(&self) -> &RocEventEntry {
&self.entry
}
pub fn resize(size: Bounds) -> Self {
Self {
tag: RocEventTag::Resize,
entry: RocEventEntry { resize: size },
}
}
pub fn key_down(keycode: VirtualKeyCode) -> Self {
Self {
tag: RocEventTag::KeyDown,
entry: RocEventEntry { key_down: keycode },
}
}
pub fn key_up(keycode: VirtualKeyCode) -> Self {
Self {
tag: RocEventTag::KeyUp,
entry: RocEventEntry { key_up: keycode },
}
}
}
#[no_mangle]
@ -193,7 +254,7 @@ pub struct ButtonStyles {
pub text_color: Rgba,
}
pub fn app_render(state: State) -> RocList<RocElem> {
pub fn app_render(state: RocEvent) -> RocList<RocElem> {
let size = unsafe { roc_program_size() } as usize;
let layout = Layout::array::<u8>(size).unwrap();
@ -212,10 +273,17 @@ pub fn app_render(state: State) -> RocList<RocElem> {
}
}
unsafe fn call_the_closure(state: State, closure_data_ptr: *const u8) -> RocList<RocElem> {
unsafe fn call_the_closure(event: RocEvent, closure_data_ptr: *const u8) -> RocList<RocElem> {
let mut output = MaybeUninit::uninit();
call_Render(&state, closure_data_ptr as *const u8, output.as_mut_ptr());
call_Render(&event, closure_data_ptr as *const u8, output.as_mut_ptr());
output.assume_init()
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct Bounds {
pub height: f32,
pub width: f32,
}