mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Pass RocButton all the way to rendering
This commit is contained in:
parent
683b505e3a
commit
4399a6dfee
8 changed files with 202 additions and 312 deletions
|
@ -1,9 +1,19 @@
|
||||||
use cgmath::Vector2;
|
use cgmath::Vector2;
|
||||||
|
|
||||||
|
/// These fields are ordered this way because in Roc, the corresponding stuct is:
|
||||||
|
///
|
||||||
|
/// { top : F32, left : F32, width : F32, height : F32 }
|
||||||
|
///
|
||||||
|
/// alphabetically, that's { height, left, top, width } - which works out to the same as:
|
||||||
|
///
|
||||||
|
/// height: f32, pos: Vector2<f32>, width: f32
|
||||||
|
///
|
||||||
|
/// ...because Vector2<f32> is a repr(C) struct of { x: f32, y: f32 }
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
|
pub color: (f32, f32, f32, f32),
|
||||||
|
pub height: f32,
|
||||||
pub top_left_coords: Vector2<f32>,
|
pub top_left_coords: Vector2<f32>,
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub height: f32,
|
|
||||||
pub color: (f32, f32, f32, f32),
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,4 @@ app "hello-gui"
|
||||||
render =
|
render =
|
||||||
# btn = button { onPress : \prev, _ -> Action.none } (text "Hello, button!")
|
# btn = button { onPress : \prev, _ -> Action.none } (text "Hello, button!")
|
||||||
|
|
||||||
Button (Text "Hello, World!")
|
Button (Text "Hello, World!") { left: 300, top: 400, height: 300, width: 400 }
|
||||||
|
|
|
@ -5,7 +5,9 @@ platform "examples/hello-world"
|
||||||
imports []
|
imports []
|
||||||
provides [ renderForHost ]
|
provides [ renderForHost ]
|
||||||
|
|
||||||
Elem : [ Text Str, Button Elem ]
|
Dim : { left : F32, top : F32, width : F32, height : F32 }
|
||||||
|
|
||||||
|
Elem : [ Button Elem Dim, Col (List Elem), Row (List Elem), Text Str ]
|
||||||
|
|
||||||
renderForHost : Elem
|
renderForHost : Elem
|
||||||
renderForHost = render
|
renderForHost = render
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
//
|
//
|
||||||
// Thank you, Benjamin!
|
// Thank you, Benjamin!
|
||||||
|
|
||||||
|
|
||||||
// Contains parts of https://github.com/iced-rs/iced/blob/adce9e04213803bd775538efddf6e7908d1c605e/wgpu/src/shader/quad.wgsl
|
// Contains parts of https://github.com/iced-rs/iced/blob/adce9e04213803bd775538efddf6e7908d1c605e/wgpu/src/shader/quad.wgsl
|
||||||
// By Héctor Ramón, Iced contributors Licensed under the MIT license.
|
// By Héctor Ramón, Iced contributors Licensed under the MIT license.
|
||||||
// The license is included in the LEGAL_DETAILS file in the root directory of this distribution.
|
// The license is included in the LEGAL_DETAILS file in the root directory of this distribution.
|
||||||
|
@ -13,9 +12,9 @@
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use super::{vertex::Vertex, quad::Quad};
|
use super::{quad::Quad, vertex::Vertex};
|
||||||
use crate::graphics::{colors::to_slice, primitives::rect::RectElt};
|
use crate::graphics::{colors::to_slice, primitives::rect::RectElt};
|
||||||
use wgpu::util::{ DeviceExt};
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
pub struct RectBuffers {
|
pub struct RectBuffers {
|
||||||
pub vertex_buffer: wgpu::Buffer,
|
pub vertex_buffer: wgpu::Buffer,
|
||||||
|
@ -47,7 +46,6 @@ pub fn create_rect_buffers(
|
||||||
cmd_encoder: &mut wgpu::CommandEncoder,
|
cmd_encoder: &mut wgpu::CommandEncoder,
|
||||||
rects: &[RectElt],
|
rects: &[RectElt],
|
||||||
) -> RectBuffers {
|
) -> RectBuffers {
|
||||||
|
|
||||||
let vertex_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let vertex_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
contents: bytemuck::cast_slice(&QUAD_VERTS),
|
contents: bytemuck::cast_slice(&QUAD_VERTS),
|
||||||
|
@ -67,10 +65,9 @@ pub fn create_rect_buffers(
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let quads: Vec<Quad> = rects.iter().map(|rect| to_quad(rect)).collect();
|
||||||
let quads: Vec<Quad> = rects.iter().map(|rect| {to_quad(rect)}).collect();
|
|
||||||
|
|
||||||
let buffer_size = (quads.len() as u64 ) * Quad::SIZE;
|
let buffer_size = (quads.len() as u64) * Quad::SIZE;
|
||||||
|
|
||||||
let staging_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
let staging_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
|
@ -79,7 +76,6 @@ pub fn create_rect_buffers(
|
||||||
});
|
});
|
||||||
|
|
||||||
cmd_encoder.copy_buffer_to_buffer(&staging_buffer, 0, &quad_buffer, 0, buffer_size);
|
cmd_encoder.copy_buffer_to_buffer(&staging_buffer, 0, &quad_buffer, 0, buffer_size);
|
||||||
|
|
||||||
|
|
||||||
RectBuffers {
|
RectBuffers {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
|
@ -90,7 +86,7 @@ pub fn create_rect_buffers(
|
||||||
|
|
||||||
pub fn to_quad(rect_elt: &RectElt) -> Quad {
|
pub fn to_quad(rect_elt: &RectElt) -> Quad {
|
||||||
Quad {
|
Quad {
|
||||||
pos: rect_elt.rect.top_left_coords.into(),
|
pos: rect_elt.rect.pos.into(),
|
||||||
width: rect_elt.rect.width,
|
width: rect_elt.rect.width,
|
||||||
height: rect_elt.rect.height,
|
height: rect_elt.rect.height,
|
||||||
color: to_slice(rect_elt.color),
|
color: to_slice(rect_elt.color),
|
||||||
|
|
|
@ -8,9 +8,19 @@ pub struct RectElt {
|
||||||
pub border_color: (f32, f32, f32, f32),
|
pub border_color: (f32, f32, f32, f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// These fields are ordered this way because in Roc, the corresponding stuct is:
|
||||||
|
///
|
||||||
|
/// { top : F32, left : F32, width : F32, height : F32 }
|
||||||
|
///
|
||||||
|
/// alphabetically, that's { height, left, top, width } - which works out to the same as:
|
||||||
|
///
|
||||||
|
/// struct Rect { height: f32, pos: Vector2<f32>, width: f32 }
|
||||||
|
///
|
||||||
|
/// ...because Vector2<f32> is a repr(C) struct of { x: f32, y: f32 }
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
pub top_left_coords: Vector2<f32>,
|
|
||||||
pub width: f32,
|
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
|
pub pos: Vector2<f32>,
|
||||||
|
pub width: f32,
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ fn glyph_to_rect(glyph: &wgpu_glyph::SectionGlyph) -> Rect {
|
||||||
let top_y = glyph_top_y(&glyph.glyph);
|
let top_y = glyph_top_y(&glyph.glyph);
|
||||||
|
|
||||||
Rect {
|
Rect {
|
||||||
top_left_coords: [position.x, top_y].into(),
|
pos: [position.x, top_y].into(),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,14 @@ use crate::{
|
||||||
graphics::{
|
graphics::{
|
||||||
colors::{self, from_hsb, to_wgpu_color},
|
colors::{self, from_hsb, to_wgpu_color},
|
||||||
lowlevel::buffer::create_rect_buffers,
|
lowlevel::buffer::create_rect_buffers,
|
||||||
lowlevel::{ortho::update_ortho_buffer, buffer::MAX_QUADS},
|
lowlevel::{buffer::MAX_QUADS, ortho::update_ortho_buffer},
|
||||||
lowlevel::{pipelines, buffer::QUAD_INDICES},
|
lowlevel::{buffer::QUAD_INDICES, pipelines},
|
||||||
primitives::{text::{build_glyph_brush, Text}, rect::{Rect, RectElt}},
|
primitives::{
|
||||||
|
rect::{Rect, RectElt},
|
||||||
|
text::{build_glyph_brush, Text},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rects_and_texts::RectsAndTexts,
|
roc::{RocElem, RocElemTag},
|
||||||
};
|
};
|
||||||
use pipelines::RectResources;
|
use pipelines::RectResources;
|
||||||
use roc_std::RocStr;
|
use roc_std::RocStr;
|
||||||
|
@ -26,7 +29,7 @@ use winit::{
|
||||||
//
|
//
|
||||||
// See this link to learn wgpu: https://sotrh.github.io/learn-wgpu/
|
// See this link to learn wgpu: https://sotrh.github.io/learn-wgpu/
|
||||||
|
|
||||||
fn run_event_loop(title: &str, rects_and_texts: RectsAndTexts) -> Result<(), Box<dyn Error>> {
|
fn run_event_loop(title: &str, root: RocElem) -> Result<(), Box<dyn Error>> {
|
||||||
// Open window and create a surface
|
// Open window and create a surface
|
||||||
let mut event_loop = winit::event_loop::EventLoop::new();
|
let mut event_loop = winit::event_loop::EventLoop::new();
|
||||||
|
|
||||||
|
@ -197,36 +200,36 @@ fn run_event_loop(title: &str, rects_and_texts: RectsAndTexts) -> Result<(), Box
|
||||||
.texture
|
.texture
|
||||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
draw_rects(
|
// for text_section in &rects_and_texts.text_sections_behind {
|
||||||
&rects_and_texts.rects_behind,
|
// let borrowed_text = text_section.to_borrowed();
|
||||||
&mut cmd_encoder,
|
|
||||||
&view,
|
|
||||||
&gpu_device,
|
|
||||||
&rect_resources,
|
|
||||||
wgpu::LoadOp::Clear(to_wgpu_color(from_hsb(240, 10, 19))),
|
|
||||||
);
|
|
||||||
|
|
||||||
for text_section in &rects_and_texts.text_sections_behind {
|
// glyph_brush.queue(borrowed_text);
|
||||||
let borrowed_text = text_section.to_borrowed();
|
// }
|
||||||
|
|
||||||
glyph_brush.queue(borrowed_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw first layer of text
|
// draw first layer of text
|
||||||
glyph_brush
|
// glyph_brush
|
||||||
.draw_queued(
|
// .draw_queued(
|
||||||
&gpu_device,
|
// &gpu_device,
|
||||||
&mut staging_belt,
|
// &mut staging_belt,
|
||||||
&mut cmd_encoder,
|
// &mut cmd_encoder,
|
||||||
&view,
|
// &view,
|
||||||
size.width,
|
// size.width,
|
||||||
size.height,
|
// size.height,
|
||||||
)
|
// )
|
||||||
.expect("Failed to draw first layer of text.");
|
// .expect("Failed to draw first layer of text.");
|
||||||
|
|
||||||
// draw rects on top of first text layer
|
// draw rects on top of first text layer
|
||||||
draw_rects(
|
// draw_rects(
|
||||||
&rects_and_texts.rects_front,
|
// &rects_and_texts.rects_front,
|
||||||
|
// &mut cmd_encoder,
|
||||||
|
// &view,
|
||||||
|
// &gpu_device,
|
||||||
|
// &rect_resources,
|
||||||
|
// wgpu::LoadOp::Load,
|
||||||
|
// );
|
||||||
|
|
||||||
|
display_elem(
|
||||||
|
&root,
|
||||||
&mut cmd_encoder,
|
&mut cmd_encoder,
|
||||||
&view,
|
&view,
|
||||||
&gpu_device,
|
&gpu_device,
|
||||||
|
@ -234,23 +237,23 @@ fn run_event_loop(title: &str, rects_and_texts: RectsAndTexts) -> Result<(), Box
|
||||||
wgpu::LoadOp::Load,
|
wgpu::LoadOp::Load,
|
||||||
);
|
);
|
||||||
|
|
||||||
for text_section in &rects_and_texts.text_sections_front {
|
// for text_section in &rects_and_texts.text_sections_front {
|
||||||
let borrowed_text = text_section.to_borrowed();
|
// let borrowed_text = text_section.to_borrowed();
|
||||||
|
|
||||||
glyph_brush.queue(borrowed_text);
|
// glyph_brush.queue(borrowed_text);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// draw text
|
// draw text
|
||||||
glyph_brush
|
// glyph_brush
|
||||||
.draw_queued(
|
// .draw_queued(
|
||||||
&gpu_device,
|
// &gpu_device,
|
||||||
&mut staging_belt,
|
// &mut staging_belt,
|
||||||
&mut cmd_encoder,
|
// &mut cmd_encoder,
|
||||||
&view,
|
// &view,
|
||||||
size.width,
|
// size.width,
|
||||||
size.height,
|
// size.height,
|
||||||
)
|
// )
|
||||||
.expect("Failed to draw queued text.");
|
// .expect("Failed to draw queued text.");
|
||||||
|
|
||||||
staging_belt.finish();
|
staging_belt.finish();
|
||||||
cmd_queue.submit(Some(cmd_encoder.finish()));
|
cmd_queue.submit(Some(cmd_encoder.finish()));
|
||||||
|
@ -319,74 +322,124 @@ fn begin_render_pass<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(title: RocStr) {
|
pub fn render(title: RocStr, root: RocElem) {
|
||||||
let rects_behind = vec![
|
// let rects_behind = vec![
|
||||||
RectElt {
|
// RectElt {
|
||||||
rect: Rect {
|
// rect: Rect {
|
||||||
top_left_coords: (20.0, 20.0).into(),
|
// top_left_coords: (20.0, 20.0).into(),
|
||||||
width: 200.0,
|
// width: 200.0,
|
||||||
height: 100.0
|
// height: 100.0
|
||||||
},
|
// },
|
||||||
color: (0.4, 0.2, 0.5, 1.0),
|
// color: (0.4, 0.2, 0.5, 1.0),
|
||||||
border_width: 5.0,
|
// border_width: 5.0,
|
||||||
border_color: (0.75, 0.5, 0.5, 1.0)
|
// border_color: (0.75, 0.5, 0.5, 1.0)
|
||||||
},
|
// },
|
||||||
RectElt {
|
// RectElt {
|
||||||
rect: Rect {
|
// rect: Rect {
|
||||||
top_left_coords: (420.0, 420.0).into(),
|
// top_left_coords: (420.0, 420.0).into(),
|
||||||
width: 150.0,
|
// width: 150.0,
|
||||||
height: 150.0
|
// height: 150.0
|
||||||
},
|
// },
|
||||||
color: (0.9, 0.2, 0.5, 1.0),
|
// color: (0.9, 0.2, 0.5, 1.0),
|
||||||
border_width: 10.0,
|
// border_width: 10.0,
|
||||||
border_color: (0.2, 0.5, 0.5, 1.0)
|
// border_color: (0.2, 0.5, 0.5, 1.0)
|
||||||
},
|
// },
|
||||||
RectElt {
|
// RectElt {
|
||||||
rect: Rect {
|
// rect: Rect {
|
||||||
top_left_coords: (571.0, 420.0).into(),
|
// top_left_coords: (571.0, 420.0).into(),
|
||||||
width: 150.0,
|
// width: 150.0,
|
||||||
height: 150.0
|
// height: 150.0
|
||||||
},
|
// },
|
||||||
color: (0.2, 0.2, 0.5, 1.0),
|
// color: (0.2, 0.2, 0.5, 1.0),
|
||||||
border_width: 10.0,
|
// border_width: 10.0,
|
||||||
border_color: (0.2, 0.5, 0.5, 1.0)
|
// border_color: (0.2, 0.5, 0.5, 1.0)
|
||||||
}
|
// }
|
||||||
];
|
// ];
|
||||||
|
|
||||||
let texts_behind = vec![
|
// let texts_behind = vec![
|
||||||
Text {
|
// Text {
|
||||||
position: (50.0, 50.0).into(),
|
// position: (50.0, 50.0).into(),
|
||||||
color: colors::WHITE,
|
// color: colors::WHITE,
|
||||||
text: "Back",
|
// text: "Back",
|
||||||
size: 40.0,
|
// size: 40.0,
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
}
|
// }
|
||||||
];
|
// ];
|
||||||
|
|
||||||
let rects_front = vec![
|
// let rects_front = vec![
|
||||||
RectElt {
|
// RectElt {
|
||||||
rect: Rect {
|
// rect: Rect {
|
||||||
top_left_coords: (30.0, 30.0).into(),
|
// top_left_coords: (30.0, 30.0).into(),
|
||||||
width: 70.0,
|
// width: 70.0,
|
||||||
height: 70.0
|
// height: 70.0
|
||||||
},
|
// },
|
||||||
color: (0.7, 0.2, 0.2, 0.6),
|
// color: (0.7, 0.2, 0.2, 0.6),
|
||||||
border_width: 10.0,
|
// border_width: 10.0,
|
||||||
border_color: (0.75, 0.5, 0.5, 1.0)
|
// border_color: (0.75, 0.5, 0.5, 1.0)
|
||||||
}
|
// }
|
||||||
];
|
// ];
|
||||||
|
|
||||||
let texts_front = vec![
|
// let texts_front = vec![
|
||||||
Text {
|
// Text {
|
||||||
position: (70.0, 70.0).into(),
|
// position: (70.0, 70.0).into(),
|
||||||
color: colors::WHITE,
|
// color: colors::WHITE,
|
||||||
text: "Front",
|
// text: "Front",
|
||||||
size: 40.0,
|
// size: 40.0,
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
}
|
// }
|
||||||
];
|
// ];
|
||||||
|
|
||||||
let rects_and_texts = RectsAndTexts::init(rects_behind, texts_behind, rects_front, texts_front);
|
// let rects_and_texts = RectsAndTexts::init(rects_behind, texts_behind, rects_front, texts_front);
|
||||||
|
|
||||||
run_event_loop(title.as_str(), rects_and_texts).expect("Error running event loop");
|
run_event_loop(title.as_str(), root).expect("Error running event loop");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_elem(
|
||||||
|
elem: &RocElem,
|
||||||
|
cmd_encoder: &mut CommandEncoder,
|
||||||
|
texture_view: &TextureView,
|
||||||
|
gpu_device: &wgpu::Device,
|
||||||
|
rect_resources: &RectResources,
|
||||||
|
load_op: LoadOp<wgpu::Color>,
|
||||||
|
) {
|
||||||
|
use RocElemTag::*;
|
||||||
|
|
||||||
|
match elem.tag() {
|
||||||
|
Button => {
|
||||||
|
let button = unsafe { &elem.entry().button };
|
||||||
|
let rect_elt = RectElt {
|
||||||
|
rect: button.bounds,
|
||||||
|
color: (0.2, 0.2, 0.5, 1.0),
|
||||||
|
border_width: 10.0,
|
||||||
|
border_color: (0.2, 0.5, 0.5, 1.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
draw_rects(
|
||||||
|
&[rect_elt],
|
||||||
|
cmd_encoder,
|
||||||
|
texture_view,
|
||||||
|
gpu_device,
|
||||||
|
rect_resources,
|
||||||
|
load_op,
|
||||||
|
);
|
||||||
|
|
||||||
|
display_elem(
|
||||||
|
&*button.child,
|
||||||
|
cmd_encoder,
|
||||||
|
texture_view,
|
||||||
|
gpu_device,
|
||||||
|
rect_resources,
|
||||||
|
load_op,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Text => {
|
||||||
|
let text = unsafe { &elem.entry().text };
|
||||||
|
}
|
||||||
|
Row => {
|
||||||
|
todo!("Row");
|
||||||
|
}
|
||||||
|
Col => {
|
||||||
|
todo!("Col");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,105 +1,16 @@
|
||||||
#![allow(non_snake_case)]
|
|
||||||
|
|
||||||
use core::ffi::c_void;
|
|
||||||
use core::mem::{self, ManuallyDrop};
|
|
||||||
use roc_std::RocStr;
|
|
||||||
use std::ffi::CStr;
|
|
||||||
use std::os::raw::c_char;
|
|
||||||
|
|
||||||
mod graphics;
|
mod graphics;
|
||||||
mod gui;
|
mod gui;
|
||||||
mod rects_and_texts;
|
mod rects_and_texts;
|
||||||
|
mod roc;
|
||||||
|
|
||||||
|
use crate::roc::RocElem;
|
||||||
|
use roc_std::RocStr;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "roc__renderForHost_1_exposed"]
|
#[link_name = "roc__renderForHost_1_exposed"]
|
||||||
fn roc_render() -> RocElem;
|
fn roc_render() -> RocElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
|
||||||
#[cfg(target_pointer_width = "64")] // on a 64-bit system, the tag fits in this pointer's spare 3 bits
|
|
||||||
struct RocElem {
|
|
||||||
entry: *const RocElemEntry,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RocElem {
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
fn tag(&self) -> RocElemTag {
|
|
||||||
// On a 64-bit system, the last 3 bits of the pointer store the tag
|
|
||||||
unsafe { mem::transmute::<u8, RocElemTag>((self.entry as u8) & 0b0000_0111) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn entry(&self) -> &RocElemEntry {
|
|
||||||
// On a 64-bit system, the last 3 bits of the pointer store the tag
|
|
||||||
let cleared = self.entry as usize & !0b111;
|
|
||||||
|
|
||||||
unsafe { &*(cleared as *const RocElemEntry) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
pub fn entry_mut(&mut self) -> &mut RocElemEntry {
|
|
||||||
// On a 64-bit system, the last 3 bits of the pointer store the tag
|
|
||||||
let cleared = self.entry as usize & !0b111;
|
|
||||||
|
|
||||||
unsafe { &mut *(cleared as *mut RocElemEntry) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
enum RocElemTag {
|
|
||||||
Button = 0,
|
|
||||||
Text,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
union RocElemEntry {
|
|
||||||
button: ManuallyDrop<RocElem>,
|
|
||||||
text: ManuallyDrop<RocStr>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
|
||||||
return libc::malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn roc_realloc(
|
|
||||||
c_ptr: *mut c_void,
|
|
||||||
new_size: usize,
|
|
||||||
_old_size: usize,
|
|
||||||
_alignment: u32,
|
|
||||||
) -> *mut c_void {
|
|
||||||
return libc::realloc(c_ptr, new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) {
|
|
||||||
return libc::free(c_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) {
|
|
||||||
match tag_id {
|
|
||||||
0 => {
|
|
||||||
let slice = CStr::from_ptr(c_ptr as *const c_char);
|
|
||||||
let string = slice.to_str().unwrap();
|
|
||||||
eprintln!("Roc hit a panic: {}", string);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn roc_memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void {
|
|
||||||
libc::memcpy(dst, src, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void {
|
|
||||||
libc::memset(dst, c, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Action<State> {
|
enum Action<State> {
|
||||||
Update(State),
|
Update(State),
|
||||||
DoNothing,
|
DoNothing,
|
||||||
|
@ -151,101 +62,9 @@ struct AppState {
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main() -> i32 {
|
pub extern "C" fn rust_main() -> i32 {
|
||||||
println!("Calling roc_render()...");
|
let root_elem = unsafe { roc_render() };
|
||||||
|
|
||||||
let elem = unsafe { roc_render() };
|
gui::render("test title".into(), root_elem);
|
||||||
|
|
||||||
fn display_elem(elem: &RocElem) {
|
|
||||||
use RocElemTag::*;
|
|
||||||
|
|
||||||
println!("Got this tag: {:?}", elem.tag());
|
|
||||||
|
|
||||||
match elem.tag() {
|
|
||||||
Button => {
|
|
||||||
println!("Button!");
|
|
||||||
|
|
||||||
let child = unsafe { &elem.entry().button };
|
|
||||||
|
|
||||||
println!("Got this child:");
|
|
||||||
|
|
||||||
display_elem(child);
|
|
||||||
}
|
|
||||||
Text => {
|
|
||||||
let text = unsafe { &elem.entry().text };
|
|
||||||
println!("Text: {}", (*text).as_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
display_elem(&elem);
|
|
||||||
|
|
||||||
// #[repr(C)]
|
|
||||||
// struct RocElem {
|
|
||||||
// entry: RocElemEntry
|
|
||||||
// tag: RocElemTag,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[repr(u8)]
|
|
||||||
// enum RocElemTag {
|
|
||||||
// Button = 0,
|
|
||||||
// Text,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[repr(C)]
|
|
||||||
// union RocElemEntry {
|
|
||||||
// text: ManuallyDrop<RocStr>,
|
|
||||||
// button: *const RocElem,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn render(clicks: i64) -> Elem<i64> {
|
|
||||||
// let txt = Elem::Text(Key::null(), format!("Clicks: {}", clicks).as_str().into());
|
|
||||||
|
|
||||||
// Elem::Button(
|
|
||||||
// Key::null(),
|
|
||||||
// Box::new(move || Action::Update(clicks + 1)),
|
|
||||||
// Box::new(txt),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn draw_elem<T>(elem: Elem<T>) {
|
|
||||||
// use Elem::*;
|
|
||||||
|
|
||||||
// match elem {
|
|
||||||
// Button(_key, _on_click, label) => {
|
|
||||||
// print!("Drawing button label:\n\t");
|
|
||||||
|
|
||||||
// draw_elem(*label);
|
|
||||||
// }
|
|
||||||
// Text(_key, roc_str) => {
|
|
||||||
// println!("Drawing string \"{}\"", roc_str);
|
|
||||||
// }
|
|
||||||
// Col(_key, elems) => {
|
|
||||||
// println!("Drawing col contents...");
|
|
||||||
|
|
||||||
// for elem in elems {
|
|
||||||
// draw_elem(elem);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Row(_key, elems) => {
|
|
||||||
// println!("Drawing row contents...");
|
|
||||||
|
|
||||||
// for elem in elems {
|
|
||||||
// draw_elem(elem);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// TextInput {
|
|
||||||
// key: _,
|
|
||||||
// text,
|
|
||||||
// on_change: _,
|
|
||||||
// } => {
|
|
||||||
// println!("Drawing text input with current text \"{}\"", text);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// draw_elem(render(0));
|
|
||||||
|
|
||||||
// gui::render("test title".into());
|
|
||||||
|
|
||||||
// Exit code
|
// Exit code
|
||||||
0
|
0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue