mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-21 22:38:41 -06:00
glium ui backend, misc gui changes
This commit is contained in:
parent
fe1427249b
commit
a3857d0586
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1033,6 +1033,7 @@ dependencies = [
|
|||
"glam",
|
||||
"glium",
|
||||
"hashbrown",
|
||||
"log",
|
||||
"nohash-hasher",
|
||||
]
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ hashbrown = "0.14"
|
|||
nohash-hasher = "0.2"
|
||||
glam = { version = "0.24", features = ["approx"] }
|
||||
glium = { git = "https://github.com/glium/glium", rev = "968fc92378caf", optional = true }
|
||||
log = "0.4"
|
||||
|
||||
[features]
|
||||
default = ["backend_glium", "builtin_elements"]
|
||||
|
|
10
kubi-ui/shaders/fragment.frag
Normal file
10
kubi-ui/shaders/fragment.frag
Normal file
|
@ -0,0 +1,10 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
out vec4 out_color;
|
||||
uniform vec4 color;
|
||||
|
||||
void main() {
|
||||
if (color.w <= 0.) discard;
|
||||
out_color = color;
|
||||
}
|
8
kubi-ui/shaders/vertex.vert
Normal file
8
kubi-ui/shaders/vertex.vert
Normal file
|
@ -0,0 +1,8 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
in vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0., 1.);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
use glam::Vec2;
|
||||
use glium::{
|
||||
Surface, DrawParameters, Blend,
|
||||
Program, VertexBuffer, IndexBuffer,
|
||||
backend::Facade,
|
||||
index::PrimitiveType,
|
||||
implement_vertex, uniform,
|
||||
};
|
||||
|
||||
use crate::draw::{UiDrawPlan, UiVertex};
|
||||
|
||||
const VERTEX_SHADER: &str = include_str!("../../shaders/fragment.frag");
|
||||
const FRAGMENT_SHADER: &str = include_str!("../../shaders/vertex.vert");
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Vertex {
|
||||
position: [f32; 2],
|
||||
color: [f32; 4],
|
||||
}
|
||||
|
||||
impl From<UiVertex> for Vertex {
|
||||
fn from(v: UiVertex) -> Self {
|
||||
Self {
|
||||
position: v.position.to_array(),
|
||||
color: v.color.to_array(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implement_vertex!(Vertex, position, color);
|
||||
|
||||
pub struct GliumUiRenderer {
|
||||
pub program: glium::Program,
|
||||
pub vertex_buffer: glium::VertexBuffer<Vertex>,
|
||||
pub index_buffer: glium::IndexBuffer<u32>,
|
||||
}
|
||||
|
||||
impl GliumUiRenderer {
|
||||
pub fn new<F: Facade>(facade: &F) -> Self {
|
||||
log::info!("init glium backend for ui");
|
||||
log::debug!("init program");
|
||||
let program = Program::from_source(facade, VERTEX_SHADER, FRAGMENT_SHADER, None).unwrap();
|
||||
log::debug!("init buffers");
|
||||
let vertex_buffer = VertexBuffer::empty_persistent(facade, 1024).unwrap();
|
||||
let index_buffer = IndexBuffer::empty_persistent(facade, PrimitiveType::TrianglesList, 1024).unwrap();
|
||||
Self {
|
||||
program,
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, frame: &mut glium::Frame, resolution: Vec2, plan: &UiDrawPlan) {
|
||||
self.vertex_buffer.write(&plan.vertices.iter().copied().map(Vertex::from).collect::<Vec<_>>());
|
||||
self.index_buffer.write(&plan.indices);
|
||||
|
||||
let params = DrawParameters {
|
||||
blend: Blend::alpha_blending(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
frame.draw(
|
||||
&self.vertex_buffer,
|
||||
&self.index_buffer,
|
||||
&self.program,
|
||||
&uniform! {
|
||||
resolution: resolution.to_array(),
|
||||
},
|
||||
¶ms,
|
||||
).unwrap();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
use glam::{Vec2, vec2, Vec4};
|
||||
use std::num::NonZeroU16;
|
||||
use glam::{Vec2, Vec4};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum UiDrawCall {
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum UiDrawCommand {
|
||||
///Filled, colored rectangle
|
||||
Rectangle {
|
||||
///Position in pixels
|
||||
|
@ -13,10 +14,60 @@ pub enum UiDrawCall {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct UiDrawCalls {
|
||||
pub calls: Vec<UiDrawCall>,
|
||||
#[derive(Default)]
|
||||
pub struct UiDrawCommands {
|
||||
pub commands: Vec<UiDrawCommand>,
|
||||
}
|
||||
|
||||
// impl UiDrawCommands {
|
||||
// pub fn compare(&self, other: &Self) -> bool {
|
||||
// // if self.commands.len() != other.commands.len() { return false }
|
||||
// // self.commands.iter().zip(other.commands.iter()).all(|(a, b)| a == b)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct UiVertex {
|
||||
pub position: Vec2,
|
||||
pub color: Vec4,
|
||||
//pub texture: Option<NonZeroU16>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UiDrawPlan {
|
||||
|
||||
pub vertices: Vec<UiVertex>,
|
||||
pub indices: Vec<u32>,
|
||||
}
|
||||
|
||||
impl UiDrawPlan {
|
||||
pub fn build(calls: &UiDrawCommands) -> Self {
|
||||
let mut plan = Self::default();
|
||||
for call in &calls.commands {
|
||||
match call {
|
||||
UiDrawCommand::Rectangle { position, size, color } => {
|
||||
let idx = plan.vertices.len() as u32;
|
||||
plan.indices.extend([idx, idx + 1, idx + 2, idx, idx + 2, idx + 3]);
|
||||
plan.vertices.extend([
|
||||
UiVertex {
|
||||
position: *position,
|
||||
color: *color,
|
||||
},
|
||||
UiVertex {
|
||||
position: *position + Vec2::new(size.x, 0.0),
|
||||
color: *color,
|
||||
},
|
||||
UiVertex {
|
||||
position: *position + *size,
|
||||
color: *color,
|
||||
},
|
||||
UiVertex {
|
||||
position: *position + Vec2::new(0.0, size.y),
|
||||
color: *color,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
plan
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::Any;
|
||||
use crate::{
|
||||
LayoutInfo,
|
||||
draw::UiDrawCall,
|
||||
draw::UiDrawCommand,
|
||||
measure::Response,
|
||||
state::StateRepo
|
||||
};
|
||||
|
@ -17,5 +17,5 @@ pub trait UiElement {
|
|||
fn is_stateless(&self) -> bool { self.state_id().is_none() }
|
||||
fn init_state(&self) -> Option<Box<dyn Any>> { None }
|
||||
fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response;
|
||||
fn draw(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>);
|
||||
fn process(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCommand>);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use glam::{Vec2, Vec4};
|
||||
use crate::{UiDirection, LayoutInfo, draw::UiDrawCall, measure::{IsMeasurable, Response}, state::StateRepo, UiSize};
|
||||
use crate::{UiDirection, LayoutInfo, draw::UiDrawCommand, measure::{IsMeasurable, Response}, state::StateRepo, UiSize};
|
||||
use super::UiElement;
|
||||
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
|
@ -73,9 +73,9 @@ impl UiElement for Container {
|
|||
Response { desired_size: size }
|
||||
}
|
||||
|
||||
fn draw(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) {
|
||||
fn process(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCommand>) {
|
||||
if let Some(color) = self.background {
|
||||
draw.push(UiDrawCall::Rectangle {
|
||||
draw.push(UiDrawCommand::Rectangle {
|
||||
position: layout.position,
|
||||
size: measure.desired_size,
|
||||
color
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use glam::{vec2, Vec4};
|
||||
use crate::{
|
||||
UiSize, LayoutInfo,
|
||||
draw::UiDrawCall,
|
||||
draw::UiDrawCommand,
|
||||
measure::Response,
|
||||
state::StateRepo
|
||||
};
|
||||
|
@ -36,14 +36,14 @@ impl UiElement for ProgressBar {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) {
|
||||
draw.push(UiDrawCall::Rectangle {
|
||||
fn process(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCommand>) {
|
||||
draw.push(UiDrawCommand::Rectangle {
|
||||
position: layout.position,
|
||||
size: measure.desired_size,
|
||||
color: self.color_background
|
||||
});
|
||||
|
||||
draw.push(UiDrawCall::Rectangle {
|
||||
draw.push(UiDrawCommand::Rectangle {
|
||||
position: layout.position,
|
||||
size: measure.desired_size * vec2(self.value, 1.0),
|
||||
color: self.color_foreground
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use glam::vec2;
|
||||
use crate::{state::StateRepo, LayoutInfo, measure::Response, draw::UiDrawCall, UiDirection};
|
||||
use crate::{state::StateRepo, LayoutInfo, measure::Response, draw::UiDrawCommand, UiDirection};
|
||||
use super::UiElement;
|
||||
|
||||
pub struct Spacer(f32);
|
||||
|
@ -14,5 +14,5 @@ impl UiElement for Spacer {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw(&self, _measure: &Response, _state: &mut StateRepo, _layout: &LayoutInfo, _draw: &mut Vec<UiDrawCall>) {}
|
||||
fn process(&self, _measure: &Response, _state: &mut StateRepo, _layout: &LayoutInfo, _draw: &mut Vec<UiDrawCommand>) {}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,19 @@ pub mod backend;
|
|||
pub mod measure;
|
||||
pub mod state;
|
||||
|
||||
use element::UiElement;
|
||||
use state::StateRepo;
|
||||
use event::UiEvent;
|
||||
use draw::{UiDrawCommands, UiDrawPlan};
|
||||
|
||||
pub struct KubiUi {
|
||||
mouse_position: Vec2,
|
||||
stateful_state: StateRepo,
|
||||
event_queue: VecDeque<event::UiEvent>,
|
||||
event_queue: VecDeque<UiEvent>,
|
||||
prev_draw_commands: UiDrawCommands,
|
||||
draw_commands: UiDrawCommands,
|
||||
draw_plan: UiDrawPlan,
|
||||
draw_plan_modified: bool,
|
||||
}
|
||||
|
||||
impl KubiUi {
|
||||
|
@ -22,8 +29,31 @@ impl KubiUi {
|
|||
mouse_position: Vec2::ZERO,
|
||||
stateful_state: StateRepo::default(),
|
||||
event_queue: VecDeque::new(),
|
||||
// root_elements: Vec::new(),
|
||||
prev_draw_commands: UiDrawCommands::default(),
|
||||
draw_commands: UiDrawCommands::default(),
|
||||
draw_plan: UiDrawPlan::default(),
|
||||
draw_plan_modified: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn begin(&mut self) {
|
||||
std::mem::swap(&mut self.prev_draw_commands, &mut self.draw_commands);
|
||||
self.draw_plan_modified = false;
|
||||
self.draw_commands.commands.clear();
|
||||
}
|
||||
|
||||
pub fn end(&mut self) {
|
||||
if self.draw_commands.commands == self.prev_draw_commands.commands {
|
||||
return
|
||||
}
|
||||
self.draw_plan = UiDrawPlan::build(&self.draw_commands);
|
||||
self.draw_plan_modified = true;
|
||||
}
|
||||
|
||||
pub fn draw_plan(&self) -> (bool, &UiDrawPlan) {
|
||||
(self.draw_plan_modified, &self.draw_plan)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for KubiUi {
|
||||
|
|
0
kubi/src/gui_integration.rs
Normal file
0
kubi/src/gui_integration.rs
Normal file
Loading…
Reference in a new issue