mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-22 14:58:44 -06:00
Compare commits
No commits in common. "711942567fe7df7bccd8af4f9dd8560b449503ed" and "ac497b06516ea2fb8ad2e8ddce90d6530ae4a65e" have entirely different histories.
711942567f
...
ac497b0651
|
@ -1,11 +1,10 @@
|
||||||
#version 300 es
|
#version 300 es
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
out vec4 out_color;
|
out vec4 out_color;
|
||||||
in vec4 vtx_color;
|
uniform vec4 color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (vtx_color.w <= 0.) discard;
|
if (color.w <= 0.) discard;
|
||||||
out_color = vtx_color;
|
out_color = color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
#version 300 es
|
#version 300 es
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
uniform vec2 resolution;
|
|
||||||
in vec4 color;
|
|
||||||
in vec2 position;
|
in vec2 position;
|
||||||
out vec4 vtx_color;
|
uniform vec2 resolution;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vtx_color = color;
|
gl_Position = vec4(vec2(1., -1.) * (position / resolution), 0., 1.);
|
||||||
vec2 pos2d = (vec2(2., -2.) * (position / resolution)) + vec2(-1, 1);
|
|
||||||
gl_Position = vec4(pos2d, 0., 1.);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,25 +29,28 @@ impl From<UiVertex> for Vertex {
|
||||||
|
|
||||||
implement_vertex!(Vertex, position, color);
|
implement_vertex!(Vertex, position, color);
|
||||||
|
|
||||||
struct BufferPair {
|
pub struct GliumUiRenderer {
|
||||||
vertex_buffer: glium::VertexBuffer<Vertex>,
|
pub program: glium::Program,
|
||||||
index_buffer: glium::IndexBuffer<u32>,
|
pub vertex_buffer: glium::VertexBuffer<Vertex>,
|
||||||
vertex_count: usize,
|
pub index_buffer: glium::IndexBuffer<u32>,
|
||||||
index_count: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufferPair {
|
impl GliumUiRenderer {
|
||||||
pub fn new<F: Facade>(facade: &F) -> Self {
|
pub fn new<F: Facade>(facade: &F) -> Self {
|
||||||
log::debug!("init ui buffers...");
|
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 {
|
Self {
|
||||||
vertex_buffer: VertexBuffer::empty_persistent(facade, 1024).unwrap(),
|
program,
|
||||||
index_buffer: IndexBuffer::empty_persistent(facade, PrimitiveType::TrianglesList, 1024).unwrap(),
|
vertex_buffer,
|
||||||
vertex_count: 0,
|
index_buffer,
|
||||||
index_count: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_buffer_size(&mut self, need_vtx: usize, need_idx: usize) {
|
fn ensure_buffer_size(&mut self, need_vtx: usize, need_idx: usize) {
|
||||||
let current_vtx_size = self.vertex_buffer.get_size();
|
let current_vtx_size = self.vertex_buffer.get_size();
|
||||||
let current_idx_size = self.index_buffer.get_size();
|
let current_idx_size = self.index_buffer.get_size();
|
||||||
if current_vtx_size >= need_vtx && current_idx_size >= need_idx {
|
if current_vtx_size >= need_vtx && current_idx_size >= need_idx {
|
||||||
|
@ -57,79 +60,37 @@ impl BufferPair {
|
||||||
let new_idx_size = (need_idx + 1).next_power_of_two();
|
let new_idx_size = (need_idx + 1).next_power_of_two();
|
||||||
log::debug!("resizing buffers: vtx {} -> {}, idx {} -> {}", current_vtx_size, new_vtx_size, current_idx_size, new_idx_size);
|
log::debug!("resizing buffers: vtx {} -> {}, idx {} -> {}", current_vtx_size, new_vtx_size, current_idx_size, new_idx_size);
|
||||||
if current_vtx_size != new_vtx_size {
|
if current_vtx_size != new_vtx_size {
|
||||||
self.vertex_buffer = VertexBuffer::empty_persistent(
|
self.vertex_buffer = VertexBuffer::empty_persistent(self.vertex_buffer.get_context(), new_vtx_size).unwrap();
|
||||||
self.vertex_buffer.get_context(),
|
|
||||||
new_vtx_size
|
|
||||||
).unwrap();
|
|
||||||
}
|
}
|
||||||
if current_idx_size != new_idx_size {
|
if current_idx_size != new_idx_size {
|
||||||
self.index_buffer = IndexBuffer::empty_persistent(
|
self.index_buffer = IndexBuffer::empty_persistent(self.index_buffer.get_context(), PrimitiveType::TrianglesList, new_idx_size).unwrap();
|
||||||
self.index_buffer.get_context(),
|
|
||||||
PrimitiveType::TrianglesList,
|
|
||||||
new_idx_size
|
|
||||||
).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_data(&mut self, vtx: &[Vertex], idx: &[u32]) {
|
fn write_buffer_data(&mut self, vtx: &[Vertex], idx: &[u32]) {
|
||||||
log::debug!("uploading {} vertices and {} indices", vtx.len(), idx.len());
|
log::info!("uploading {} vertices and {} indices", vtx.len(), idx.len());
|
||||||
|
|
||||||
self.vertex_count = vtx.len();
|
|
||||||
self.index_count = idx.len();
|
|
||||||
|
|
||||||
self.vertex_buffer.invalidate();
|
|
||||||
self.index_buffer.invalidate();
|
|
||||||
|
|
||||||
if self.vertex_count == 0 || self.index_count == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ensure_buffer_size(vtx.len(), idx.len());
|
self.ensure_buffer_size(vtx.len(), idx.len());
|
||||||
|
self.vertex_buffer.invalidate();
|
||||||
self.vertex_buffer.slice_mut(0..vtx.len()).unwrap().write(vtx);
|
self.vertex_buffer.slice_mut(0..vtx.len()).unwrap().write(vtx);
|
||||||
|
self.index_buffer.invalidate();
|
||||||
self.index_buffer.slice_mut(0..idx.len()).unwrap().write(idx);
|
self.index_buffer.slice_mut(0..idx.len()).unwrap().write(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.vertex_count == 0 || self.index_count == 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct GliumUiRenderer {
|
|
||||||
program: glium::Program,
|
|
||||||
buffer: BufferPair,
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
Self {
|
|
||||||
program,
|
|
||||||
buffer: BufferPair::new(facade)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, plan: &UiDrawPlan) {
|
pub fn update(&mut self, plan: &UiDrawPlan) {
|
||||||
assert!(plan.calls.len() == 1, "multiple draw calls not supported yet");
|
let data_vtx = &plan.vertices.iter().copied().map(Vertex::from).collect::<Vec<_>>();
|
||||||
let data_vtx = &plan.calls[0].vertices.iter().copied().map(Vertex::from).collect::<Vec<_>>();
|
let data_idx = &plan.indices;
|
||||||
let data_idx = &plan.calls[0].indices;
|
self.write_buffer_data(data_vtx, data_idx);
|
||||||
self.buffer.write_data(data_vtx, data_idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self, frame: &mut glium::Frame, resolution: Vec2) {
|
pub fn draw(&self, frame: &mut glium::Frame, resolution: Vec2) {
|
||||||
if self.buffer.is_empty() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let params = DrawParameters {
|
let params = DrawParameters {
|
||||||
blend: Blend::alpha_blending(),
|
blend: Blend::alpha_blending(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
frame.draw(
|
frame.draw(
|
||||||
self.buffer.vertex_buffer.slice(0..self.buffer.vertex_count).unwrap(),
|
&self.vertex_buffer,
|
||||||
self.buffer.index_buffer.slice(0..self.buffer.index_count).unwrap(),
|
&self.index_buffer,
|
||||||
&self.program,
|
&self.program,
|
||||||
&uniform! {
|
&uniform! {
|
||||||
resolution: resolution.to_array(),
|
resolution: resolution.to_array(),
|
||||||
|
|
|
@ -34,25 +34,20 @@ pub struct UiVertex {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UiDrawCall {
|
pub struct UiDrawPlan {
|
||||||
pub vertices: Vec<UiVertex>,
|
pub vertices: Vec<UiVertex>,
|
||||||
pub indices: Vec<u32>,
|
pub indices: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct UiDrawPlan {
|
|
||||||
pub calls: Vec<UiDrawCall>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UiDrawPlan {
|
impl UiDrawPlan {
|
||||||
pub fn build(calls: &UiDrawCommands) -> Self {
|
pub fn build(calls: &UiDrawCommands) -> Self {
|
||||||
let mut call = UiDrawCall::default();
|
let mut plan = Self::default();
|
||||||
for command in &calls.commands {
|
for call in &calls.commands {
|
||||||
match command {
|
match call {
|
||||||
UiDrawCommand::Rectangle { position, size, color } => {
|
UiDrawCommand::Rectangle { position, size, color } => {
|
||||||
let idx = call.vertices.len() as u32;
|
let idx = plan.vertices.len() as u32;
|
||||||
call.indices.extend([idx, idx + 1, idx + 2, idx, idx + 2, idx + 3]);
|
plan.indices.extend([idx, idx + 1, idx + 2, idx, idx + 2, idx + 3]);
|
||||||
call.vertices.extend([
|
plan.vertices.extend([
|
||||||
UiVertex {
|
UiVertex {
|
||||||
position: *position,
|
position: *position,
|
||||||
color: *color,
|
color: *color,
|
||||||
|
@ -73,8 +68,6 @@ impl UiDrawPlan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self {
|
plan
|
||||||
calls: vec![call]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use glam::{Vec2, Vec4};
|
use glam::{Vec2, Vec4};
|
||||||
use crate::{UiDirection, LayoutInfo, draw::UiDrawCommand, measure::Response, state::StateRepo, UiSize};
|
use crate::{UiDirection, LayoutInfo, draw::UiDrawCommand, measure::{IsMeasurable, Response}, state::StateRepo, UiSize};
|
||||||
use super::UiElement;
|
use super::UiElement;
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy, Debug)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
|
|
|
@ -48,20 +48,16 @@ impl UiElement for ProgressBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCommand>) {
|
fn process(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCommand>) {
|
||||||
let value = self.value.clamp(0., 1.);
|
|
||||||
if value < 1. {
|
|
||||||
draw.push(UiDrawCommand::Rectangle {
|
draw.push(UiDrawCommand::Rectangle {
|
||||||
position: layout.position,
|
position: layout.position,
|
||||||
size: measure.desired_size,
|
size: measure.desired_size,
|
||||||
color: self.color_background
|
color: self.color_background
|
||||||
});
|
});
|
||||||
}
|
|
||||||
if value > 0. {
|
|
||||||
draw.push(UiDrawCommand::Rectangle {
|
draw.push(UiDrawCommand::Rectangle {
|
||||||
position: layout.position,
|
position: layout.position,
|
||||||
size: measure.desired_size * vec2(value, 1.0),
|
size: measure.desired_size * vec2(self.value, 1.0),
|
||||||
color: self.color_foreground
|
color: self.color_foreground
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -37,16 +37,6 @@ impl KubiUi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add<T: UiElement>(&mut self, element: T, max_size: Vec2) {
|
|
||||||
let layout = LayoutInfo {
|
|
||||||
position: Vec2::ZERO,
|
|
||||||
max_size,
|
|
||||||
direction: UiDirection::Vertical,
|
|
||||||
};
|
|
||||||
let measure = element.measure(&self.stateful_state, &layout);
|
|
||||||
element.process(&measure, &mut self.stateful_state, &layout, &mut self.draw_commands.commands);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn begin(&mut self) {
|
pub fn begin(&mut self) {
|
||||||
std::mem::swap(&mut self.prev_draw_commands, &mut self.draw_commands);
|
std::mem::swap(&mut self.prev_draw_commands, &mut self.draw_commands);
|
||||||
self.draw_plan_modified = false;
|
self.draw_plan_modified = false;
|
||||||
|
@ -87,9 +77,9 @@ pub enum UiDirection {
|
||||||
Horizontal,
|
Horizontal,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LayoutInfo {
|
struct LayoutInfo {
|
||||||
///Not availabe during measuring step
|
///Not availabe during measuring step
|
||||||
pub position: Vec2,
|
position: Vec2,
|
||||||
pub max_size: Vec2,
|
max_size: Vec2,
|
||||||
pub direction: UiDirection,
|
direction: UiDirection,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum IsMeasurable {
|
||||||
|
#[default]
|
||||||
|
No,
|
||||||
|
Maybe,
|
||||||
|
Yes
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
pub desired_size: Vec2
|
pub desired_size: Vec2
|
||||||
}
|
}
|
||||||
|
|
17
kubi/shaders/gui/progressbar.frag
Normal file
17
kubi/shaders/gui/progressbar.frag
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
in vec2 v_uv;
|
||||||
|
out vec4 out_color;
|
||||||
|
uniform float progress;
|
||||||
|
uniform vec4 color;
|
||||||
|
uniform vec4 bg_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if (v_uv.x <= progress) {
|
||||||
|
out_color = color;
|
||||||
|
} else {
|
||||||
|
out_color = bg_color;
|
||||||
|
}
|
||||||
|
}
|
12
kubi/shaders/gui/progressbar.vert
Normal file
12
kubi/shaders/gui/progressbar.vert
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
in vec2 position;
|
||||||
|
out vec2 v_uv;
|
||||||
|
uniform mat4 ui_view;
|
||||||
|
uniform mat3 transform;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
v_uv = position;
|
||||||
|
vec2 transformed = (transform * vec3(position, 1.)).xy;
|
||||||
|
gl_Position = ui_view * vec4(transformed, 0., 1.);
|
||||||
|
}
|
|
@ -19,11 +19,9 @@ uniform sampler2DArray tex;
|
||||||
void main() {
|
void main() {
|
||||||
// base color from texture
|
// base color from texture
|
||||||
color = texture(tex, vec3(v_uv, v_tex_index));
|
color = texture(tex, vec3(v_uv, v_tex_index));
|
||||||
// discard transparent pixels
|
// discard fully transparent pixels
|
||||||
if (color.w < 0.5) discard;
|
if (color.w <= 0.0) discard;
|
||||||
//basic "lighting"
|
//basic "lighting"
|
||||||
float light = abs(v_normal.x) + .8 * abs(v_normal.y) + .6 * abs(v_normal.z);
|
float light = abs(v_normal.x) + .8 * abs(v_normal.y) + .6 * abs(v_normal.z);
|
||||||
color *= vec4(vec3(light), 1.);
|
color *= vec4(vec3(light), 1.);
|
||||||
//discard alpha
|
|
||||||
color.w = 1.;
|
|
||||||
}
|
}
|
||||||
|
|
78
kubi/src/legacy_gui.rs
Normal file
78
kubi/src/legacy_gui.rs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
use shipyard::{Component, Unique, Workload, IntoWorkload, AllStoragesView, View, UniqueViewMut, IntoIter};
|
||||||
|
use glam::{Vec4, Mat4};
|
||||||
|
use crate::{color::color_hex, events::WindowResizedEvent};
|
||||||
|
|
||||||
|
pub mod text_widget;
|
||||||
|
pub mod progressbar;
|
||||||
|
|
||||||
|
use progressbar::render_progressbars;
|
||||||
|
|
||||||
|
//TODO compute gui scale on window resize
|
||||||
|
#[derive(Unique, Clone, Copy, Debug, Default)]
|
||||||
|
pub struct LegacyGuiView(pub Mat4);
|
||||||
|
|
||||||
|
#[derive(Component, Clone, Copy, Debug, Default)]
|
||||||
|
pub struct LegacyGuiComponent;
|
||||||
|
|
||||||
|
#[derive(Component, Clone, Copy, Debug)]
|
||||||
|
pub struct LegacyPrimaryColor(pub Vec4);
|
||||||
|
impl Default for LegacyPrimaryColor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(color_hex(0x156cddff))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Clone, Copy, Debug)]
|
||||||
|
pub struct LegacySecondaryColor(pub Vec4);
|
||||||
|
impl Default for LegacySecondaryColor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(color_hex(0xc9d5e4ff))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_legacy_gui_view(
|
||||||
|
mut view: UniqueViewMut<LegacyGuiView>,
|
||||||
|
resize: View<WindowResizedEvent>,
|
||||||
|
) {
|
||||||
|
let Some(&size) = resize.iter().next() else {
|
||||||
|
return
|
||||||
|
};
|
||||||
|
let [w, h] = size.0.to_array();
|
||||||
|
view.0 = Mat4::orthographic_rh_gl(0.0, w as f32, h as f32, 0.0, -1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn legacy_ui_init(
|
||||||
|
storages: AllStoragesView
|
||||||
|
) {
|
||||||
|
storages.add_unique(LegacyGuiView::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn legacy_ui_update() -> Workload {
|
||||||
|
(
|
||||||
|
update_legacy_gui_view
|
||||||
|
).into_sequential_workload()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn legacy_ui_render() -> Workload {
|
||||||
|
(
|
||||||
|
render_progressbars
|
||||||
|
).into_sequential_workload()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn gui_testing(
|
||||||
|
// mut storages: AllStoragesViewMut,
|
||||||
|
// ) {
|
||||||
|
// storages.add_entity((
|
||||||
|
// GuiComponent,
|
||||||
|
// Transform2d(Mat3::from_scale_angle_translation(
|
||||||
|
// vec2(1920., 16.),
|
||||||
|
// 0.,
|
||||||
|
// vec2(0., 0.)
|
||||||
|
// )),
|
||||||
|
// ProgressbarComponent {
|
||||||
|
// progress: 0.33
|
||||||
|
// },
|
||||||
|
// PrimaryColor::default(),
|
||||||
|
// SecondaryColor::default(),
|
||||||
|
// ));
|
||||||
|
// }
|
46
kubi/src/legacy_gui/progressbar.rs
Normal file
46
kubi/src/legacy_gui/progressbar.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use shipyard::{UniqueView, UniqueViewMut, NonSendSync, View, Component, IntoIter, IntoWithId, Get, track};
|
||||||
|
use glium::{Surface, uniform, DrawParameters};
|
||||||
|
use crate::{
|
||||||
|
prefabs::ProgressbarShaderPrefab,
|
||||||
|
rendering::{
|
||||||
|
RenderTarget,
|
||||||
|
primitives::rect::RectPrimitive
|
||||||
|
},
|
||||||
|
transform::Transform2d,
|
||||||
|
};
|
||||||
|
use super::{LegacyGuiComponent, LegacyPrimaryColor, LegacySecondaryColor, LegacyGuiView};
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Clone, Copy, Default)]
|
||||||
|
pub struct ProgressbarComponent {
|
||||||
|
pub progress: f32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_progressbars(
|
||||||
|
mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
|
||||||
|
rect: NonSendSync<UniqueView<RectPrimitive>>,
|
||||||
|
program: NonSendSync<UniqueView<ProgressbarShaderPrefab>>,
|
||||||
|
view: UniqueView<LegacyGuiView>,
|
||||||
|
components: View<LegacyGuiComponent>,
|
||||||
|
transforms: View<Transform2d, track::All>,
|
||||||
|
progressbars: View<ProgressbarComponent>,
|
||||||
|
primary: View<LegacyPrimaryColor>,
|
||||||
|
secondary: View<LegacySecondaryColor>,
|
||||||
|
) {
|
||||||
|
for (eid, (_, transform, progress)) in (&components, &transforms, &progressbars).iter().with_id() {
|
||||||
|
let primary_color = primary.get(eid).copied().unwrap_or_default();
|
||||||
|
let secondary_color = secondary.get(eid).copied().unwrap_or_default();
|
||||||
|
target.0.draw(
|
||||||
|
&rect.0,
|
||||||
|
&rect.1,
|
||||||
|
&program.0,
|
||||||
|
&uniform! {
|
||||||
|
transform: transform.0.to_cols_array_2d(),
|
||||||
|
ui_view: view.0.to_cols_array_2d(),
|
||||||
|
progress: progress.progress,
|
||||||
|
color: primary_color.0.to_array(),
|
||||||
|
bg_color: secondary_color.0.to_array(),
|
||||||
|
},
|
||||||
|
&DrawParameters::default()
|
||||||
|
).unwrap();
|
||||||
|
}
|
||||||
|
}
|
1
kubi/src/legacy_gui/text_widget.rs
Normal file
1
kubi/src/legacy_gui/text_widget.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
//TODO text widget
|
|
@ -29,6 +29,7 @@ pub(crate) mod delta_time;
|
||||||
pub(crate) mod cursor_lock;
|
pub(crate) mod cursor_lock;
|
||||||
pub(crate) mod control_flow;
|
pub(crate) mod control_flow;
|
||||||
pub(crate) mod state;
|
pub(crate) mod state;
|
||||||
|
pub(crate) mod legacy_gui;
|
||||||
pub(crate) mod guiv2_integration;
|
pub(crate) mod guiv2_integration;
|
||||||
pub(crate) mod networking;
|
pub(crate) mod networking;
|
||||||
pub(crate) mod init;
|
pub(crate) mod init;
|
||||||
|
@ -76,6 +77,7 @@ use control_flow::{exit_on_esc, insert_control_flow_unique, RequestExit};
|
||||||
use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state, is_connecting};
|
use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state, is_connecting};
|
||||||
use networking::{update_networking, update_networking_late, is_multiplayer, disconnect_on_exit, is_singleplayer};
|
use networking::{update_networking, update_networking_late, is_multiplayer, disconnect_on_exit, is_singleplayer};
|
||||||
use init::initialize_from_args;
|
use init::initialize_from_args;
|
||||||
|
use legacy_gui::{legacy_ui_render, legacy_ui_init, legacy_ui_update};
|
||||||
use guiv2_integration::{kubi_ui_init, kubi_ui_begin, kubi_ui_end, kubi_ui_draw};
|
use guiv2_integration::{kubi_ui_init, kubi_ui_begin, kubi_ui_end, kubi_ui_draw};
|
||||||
use loading_screen::update_loading_screen;
|
use loading_screen::update_loading_screen;
|
||||||
use connecting_screen::switch_to_loading_if_connected;
|
use connecting_screen::switch_to_loading_if_connected;
|
||||||
|
@ -102,6 +104,7 @@ fn startup() -> Workload {
|
||||||
initialize_from_args,
|
initialize_from_args,
|
||||||
lock_cursor_now,
|
lock_cursor_now,
|
||||||
init_input,
|
init_input,
|
||||||
|
legacy_ui_init,
|
||||||
insert_control_flow_unique,
|
insert_control_flow_unique,
|
||||||
init_delta_time,
|
init_delta_time,
|
||||||
).into_sequential_workload()
|
).into_sequential_workload()
|
||||||
|
@ -138,6 +141,7 @@ fn update() -> Workload {
|
||||||
).into_sequential_workload().run_if(is_ingame),
|
).into_sequential_workload().run_if(is_ingame),
|
||||||
update_networking_late.run_if(is_multiplayer),
|
update_networking_late.run_if(is_multiplayer),
|
||||||
compute_cameras,
|
compute_cameras,
|
||||||
|
legacy_ui_update,
|
||||||
kubi_ui_end,
|
kubi_ui_end,
|
||||||
update_state,
|
update_state,
|
||||||
exit_on_esc,
|
exit_on_esc,
|
||||||
|
@ -154,7 +158,7 @@ fn render() -> Workload {
|
||||||
render_selection_box,
|
render_selection_box,
|
||||||
render_entities,
|
render_entities,
|
||||||
).into_sequential_workload().run_if(is_ingame),
|
).into_sequential_workload().run_if(is_ingame),
|
||||||
kubi_ui_draw,
|
legacy_ui_render,
|
||||||
).into_sequential_workload()
|
).into_sequential_workload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,60 @@
|
||||||
use kubi_ui::element::progress_bar::ProgressBar;
|
use shipyard::{UniqueView, UniqueViewMut, Workload, IntoWorkload, EntityId, Unique, AllStoragesViewMut, ViewMut, Get, SystemModificator, track};
|
||||||
use shipyard::{UniqueView, UniqueViewMut, Workload, NonSendSync, IntoWorkload};
|
|
||||||
use winit::keyboard::KeyCode;
|
use winit::keyboard::KeyCode;
|
||||||
|
use glam::{Mat3, vec2};
|
||||||
use crate::{
|
use crate::{
|
||||||
world::ChunkStorage,
|
world::ChunkStorage,
|
||||||
state::{GameState, NextState},
|
state::{GameState, NextState, is_changing_state},
|
||||||
rendering::WindowSize,
|
transform::Transform2d,
|
||||||
|
legacy_gui::{
|
||||||
|
LegacyGuiComponent,
|
||||||
|
progressbar::ProgressbarComponent
|
||||||
|
},
|
||||||
|
rendering::{WindowSize, if_resized},
|
||||||
input::RawKbmInputState,
|
input::RawKbmInputState,
|
||||||
guiv2_integration::UiState,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn render_progressbar(
|
#[derive(Unique, Clone, Copy)]
|
||||||
mut ui: NonSendSync<UniqueViewMut<UiState>>,
|
struct ProgressbarId(EntityId);
|
||||||
world: UniqueView<ChunkStorage>,
|
|
||||||
size: UniqueView<WindowSize>
|
fn spawn_loading_screen(
|
||||||
|
mut storages: AllStoragesViewMut,
|
||||||
) {
|
) {
|
||||||
let value = {
|
let size = *storages.borrow::<UniqueView<WindowSize>>().unwrap();
|
||||||
|
let entity = storages.add_entity((
|
||||||
|
LegacyGuiComponent,
|
||||||
|
Transform2d(Mat3::from_scale_angle_translation(
|
||||||
|
vec2(size.0.x as f32, 16.),
|
||||||
|
0.,
|
||||||
|
vec2(0., 0.)
|
||||||
|
)),
|
||||||
|
ProgressbarComponent {
|
||||||
|
progress: 0.33
|
||||||
|
},
|
||||||
|
));
|
||||||
|
storages.add_unique(ProgressbarId(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize_progress_bar(
|
||||||
|
size: UniqueView<WindowSize>,
|
||||||
|
bar: UniqueView<ProgressbarId>,
|
||||||
|
mut transforms: ViewMut<Transform2d, track::All>
|
||||||
|
) {
|
||||||
|
let mut trans = (&mut transforms).get(bar.0).unwrap();
|
||||||
|
trans.0.x_axis.x = size.0.x as f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_progress_bar_progress (
|
||||||
|
world: UniqueView<ChunkStorage>,
|
||||||
|
mut bar: ViewMut<ProgressbarComponent>,
|
||||||
|
eid: UniqueView<ProgressbarId>,
|
||||||
|
) {
|
||||||
|
let mut bar = (&mut bar).get(eid.0).unwrap();
|
||||||
let loaded = world.chunks.iter().fold(0, |acc, (&_, chunk)| {
|
let loaded = world.chunks.iter().fold(0, |acc, (&_, chunk)| {
|
||||||
acc + chunk.desired_state.matches_current(chunk.current_state) as usize
|
acc + chunk.desired_state.matches_current(chunk.current_state) as usize
|
||||||
});
|
});
|
||||||
let total = world.chunks.len();
|
let total = world.chunks.len();
|
||||||
loaded as f32 / total as f32
|
let progress = loaded as f32 / total as f32;
|
||||||
};
|
bar.progress = progress;
|
||||||
ui.ui.add(
|
|
||||||
ProgressBar { value, ..Default::default() },
|
|
||||||
size.0.as_vec2()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn switch_to_ingame_if_loaded(
|
fn switch_to_ingame_if_loaded(
|
||||||
|
@ -51,10 +81,24 @@ fn override_loading(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn despawn_loading_screen_if_switching_state(
|
||||||
|
mut storages: AllStoragesViewMut,
|
||||||
|
) {
|
||||||
|
let state = storages.borrow::<UniqueView<NextState>>().unwrap().0.unwrap();
|
||||||
|
if state != GameState::LoadingWorld {
|
||||||
|
let progress_bar = storages.borrow::<UniqueView<ProgressbarId>>().unwrap().0;
|
||||||
|
storages.delete_entity(progress_bar);
|
||||||
|
storages.remove_unique::<ProgressbarId>().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_loading_screen() -> Workload {
|
pub fn update_loading_screen() -> Workload {
|
||||||
(
|
(
|
||||||
render_progressbar,
|
spawn_loading_screen.run_if_missing_unique::<ProgressbarId>(),
|
||||||
|
resize_progress_bar.run_if(if_resized),
|
||||||
|
update_progress_bar_progress,
|
||||||
override_loading,
|
override_loading,
|
||||||
switch_to_ingame_if_loaded,
|
switch_to_ingame_if_loaded,
|
||||||
|
despawn_loading_screen_if_switching_state.run_if(is_changing_state),
|
||||||
).into_sequential_workload()
|
).into_sequential_workload()
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,10 @@ pub struct ChunkShaderPrefab(pub Program);
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct ColoredShaderPrefab(pub Program);
|
pub struct ColoredShaderPrefab(pub Program);
|
||||||
|
|
||||||
|
#[derive(Unique)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ProgressbarShaderPrefab(pub Program);
|
||||||
|
|
||||||
pub fn load_prefabs(
|
pub fn load_prefabs(
|
||||||
storages: AllStoragesView,
|
storages: AllStoragesView,
|
||||||
renderer: NonSendSync<UniqueView<Renderer>>,
|
renderer: NonSendSync<UniqueView<Renderer>>,
|
||||||
|
@ -80,6 +84,14 @@ pub fn load_prefabs(
|
||||||
&renderer.display
|
&renderer.display
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
storages.add_unique_non_send_sync(ProgressbarShaderPrefab(
|
||||||
|
include_shader_prefab!(
|
||||||
|
"gui/progressbar",
|
||||||
|
"../shaders/gui/progressbar.vert",
|
||||||
|
"../shaders/gui/progressbar.frag",
|
||||||
|
&renderer.display
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
log::info!("releasing shader compiler");
|
log::info!("releasing shader compiler");
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,10 @@ use winit::{
|
||||||
use glium::{Display, Surface, Version, Api};
|
use glium::{Display, Surface, Version, Api};
|
||||||
use glutin::{
|
use glutin::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
context::{ContextAttributesBuilder, GlProfile},
|
context::ContextAttributesBuilder,
|
||||||
surface::{WindowSurface, SurfaceAttributesBuilder},
|
surface::{WindowSurface, SurfaceAttributesBuilder},
|
||||||
display::GetGlDisplay,
|
display::GetGlDisplay,
|
||||||
config::ConfigTemplateBuilder
|
|
||||||
};
|
};
|
||||||
use glutin_winit::DisplayBuilder;
|
|
||||||
use glam::{Vec3, UVec2};
|
use glam::{Vec3, UVec2};
|
||||||
use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}};
|
use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}};
|
||||||
|
|
||||||
|
@ -91,21 +89,15 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let display_builder = DisplayBuilder::new()
|
// First we start by opening a new Window
|
||||||
.with_window_builder(Some(wb));
|
let display_builder = glutin_winit::DisplayBuilder::new().with_window_builder(Some(wb));
|
||||||
|
let config_template_builder = glutin::config::ConfigTemplateBuilder::new();
|
||||||
let config_template_builder = ConfigTemplateBuilder::new()
|
|
||||||
.prefer_hardware_accelerated(Some(true))
|
|
||||||
.with_depth_size(24)
|
|
||||||
.with_multisampling(settings.msaa.unwrap_or_default());
|
|
||||||
|
|
||||||
let (window, gl_config) = display_builder
|
let (window, gl_config) = display_builder
|
||||||
.build(event_loop, config_template_builder, |mut configs| {
|
.build(event_loop, config_template_builder, |mut configs| {
|
||||||
configs.next().unwrap()
|
configs.next().unwrap()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let window = window.unwrap();
|
||||||
let window = window.expect("no window");
|
|
||||||
|
|
||||||
// Now we get the window size to use as the initial size of the Surface
|
// Now we get the window size to use as the initial size of the Surface
|
||||||
let (width, height): (u32, u32) = window.inner_size().into();
|
let (width, height): (u32, u32) = window.inner_size().into();
|
||||||
|
@ -116,22 +108,11 @@ impl Renderer {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Finally we can create a Surface, use it to make a PossiblyCurrentContext and create the glium Display
|
// Finally we can create a Surface, use it to make a PossiblyCurrentContext and create the glium Display
|
||||||
let surface = unsafe {
|
let surface = unsafe { gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() };
|
||||||
gl_config.display().create_window_surface(&gl_config, &attrs).unwrap()
|
let context_attributes = ContextAttributesBuilder::new().build(Some(window.raw_window_handle()));
|
||||||
};
|
|
||||||
|
|
||||||
let context_attributes = ContextAttributesBuilder::new()
|
|
||||||
.with_debug(cfg!(debug_assertions))
|
|
||||||
.with_context_api(glutin::context::ContextApi::Gles(None))
|
|
||||||
.with_profile(GlProfile::Core)
|
|
||||||
.build(Some(window.raw_window_handle()));
|
|
||||||
|
|
||||||
let current_context = unsafe {
|
let current_context = unsafe {
|
||||||
gl_config.display()
|
gl_config.display().create_context(&gl_config, &context_attributes).expect("failed to create context")
|
||||||
.create_context(&gl_config, &context_attributes)
|
|
||||||
.expect("failed to create context")
|
|
||||||
}.make_current(&surface).unwrap();
|
}.make_current(&surface).unwrap();
|
||||||
|
|
||||||
let display = Display::from_context_surface(current_context, surface).unwrap();
|
let display = Display::from_context_surface(current_context, surface).unwrap();
|
||||||
|
|
||||||
//TODO MIGRATION
|
//TODO MIGRATION
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub struct FullscreenSettings {
|
||||||
pub struct GameSettings {
|
pub struct GameSettings {
|
||||||
pub vsync: bool,
|
pub vsync: bool,
|
||||||
pub fullscreen: Option<FullscreenSettings>,
|
pub fullscreen: Option<FullscreenSettings>,
|
||||||
pub msaa: Option<u8>,
|
pub msaa: Option<u16>,
|
||||||
pub max_anisotropy: Option<u16>,
|
pub max_anisotropy: Option<u16>,
|
||||||
/// there's a 1 chunk border of loaded but invisible around this
|
/// there's a 1 chunk border of loaded but invisible around this
|
||||||
pub render_distance: u8,
|
pub render_distance: u8,
|
||||||
|
|
Loading…
Reference in a new issue