mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-11-25 08:18:43 -06:00
Compare commits
20 commits
927337c86d
...
fe1427249b
Author | SHA1 | Date | |
---|---|---|---|
griffi-gh | fe1427249b | ||
griffi-gh | 6f982d4308 | ||
griffi-gh | 3069c1c72f | ||
griffi-gh | 5e62e1781d | ||
griffi-gh | f7210e4dec | ||
griffi-gh | 7dc33c2dce | ||
griffi-gh | 517838e2ae | ||
griffi-gh | 5987484452 | ||
griffi-gh | ae7cc718cf | ||
griffi-gh | 06a49e1b93 | ||
griffi-gh | bc36bb8ce2 | ||
griffi-gh | 612e46f454 | ||
griffi-gh | c69ce9105c | ||
griffi-gh | 363dcddeca | ||
griffi-gh | 2656f5af21 | ||
griffi-gh | 3388dd6491 | ||
griffi-gh | dec20225cb | ||
griffi-gh | d50f4323b1 | ||
griffi-gh | 014e0e7824 | ||
griffi-gh | 5678b0c06f |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -15,3 +15,6 @@ _src
|
||||||
_visualizer.json
|
_visualizer.json
|
||||||
|
|
||||||
*.kubi
|
*.kubi
|
||||||
|
|
||||||
|
/*_log*.txt
|
||||||
|
/*.log
|
||||||
|
|
1679
Cargo.lock
generated
1679
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,7 @@ publish = false
|
||||||
kubi-shared = { path = "../kubi-shared" }
|
kubi-shared = { path = "../kubi-shared" }
|
||||||
kubi-logging = { path = "../kubi-logging" }
|
kubi-logging = { path = "../kubi-logging" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
shipyard = { git = "https://github.com/leudz/shipyard", rev = "0934b426eb9a8", default-features = false, features = ["std", "proc", "thread_local"] }
|
shipyard = { git = "https://github.com/leudz/shipyard", rev = "8ef90ea6c4d1eb6c9cb0988f0d2f873f75044d49", default-features = false, features = ["std", "proc", "thread_local"] }
|
||||||
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
|
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math"] }
|
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math"] }
|
||||||
|
|
|
@ -6,7 +6,7 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math", "serde"] }
|
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math", "serde"] }
|
||||||
shipyard = { git = "https://github.com/leudz/shipyard", rev = "0934b426eb9a8", default-features = false, features = ["std"] }
|
shipyard = { git = "https://github.com/leudz/shipyard", rev = "8ef90ea6c4d1eb6c9cb0988f0d2f873f75044d49", default-features = false, features = ["std"] }
|
||||||
strum = { version = "0.25", features = ["derive"] }
|
strum = { version = "0.25", features = ["derive"] }
|
||||||
num_enum = "0.7"
|
num_enum = "0.7"
|
||||||
postcard = { version = "1.0", features = ["alloc"] }
|
postcard = { version = "1.0", features = ["alloc"] }
|
||||||
|
|
|
@ -8,7 +8,7 @@ publish = false
|
||||||
hashbrown = "0.14"
|
hashbrown = "0.14"
|
||||||
nohash-hasher = "0.2"
|
nohash-hasher = "0.2"
|
||||||
glam = { version = "0.24", features = ["approx"] }
|
glam = { version = "0.24", features = ["approx"] }
|
||||||
glium = { git = "https://github.com/glium/glium", rev = "5d50e7", optional = true }
|
glium = { git = "https://github.com/glium/glium", rev = "968fc92378caf", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["backend_glium", "builtin_elements"]
|
default = ["backend_glium", "builtin_elements"]
|
||||||
|
|
|
@ -2,12 +2,13 @@ use std::any::Any;
|
||||||
use crate::{
|
use crate::{
|
||||||
LayoutInfo,
|
LayoutInfo,
|
||||||
draw::UiDrawCall,
|
draw::UiDrawCall,
|
||||||
measure::{IsMeasurable, Response},
|
measure::Response,
|
||||||
state::StateRepo
|
state::StateRepo
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "builtin_elements")] pub mod container;
|
||||||
|
#[cfg(feature = "builtin_elements")] pub mod spacer;
|
||||||
#[cfg(feature = "builtin_elements")] pub mod progress_bar;
|
#[cfg(feature = "builtin_elements")] pub mod progress_bar;
|
||||||
#[cfg(feature = "builtin_elements")] pub mod layout_box;
|
|
||||||
|
|
||||||
pub trait UiElement {
|
pub trait UiElement {
|
||||||
fn name(&self) -> &'static str { "UiElement" }
|
fn name(&self) -> &'static str { "UiElement" }
|
||||||
|
@ -15,7 +16,6 @@ pub trait UiElement {
|
||||||
fn is_stateful(&self) -> bool { self.state_id().is_some() }
|
fn is_stateful(&self) -> bool { self.state_id().is_some() }
|
||||||
fn is_stateless(&self) -> bool { self.state_id().is_none() }
|
fn is_stateless(&self) -> bool { self.state_id().is_none() }
|
||||||
fn init_state(&self) -> Option<Box<dyn Any>> { None }
|
fn init_state(&self) -> Option<Box<dyn Any>> { None }
|
||||||
fn is_measurable(&self) -> IsMeasurable { IsMeasurable::No }
|
fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response;
|
||||||
fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Option<Response> { None }
|
fn draw(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>);
|
||||||
fn process(&self, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) -> Response;
|
|
||||||
}
|
}
|
||||||
|
|
87
kubi-ui/src/element/container.rs
Normal file
87
kubi-ui/src/element/container.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
use glam::{Vec2, Vec4};
|
||||||
|
use crate::{UiDirection, LayoutInfo, draw::UiDrawCall, measure::{IsMeasurable, Response}, state::StateRepo, UiSize};
|
||||||
|
use super::UiElement;
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
|
pub struct ContainerBorders {
|
||||||
|
pub top: Option<(Vec4, f32)>,
|
||||||
|
pub bottom: Option<(Vec4, f32)>,
|
||||||
|
pub left: Option<(Vec4, f32)>,
|
||||||
|
pub right: Option<(Vec4, f32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ContainerAlign {
|
||||||
|
Begin,
|
||||||
|
Center,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Container {
|
||||||
|
pub min_size: (UiSize, UiSize),
|
||||||
|
pub max_size: (UiSize, UiSize),
|
||||||
|
pub direction: UiDirection,
|
||||||
|
pub gap: f32,
|
||||||
|
pub padding: f32,
|
||||||
|
pub align: (ContainerAlign, ContainerAlign),
|
||||||
|
pub background: Option<Vec4>,
|
||||||
|
pub borders: ContainerBorders,
|
||||||
|
pub clip: bool,
|
||||||
|
pub elements: Vec<Box<dyn UiElement>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Container {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
min_size: (UiSize::Auto, UiSize::Auto),
|
||||||
|
max_size: (UiSize::Auto, UiSize::Auto),
|
||||||
|
direction: UiDirection::Vertical,
|
||||||
|
gap: 0.,
|
||||||
|
padding: 0.,
|
||||||
|
align: (ContainerAlign::Center, ContainerAlign::Begin),
|
||||||
|
background: Default::default(),
|
||||||
|
borders: Default::default(),
|
||||||
|
clip: Default::default(),
|
||||||
|
elements: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UiElement for Container {
|
||||||
|
fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response {
|
||||||
|
let mut size = Vec2::ZERO;
|
||||||
|
let mut leftover_gap = Vec2::ZERO;
|
||||||
|
for element in &self.elements {
|
||||||
|
let measure = element.measure(state, &LayoutInfo {
|
||||||
|
position: layout.position + size,
|
||||||
|
max_size: layout.max_size - size,
|
||||||
|
direction: self.direction,
|
||||||
|
});
|
||||||
|
match self.direction {
|
||||||
|
UiDirection::Horizontal => {
|
||||||
|
size.x += measure.desired_size.x + self.gap;
|
||||||
|
size.y = size.y.max(measure.desired_size.y);
|
||||||
|
leftover_gap.x = self.gap;
|
||||||
|
},
|
||||||
|
UiDirection::Vertical => {
|
||||||
|
size.x = size.x.max(measure.desired_size.x);
|
||||||
|
size.y += measure.desired_size.y + self.gap;
|
||||||
|
leftover_gap.y = self.gap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size -= leftover_gap;
|
||||||
|
Response { desired_size: size }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) {
|
||||||
|
if let Some(color) = self.background {
|
||||||
|
draw.push(UiDrawCall::Rectangle {
|
||||||
|
position: layout.position,
|
||||||
|
size: measure.desired_size,
|
||||||
|
color
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO draw borders
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
use std::any::Any;
|
|
||||||
use crate::{UiDirection, LayoutInfo, draw::UiDrawCall, measure::{IsMeasurable, Response}, state::StateRepo};
|
|
||||||
use super::UiElement;
|
|
||||||
|
|
||||||
pub struct LayoutBox {
|
|
||||||
pub direction: UiDirection,
|
|
||||||
pub gap: f32,
|
|
||||||
pub elements: Vec<Box<dyn UiElement>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UiElement for LayoutBox {
|
|
||||||
fn is_measurable(&self) -> IsMeasurable {
|
|
||||||
IsMeasurable::Maybe
|
|
||||||
}
|
|
||||||
|
|
||||||
fn measure(&self, state: StateRepo, layout: &LayoutInfo) -> Option<Response> {
|
|
||||||
for element in &self.elements {
|
|
||||||
if element.is_measurable() == IsMeasurable::No {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
element.measure(None, layout);
|
|
||||||
}
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process(&self, _state: Option<&mut Box<dyn Any>>, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) -> Response {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
use glam::{vec2, Vec2, Vec4};
|
use glam::{vec2, Vec4};
|
||||||
use crate::{
|
use crate::{
|
||||||
UiSize, LayoutInfo,
|
UiSize, LayoutInfo,
|
||||||
draw::UiDrawCall,
|
draw::UiDrawCall,
|
||||||
measure::{Response, IsMeasurable},
|
measure::Response,
|
||||||
state::StateRepo
|
state::StateRepo
|
||||||
};
|
};
|
||||||
use super::UiElement;
|
use super::UiElement;
|
||||||
|
@ -19,13 +19,11 @@ const BAR_HEIGHT: f32 = 20.0;
|
||||||
impl UiElement for ProgressBar {
|
impl UiElement for ProgressBar {
|
||||||
fn name(&self) -> &'static str { "Progress bar" }
|
fn name(&self) -> &'static str { "Progress bar" }
|
||||||
|
|
||||||
fn is_measurable(&self) -> IsMeasurable { IsMeasurable::Yes }
|
fn measure(&self, _: &StateRepo, layout: &LayoutInfo) -> Response {
|
||||||
|
Response {
|
||||||
fn measure(&self, _: &StateRepo, layout: &LayoutInfo) -> Option<Response> {
|
desired_size: vec2(
|
||||||
Some(Response {
|
|
||||||
size: Vec2::new(
|
|
||||||
match self.size.0 {
|
match self.size.0 {
|
||||||
UiSize::Auto => layout.max_size.x,
|
UiSize::Auto => layout.max_size.x.max(300.),
|
||||||
UiSize::Percentage(p) => layout.max_size.x * p,
|
UiSize::Percentage(p) => layout.max_size.x * p,
|
||||||
UiSize::Pixels(p) => p,
|
UiSize::Pixels(p) => p,
|
||||||
},
|
},
|
||||||
|
@ -35,24 +33,20 @@ impl UiElement for ProgressBar {
|
||||||
UiSize::Pixels(p) => p,
|
UiSize::Pixels(p) => p,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(&self, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) -> Response {
|
fn draw(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec<UiDrawCall>) {
|
||||||
let measure = self.measure(&state, layout).unwrap();
|
|
||||||
|
|
||||||
draw.push(UiDrawCall::Rectangle {
|
draw.push(UiDrawCall::Rectangle {
|
||||||
position: layout.position,
|
position: layout.position,
|
||||||
size: measure.size,
|
size: measure.desired_size,
|
||||||
color: self.color_background
|
color: self.color_background
|
||||||
});
|
});
|
||||||
|
|
||||||
draw.push(UiDrawCall::Rectangle {
|
draw.push(UiDrawCall::Rectangle {
|
||||||
position: layout.position,
|
position: layout.position,
|
||||||
size: measure.size * vec2(self.value, 1.0),
|
size: measure.desired_size * vec2(self.value, 1.0),
|
||||||
color: self.color_foreground
|
color: self.color_foreground
|
||||||
});
|
});
|
||||||
|
|
||||||
measure
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
kubi-ui/src/element/spacer.rs
Normal file
18
kubi-ui/src/element/spacer.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use glam::vec2;
|
||||||
|
use crate::{state::StateRepo, LayoutInfo, measure::Response, draw::UiDrawCall, UiDirection};
|
||||||
|
use super::UiElement;
|
||||||
|
|
||||||
|
pub struct Spacer(f32);
|
||||||
|
|
||||||
|
impl UiElement for Spacer {
|
||||||
|
fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response {
|
||||||
|
Response {
|
||||||
|
desired_size: match layout.direction {
|
||||||
|
UiDirection::Horizontal => vec2(self.0, 0.),
|
||||||
|
UiDirection::Vertical => vec2(0., self.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&self, _measure: &Response, _state: &mut StateRepo, _layout: &LayoutInfo, _draw: &mut Vec<UiDrawCall>) {}
|
||||||
|
}
|
|
@ -32,13 +32,15 @@ impl Default for KubiUi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub enum UiSize {
|
pub enum UiSize {
|
||||||
|
#[default]
|
||||||
Auto,
|
Auto,
|
||||||
Percentage(f32),
|
Percentage(f32),
|
||||||
Pixels(f32),
|
Pixels(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum UiDirection {
|
pub enum UiDirection {
|
||||||
#[default]
|
#[default]
|
||||||
Vertical,
|
Vertical,
|
||||||
|
@ -46,6 +48,7 @@ pub enum UiDirection {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LayoutInfo {
|
struct LayoutInfo {
|
||||||
|
///Not availabe during measuring step
|
||||||
position: Vec2,
|
position: Vec2,
|
||||||
max_size: Vec2,
|
max_size: Vec2,
|
||||||
direction: UiDirection,
|
direction: UiDirection,
|
||||||
|
|
|
@ -9,5 +9,5 @@ pub enum IsMeasurable {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
pub size: Vec2
|
pub desired_size: Vec2
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,18 @@ kubi-shared = { path = "../kubi-shared" }
|
||||||
kubi-logging = { path = "../kubi-logging" }
|
kubi-logging = { path = "../kubi-logging" }
|
||||||
kubi-ui = { path = "../kubi-ui" }
|
kubi-ui = { path = "../kubi-ui" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
glium = { git = "https://github.com/glium/glium", rev = "5d50e7" }
|
glium = { git = "https://github.com/glium/glium", rev = "968fc92378caf" }
|
||||||
|
glutin = "0.31"
|
||||||
|
winit = { version = "0.29", features = ["android-native-activity"] }
|
||||||
|
glutin-winit = "0.4"
|
||||||
|
raw-window-handle = "0.5"
|
||||||
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math"] }
|
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math"] }
|
||||||
image = { version = "0.24", default_features = false, features = ["png"] }
|
image = { version = "0.24", default_features = false, features = ["png"] }
|
||||||
strum = { version = "0.25", features = ["derive"] }
|
strum = { version = "0.25", features = ["derive"] }
|
||||||
hashbrown = "0.14"
|
hashbrown = "0.14"
|
||||||
nohash-hasher = "0.2"
|
nohash-hasher = "0.2"
|
||||||
rayon = "1.7"
|
rayon = "1.7"
|
||||||
shipyard = { git = "https://github.com/leudz/shipyard", rev = "0934b426eb9a8", default-features = false, features = ["std", "proc", "thread_local"] }
|
shipyard = { git = "https://github.com/leudz/shipyard", rev = "8ef90ea6c4d1eb6c9cb0988f0d2f873f75044d49", default-features = false, features = ["std", "proc", "thread_local"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
flume = "0.11"
|
flume = "0.11"
|
||||||
gilrs = { version = "0.10", default_features = false, features = ["xinput"] }
|
gilrs = { version = "0.10", default_features = false, features = ["xinput"] }
|
||||||
|
@ -32,8 +36,8 @@ tinyset = "0.4"
|
||||||
serde_json = { version = "1.0", optional = true } #only used for `generate_visualizer_data`
|
serde_json = { version = "1.0", optional = true } #only used for `generate_visualizer_data`
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
ndk = "0.7"
|
android-activity = "0.5"
|
||||||
ndk-glue = "0.7"
|
ndk = "0.8"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
|
@ -64,6 +68,14 @@ target_sdk_version = 30
|
||||||
required = true
|
required = true
|
||||||
glEsVersion = 0x00030000
|
glEsVersion = 0x00030000
|
||||||
|
|
||||||
|
[[package.metadata.android.uses_feature]]
|
||||||
|
name = "android.hardware.touchscreen.multitouch"
|
||||||
|
required = true
|
||||||
|
|
||||||
|
[[package.metadata.android.uses_feature]]
|
||||||
|
name = "android.hardware.touchscreen.multitouch.distinct"
|
||||||
|
required = true
|
||||||
|
|
||||||
[package.metadata.android.application.activity]
|
[package.metadata.android.application.activity]
|
||||||
config_changes = "orientation|keyboardHidden|screenLayout|screenSize"
|
config_changes = "orientation|keyboardHidden|screenLayout|screenSize"
|
||||||
exported = true
|
exported = true
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut, Workload, IntoWorkload};
|
use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut, Workload, IntoWorkload};
|
||||||
use glium::glutin::event::VirtualKeyCode;
|
use winit::keyboard::KeyCode;
|
||||||
use kubi_shared::{
|
use kubi_shared::{
|
||||||
block::Block,
|
block::Block,
|
||||||
queue::QueuedBlock,
|
queue::QueuedBlock,
|
||||||
player::PlayerHolding,
|
player::PlayerHolding,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
player::MainPlayer,
|
player::MainPlayer,
|
||||||
world::{raycast::{LookingAtBlock, RAYCAST_STEP}, queue::BlockUpdateQueue},
|
world::{
|
||||||
input::{Inputs, PrevInputs, RawKbmInputState},
|
raycast::{LookingAtBlock, RAYCAST_STEP},
|
||||||
events::{EventComponent, player_actions::PlayerActionEvent},
|
queue::BlockUpdateQueue
|
||||||
|
},
|
||||||
|
input::{Inputs, PrevInputs, RawKbmInputState},
|
||||||
|
events::{
|
||||||
|
EventComponent,
|
||||||
|
player_actions::PlayerActionEvent
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const BLOCK_KEY_MAP: &[(VirtualKeyCode, Block)] = &[
|
const BLOCK_KEY_MAP: &[(KeyCode, Block)] = &[
|
||||||
(VirtualKeyCode::Key1, Block::Cobblestone),
|
(KeyCode::Digit1, Block::Cobblestone),
|
||||||
(VirtualKeyCode::Key2, Block::Planks),
|
(KeyCode::Digit2, Block::Planks),
|
||||||
(VirtualKeyCode::Key3, Block::Dirt),
|
(KeyCode::Digit3, Block::Dirt),
|
||||||
(VirtualKeyCode::Key4, Block::Grass),
|
(KeyCode::Digit4, Block::Grass),
|
||||||
(VirtualKeyCode::Key5, Block::Sand),
|
(KeyCode::Digit5, Block::Sand),
|
||||||
(VirtualKeyCode::Key6, Block::Stone),
|
(KeyCode::Digit6, Block::Stone),
|
||||||
(VirtualKeyCode::Key7, Block::Torch),
|
(KeyCode::Digit7, Block::Torch),
|
||||||
(VirtualKeyCode::Key8, Block::Leaf),
|
(KeyCode::Digit8, Block::Leaf),
|
||||||
];
|
];
|
||||||
|
|
||||||
fn pick_block_with_number_keys(
|
fn pick_block_with_number_keys(
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
use shipyard::{UniqueView, UniqueViewMut, Unique, AllStoragesView};
|
use shipyard::{UniqueView, UniqueViewMut, Unique, AllStoragesView};
|
||||||
use glium::glutin::{event::VirtualKeyCode, event_loop::ControlFlow};
|
use winit::{keyboard::KeyCode, event_loop::ControlFlow};
|
||||||
use crate::input::RawKbmInputState;
|
use crate::input::RawKbmInputState;
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique)]
|
||||||
pub struct SetControlFlow(pub Option<ControlFlow>);
|
pub struct RequestExit(pub bool);
|
||||||
|
|
||||||
pub fn exit_on_esc(
|
pub fn exit_on_esc(
|
||||||
raw_inputs: UniqueView<RawKbmInputState>,
|
raw_inputs: UniqueView<RawKbmInputState>,
|
||||||
mut control_flow: UniqueViewMut<SetControlFlow>
|
mut exit: UniqueViewMut<RequestExit>
|
||||||
) {
|
) {
|
||||||
if raw_inputs.keyboard_state.contains(VirtualKeyCode::Escape as u32) {
|
if raw_inputs.keyboard_state.contains(KeyCode::Escape as u32) {
|
||||||
control_flow.0 = Some(ControlFlow::Exit);
|
exit.0 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_control_flow_unique(
|
pub fn insert_control_flow_unique(
|
||||||
storages: AllStoragesView
|
storages: AllStoragesView
|
||||||
) {
|
) {
|
||||||
storages.add_unique(SetControlFlow(None))
|
storages.add_unique(RequestExit(false))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use shipyard::{AllStoragesView, Unique, NonSendSync, UniqueView, UniqueViewMut};
|
use shipyard::{AllStoragesView, Unique, NonSendSync, UniqueView, UniqueViewMut};
|
||||||
use crate::rendering::Renderer;
|
use crate::rendering::Renderer;
|
||||||
use glium::glutin::window::CursorGrabMode;
|
use winit::window::CursorGrabMode;
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique)]
|
||||||
pub struct CursorLock(pub bool);
|
pub struct CursorLock(pub bool);
|
||||||
|
@ -13,8 +13,8 @@ pub fn update_cursor_lock_state(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if lock.is_inserted_or_modified() {
|
if lock.is_inserted_or_modified() {
|
||||||
let gl_window = display.display.gl_window();
|
//TODO MIGRATION
|
||||||
let window = gl_window.window();
|
let window = &display.window;
|
||||||
window.set_cursor_grab(match lock.0 {
|
window.set_cursor_grab(match lock.0 {
|
||||||
true => CursorGrabMode::Confined,
|
true => CursorGrabMode::Confined,
|
||||||
false => CursorGrabMode::None,
|
false => CursorGrabMode::None,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use glam::UVec2;
|
use glam::UVec2;
|
||||||
use shipyard::{World, Component, AllStoragesViewMut, SparseSet, NonSendSync, UniqueView};
|
use shipyard::{World, Component, AllStoragesViewMut, SparseSet, NonSendSync, UniqueView};
|
||||||
use glium::glutin::event::{Event, DeviceEvent, DeviceId, WindowEvent, Touch};
|
use winit::event::{Event, DeviceEvent, DeviceId, WindowEvent, Touch, RawKeyEvent, TouchPhase};
|
||||||
use crate::rendering::Renderer;
|
use crate::rendering::Renderer;
|
||||||
|
|
||||||
pub mod player_actions;
|
pub mod player_actions;
|
||||||
|
@ -24,7 +24,7 @@ pub struct TouchEvent(pub Touch);
|
||||||
#[derive(Component, Clone, Copy, Debug, Default)]
|
#[derive(Component, Clone, Copy, Debug, Default)]
|
||||||
pub struct WindowResizedEvent(pub UVec2);
|
pub struct WindowResizedEvent(pub UVec2);
|
||||||
|
|
||||||
pub fn process_glutin_events(world: &mut World, event: &Event<'_, ()>) {
|
pub fn process_glutin_events(world: &mut World, event: &Event<()>) {
|
||||||
#[allow(clippy::collapsible_match, clippy::single_match)]
|
#[allow(clippy::collapsible_match, clippy::single_match)]
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { window_id: _, event } => match event {
|
Event::WindowEvent { window_id: _, event } => match event {
|
||||||
|
@ -36,17 +36,25 @@ pub fn process_glutin_events(world: &mut World, event: &Event<'_, ()>) {
|
||||||
},
|
},
|
||||||
|
|
||||||
#[cfg(not(feature = "raw-evt"))]
|
#[cfg(not(feature = "raw-evt"))]
|
||||||
WindowEvent::KeyboardInput { device_id, input, is_synthetic } => {
|
WindowEvent::KeyboardInput { device_id, event, .. } => {
|
||||||
world.add_entity((
|
world.add_entity((
|
||||||
EventComponent,
|
EventComponent,
|
||||||
InputDeviceEvent {
|
InputDeviceEvent {
|
||||||
device_id: *device_id,
|
device_id: *device_id,
|
||||||
event: DeviceEvent::Key(*input)
|
event: DeviceEvent::Key(RawKeyEvent {
|
||||||
|
physical_key: event.physical_key,
|
||||||
|
state: event.state,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowEvent::Touch(touch) => {
|
WindowEvent::Touch(touch) => {
|
||||||
|
// if matches!(touch.phase, TouchPhase::Started | TouchPhase::Cancelled | TouchPhase::Ended) {
|
||||||
|
// println!("TOUCH ==================== {:#?}", touch);
|
||||||
|
// } else {
|
||||||
|
// println!("TOUCH MOVED {:?} {}", touch.phase, touch.id);
|
||||||
|
// }
|
||||||
world.add_entity((
|
world.add_entity((
|
||||||
EventComponent,
|
EventComponent,
|
||||||
TouchEvent(*touch)
|
TouchEvent(*touch)
|
||||||
|
@ -67,13 +75,13 @@ pub fn process_glutin_events(world: &mut World, event: &Event<'_, ()>) {
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
|
||||||
Event::LoopDestroyed => {
|
Event::LoopExiting => {
|
||||||
world.add_entity((
|
world.add_entity((
|
||||||
EventComponent,
|
EventComponent,
|
||||||
OnBeforeExitEvent
|
OnBeforeExitEvent
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
use std::{fs::File, path::Path, io::{Read, Seek}};
|
use std::{fs::File, path::Path, io::{Read, Seek}};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use shipyard::{Unique, AllStoragesView};
|
||||||
|
|
||||||
pub trait ReadOnly: Read + Seek {}
|
pub trait ReadOnly: Read + Seek {}
|
||||||
impl<T: Read + Seek> ReadOnly for T {}
|
impl<T: Read + Seek> ReadOnly for T {}
|
||||||
|
|
||||||
pub fn open_asset(path: &Path) -> Result<Box<dyn ReadOnly>> {
|
#[derive(Unique)]
|
||||||
#[cfg(target_os = "android")] {
|
pub struct AssetManager {
|
||||||
use anyhow::Context;
|
#[cfg(target_os = "android")]
|
||||||
use std::ffi::CString;
|
pub(crate) app: android_activity::AndroidApp,
|
||||||
|
}
|
||||||
let asset_manager = ndk_glue::native_activity().asset_manager();
|
|
||||||
let path_cstr = CString::new(path.to_string_lossy().as_bytes())?;
|
impl AssetManager {
|
||||||
let handle = asset_manager.open(&path_cstr).context("Asset doesn't exist")?;
|
pub fn open_asset(&self, path: &Path) -> Result<Box<dyn ReadOnly>> {
|
||||||
Ok(Box::new(handle))
|
#[cfg(target_os = "android")] {
|
||||||
}
|
use anyhow::Context;
|
||||||
#[cfg(not(target_os = "android"))] {
|
use std::ffi::CString;
|
||||||
let asset_path = Path::new("./assets/").join(path);
|
let asset_manager = self.app.asset_manager();
|
||||||
Ok(Box::new(File::open(asset_path)?))
|
let path_cstr = CString::new(path.to_string_lossy().as_bytes())?;
|
||||||
|
let handle = asset_manager.open(&path_cstr).context("Asset doesn't exist")?;
|
||||||
|
Ok(Box::new(handle))
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "android"))] {
|
||||||
|
let asset_path = Path::new("./assets/").join(path);
|
||||||
|
Ok(Box::new(File::open(asset_path)?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use gilrs::{Gilrs, GamepadId, Button, Event, Axis};
|
use gilrs::{Gilrs, GamepadId, Button, Event, Axis};
|
||||||
use glam::{Vec2, DVec2, vec2, dvec2};
|
use glam::{Vec2, DVec2, vec2, dvec2};
|
||||||
use glium::glutin::event::{DeviceEvent, DeviceId, VirtualKeyCode, ElementState, TouchPhase};
|
use winit::{
|
||||||
|
keyboard::{KeyCode, PhysicalKey},
|
||||||
|
event::{DeviceEvent, DeviceId, ElementState, TouchPhase}
|
||||||
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use tinyset::{SetU32, SetU64};
|
use tinyset::{SetU32, SetU64};
|
||||||
use nohash_hasher::BuildNoHashHasher;
|
use nohash_hasher::BuildNoHashHasher;
|
||||||
|
@ -94,21 +97,21 @@ fn process_events(
|
||||||
) {
|
) {
|
||||||
input_state.mouse_delta = DVec2::ZERO;
|
input_state.mouse_delta = DVec2::ZERO;
|
||||||
for event in device_events.iter() {
|
for event in device_events.iter() {
|
||||||
match event.event {
|
match &event.event {
|
||||||
DeviceEvent::MouseMotion { delta } => {
|
DeviceEvent::MouseMotion { delta } => {
|
||||||
input_state.mouse_delta = DVec2::from(delta);
|
input_state.mouse_delta = DVec2::from(*delta);
|
||||||
},
|
},
|
||||||
DeviceEvent::Key(input) => {
|
DeviceEvent::Key(input) => {
|
||||||
if let Some(keycode) = input.virtual_keycode {
|
if let PhysicalKey::Code(code) = input.physical_key {
|
||||||
match input.state {
|
match input.state {
|
||||||
ElementState::Pressed => input_state.keyboard_state.insert(keycode as u32),
|
ElementState::Pressed => input_state.keyboard_state.insert(code as u32),
|
||||||
ElementState::Released => input_state.keyboard_state.remove(keycode as u32),
|
ElementState::Released => input_state.keyboard_state.remove(code as u32),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DeviceEvent::Button { button, state } => {
|
DeviceEvent::Button { button, state } => {
|
||||||
if button < 32 {
|
if *button < 32 {
|
||||||
input_state.button_state[button as usize] = matches!(state, ElementState::Pressed);
|
input_state.button_state[*button as usize] = matches!(*state, ElementState::Pressed);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => ()
|
_ => ()
|
||||||
|
@ -127,6 +130,7 @@ fn process_touch_events(
|
||||||
let position = dvec2(event.0.location.x, event.0.location.y);
|
let position = dvec2(event.0.location.x, event.0.location.y);
|
||||||
match event.0.phase {
|
match event.0.phase {
|
||||||
TouchPhase::Started => {
|
TouchPhase::Started => {
|
||||||
|
//println!("touch started: finger {}", event.0.id);
|
||||||
touch_state.fingers.insert(event.0.id, Finger {
|
touch_state.fingers.insert(event.0.id, Finger {
|
||||||
id: event.0.id,
|
id: event.0.id,
|
||||||
device_id: event.0.device_id,
|
device_id: event.0.device_id,
|
||||||
|
@ -143,6 +147,7 @@ fn process_touch_events(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TouchPhase::Ended | TouchPhase::Cancelled => {
|
TouchPhase::Ended | TouchPhase::Cancelled => {
|
||||||
|
//println!("touch ended: finger {}", event.0.id);
|
||||||
touch_state.fingers.remove(&event.0.id);
|
touch_state.fingers.remove(&event.0.id);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -173,14 +178,14 @@ fn update_input_state (
|
||||||
mut inputs: UniqueViewMut<Inputs>,
|
mut inputs: UniqueViewMut<Inputs>,
|
||||||
) {
|
) {
|
||||||
inputs.movement += Vec2::new(
|
inputs.movement += Vec2::new(
|
||||||
raw_inputs.keyboard_state.contains(VirtualKeyCode::D as u32) as u32 as f32 -
|
raw_inputs.keyboard_state.contains(KeyCode::KeyD as u32) as u32 as f32 -
|
||||||
raw_inputs.keyboard_state.contains(VirtualKeyCode::A as u32) as u32 as f32,
|
raw_inputs.keyboard_state.contains(KeyCode::KeyA as u32) as u32 as f32,
|
||||||
raw_inputs.keyboard_state.contains(VirtualKeyCode::W as u32) as u32 as f32 -
|
raw_inputs.keyboard_state.contains(KeyCode::KeyW as u32) as u32 as f32 -
|
||||||
raw_inputs.keyboard_state.contains(VirtualKeyCode::S as u32) as u32 as f32
|
raw_inputs.keyboard_state.contains(KeyCode::KeyS as u32) as u32 as f32
|
||||||
);
|
);
|
||||||
inputs.look += raw_inputs.mouse_delta.as_vec2();
|
inputs.look += raw_inputs.mouse_delta.as_vec2();
|
||||||
inputs.action_a |= raw_inputs.button_state[1];
|
inputs.action_a |= raw_inputs.button_state[0];
|
||||||
inputs.action_b |= raw_inputs.button_state[3];
|
inputs.action_b |= raw_inputs.button_state[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_input_state_gamepad (
|
fn update_input_state_gamepad (
|
||||||
|
|
100
kubi/src/lib.rs
100
kubi/src/lib.rs
|
@ -6,7 +6,7 @@ use shipyard::{
|
||||||
NonSendSync, WorkloadModificator,
|
NonSendSync, WorkloadModificator,
|
||||||
SystemModificator
|
SystemModificator
|
||||||
};
|
};
|
||||||
use glium::glutin::{
|
use winit::{
|
||||||
event_loop::{EventLoop, ControlFlow},
|
event_loop::{EventLoop, ControlFlow},
|
||||||
event::{Event, WindowEvent}
|
event::{Event, WindowEvent}
|
||||||
};
|
};
|
||||||
|
@ -72,7 +72,7 @@ use rendering::{
|
||||||
use block_placement::update_block_placement;
|
use block_placement::update_block_placement;
|
||||||
use delta_time::{DeltaTime, init_delta_time};
|
use delta_time::{DeltaTime, init_delta_time};
|
||||||
use cursor_lock::{insert_lock_state, update_cursor_lock_state, lock_cursor_now};
|
use cursor_lock::{insert_lock_state, update_cursor_lock_state, lock_cursor_now};
|
||||||
use control_flow::{exit_on_esc, insert_control_flow_unique, SetControlFlow};
|
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;
|
||||||
|
@ -80,6 +80,7 @@ use legacy_gui::{render_gui, init_gui, update_gui};
|
||||||
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;
|
||||||
use fixed_timestamp::init_fixed_timestamp_storage;
|
use fixed_timestamp::init_fixed_timestamp_storage;
|
||||||
|
use filesystem::AssetManager;
|
||||||
|
|
||||||
/// stuff required to init the renderer and other basic systems
|
/// stuff required to init the renderer and other basic systems
|
||||||
fn pre_startup() -> Workload {
|
fn pre_startup() -> Workload {
|
||||||
|
@ -169,8 +170,15 @@ fn attach_console() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
|
#[cfg(target_os = "android")]
|
||||||
pub fn kubi_main() {
|
pub fn android_main(app: android_activity::AndroidApp) {
|
||||||
|
use android_activity::WindowManagerFlags;
|
||||||
|
app.set_window_flags(WindowManagerFlags::FULLSCREEN, WindowManagerFlags::empty());
|
||||||
|
kubi_main(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn kubi_main(#[cfg(target_os = "android")] app: android_activity::AndroidApp) {
|
||||||
//Attach console on release builds on windows
|
//Attach console on release builds on windows
|
||||||
#[cfg(all(windows, not(debug_assertions)))] attach_console();
|
#[cfg(all(windows, not(debug_assertions)))] attach_console();
|
||||||
|
|
||||||
|
@ -182,26 +190,19 @@ pub fn kubi_main() {
|
||||||
|
|
||||||
//Create a shipyard world
|
//Create a shipyard world
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
|
|
||||||
|
//Init assman
|
||||||
|
world.add_unique(AssetManager {
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
app: app.clone()
|
||||||
|
});
|
||||||
|
|
||||||
//Register workloads
|
//Register workloads
|
||||||
world.add_workload(pre_startup);
|
world.add_workload(pre_startup);
|
||||||
world.add_workload(startup);
|
world.add_workload(startup);
|
||||||
world.add_workload(update);
|
world.add_workload(update);
|
||||||
world.add_workload(render);
|
world.add_workload(render);
|
||||||
world.add_workload(after_frame_end);
|
world.add_workload(after_frame_end);
|
||||||
|
|
||||||
//Run pre-startup procedure
|
|
||||||
world.run_workload(pre_startup).unwrap();
|
|
||||||
|
|
||||||
//Create event loop
|
|
||||||
let event_loop = EventLoop::new();
|
|
||||||
|
|
||||||
//Initialize renderer
|
|
||||||
{
|
|
||||||
let settings = world.borrow::<UniqueView<GameSettings>>().unwrap();
|
|
||||||
world.add_unique_non_send_sync(Renderer::init(&event_loop, &settings));
|
|
||||||
}
|
|
||||||
world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.)));
|
|
||||||
|
|
||||||
//Save _visualizer.json
|
//Save _visualizer.json
|
||||||
#[cfg(feature = "generate_visualizer_data")]
|
#[cfg(feature = "generate_visualizer_data")]
|
||||||
|
@ -210,24 +211,65 @@ pub fn kubi_main() {
|
||||||
serde_json::to_string(&world.workloads_info()).unwrap(),
|
serde_json::to_string(&world.workloads_info()).unwrap(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
//Run startup systems
|
//Run pre-startup procedure
|
||||||
world.run_workload(startup).unwrap();
|
world.run_workload(pre_startup).unwrap();
|
||||||
|
|
||||||
|
//Create event loop
|
||||||
|
let event_loop ={
|
||||||
|
#[cfg(not(target_os = "android"))] { EventLoop::new().unwrap() }
|
||||||
|
#[cfg(target_os = "android")] {
|
||||||
|
use winit::{
|
||||||
|
platform::android::EventLoopBuilderExtAndroid,
|
||||||
|
event_loop::EventLoopBuilder
|
||||||
|
};
|
||||||
|
EventLoopBuilder::new().with_android_app(app).build().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//Run the event loop
|
//Run the event loop
|
||||||
let mut last_update = Instant::now();
|
let mut last_update = Instant::now();
|
||||||
event_loop.run(move |event, _, control_flow| {
|
let mut ready = false;
|
||||||
*control_flow = ControlFlow::Poll;
|
event_loop.run(move |event, window_target| {
|
||||||
|
//Wait for the window to become active (required for android)
|
||||||
|
if !ready {
|
||||||
|
if Event::Resumed != event {
|
||||||
|
window_target.set_control_flow(ControlFlow::Wait);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize renderer
|
||||||
|
{
|
||||||
|
let settings = world.borrow::<UniqueView<GameSettings>>().unwrap();
|
||||||
|
world.add_unique_non_send_sync(Renderer::init(window_target, &settings));
|
||||||
|
}
|
||||||
|
world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.)));
|
||||||
|
|
||||||
|
//Run startup systems
|
||||||
|
world.run_workload(startup).unwrap();
|
||||||
|
|
||||||
|
ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_target.set_control_flow(ControlFlow::Poll);
|
||||||
|
|
||||||
process_glutin_events(&mut world, &event);
|
process_glutin_events(&mut world, &event);
|
||||||
|
|
||||||
#[allow(clippy::collapsible_match, clippy::single_match)]
|
#[allow(clippy::collapsible_match, clippy::single_match)]
|
||||||
match event {
|
match event {
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
Event::Suspended => {
|
||||||
|
window_target.exit();
|
||||||
|
}
|
||||||
|
|
||||||
Event::WindowEvent { event, .. } => match event {
|
Event::WindowEvent { event, .. } => match event {
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
log::info!("exit requested");
|
log::info!("exit requested");
|
||||||
*control_flow = ControlFlow::Exit;
|
window_target.exit();
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
Event::MainEventsCleared => {
|
|
||||||
|
Event::AboutToWait => {
|
||||||
//Update delta time (maybe move this into a system?)
|
//Update delta time (maybe move this into a system?)
|
||||||
{
|
{
|
||||||
let mut dt_view = world.borrow::<UniqueViewMut<DeltaTime>>().unwrap();
|
let mut dt_view = world.borrow::<UniqueViewMut<DeltaTime>>().unwrap();
|
||||||
|
@ -235,10 +277,10 @@ pub fn kubi_main() {
|
||||||
dt_view.0 = now - last_update;
|
dt_view.0 = now - last_update;
|
||||||
last_update = now;
|
last_update = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Run update workflows
|
//Run update workflows
|
||||||
world.run_workload(update).unwrap();
|
world.run_workload(update).unwrap();
|
||||||
|
|
||||||
//Start rendering (maybe use custom views for this?)
|
//Start rendering (maybe use custom views for this?)
|
||||||
let target = {
|
let target = {
|
||||||
let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
|
let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
|
||||||
|
@ -257,11 +299,11 @@ pub fn kubi_main() {
|
||||||
world.run_workload(after_frame_end).unwrap();
|
world.run_workload(after_frame_end).unwrap();
|
||||||
|
|
||||||
//Process control flow changes
|
//Process control flow changes
|
||||||
if let Some(flow) = world.borrow::<UniqueView<SetControlFlow>>().unwrap().0 {
|
if world.borrow::<UniqueView<RequestExit>>().unwrap().0 {
|
||||||
*control_flow = flow;
|
window_target.exit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
});
|
}).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use shipyard::{UniqueView, UniqueViewMut, Workload, IntoWorkload, EntityId, Unique, AllStoragesViewMut, ViewMut, Get, SystemModificator, track};
|
use shipyard::{UniqueView, UniqueViewMut, Workload, IntoWorkload, EntityId, Unique, AllStoragesViewMut, ViewMut, Get, SystemModificator, track};
|
||||||
use glium::glutin::event::VirtualKeyCode;
|
use winit::keyboard::KeyCode;
|
||||||
use glam::{Mat3, vec2};
|
use glam::{Mat3, vec2};
|
||||||
use crate::{
|
use crate::{
|
||||||
world::ChunkStorage,
|
world::ChunkStorage,
|
||||||
state::{GameState, NextState, is_changing_state},
|
state::{GameState, NextState, is_changing_state},
|
||||||
transform::Transform2d,
|
transform::Transform2d,
|
||||||
legacy_gui::{
|
legacy_gui::{
|
||||||
GuiComponent,
|
GuiComponent,
|
||||||
progressbar::ProgressbarComponent
|
progressbar::ProgressbarComponent
|
||||||
},
|
},
|
||||||
rendering::{WindowSize, if_resized},
|
rendering::{WindowSize, if_resized},
|
||||||
|
@ -76,7 +76,7 @@ fn override_loading(
|
||||||
kbm_state: UniqueView<RawKbmInputState>,
|
kbm_state: UniqueView<RawKbmInputState>,
|
||||||
mut state: UniqueViewMut<NextState>
|
mut state: UniqueViewMut<NextState>
|
||||||
) {
|
) {
|
||||||
if kbm_state.keyboard_state.contains(VirtualKeyCode::F as u32) {
|
if kbm_state.keyboard_state.contains(KeyCode::KeyF as u32) {
|
||||||
state.0 = Some(GameState::InGame);
|
state.0 = Some(GameState::InGame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use shipyard::{Unique, AllStoragesView, UniqueView, UniqueViewMut, Workload, IntoWorkload, EntitiesViewMut, Component, ViewMut, SystemModificator, View, IntoIter, WorkloadModificator};
|
use shipyard::{Unique, AllStoragesView, UniqueView, UniqueViewMut, Workload, IntoWorkload, EntitiesViewMut, Component, ViewMut, SystemModificator, View, IntoIter, WorkloadModificator};
|
||||||
use glium::glutin::event_loop::ControlFlow;
|
use winit::event_loop::ControlFlow;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use uflow::{
|
use uflow::{
|
||||||
client::{Client, Config as ClientConfig, Event as ClientEvent},
|
client::{Client, Config as ClientConfig, Event as ClientEvent},
|
||||||
|
@ -12,7 +12,7 @@ use kubi_shared::networking::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
events::EventComponent,
|
events::EventComponent,
|
||||||
control_flow::SetControlFlow,
|
control_flow::RequestExit,
|
||||||
world::tasks::ChunkTaskManager,
|
world::tasks::ChunkTaskManager,
|
||||||
state::is_ingame_or_loading,
|
state::is_ingame_or_loading,
|
||||||
fixed_timestamp::FixedTimestamp
|
fixed_timestamp::FixedTimestamp
|
||||||
|
@ -155,10 +155,11 @@ pub fn update_networking_late() -> Workload {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disconnect_on_exit(
|
pub fn disconnect_on_exit(
|
||||||
control_flow: UniqueView<SetControlFlow>,
|
exit: UniqueView<RequestExit>,
|
||||||
mut client: UniqueViewMut<UdpClient>,
|
mut client: UniqueViewMut<UdpClient>,
|
||||||
) {
|
) {
|
||||||
if let Some(ControlFlow::ExitWithCode(_)) = control_flow.0 {
|
//TODO check if this works
|
||||||
|
if exit.0 {
|
||||||
if client.0.is_active() {
|
if client.0.is_active() {
|
||||||
client.0.flush();
|
client.0.flush();
|
||||||
client.0.disconnect();
|
client.0.disconnect();
|
||||||
|
@ -167,11 +168,6 @@ pub fn disconnect_on_exit(
|
||||||
} else {
|
} else {
|
||||||
log::info!("Client inactive")
|
log::info!("Client inactive")
|
||||||
}
|
}
|
||||||
// if let Err(error) = client.0. {
|
|
||||||
// log::error!("failed to disconnect: {}", error);
|
|
||||||
// } else {
|
|
||||||
// log::info!("Client disconnected");
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use shipyard::{NonSendSync, UniqueView, Unique, AllStoragesView};
|
use shipyard::{NonSendSync, UniqueView, Unique, AllStoragesView};
|
||||||
use glium::{texture::{SrgbTexture2dArray, MipmapsOption}, Program};
|
use glium::{texture::{SrgbTexture2dArray, MipmapsOption}, Program};
|
||||||
use kubi_shared::block::BlockTexture;
|
use kubi_shared::block::BlockTexture;
|
||||||
use crate::rendering::Renderer;
|
use crate::{rendering::Renderer, filesystem::AssetManager};
|
||||||
|
|
||||||
mod texture;
|
mod texture;
|
||||||
mod shaders;
|
mod shaders;
|
||||||
|
@ -54,12 +54,14 @@ 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>>,
|
||||||
|
assman: UniqueView<AssetManager>
|
||||||
) {
|
) {
|
||||||
log::info!("Loading textures...");
|
log::info!("Loading textures...");
|
||||||
storages.add_unique_non_send_sync(BlockTexturesPrefab(
|
storages.add_unique_non_send_sync(BlockTexturesPrefab(
|
||||||
load_texture2darray_prefab::<BlockTexture, _>(
|
load_texture2darray_prefab::<BlockTexture, _>(
|
||||||
"blocks".into(),
|
&assman,
|
||||||
|
"blocks".into(),
|
||||||
&renderer.display,
|
&renderer.display,
|
||||||
MipmapsOption::AutoGeneratedMipmaps
|
MipmapsOption::AutoGeneratedMipmaps
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,13 +2,14 @@ use strum::IntoEnumIterator;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::{path::PathBuf, io::BufReader};
|
use std::{path::PathBuf, io::BufReader};
|
||||||
use glium::{texture::{SrgbTexture2dArray, RawImage2d, MipmapsOption}, backend::Facade};
|
use glium::{texture::{SrgbTexture2dArray, RawImage2d, MipmapsOption}, backend::Facade};
|
||||||
use crate::filesystem::open_asset;
|
use crate::filesystem::AssetManager;
|
||||||
use super::AssetPaths;
|
use super::AssetPaths;
|
||||||
|
|
||||||
pub fn load_texture2darray_prefab<
|
pub fn load_texture2darray_prefab<
|
||||||
T: AssetPaths + IntoEnumIterator,
|
T: AssetPaths + IntoEnumIterator,
|
||||||
E: Facade
|
E: Facade
|
||||||
>(
|
>(
|
||||||
|
assman: &AssetManager,
|
||||||
directory: PathBuf,
|
directory: PathBuf,
|
||||||
facade: &E,
|
facade: &E,
|
||||||
mipmaps: MipmapsOption,
|
mipmaps: MipmapsOption,
|
||||||
|
@ -21,7 +22,7 @@ pub fn load_texture2darray_prefab<
|
||||||
//Get path to the image and open the file
|
//Get path to the image and open the file
|
||||||
let reader = {
|
let reader = {
|
||||||
let path = directory.join(file_name);
|
let path = directory.join(file_name);
|
||||||
BufReader::new(open_asset(&path).expect("Failed to open texture file"))
|
BufReader::new(assman.open_asset(&path).expect("Failed to open texture file"))
|
||||||
};
|
};
|
||||||
//Parse image data
|
//Parse image data
|
||||||
let (image_data, dimensions) = {
|
let (image_data, dimensions) = {
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
|
use std::num::NonZeroU32;
|
||||||
|
use raw_window_handle::HasRawWindowHandle;
|
||||||
use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView};
|
use shipyard::{Unique, NonSendSync, UniqueView, UniqueViewMut, View, IntoIter, AllStoragesView};
|
||||||
use glium::{
|
use winit::{
|
||||||
Display, Surface,
|
event_loop::EventLoopWindowTarget,
|
||||||
Version, Api,
|
window::{WindowBuilder, Fullscreen, Window},
|
||||||
glutin::{
|
dpi::PhysicalSize
|
||||||
event_loop::EventLoop,
|
};
|
||||||
window::{WindowBuilder, Fullscreen},
|
use glium::{Display, Surface, Version, Api};
|
||||||
ContextBuilder, GlProfile, GlRequest, dpi::PhysicalSize
|
use glutin::{
|
||||||
},
|
prelude::*,
|
||||||
|
context::ContextAttributesBuilder,
|
||||||
|
surface::{WindowSurface, SurfaceAttributesBuilder},
|
||||||
|
display::GetGlDisplay,
|
||||||
};
|
};
|
||||||
use glam::{Vec3, UVec2};
|
use glam::{Vec3, UVec2};
|
||||||
use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}};
|
use crate::{events::WindowResizedEvent, settings::{GameSettings, FullscreenMode}};
|
||||||
|
@ -30,12 +35,14 @@ pub struct WindowSize(pub UVec2);
|
||||||
|
|
||||||
#[derive(Unique)]
|
#[derive(Unique)]
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
pub display: Display
|
pub window: Window,
|
||||||
|
pub display: Display<WindowSurface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
pub fn init(event_loop: &EventLoop<()>, settings: &GameSettings) -> Self {
|
pub fn init(event_loop: &EventLoopWindowTarget<()>, settings: &GameSettings) -> Self {
|
||||||
log::info!("initializing display");
|
log::info!("initializing display");
|
||||||
|
|
||||||
let wb = WindowBuilder::new()
|
let wb = WindowBuilder::new()
|
||||||
.with_title("kubi")
|
.with_title("kubi")
|
||||||
.with_maximized(true)
|
.with_maximized(true)
|
||||||
|
@ -82,16 +89,43 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let cb = ContextBuilder::new()
|
// First we start by opening a new Window
|
||||||
//.with_srgb(false)
|
let display_builder = glutin_winit::DisplayBuilder::new().with_window_builder(Some(wb));
|
||||||
.with_depth_buffer(24)
|
let config_template_builder = glutin::config::ConfigTemplateBuilder::new();
|
||||||
.with_multisampling(settings.msaa.unwrap_or_default())
|
let (window, gl_config) = display_builder
|
||||||
.with_vsync(settings.vsync)
|
.build(event_loop, config_template_builder, |mut configs| {
|
||||||
.with_gl_profile(GlProfile::Core)
|
configs.next().unwrap()
|
||||||
.with_gl(GlRequest::Latest);
|
})
|
||||||
|
.unwrap();
|
||||||
|
let window = window.unwrap();
|
||||||
|
|
||||||
let display = Display::new(wb, cb, event_loop)
|
// Now we get the window size to use as the initial size of the Surface
|
||||||
.expect("Failed to create a glium Display");
|
let (width, height): (u32, u32) = window.inner_size().into();
|
||||||
|
let attrs = SurfaceAttributesBuilder::<WindowSurface>::new().build(
|
||||||
|
window.raw_window_handle(),
|
||||||
|
NonZeroU32::new(width).unwrap(),
|
||||||
|
NonZeroU32::new(height).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Finally we can create a Surface, use it to make a PossiblyCurrentContext and create the glium Display
|
||||||
|
let surface = unsafe { gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() };
|
||||||
|
let context_attributes = ContextAttributesBuilder::new().build(Some(window.raw_window_handle()));
|
||||||
|
let current_context = unsafe {
|
||||||
|
gl_config.display().create_context(&gl_config, &context_attributes).expect("failed to create context")
|
||||||
|
}.make_current(&surface).unwrap();
|
||||||
|
let display = Display::from_context_surface(current_context, surface).unwrap();
|
||||||
|
|
||||||
|
//TODO MIGRATION
|
||||||
|
// let cb = ContextBuilder::new()
|
||||||
|
// //.with_srgb(false)
|
||||||
|
// .with_depth_buffer(24)
|
||||||
|
// .with_multisampling(settings.msaa.unwrap_or_default())
|
||||||
|
// .with_vsync(settings.vsync)
|
||||||
|
// .with_gl_profile(GlProfile::Core)
|
||||||
|
// .with_gl(GlRequest::Latest);
|
||||||
|
|
||||||
|
// let display = Display::new(wb, cb)
|
||||||
|
// .expect("Failed to create a glium Display");
|
||||||
|
|
||||||
log::info!("Vendor: {}", display.get_opengl_vendor_string());
|
log::info!("Vendor: {}", display.get_opengl_vendor_string());
|
||||||
log::info!("Renderer: {}", display.get_opengl_renderer_string());
|
log::info!("Renderer: {}", display.get_opengl_renderer_string());
|
||||||
|
@ -101,10 +135,10 @@ impl Renderer {
|
||||||
if display.is_context_loss_possible() { log::warn!("OpenGL context loss possible") }
|
if display.is_context_loss_possible() { log::warn!("OpenGL context loss possible") }
|
||||||
if display.is_robust() { log::warn!("OpenGL implementation is not robust") }
|
if display.is_robust() { log::warn!("OpenGL implementation is not robust") }
|
||||||
if display.is_debug() { log::info!("OpenGL context is in debug mode") }
|
if display.is_debug() { log::info!("OpenGL context is in debug mode") }
|
||||||
|
|
||||||
assert!(display.is_glsl_version_supported(&Version(Api::GlEs, 3, 0)), "GLSL ES 3.0 is not supported");
|
assert!(display.is_glsl_version_supported(&Version(Api::GlEs, 3, 0)), "GLSL ES 3.0 is not supported");
|
||||||
|
|
||||||
Self { display }
|
Self { window, display }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,13 @@ impl Default for GameSettings {
|
||||||
fullscreen: None,
|
fullscreen: None,
|
||||||
msaa: Some(4),
|
msaa: Some(4),
|
||||||
max_anisotropy: Some(16),
|
max_anisotropy: Some(16),
|
||||||
render_distance: 6,
|
render_distance: match true {
|
||||||
|
cfg!(debug_assertions) => 5,
|
||||||
|
cfg!(target_os = "android") => 6,
|
||||||
|
#[allow(unreachable_patterns)] _ => 8,
|
||||||
|
},
|
||||||
mouse_sensitivity: 1.,
|
mouse_sensitivity: 1.,
|
||||||
debug_draw_current_chunk_border: cfg!(not(target_os = "android")) && cfg!(debug_assertions),
|
debug_draw_current_chunk_border: false, //cfg!(not(target_os = "android")) && cfg!(debug_assertions),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue