From eafa69ee4cb60d2ea3298ba642f2cae6debcf567 Mon Sep 17 00:00:00 2001 From: Vincent Foulon Date: Wed, 17 Mar 2021 23:41:28 +0100 Subject: [PATCH] allow loading animations to be contributed from a manifest file --- CHANGELOG.md | 1 + .../element/animation/loaders/manifest.ron | 37 ++++++ voxygen/src/menu/main/ui/connecting.rs | 120 ++++++------------ voxygen/src/menu/main/ui/mod.rs | 45 ++----- 4 files changed, 90 insertions(+), 113 deletions(-) create mode 100644 assets/voxygen/element/animation/loaders/manifest.ron diff --git a/CHANGELOG.md b/CHANGELOG.md index f19402b1aa..5eada43a0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Overhauled the sceptre - Make the /time command relative to the current day - Spatial partitioning via a grid for entity versus entity collisions was added which can more than halve the total tick time at higher entity counts (> ~1000) +- The loading screen will now display random animations ### Removed diff --git a/assets/voxygen/element/animation/loaders/manifest.ron b/assets/voxygen/element/animation/loaders/manifest.ron new file mode 100644 index 0000000000..a55554099a --- /dev/null +++ b/assets/voxygen/element/animation/loaders/manifest.ron @@ -0,0 +1,37 @@ +([ + (8.0, [ + "voxygen.element.animation.loaders.cauldron1", + "voxygen.element.animation.loaders.cauldron2", + "voxygen.element.animation.loaders.cauldron3", + "voxygen.element.animation.loaders.cauldron4", + "voxygen.element.animation.loaders.cauldron5", + ]), + (6.0, [ + "voxygen.element.animation.loaders.cheese1", + "voxygen.element.animation.loaders.cheese2", + "voxygen.element.animation.loaders.cheese3", + "voxygen.element.animation.loaders.cheese4", + "voxygen.element.animation.loaders.cheese5", + ]), + (6.0, [ + "voxygen.element.animation.loaders.coins1", + "voxygen.element.animation.loaders.coins2", + "voxygen.element.animation.loaders.coins3", + "voxygen.element.animation.loaders.coins4", + "voxygen.element.animation.loaders.coins5", + ]), + (1.0, [ + "voxygen.element.animation.loaders.house1", + "voxygen.element.animation.loaders.house2", + "voxygen.element.animation.loaders.house3", + "voxygen.element.animation.loaders.house4", + "voxygen.element.animation.loaders.house5", + ]), + (1.0, [ + "voxygen.element.animation.loaders.ship1", + "voxygen.element.animation.loaders.ship2", + "voxygen.element.animation.loaders.ship3", + "voxygen.element.animation.loaders.ship4", + "voxygen.element.animation.loaders.ship5", + ]), +]) \ No newline at end of file diff --git a/voxygen/src/menu/main/ui/connecting.rs b/voxygen/src/menu/main/ui/connecting.rs index add8f5fef9..7df6acd662 100644 --- a/voxygen/src/menu/main/ui/connecting.rs +++ b/voxygen/src/menu/main/ui/connecting.rs @@ -3,52 +3,65 @@ use crate::{ i18n::Localization, ui::{ fonts::IcedFonts as Fonts, - ice::{component::neat_button, style, widget::Image, Element}, + ice::{component::neat_button, style, widget::Image, Element, IcedUi as Ui, Id}, + Graphic, }, }; +use common::assets::{self, AssetExt}; use iced::{button, Align, Column, Container, Length, Row, Space, Text}; +use serde::{Deserialize, Serialize}; -const LOADER_CAULDRON_SPEED_FACTOR: f64 = 8.0; -const LOADER_CHEESE_SPEED_FACTOR: f64 = 6.0; -const LOADER_COINS_SPEED_FACTOR: f64 = 6.0; -const LOADER_HOUSE_SPEED_FACTOR: f64 = 1.0; -const LOADER_SHIP_SPEED_FACTOR: f64 = 1.0; - -enum LoaderAnimation { - Cauldron, - Cheese, - Coins, - House, - Ship, +struct LoadingAnimation { + speed_factor: f32, + frames: Vec, } - -impl LoaderAnimation { - fn random() -> LoaderAnimation { - match rand::random::() % 5 { - 0 => LoaderAnimation::Cauldron, - 1 => LoaderAnimation::Cheese, - 2 => LoaderAnimation::Coins, - 3 => LoaderAnimation::House, - _ => LoaderAnimation::Ship, +impl LoadingAnimation { + fn new(raw: &(f32, Vec), ui: &mut Ui) -> Self { + let mut frames = vec![]; + for frame_path in raw.1.iter() { + frames.push(ui.add_graphic(Graphic::Image( + assets::Image::load(frame_path).unwrap().read().to_image(), + None, + ))); + } + Self { + speed_factor: raw.0, + frames, } } } +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +struct LoadingAnimationManifest(Vec<(f32, Vec)>); +impl assets::Asset for LoadingAnimationManifest { + type Loader = assets::RonLoader; + + const EXTENSION: &'static str = "ron"; +} + /// Connecting screen for the main menu pub struct Screen { cancel_button: button::State, add_button: button::State, tip_number: u16, - loader_animation: LoaderAnimation, + loading_animation: LoadingAnimation, } impl Screen { - pub fn new() -> Self { + pub fn new(ui: &mut Ui) -> Self { + let animations = + LoadingAnimationManifest::load("voxygen.element.animation.loaders.manifest") + .unwrap() + .cloned() + .0; Self { cancel_button: Default::default(), add_button: Default::default(), tip_number: rand::random(), - loader_animation: LoaderAnimation::random(), + loading_animation: LoadingAnimation::new( + &animations[rand::random::() % animations.len()], + ui, + ), } } @@ -63,58 +76,9 @@ impl Screen { show_tip: bool, ) -> Element { // TODO: add built in support for animated images - let gear_anim_image = match self.loader_animation { - LoaderAnimation::Cauldron => { - let gear_anim_time = time * LOADER_CAULDRON_SPEED_FACTOR; - match (gear_anim_time % 5.0).trunc() as u8 { - 0 => imgs.loader_cauldron1, - 1 => imgs.loader_cauldron2, - 2 => imgs.loader_cauldron3, - 3 => imgs.loader_cauldron4, - _ => imgs.loader_cauldron5, - } - }, - LoaderAnimation::Cheese => { - let gear_anim_time = time * LOADER_CHEESE_SPEED_FACTOR; - match (gear_anim_time % 5.0).trunc() as u8 { - 0 => imgs.loader_cheese1, - 1 => imgs.loader_cheese2, - 2 => imgs.loader_cheese3, - 3 => imgs.loader_cheese4, - _ => imgs.loader_cheese5, - } - }, - LoaderAnimation::Coins => { - let gear_anim_time = time * LOADER_COINS_SPEED_FACTOR; - match (gear_anim_time % 5.0).trunc() as u8 { - 0 => imgs.loader_coins1, - 1 => imgs.loader_coins2, - 2 => imgs.loader_coins3, - 3 => imgs.loader_coins4, - _ => imgs.loader_coins5, - } - }, - LoaderAnimation::House => { - let gear_anim_time = time * LOADER_HOUSE_SPEED_FACTOR; - match (gear_anim_time % 5.0).trunc() as u8 { - 0 => imgs.loader_house1, - 1 => imgs.loader_house2, - 2 => imgs.loader_house3, - 3 => imgs.loader_house4, - _ => imgs.loader_house5, - } - }, - LoaderAnimation::Ship => { - let gear_anim_time = time * LOADER_SHIP_SPEED_FACTOR; - match (gear_anim_time % 5.0).trunc() as u8 { - 0 => imgs.loader_ship1, - 1 => imgs.loader_ship2, - 2 => imgs.loader_ship3, - 3 => imgs.loader_ship4, - _ => imgs.loader_ship5, - } - }, - }; + let frame_index = (time * self.loading_animation.speed_factor as f64) + % self.loading_animation.frames.len() as f64; + let frame_id = self.loading_animation.frames[frame_index as usize]; let children = match connection_state { ConnectionState::InProgress => { @@ -153,7 +117,7 @@ impl Screen { .padding(5); let gear = Container::new( - Image::new(gear_anim_image) + Image::new(frame_id) .width(Length::Units(64)) .height(Length::Units(64)), ) diff --git a/voxygen/src/menu/main/ui/mod.rs b/voxygen/src/menu/main/ui/mod.rs index bd965f7f34..25e331cb3b 100644 --- a/voxygen/src/menu/main/ui/mod.rs +++ b/voxygen/src/menu/main/ui/mod.rs @@ -51,37 +51,6 @@ image_ids_ice! { selection: "voxygen.element.frames.selection", selection_hover: "voxygen.element.frames.selection_hover", selection_press: "voxygen.element.frames.selection_press", - - // Loader Animations - loader_cauldron1: "voxygen.element.animation.loaders.cauldron1", - loader_cauldron2: "voxygen.element.animation.loaders.cauldron2", - loader_cauldron3: "voxygen.element.animation.loaders.cauldron3", - loader_cauldron4: "voxygen.element.animation.loaders.cauldron4", - loader_cauldron5: "voxygen.element.animation.loaders.cauldron5", - - loader_cheese1: "voxygen.element.animation.loaders.cheese1", - loader_cheese2: "voxygen.element.animation.loaders.cheese2", - loader_cheese3: "voxygen.element.animation.loaders.cheese3", - loader_cheese4: "voxygen.element.animation.loaders.cheese4", - loader_cheese5: "voxygen.element.animation.loaders.cheese5", - - loader_coins1: "voxygen.element.animation.loaders.coins1", - loader_coins2: "voxygen.element.animation.loaders.coins2", - loader_coins3: "voxygen.element.animation.loaders.coins3", - loader_coins4: "voxygen.element.animation.loaders.coins4", - loader_coins5: "voxygen.element.animation.loaders.coins5", - - loader_house1: "voxygen.element.animation.loaders.house1", - loader_house2: "voxygen.element.animation.loaders.house2", - loader_house3: "voxygen.element.animation.loaders.house3", - loader_house4: "voxygen.element.animation.loaders.house4", - loader_house5: "voxygen.element.animation.loaders.house5", - - loader_ship1: "voxygen.element.animation.loaders.ship1", - loader_ship2: "voxygen.element.animation.loaders.ship2", - loader_ship3: "voxygen.element.animation.loaders.ship3", - loader_ship4: "voxygen.element.animation.loaders.ship4", - loader_ship5: "voxygen.element.animation.loaders.ship5", } } @@ -343,7 +312,13 @@ impl Controls { .into() } - fn update(&mut self, message: Message, events: &mut Vec, settings: &Settings) { + fn update( + &mut self, + message: Message, + events: &mut Vec, + settings: &Settings, + ui: &mut Ui, + ) { let servers = &settings.networking.servers; let mut language_metadatas = crate::i18n::list_localizations(); @@ -367,14 +342,14 @@ impl Controls { #[cfg(feature = "singleplayer")] Message::Singleplayer => { self.screen = Screen::Connecting { - screen: connecting::Screen::new(), + screen: connecting::Screen::new(ui), connection_state: ConnectionState::InProgress, }; events.push(Event::StartSingleplayer); }, Message::Multiplayer => { self.screen = Screen::Connecting { - screen: connecting::Screen::new(), + screen: connecting::Screen::new(ui), connection_state: ConnectionState::InProgress, }; @@ -601,7 +576,7 @@ impl<'a> MainMenuUi { messages.into_iter().for_each(|message| { self.controls - .update(message, &mut events, &global_state.settings) + .update(message, &mut events, &global_state.settings, &mut self.ui) }); events