Doesn't work, but saving my place

main
Elijah C. Voigt 2 years ago
parent 974e878763
commit 2bcc240cc3

@ -0,0 +1,93 @@
Copyright 2001 The Silkscreen Project Authors (https://github.com/googlefonts/silkscreen)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 KiB

@ -30,29 +30,45 @@ Concrete Energy Pole - https://www.textures.com/download/PBR0340/136381
Space Blanket Folds - https://www.textures.com/download/PBR0152/133187 Space Blanket Folds - https://www.textures.com/download/PBR0152/133187
Background 2D art by NASA: LINK HERE Background 2D art by NASA: LINK HERE
Silkscreen Font by Jason Kottke - https://www.kottke.org/plus/type/silkscreen/
""" """
### ###
# Intro text, typed out during normal gameplay # Intro text, typed out during normal gameplay
### ###
[intro] [intro]
# Colors are in hex (RED GREEN BLUE ALPHA)
rgba_hidden = "#00000000"
rgba_visible = "#FFFFFFFF"
rgba_background = "#000000FF"
# Higher rate is slower typing speed. Integers only! # Higher rate is slower typing speed. Integers only!
rate = 5 delay = 1.0
text = """ text = [
"""
At the intersection of humanity's wildest imaginations and the infinite of the cosmos, the lines between possible and real fall apart like dissolving paper. At the intersection of humanity's wildest imaginations and the infinite of the cosmos, the lines between possible and real fall apart like dissolving paper.
""",
"""
On Earth, a long tradition of combat and destruction amongst different groups has been upheld and respected; given a place in the social mind. As spacetime stretches ever on, the rhyme of the universe reveals itself, and even includes such traditions. On Earth, a long tradition of combat and destruction amongst different groups has been upheld and respected; given a place in the social mind. As spacetime stretches ever on, the rhyme of the universe reveals itself, and even includes such traditions.
""",
"""
And so, humanity came face to face with a curiosity. Looking to our martian analogues, we find a twin destructive tradition, but one which seems backwards. In their tradition, each victory is also a loss. Each battle is waged simultaneously with opponent and self, and a mutual pact of annihilation and tactics unfolds until one side lays barren, just as likely to be the victor. And so, humanity came face to face with a curiosity. Looking to our martian analogues, we find a twin destructive tradition, but one which seems backwards. In their tradition, each victory is also a loss. Each battle is waged simultaneously with opponent and self, and a mutual pact of annihilation and tactics unfolds until one side lays barren, just as likely to be the victor.
""",
"""
But Can you adapt? But Can you adapt?
Will you be a part of the universal rhyme, and if so, which side are you on? Will you be a part of the universal rhyme, and if so, which side are you on?
""" """,
]
### ###
# Tutorial text, revealed interactively based on context # Tutorial text, revealed interactively based on context
### ###
[tutorial] [tutorial]
# Hex colors for in/visible text (only visible used for now)
rgba_hidden = "#00000000"
rgba_visible = "#FFFFFFFF"
rgba_background = "#000000FF"
intro = [ intro = [
""" """
Greetings general, and welcome to 'Martian Advanced Rules for Generals: Long-Term engagement strategies'. As a part of your assignment to operation Red Rocks, it is in your best interest to thoroughly utilize this simulation to best prepare you for engagement with, and strategic domination of, Martian forces. Greetings general, and welcome to 'Martian Advanced Rules for Generals: Long-Term engagement strategies'. As a part of your assignment to operation Red Rocks, it is in your best interest to thoroughly utilize this simulation to best prepare you for engagement with, and strategic domination of, Martian forces.
@ -242,4 +258,7 @@ tonemapping = "ReinhardLuminance"
exposure = 2.0 exposure = 2.0
gamma = 1.0 gamma = 1.0
pre_saturation = 1.0 pre_saturation = 1.0
post_saturation = 1.0 post_saturation = 1.0
[display3d.bloom]
intensity = 0.15

@ -6,12 +6,16 @@ use crate::{
use bevy::{ use bevy::{
animation::RepeatAnimation, animation::RepeatAnimation,
core_pipeline::{ core_pipeline::{
bloom::BloomSettings,
experimental::taa::{TemporalAntiAliasPlugin, TemporalAntiAliasSettings}, experimental::taa::{TemporalAntiAliasPlugin, TemporalAntiAliasSettings},
prepass::MotionVectorPrepass, prepass::MotionVectorPrepass,
tonemapping::{DebandDither, Tonemapping}, tonemapping::{DebandDither, Tonemapping},
Skybox, Skybox,
}, },
input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, input::{
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
ButtonState,
},
pbr::{ pbr::{
ExtendedMaterial, MaterialExtension, ScreenSpaceAmbientOcclusionBundle, ExtendedMaterial, MaterialExtension, ScreenSpaceAmbientOcclusionBundle,
ScreenSpaceAmbientOcclusionSettings, ScreenSpaceAmbientOcclusionSettings,
@ -254,6 +258,7 @@ fn hydrate_camera(
color_grading: ColorGrading { ..default() }, color_grading: ColorGrading { ..default() },
..default() ..default()
}, },
BloomSettings { ..default() },
Skybox(skybox_handle.clone()), Skybox(skybox_handle.clone()),
EnvironmentMapLight { EnvironmentMapLight {
diffuse_map: skybox_handle.clone(), diffuse_map: skybox_handle.clone(),
@ -304,6 +309,7 @@ fn update_tweaks(
&mut FogSettings, &mut FogSettings,
&mut ColorGrading, &mut ColorGrading,
&mut Tonemapping, &mut Tonemapping,
&mut BloomSettings,
), ),
With<Display3d>, With<Display3d>,
>, >,
@ -321,7 +327,7 @@ fn update_tweaks(
) { ) {
if let Some(tweak) = tweaks.get(tweaks_file.handle.clone()) { if let Some(tweak) = tweaks.get(tweaks_file.handle.clone()) {
camera_settings.iter_mut().for_each( camera_settings.iter_mut().for_each(
|(entity, mut fog, mut color_grading, mut tonemapping)| { |(entity, mut fog, mut color_grading, mut tonemapping, mut bloom)| {
*fog = tweak *fog = tweak
.get::<TweakFogSettings>("display3d_fog") .get::<TweakFogSettings>("display3d_fog")
.unwrap() .unwrap()
@ -334,6 +340,10 @@ fn update_tweaks(
.get::<TweakTonemapping>("display3d_color_tonemapping") .get::<TweakTonemapping>("display3d_color_tonemapping")
.unwrap() .unwrap()
.into(); .into();
*bloom = tweak
.get::<TweakBloomSettings>("display3d_bloom")
.unwrap()
.into();
let quality_level = tweak.get::<TweakScreenSpaceAmbientOcclusionQualityLevel>( let quality_level = tweak.get::<TweakScreenSpaceAmbientOcclusionQualityLevel>(
"display3d_ssao_quality_level", "display3d_ssao_quality_level",
@ -1116,9 +1126,10 @@ fn scale_lighting(
pub(super) mod tweaks { pub(super) mod tweaks {
use bevy::{ use bevy::{
core_pipeline::tonemapping::Tonemapping, core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping},
math::Vec3, math::Vec3,
pbr::{FogFalloff, FogSettings, ScreenSpaceAmbientOcclusionQualityLevel}, pbr::{FogFalloff, FogSettings, ScreenSpaceAmbientOcclusionQualityLevel},
prelude::*,
render::{ render::{
color::Color, color::Color,
view::{ColorGrading, Msaa}, view::{ColorGrading, Msaa},
@ -1155,6 +1166,20 @@ pub(super) mod tweaks {
} }
} }
#[derive(Debug, Deserialize)]
pub struct TweakBloomSettings {
intensity: f32,
}
impl From<TweakBloomSettings> for BloomSettings {
fn from(src: TweakBloomSettings) -> BloomSettings {
BloomSettings {
intensity: src.intensity,
..default()
}
}
}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub enum TweakMsaa { pub enum TweakMsaa {
Off, Off,

@ -1,7 +1,11 @@
use bevy::core::FrameCount; use std::collections::VecDeque;
use bevy::{core::FrameCount, utils::HashMap};
use crate::prelude::*; use crate::prelude::*;
use self::ui::TextScroll;
pub(crate) struct IntroPlugin; pub(crate) struct IntroPlugin;
impl Plugin for IntroPlugin { impl Plugin for IntroPlugin {
@ -12,27 +16,22 @@ impl Plugin for IntroPlugin {
.run_if(resource_exists::<tweak::GameTweaks>()) .run_if(resource_exists::<tweak::GameTweaks>())
.run_if(run_once()), .run_if(run_once()),
) )
.init_resource::<IntroProgress>() .add_systems(OnEnter(GameState::Intro), (activate::<Intro>, start_intro))
.add_systems(OnEnter(GameState::Intro), activate::<Intro>)
.add_systems(OnExit(GameState::Intro), deactivate::<Intro>) .add_systems(OnExit(GameState::Intro), deactivate::<Intro>)
.add_systems( .add_systems(
Update, Update,
manage_intro_progress play_text_scroll
.run_if(in_state(GameState::Intro))
.run_if(not(resource_exists::<IntroPlayed>())),
)
.add_systems(
Update,
play_intro
.run_if(in_state(GameState::Intro)) .run_if(in_state(GameState::Intro))
.run_if(resource_changed::<IntroProgress>()), .run_if(any_component_changed::<ui::TextScroll>),
) )
// Continue to play state if the intro is done playing out
.add_systems( .add_systems(
Update, Update,
continue_to_play // Play intro manages playing the intro of each individual paragraph
.run_if(|keys: Res<Input<KeyCode>>| -> bool { keys.just_pressed(KeyCode::Return) }) play_intro.run_if(
.run_if(resource_exists::<IntroPlayed>()), any_component_added::<TextScroll>
.or_else(any_component_removed::<TextScroll>())
.or_else(|keys: Res<Input<KeyCode>>| -> bool { keys.just_pressed(KeyCode::Return) })
)
); );
} }
} }
@ -43,19 +42,20 @@ struct Intro;
#[derive(Debug, Resource)] #[derive(Debug, Resource)]
struct IntroPlayed; struct IntroPlayed;
#[derive(Debug, Resource, Default)]
struct IntroProgress(usize);
// Draw the intro text (invisible) on startup // Draw the intro text (invisible) on startup
// Requires the Tweakfile to be loaded // Requires the Tweakfile to be loaded
fn init_intro_text( fn init_intro_text(
tweaks_file: Res<tweak::GameTweaks>, tweaks_file: Res<tweak::GameTweaks>,
tweaks: Res<Assets<tweak::Tweaks>>, tweaks: Res<Assets<tweak::Tweaks>>,
ui_font: Res<ui::UiFont>,
mut commands: Commands, mut commands: Commands,
) { ) {
let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks"); let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks");
let text = tweak.get::<String>("intro_text").expect("Intro text"); let texts = tweak.get::<Vec<String>>("intro_text").expect("Intro text");
let background_hex = tweak.get::<String>("intro_rgba_background").unwrap();
let text_hidden_hex = tweak.get::<String>("intro_rgba_hidden").unwrap();
commands commands
.spawn(( .spawn((
@ -85,88 +85,124 @@ fn init_intro_text(
padding: UiRect::all(Val::Px(25.0)), padding: UiRect::all(Val::Px(25.0)),
..default() ..default()
}, },
background_color: Color::BLACK.with_a(1.0).into(), background_color: Color::hex(&background_hex).unwrap().into(),
..default() ..default()
}, },
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(( texts.iter().for_each(|text| {
Intro, parent.spawn((
TextBundle::from_sections(text.chars().into_iter().map(|c| TextSection { Intro,
value: c.to_string(), TextBundle::from_sections(text.chars().into_iter().map(|c| TextSection {
style: TextStyle { value: c.to_string(),
font_size: 16.0, style: TextStyle {
color: Color::WHITE.with_a(0.2), font_size: 16.0,
..default() color: Color::hex(&text_hidden_hex).unwrap(),
}, font: ui_font.handle.clone(),
})) },
.with_text_alignment(TextAlignment::Center), }))
)); .with_text_alignment(TextAlignment::Center),
));
});
}); });
}); });
} }
fn manage_intro_progress( fn start_intro(
keys: Res<Input<KeyCode>>, query: Query<Entity, (With<Node>, With<Intro>)>,
mut start: Local<u32>, mut commands: Commands,
mut progress: ResMut<IntroProgress>, ) {
framecount: Res<FrameCount>, query.iter().for_each(|e| {
commands.entity(e).insert(TextScroll { progress: 0, start: 0 });
});
}
// Manages playing the intro animation
// Each paragrpah types out letter by letter in a separate animation handled by play_text_scroll
// This simply marks each paragraph for play and (should) stay dormant while those animations are playing
fn play_intro(
parents: Query<Entity, (With<Node>, With<Intro>, With<TextScroll>)>,
mut texts: Query<(Entity, Option<&mut TextScroll>), (With<Text>, With<Intro>)>,
children: Query<&Children>,
mut queues: Local<HashMap<Entity, VecDeque<Entity>>>,
mut commands: Commands, mut commands: Commands,
tweaks_file: Res<tweak::GameTweaks>, tweaks_file: Res<tweak::GameTweaks>,
tweaks: Res<Assets<tweak::Tweaks>>, tweaks: Res<Assets<tweak::Tweaks>>,
framecount: Res<FrameCount>,
) { ) {
// If this is the first run, initialize the starting point info!("Play intro...");
if *start == 0 {
*start = framecount.0;
}
// If the user hits 'return' set this to the end of the animation
if keys.just_pressed(KeyCode::Return) {
progress.0 = usize::MAX;
commands.insert_resource(IntroPlayed);
// Otherwise progress by N characters (1)
} else {
let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks");
let rate = tweak.get::<u32>("intro_rate").expect("[intro] rate = #");
progress.0 = ((framecount.0 - *start) / rate) as usize; // Iterate over all UI nodes which are marked for animation
} parents.iter().for_each(|p| {
// If the hash does not contain this parent key, add the VecDeque of child entities
if !(*queues).contains_key(&p) {
(*queues).insert(p, texts.iter_many(children.iter_descendants(p)).map(|(e, _)| e).collect());
}
// Fetch the VecDeque so we can play with it
let queue = (*queues).get_mut(&p).unwrap();
// Pop the front of the line, this is the next entity to animate
if let Some(e) = queue.pop_front() {
if let Ok((e, opt_ts)) = texts.get_mut(e) {
// If this entity has a TextScroll already, update it
if let Some(mut ts) = opt_ts {
// Increment the progress counter by some variable amount
let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks");
let delay = tweak.get::<f32>("intro_delay").expect("[intro] delay = float");
ts.progress = ((framecount.0 - ts.start) as f32 / delay) as usize;
// Otherwise, initialize it with one
} else {
// Insert a fresh TextScroll into this paragraph
commands.entity(e).insert(TextScroll { start: framecount.0, progress: 0 });
}
} else {
panic!("This shouldn't happen!");
}
} else {
// We have played all child entities, so remove the animate marker
commands.entity(p).remove::<TextScroll>();
}
})
} }
// Upon entering the Intro state, start the intro "animation" // Upon entering the Intro state, start the intro "animation"
fn play_intro( fn play_text_scroll(
mut text: Query<(&mut Text, &mut Visibility), With<Intro>>, tweaks_file: Res<tweak::GameTweaks>,
progress: Res<IntroProgress>, tweaks: Res<Assets<tweak::Tweaks>>,
mut text: Query<(Entity, &mut Text, &mut Visibility, &ui::TextScroll)>,
mut commands: Commands, mut commands: Commands,
) { ) {
info!("Play text scroll");
// Iterate over all (one) text // Iterate over all (one) text
text.iter_mut().for_each(|(mut t, mut v)| { text.iter_mut().for_each(|(e, mut t, mut v, ui::TextScroll { progress, .. })| {
// If this is the first frame of the animation, make the object visibility // If this is the first frame of the animation, make the object visibility
if progress.0 == 0 { if *progress == 0 {
*v = Visibility::Inherited; *v = Visibility::Inherited;
} }
let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks");
let text_visible_hex = tweak.get::<String>("intro_rgba_visible").unwrap();
let text_color = Color::hex(&text_visible_hex).unwrap();
// Iterate over all characters in the intro text // Iterate over all characters in the intro text
t.sections t.sections
.iter_mut() .iter_mut()
.enumerate() .enumerate()
// Only operate on sections up to this point // Only operate on sections up to this point
.filter_map(|(i, s)| (i <= progress.0).then_some(s)) .filter_map(|(i, s)| (i <= *progress).then_some(s))
// Set the alpha to 1.0 making it visible // Set the alpha to 1.0 making it visible
.for_each(|s| { .for_each(|s| {
s.style.color.set_a(1.0); s.style.color = text_color.clone();
}); });
if t.sections.iter().all(|s| s.style.color.a() == 1.0) { // Once the animation is done, remove the marker component
commands.insert_resource(IntroPlayed); if t.sections.iter().all(|s| s.style.color == text_color) {
commands.entity(e).remove::<ui::TextScroll>();
} }
}); });
} }
// Intro animation reveals one character every nth frame // Intro animation reveals one character every nth frame
// Hit enter to skip the "animation" // Hit enter to skip the "animation"
// Hit enter once the animation is complete to start the game
fn continue_to_play(mut next_state: ResMut<NextState<GameState>>) {
next_state.set(GameState::Play)
}

@ -6,48 +6,48 @@ impl Plugin for LoadingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Startup, initialize) app.add_systems(Startup, initialize)
.add_systems(Update, loading.run_if(in_state(GameState::Loading))) .add_systems(Update, loading.run_if(in_state(GameState::Loading)))
.add_systems(OnEnter(GameState::Loading), activate::<Loading>) .add_systems(OnEnter(GameState::Loading), (activate::<Loading>, enter_loading))
.add_systems(OnExit(GameState::Loading), deactivate::<Loading>); .add_systems(OnExit(GameState::Loading), (deactivate::<Loading>, exit_loading));
} }
} }
#[derive(Debug, Component)] #[derive(Debug, Component)]
struct Loading; struct Loading;
fn initialize(mut commands: Commands) { // TODO: Why is this image not showing??
commands fn initialize(mut commands: Commands, server: Res<AssetServer>) {
.spawn(( commands.spawn((
Loading, Loading,
NodeBundle { Camera2dBundle { ..default() },
style: Style { UiCameraConfig { show_ui: true },
width: Val::Percent(100.0), ));
height: Val::Percent(100.0), commands.spawn((
justify_content: JustifyContent::Center, Loading,
align_items: AlignItems::Center, ImageBundle {
position_type: PositionType::Absolute, image: UiImage {
..default() texture: server.load("images/Liquid Mirror.jpg"),
},
visibility: Visibility::Hidden,
..default() ..default()
}, },
)) style: Style {
.with_children(|parent| { width: Val::Percent(100.0),
parent.spawn((TextBundle { height: Val::Percent(100.0),
text: Text {
alignment: TextAlignment::Center,
sections: vec![TextSection {
value: "l o a d i n g . . .".into(),
style: TextStyle {
color: Color::WHITE.into(),
..default()
},
}],
..default()
},
background_color: Color::BLACK.with_a(0.5).into(),
..default() ..default()
},)); },
}); visibility: Visibility::Hidden,
..default()
},
));
}
/// On enter loading, activate camera
fn enter_loading(mut cameras: Query<&mut Camera, With<Loading>>) {
cameras.iter_mut().for_each(|mut camera| camera.is_active = true);
}
/// On exit loading, deactivate camera
/// This used to be general purpose, but we got rid of the 2d display mode, so it is hard coded for loading -> main game
fn exit_loading(mut cameras: Query<&mut Camera, With<Loading>>) {
cameras.iter_mut().for_each(|mut camera| camera.is_active = false);
} }
fn loading( fn loading(
@ -55,6 +55,7 @@ fn loading(
sprites: Res<Assets<Image>>, sprites: Res<Assets<Image>>,
gltfs: Res<Assets<Gltf>>, gltfs: Res<Assets<Gltf>>,
tweaks: Res<Assets<tweak::Tweaks>>, tweaks: Res<Assets<tweak::Tweaks>>,
fonts: Res<Assets<Font>>,
mut next_state: ResMut<NextState<GameState>>, mut next_state: ResMut<NextState<GameState>>,
) { ) {
let s = (!sprites.is_empty()) let s = (!sprites.is_empty())
@ -66,11 +67,11 @@ fn loading(
&& tweaks && tweaks
.ids() .ids()
.all(|id| server.is_loaded_with_dependencies(id)); .all(|id| server.is_loaded_with_dependencies(id));
let f = (!fonts.is_empty()) && fonts.ids().all(|id| server.is_loaded_with_dependencies(id));
debug!("s {} g {} t {}", s, g, t); debug!("s {} g {} t {} f {}", s, g, t, f);
if t { if t {
// s && g && t {
next_state.set(GameState::Menu) next_state.set(GameState::Menu)
} }
} }

@ -18,8 +18,6 @@ mod ui;
use std::time::Duration; use std::time::Duration;
use bevy::input::ButtonState;
use crate::prelude::*; use crate::prelude::*;
fn main() { fn main() {
@ -39,14 +37,6 @@ fn main() {
.run_if(resource_changed::<State<tutorial::TutorialState>>()), .run_if(resource_changed::<State<tutorial::TutorialState>>()),
), ),
); );
app.add_systems(
Update,
(
// TODO: Run this other times too so we ensure a camera is always active
toggle_display_camera.run_if(state_changed::<DisplayState>()),
toggle_display_camera.run_if(state_changed::<GameState>()),
),
);
app.add_plugins( app.add_plugins(
DefaultPlugins DefaultPlugins
.set(ImagePlugin::default_nearest()) .set(ImagePlugin::default_nearest())
@ -58,6 +48,7 @@ fn main() {
..default() ..default()
}), }),
); );
app.add_plugins(credits::CreditsPlugin); app.add_plugins(credits::CreditsPlugin);
app.add_plugins(debug::DebugPlugin); app.add_plugins(debug::DebugPlugin);
app.add_plugins(display3d::Display3dPlugin); app.add_plugins(display3d::Display3dPlugin);
@ -96,15 +87,6 @@ fn debug_state<S: States>(state: Res<State<S>>) {
info!("State change {:?}", *state); info!("State change {:?}", *state);
} }
fn toggle_display_camera(
state: Res<State<DisplayState>>,
mut cameras: Query<(&mut Camera, &DisplayState)>,
) {
cameras.iter_mut().for_each(|(mut camera, display_state)| {
camera.is_active = display_state == state.get();
});
}
fn activate<Marker: Component>( fn activate<Marker: Component>(
mut entities: Query< mut entities: Query<
&mut Visibility, &mut Visibility,

@ -75,6 +75,7 @@ pub(crate) enum TutorialState {
// Init animations, initialize all text windows but make invisible // Init animations, initialize all text windows but make invisible
// This should be run when TutorialState::Intro // This should be run when TutorialState::Intro
fn initialize_tutorial( fn initialize_tutorial(
ui_font: Res<ui::UiFont>,
tweaks_file: Res<tweak::GameTweaks>, tweaks_file: Res<tweak::GameTweaks>,
tweaks: Res<Assets<tweak::Tweaks>>, tweaks: Res<Assets<tweak::Tweaks>>,
mut commands: Commands, mut commands: Commands,
@ -83,6 +84,9 @@ fn initialize_tutorial(
info!("Initializing tutorial entities"); info!("Initializing tutorial entities");
let background_hex = tweak.get::<String>("tutorial_rgba_background").unwrap();
let text_visible_hex = tweak.get::<String>("tutorial_rgba_visible").unwrap();
// List of (state, lines) for tutorial steps // List of (state, lines) for tutorial steps
[ [
( (
@ -182,7 +186,7 @@ fn initialize_tutorial(
padding: UiRect::all(Val::Px(25.0)), padding: UiRect::all(Val::Px(25.0)),
..default() ..default()
}, },
background_color: Color::BLACK.with_a(1.0).into(), background_color: Color::hex(&background_hex).unwrap().into(),
..default() ..default()
}, },
)) ))
@ -197,8 +201,8 @@ fn initialize_tutorial(
value: line.clone(), value: line.clone(),
style: TextStyle { style: TextStyle {
font_size: 16.0, font_size: 16.0,
color: Color::WHITE.with_a(1.0), color: Color::hex(&text_visible_hex).unwrap(),
..default() font: ui_font.handle.clone(),
}, },
}) })
.collect(), .collect(),

@ -6,10 +6,12 @@ pub(crate) struct UiPlugin;
impl Plugin for UiPlugin { impl Plugin for UiPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems( app.add_systems(Startup, load_assets).add_systems(
Update, Update,
( (
manage_cursor.run_if(any_component_changed::<Interaction>), manage_cursor.run_if(
any_component_changed::<Interaction>.or_else(state_changed::<GameState>()),
),
interactive_button.run_if(any_component_changed::<Interaction>), interactive_button.run_if(any_component_changed::<Interaction>),
scale_ui.run_if( scale_ui.run_if(
on_event::<AssetEvent<tweak::Tweaks>>() on_event::<AssetEvent<tweak::Tweaks>>()
@ -24,6 +26,26 @@ impl Plugin for UiPlugin {
#[derive(Debug, Component)] #[derive(Debug, Component)]
struct UiRoot; struct UiRoot;
#[derive(Debug, Resource)]
pub(crate) struct UiFont {
pub handle: Handle<Font>,
}
#[derive(Debug, Component)]
pub(crate) struct TextScroll {
pub progress: usize,
pub start: u32,
}
#[derive(Debug, Component)]
pub(crate) struct TextScrollAnimation;
fn load_assets(server: ResMut<AssetServer>, mut commands: Commands) {
commands.insert_resource(UiFont {
handle: server.load("fonts/Silkscreen/Silkscreen-Regular.ttf"),
});
}
fn manage_cursor( fn manage_cursor(
mut window: Query<&mut Window, With<PrimaryWindow>>, mut window: Query<&mut Window, With<PrimaryWindow>>,
state: Res<State<GameState>>, state: Res<State<GameState>>,
@ -74,9 +96,6 @@ fn scale_ui(
tweakfile: Res<tweak::GameTweaks>, tweakfile: Res<tweak::GameTweaks>,
tweaks: Res<Assets<tweak::Tweaks>>, tweaks: Res<Assets<tweak::Tweaks>>,
) { ) {
// There is only 1 window
assert_eq!(windows.iter().count(), 1);
if !tweaks.contains(tweakfile.handle.clone()) { if !tweaks.contains(tweakfile.handle.clone()) {
return; return;
} }

Loading…
Cancel
Save