mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-12-21 19:38:20 -06:00
commit
1e051c47b6
|
@ -12,18 +12,25 @@ pub fn initialize_from_args(
|
||||||
// If an address is provided, we're in multiplayer mode (the first argument is the address)
|
// If an address is provided, we're in multiplayer mode (the first argument is the address)
|
||||||
// Otherwise, we're in singleplayer mode and working with local stuff
|
// Otherwise, we're in singleplayer mode and working with local stuff
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() > 1 {
|
if cfg!(target_os = "android") || (args.get(1) == Some(&"android".into())) {
|
||||||
// Parse the address and switch the state to connecting
|
// TODO REMOVE: temporarily bypass menu on Android as hUI (0.1.0-alpha.5) doesnt play well with touchscreens (yet? :3)
|
||||||
let address = args[1].parse::<SocketAddr>().expect("invalid address");
|
// TODO REMOVE: disable save files on Android as they're stored in relative path rn
|
||||||
all_storages.add_unique(GameType::Muliplayer);
|
all_storages.add_unique(GameType::Singleplayer);
|
||||||
all_storages.add_unique(ServerAddress(address));
|
all_storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::LoadingWorld);
|
||||||
all_storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::Connecting);
|
} else if args.get(1) == Some(&"play".into()) {
|
||||||
} else {
|
|
||||||
// Open the local save file
|
// Open the local save file
|
||||||
let save_file = open_local_save_file(Path::new("./world.kubi")).expect("failed to open save file");
|
let save_file = open_local_save_file(Path::new("./world.kubi")).expect("failed to open save file");
|
||||||
all_storages.add_unique(IOThreadManager::new(save_file));
|
all_storages.add_unique(IOThreadManager::new(save_file));
|
||||||
// Switch the state and kick off the world loading
|
// Switch the state and kick off the world loading
|
||||||
all_storages.add_unique(GameType::Singleplayer);
|
all_storages.add_unique(GameType::Singleplayer);
|
||||||
all_storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::LoadingWorld);
|
all_storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::LoadingWorld);
|
||||||
|
} else if args.len() > 1 {
|
||||||
|
// Parse the address and switch the state to connecting
|
||||||
|
let address = args[1].parse::<SocketAddr>().expect("invalid address");
|
||||||
|
all_storages.add_unique(GameType::Muliplayer);
|
||||||
|
all_storages.add_unique(ServerAddress(address));
|
||||||
|
all_storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::Connecting);
|
||||||
|
} else {
|
||||||
|
all_storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::MainMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ use shipyard::{
|
||||||
WorkloadModificator,
|
WorkloadModificator,
|
||||||
SystemModificator
|
SystemModificator
|
||||||
};
|
};
|
||||||
|
use ui::{main_menu::update_main_menu, settings_ui::f1_held_settings_condition};
|
||||||
use winit::{
|
use winit::{
|
||||||
event_loop::{EventLoop, ControlFlow},
|
event_loop::{EventLoop, ControlFlow},
|
||||||
event::{Event, WindowEvent}
|
event::{Event, WindowEvent}
|
||||||
|
@ -35,6 +36,7 @@ pub(crate) use ui::{
|
||||||
crosshair_ui,
|
crosshair_ui,
|
||||||
settings_ui,
|
settings_ui,
|
||||||
shutdown_screen,
|
shutdown_screen,
|
||||||
|
main_menu,
|
||||||
};
|
};
|
||||||
pub(crate) mod rendering;
|
pub(crate) mod rendering;
|
||||||
pub(crate) mod world;
|
pub(crate) mod world;
|
||||||
|
@ -77,10 +79,11 @@ use block_placement::update_block_placement;
|
||||||
use delta_time::{DeltaTime, init_delta_time};
|
use delta_time::{DeltaTime, init_delta_time};
|
||||||
use cursor_lock::{debug_toggle_lock, insert_lock_state, lock_cursor_now, update_cursor_lock_state};
|
use cursor_lock::{debug_toggle_lock, insert_lock_state, lock_cursor_now, update_cursor_lock_state};
|
||||||
use control_flow::{exit_on_esc, insert_control_flow_unique, RequestExit};
|
use control_flow::{exit_on_esc, insert_control_flow_unique, RequestExit};
|
||||||
use state::{init_state, is_connecting, is_ingame, is_ingame_or_loading, is_loading, is_shutting_down, update_state};
|
use state::{init_state, is_connecting, is_ingame, is_ingame_or_loading, is_ingame_or_loading_or_connecting_or_shutting_down, is_loading, is_main_menu, is_shutting_down, update_state};
|
||||||
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 hui_integration::{kubi_ui_begin, /*kubi_ui_draw,*/ kubi_ui_end, kubi_ui_init};
|
use hui_integration::{kubi_ui_begin, /*kubi_ui_draw,*/ kubi_ui_end, kubi_ui_init};
|
||||||
|
use main_menu::render_main_menu_ui;
|
||||||
use loading_screen::update_loading_screen;
|
use loading_screen::update_loading_screen;
|
||||||
use shutdown_screen::update_shutdown_screen;
|
use shutdown_screen::update_shutdown_screen;
|
||||||
use connecting_screen::update_connecting_screen;
|
use connecting_screen::update_connecting_screen;
|
||||||
|
@ -109,7 +112,7 @@ fn startup() -> Workload {
|
||||||
insert_lock_state,
|
insert_lock_state,
|
||||||
init_state,
|
init_state,
|
||||||
initialize_from_args,
|
initialize_from_args,
|
||||||
lock_cursor_now,
|
// lock_cursor_now,
|
||||||
init_input,
|
init_input,
|
||||||
insert_control_flow_unique,
|
insert_control_flow_unique,
|
||||||
init_delta_time,
|
init_delta_time,
|
||||||
|
@ -126,13 +129,18 @@ fn update() -> Workload {
|
||||||
update_cursor_lock_state,
|
update_cursor_lock_state,
|
||||||
process_inputs,
|
process_inputs,
|
||||||
kubi_ui_begin,
|
kubi_ui_begin,
|
||||||
|
(
|
||||||
|
update_main_menu
|
||||||
|
).into_sequential_workload().run_if(is_main_menu),
|
||||||
(
|
(
|
||||||
init_game_world.run_if_missing_unique::<ChunkTaskManager>(),
|
init_game_world.run_if_missing_unique::<ChunkTaskManager>(),
|
||||||
(
|
(
|
||||||
spawn_player.run_if_storage_empty::<MainPlayer>(),
|
spawn_player.run_if_storage_empty::<MainPlayer>(),
|
||||||
).into_sequential_workload().run_if(is_singleplayer),
|
).into_sequential_workload().run_if(is_singleplayer),
|
||||||
).into_sequential_workload().run_if(is_ingame_or_loading),
|
).into_sequential_workload().run_if(is_ingame_or_loading),
|
||||||
update_networking().run_if(is_multiplayer),
|
(
|
||||||
|
update_networking
|
||||||
|
).into_sequential_workload().run_if(is_multiplayer).run_if(is_ingame_or_loading_or_connecting_or_shutting_down),
|
||||||
(
|
(
|
||||||
update_connecting_screen,
|
update_connecting_screen,
|
||||||
).into_sequential_workload().run_if(is_connecting),
|
).into_sequential_workload().run_if(is_connecting),
|
||||||
|
@ -153,12 +161,14 @@ fn update() -> Workload {
|
||||||
//UI:
|
//UI:
|
||||||
render_chat,
|
render_chat,
|
||||||
draw_crosshair,
|
draw_crosshair,
|
||||||
render_settings_ui,
|
render_settings_ui.run_if(f1_held_settings_condition),
|
||||||
).into_sequential_workload().run_if(is_ingame),
|
).into_sequential_workload().run_if(is_ingame),
|
||||||
(
|
(
|
||||||
update_shutdown_screen,
|
update_shutdown_screen,
|
||||||
).into_sequential_workload().run_if(is_shutting_down),
|
).into_sequential_workload().run_if(is_shutting_down),
|
||||||
update_networking_late.run_if(is_multiplayer),
|
(
|
||||||
|
update_networking_late
|
||||||
|
).into_sequential_workload().run_if(is_multiplayer).run_if(is_ingame_or_loading_or_connecting_or_shutting_down),
|
||||||
compute_cameras,
|
compute_cameras,
|
||||||
kubi_ui_end,
|
kubi_ui_end,
|
||||||
exit_on_esc,
|
exit_on_esc,
|
||||||
|
|
|
@ -11,9 +11,9 @@ use kubi_shared::networking::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
events::EventComponent,
|
events::EventComponent,
|
||||||
|
fixed_timestamp::FixedTimestamp,
|
||||||
|
state::{is_ingame_or_loading, is_ingame_or_loading_or_connecting_or_shutting_down},
|
||||||
world::tasks::ChunkTaskManager,
|
world::tasks::ChunkTaskManager,
|
||||||
state::is_ingame_or_loading,
|
|
||||||
fixed_timestamp::FixedTimestamp
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod handshake;
|
mod handshake;
|
||||||
|
@ -185,13 +185,15 @@ fn is_join_state<const STATE: u8>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_multiplayer(
|
pub fn is_multiplayer(
|
||||||
game_type: UniqueView<GameType>
|
game_type: Option<UniqueView<GameType>>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let Some(game_type) = game_type else { return false };
|
||||||
*game_type == GameType::Muliplayer
|
*game_type == GameType::Muliplayer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_singleplayer(
|
pub fn is_singleplayer(
|
||||||
game_type: UniqueView<GameType>
|
game_type: Option<UniqueView<GameType>>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let Some(game_type) = game_type else { return false };
|
||||||
*game_type == GameType::Singleplayer
|
*game_type == GameType::Singleplayer
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::mem::take;
|
||||||
pub enum GameState {
|
pub enum GameState {
|
||||||
#[default]
|
#[default]
|
||||||
Initial,
|
Initial,
|
||||||
|
MainMenu,
|
||||||
Connecting,
|
Connecting,
|
||||||
LoadingWorld,
|
LoadingWorld,
|
||||||
InGame,
|
InGame,
|
||||||
|
@ -34,6 +35,12 @@ pub fn is_changing_state(
|
||||||
state.0.is_some()
|
state.0.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_main_menu(
|
||||||
|
state: UniqueView<GameState>
|
||||||
|
) -> bool {
|
||||||
|
*state == GameState::MainMenu
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_connecting(
|
pub fn is_connecting(
|
||||||
state: UniqueView<GameState>
|
state: UniqueView<GameState>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
@ -64,6 +71,12 @@ pub fn is_ingame_or_loading(
|
||||||
matches!(*state, GameState::InGame | GameState::LoadingWorld)
|
matches!(*state, GameState::InGame | GameState::LoadingWorld)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_ingame_or_loading_or_connecting_or_shutting_down(
|
||||||
|
state: UniqueView<GameState>
|
||||||
|
) -> bool {
|
||||||
|
matches!(*state, GameState::InGame | GameState::LoadingWorld | GameState::Connecting)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_ingame_or_shutting_down(
|
pub fn is_ingame_or_shutting_down(
|
||||||
state: UniqueView<GameState>
|
state: UniqueView<GameState>
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub(crate) mod main_menu;
|
||||||
pub(crate) mod loading_screen;
|
pub(crate) mod loading_screen;
|
||||||
pub(crate) mod connecting_screen;
|
pub(crate) mod connecting_screen;
|
||||||
pub(crate) mod shutdown_screen;
|
pub(crate) mod shutdown_screen;
|
||||||
|
|
165
kubi/src/ui/main_menu.rs
Normal file
165
kubi/src/ui/main_menu.rs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use glam::vec4;
|
||||||
|
use hui::{
|
||||||
|
element::{
|
||||||
|
container::Container,
|
||||||
|
interactable::ElementInteractableExt,
|
||||||
|
text::Text,
|
||||||
|
UiElementExt
|
||||||
|
},
|
||||||
|
layout::Alignment,
|
||||||
|
rect::Corners,
|
||||||
|
signal::Signal,
|
||||||
|
rect_frame,
|
||||||
|
size,
|
||||||
|
};
|
||||||
|
use kubi_shared::data::{io_thread::IOThreadManager, open_local_save_file};
|
||||||
|
use settings_overlay::{not_settings_ui_shown, settings_overlay_logic};
|
||||||
|
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoWorkload, NonSendSync, SystemModificator, Unique, UniqueView, UniqueViewMut, Workload, WorkloadModificator};
|
||||||
|
use crate::{
|
||||||
|
control_flow::RequestExit,
|
||||||
|
hui_integration::UiState, networking::GameType, rendering::Renderer, state::{GameState, NextState}};
|
||||||
|
|
||||||
|
|
||||||
|
mod settings_overlay;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum MainMenuPage {
|
||||||
|
TopMenu,
|
||||||
|
Settings,
|
||||||
|
// ListWorlds {
|
||||||
|
// list: Vec<String>,
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Unique)]
|
||||||
|
struct MainMenuState {
|
||||||
|
page: MainMenuPage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Signal, Clone, Copy)]
|
||||||
|
enum MainMenuSignal {
|
||||||
|
GotoPage(MainMenuPage),
|
||||||
|
PlayOffline,
|
||||||
|
PlayOnline,
|
||||||
|
Quit,
|
||||||
|
// CreatePlayWorld {
|
||||||
|
// name: String,
|
||||||
|
// },
|
||||||
|
// PlayWorld {
|
||||||
|
// path: PathBuf,
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main_menu_leave(
|
||||||
|
storages: AllStoragesView,
|
||||||
|
) {
|
||||||
|
if storages.remove_unique::<MainMenuState>().is_err() {
|
||||||
|
log::warn!("what the fuck? shouldn't matter tho")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_main_menu_ui(
|
||||||
|
mut hui: NonSendSync<UniqueViewMut<UiState>>,
|
||||||
|
ren: UniqueView<Renderer>,
|
||||||
|
) {
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(100%, 100%))
|
||||||
|
.with_padding(30.)
|
||||||
|
.with_gap(20.)
|
||||||
|
.with_background(Corners::top_bottom(
|
||||||
|
vec4(0.0, 0.0, 0.0, 0.85),
|
||||||
|
vec4(0.0, 0.0, 0.0, 0.0))
|
||||||
|
)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(100%, auto))
|
||||||
|
.with_align(Alignment::Center)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Text::new("Kubi")
|
||||||
|
.with_text_size(120)
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_child(ui);
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(100%, 100%=))
|
||||||
|
.with_align(Alignment::Center)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Container::default()
|
||||||
|
.with_align((Alignment::Center, Alignment::Begin))
|
||||||
|
.with_padding(20.)
|
||||||
|
.with_gap(10.)
|
||||||
|
.with_background(rect_frame! {
|
||||||
|
color: (0.1, 0.1, 0.1),
|
||||||
|
corner_radius: 10.,
|
||||||
|
})
|
||||||
|
.with_children(|ui| {
|
||||||
|
for (button_text, button_signal) in [
|
||||||
|
("Singleplayer", MainMenuSignal::PlayOffline),
|
||||||
|
("Multiplayer", MainMenuSignal::PlayOnline),
|
||||||
|
("Settings", MainMenuSignal::GotoPage(MainMenuPage::Settings)),
|
||||||
|
("Quit", MainMenuSignal::Quit),
|
||||||
|
] {
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(300, 50))
|
||||||
|
.with_align(Alignment::Center)
|
||||||
|
.with_background(rect_frame! {
|
||||||
|
color: (0.2, 0.2, 0.2),
|
||||||
|
corner_radius: 3.,
|
||||||
|
})
|
||||||
|
.with_children(|ui| {
|
||||||
|
Text::new(button_text)
|
||||||
|
.with_text_size(24)
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.on_click(move || button_signal)
|
||||||
|
.add_child(ui)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_root(&mut hui.hui, ren.size_vec2());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main_menu_process_signals(
|
||||||
|
storages: AllStoragesViewMut,
|
||||||
|
) {
|
||||||
|
let mut hui = storages.borrow::<NonSendSync<UniqueViewMut<UiState>>>().unwrap();
|
||||||
|
let mut quit = storages.borrow::<UniqueViewMut<RequestExit>>().unwrap();
|
||||||
|
hui.hui.process_signals(|signal| {
|
||||||
|
match signal {
|
||||||
|
MainMenuSignal::PlayOffline => {
|
||||||
|
log::info!("play button pressed");
|
||||||
|
// Open the local save file
|
||||||
|
let save_file = open_local_save_file(Path::new("./world.kubi")).expect("failed to open save file");
|
||||||
|
storages.add_unique(IOThreadManager::new(save_file));
|
||||||
|
// Switch the state and kick off the world loading
|
||||||
|
storages.add_unique(GameType::Singleplayer);
|
||||||
|
storages.borrow::<UniqueViewMut<NextState>>().unwrap().0 = Some(GameState::LoadingWorld);
|
||||||
|
}
|
||||||
|
MainMenuSignal::PlayOnline => {
|
||||||
|
|
||||||
|
},
|
||||||
|
MainMenuSignal::GotoPage(page) => {
|
||||||
|
log::info!("goto page button pressed");
|
||||||
|
storages.add_unique(MainMenuState { page });
|
||||||
|
}
|
||||||
|
MainMenuSignal::Quit => {
|
||||||
|
log::info!("quit button pressed");
|
||||||
|
quit.0 = true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_main_menu() -> Workload {
|
||||||
|
(
|
||||||
|
render_main_menu_ui.run_if(not_settings_ui_shown),
|
||||||
|
settings_overlay_logic,
|
||||||
|
main_menu_process_signals,
|
||||||
|
).into_sequential_workload()
|
||||||
|
}
|
68
kubi/src/ui/main_menu/settings_overlay.rs
Normal file
68
kubi/src/ui/main_menu/settings_overlay.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use glam::vec4;
|
||||||
|
use hui::{
|
||||||
|
element::{
|
||||||
|
container::Container,
|
||||||
|
interactable::ElementInteractableExt,
|
||||||
|
text::Text,
|
||||||
|
UiElementExt
|
||||||
|
},
|
||||||
|
layout::Alignment,
|
||||||
|
rect::Corners,
|
||||||
|
signal::Signal,
|
||||||
|
rect_frame,
|
||||||
|
size,
|
||||||
|
};
|
||||||
|
use kubi_shared::data::{io_thread::IOThreadManager, open_local_save_file};
|
||||||
|
use shipyard::{AllStoragesView, AllStoragesViewMut, IntoWorkload, NonSendSync, SystemModificator, Unique, UniqueView, UniqueViewMut, Workload, WorkloadModificator};
|
||||||
|
use crate::{
|
||||||
|
control_flow::RequestExit, hui_integration::UiState, main_menu::MainMenuPage, networking::GameType, rendering::Renderer, state::{GameState, NextState}};
|
||||||
|
|
||||||
|
use super::{super::settings_ui::render_settings_ui2, MainMenuSignal, MainMenuState};
|
||||||
|
|
||||||
|
pub fn settings_ui_shown(mms: Option<UniqueView<MainMenuState>>) -> bool {
|
||||||
|
let Some(mms) = mms else { return false };
|
||||||
|
matches!(mms.page, MainMenuPage::Settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::just_underscores_and_digits)]
|
||||||
|
pub fn not_settings_ui_shown(_0: Option<UniqueView<MainMenuState>>) -> bool {
|
||||||
|
!settings_ui_shown(_0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: shows the back button over the settings UI
|
||||||
|
fn show_settings_back_button(
|
||||||
|
mut hui: NonSendSync<UniqueViewMut<UiState>>,
|
||||||
|
ren: UniqueView<Renderer>,
|
||||||
|
) {
|
||||||
|
Container::default()
|
||||||
|
.with_size(size!(100%, 100%))
|
||||||
|
.with_align((Alignment::Center, Alignment::End))
|
||||||
|
.with_padding(30.)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Container::default()
|
||||||
|
.with_background(rect_frame! {
|
||||||
|
color: (0.1, 0.1, 0.1),
|
||||||
|
corner_radius: 10.,
|
||||||
|
})
|
||||||
|
.with_padding((30., 5.))
|
||||||
|
.with_size(size!(auto, 50))
|
||||||
|
.with_align(Alignment::Center)
|
||||||
|
.with_children(|ui| {
|
||||||
|
Text::new("Back to the Main Menu")
|
||||||
|
.with_text_size(24)
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.on_click(|| MainMenuSignal::GotoPage(MainMenuPage::TopMenu))
|
||||||
|
.add_child(ui);
|
||||||
|
})
|
||||||
|
.add_root(&mut hui.hui, ren.size_vec2());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn settings_overlay_logic() -> Workload {
|
||||||
|
(
|
||||||
|
render_settings_ui2,
|
||||||
|
show_settings_back_button,
|
||||||
|
).into_sequential_workload().run_if(settings_ui_shown)
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ enum SettingsSignal {
|
||||||
SetRenderDistance(u8),
|
SetRenderDistance(u8),
|
||||||
SetEnableDynamicCrosshair(bool),
|
SetEnableDynamicCrosshair(bool),
|
||||||
SetEnableVsync(bool),
|
SetEnableVsync(bool),
|
||||||
SetEnableDebugChunkBorder(bool),
|
// SetEnableDebugChunkBorder(bool),
|
||||||
SetMouseSensitivity(f32),
|
SetMouseSensitivity(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,18 +68,19 @@ fn checkbox(
|
||||||
.add_child(ui);
|
.add_child(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn f1_held_settings_condition(
|
||||||
|
kbd: UniqueView<RawKbmInputState>,
|
||||||
|
) -> bool {
|
||||||
|
//f1 must be held down to open settings
|
||||||
|
//TODO implement ModalManager instead of this
|
||||||
|
kbd.keyboard_state.contains(KeyCode::F1 as u32)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render_settings_ui(
|
pub fn render_settings_ui(
|
||||||
mut ui: NonSendSync<UniqueViewMut<UiState>>,
|
mut ui: NonSendSync<UniqueViewMut<UiState>>,
|
||||||
mut ren: UniqueViewMut<Renderer>,
|
mut ren: UniqueViewMut<Renderer>,
|
||||||
mut settings: UniqueViewMut<GameSettings>,
|
mut settings: UniqueViewMut<GameSettings>,
|
||||||
kbd: UniqueView<RawKbmInputState>,
|
|
||||||
) {
|
) {
|
||||||
//f1 must be held down to open settings
|
|
||||||
//TODO implement ModalManager instead of this
|
|
||||||
if !kbd.keyboard_state.contains(KeyCode::F1 as u32) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Container::default()
|
Container::default()
|
||||||
.with_size(size!(100%))
|
.with_size(size!(100%))
|
||||||
.with_background((0., 0., 0., 0.5))
|
.with_background((0., 0., 0., 0.5))
|
||||||
|
@ -132,13 +133,13 @@ pub fn render_settings_ui(
|
||||||
);
|
);
|
||||||
Break.add_child(ui);
|
Break.add_child(ui);
|
||||||
|
|
||||||
checkbox(
|
// checkbox(
|
||||||
ui,
|
// ui,
|
||||||
"Debug Chunk Border",
|
// "Debug Chunk Border",
|
||||||
settings.debug_draw_current_chunk_border,
|
// settings.debug_draw_current_chunk_border,
|
||||||
SettingsSignal::SetEnableDebugChunkBorder
|
// SettingsSignal::SetEnableDebugChunkBorder
|
||||||
);
|
// );
|
||||||
Break.add_child(ui);
|
// Break.add_child(ui);
|
||||||
|
|
||||||
Text::new("Mouse Sensitivity")
|
Text::new("Mouse Sensitivity")
|
||||||
.add_child(ui);
|
.add_child(ui);
|
||||||
|
@ -160,7 +161,16 @@ pub fn render_settings_ui(
|
||||||
settings.vsync = value;
|
settings.vsync = value;
|
||||||
ren.reload_settings(&settings);
|
ren.reload_settings(&settings);
|
||||||
},
|
},
|
||||||
SettingsSignal::SetEnableDebugChunkBorder(value) => settings.debug_draw_current_chunk_border = value && cfg!(not(target_os = "android")),
|
// SettingsSignal::SetEnableDebugChunkBorder(value) => settings.debug_draw_current_chunk_border = value && cfg!(not(target_os = "android")),
|
||||||
SettingsSignal::SetMouseSensitivity(value) => settings.mouse_sensitivity = value,
|
SettingsSignal::SetMouseSensitivity(value) => settings.mouse_sensitivity = value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::just_underscores_and_digits)]
|
||||||
|
pub fn render_settings_ui2(
|
||||||
|
_0: NonSendSync<UniqueViewMut<UiState>>,
|
||||||
|
_1: UniqueViewMut<Renderer>,
|
||||||
|
_2: UniqueViewMut<GameSettings>,
|
||||||
|
) {
|
||||||
|
render_settings_ui(_0, _1, _2);
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,12 @@ fn intercept_exit(
|
||||||
mut state: UniqueViewMut<NextState>,
|
mut state: UniqueViewMut<NextState>,
|
||||||
cur_state: UniqueView<GameState>,
|
cur_state: UniqueView<GameState>,
|
||||||
termination_state: Option<UniqueView<ShutdownState>>,
|
termination_state: Option<UniqueView<ShutdownState>>,
|
||||||
|
iota: Option<UniqueView<IOThreadManager>>,
|
||||||
) {
|
) {
|
||||||
|
// If iota is missing, don't bother with shutdown state (likely running without a save file)
|
||||||
|
if iota.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if exit.0 {
|
if exit.0 {
|
||||||
if *cur_state == GameState::ShuttingDown {
|
if *cur_state == GameState::ShuttingDown {
|
||||||
// If we're already shutting down, check if we're done
|
// If we're already shutting down, check if we're done
|
||||||
|
|
|
@ -507,9 +507,13 @@ fn process_completed_tasks(
|
||||||
|
|
||||||
/// Save all modified chunks to the disk
|
/// Save all modified chunks to the disk
|
||||||
pub fn save_on_exit(
|
pub fn save_on_exit(
|
||||||
io: UniqueView<IOThreadManager>,
|
io: Option<UniqueView<IOThreadManager>>,
|
||||||
world: UniqueView<ChunkStorage>,
|
world: UniqueView<ChunkStorage>,
|
||||||
) {
|
) {
|
||||||
|
let Some(io) = io else {
|
||||||
|
log::warn!("no IO thread manager, skipping save on exit");
|
||||||
|
return
|
||||||
|
};
|
||||||
for (&position, chunk) in &world.chunks {
|
for (&position, chunk) in &world.chunks {
|
||||||
if let Some(block_data) = &chunk.block_data {
|
if let Some(block_data) = &chunk.block_data {
|
||||||
if chunk.data_modified {
|
if chunk.data_modified {
|
||||||
|
|
Loading…
Reference in a new issue