diff --git a/assets/bird.jpg b/assets/bird.jpg new file mode 100644 index 0000000..a2c0f66 Binary files /dev/null and b/assets/bird.jpg differ diff --git a/assets/bird_boots.png b/assets/bird_boots.png new file mode 100644 index 0000000..cff6c81 Binary files /dev/null and b/assets/bird_boots.png differ diff --git a/assets/brock.png b/assets/brock.png new file mode 100644 index 0000000..905f575 Binary files /dev/null and b/assets/brock.png differ diff --git a/assets/business_expert.jpg b/assets/business_expert.jpg new file mode 100644 index 0000000..bf3a343 Binary files /dev/null and b/assets/business_expert.jpg differ diff --git a/assets/deer_1.png b/assets/deer_1.png new file mode 100644 index 0000000..a49a4b4 Binary files /dev/null and b/assets/deer_1.png differ diff --git a/assets/deer_2.png b/assets/deer_2.png new file mode 100644 index 0000000..607d59b Binary files /dev/null and b/assets/deer_2.png differ diff --git a/assets/dog.png b/assets/dog.png new file mode 100644 index 0000000..6ed48dd Binary files /dev/null and b/assets/dog.png differ diff --git a/assets/horse_cop.png b/assets/horse_cop.png new file mode 100644 index 0000000..7c57ca2 Binary files /dev/null and b/assets/horse_cop.png differ diff --git a/assets/house_1.jpg b/assets/house_1.jpg new file mode 100644 index 0000000..b48a907 Binary files /dev/null and b/assets/house_1.jpg differ diff --git a/assets/house_2.jpg b/assets/house_2.jpg new file mode 100644 index 0000000..2486c76 Binary files /dev/null and b/assets/house_2.jpg differ diff --git a/assets/lobster.png b/assets/lobster.png new file mode 100644 index 0000000..6a2f9f8 Binary files /dev/null and b/assets/lobster.png differ diff --git a/assets/monks.png b/assets/monks.png new file mode 100644 index 0000000..dd54414 Binary files /dev/null and b/assets/monks.png differ diff --git a/assets/polar_board.png b/assets/polar_board.png new file mode 100644 index 0000000..02e731c Binary files /dev/null and b/assets/polar_board.png differ diff --git a/assets/putin_kim.png b/assets/putin_kim.png new file mode 100644 index 0000000..d6a2c31 Binary files /dev/null and b/assets/putin_kim.png differ diff --git a/assets/waltuh.png b/assets/waltuh.png new file mode 100644 index 0000000..6bbd064 Binary files /dev/null and b/assets/waltuh.png differ diff --git a/assets/willem.png b/assets/willem.png new file mode 100644 index 0000000..904a81f Binary files /dev/null and b/assets/willem.png differ diff --git a/src/dashboard_defs/funky_remake_transitions.rs b/src/dashboard_defs/funky_remake_transitions.rs new file mode 100644 index 0000000..7471c76 --- /dev/null +++ b/src/dashboard_defs/funky_remake_transitions.rs @@ -0,0 +1,126 @@ +use rand::Rng; +use std::borrow::Cow; + +use crate::{ + utility_types::{ + time::Duration, + generic_result::* + }, + + texture::{ + TexturePool, + TextureCreationInfo, + RemakeTransitionInfo, + TextureTransitionOpacityEaser, + TextureTransitionAspectRatioEaser + }, + + dashboard_defs::easing_fns, + window_tree::WindowContents +}; + +pub struct IntermediateTextureTransitionInfo { + pub percent_chance_to_show_rand_intermediate_texture: f64, + pub rand_duration_range_for_intermediate: (f64, f64), + pub max_random_transitions: usize +} + +fn pick_from_slice<'a, T>(choices: &'a [T], rand_generator: &mut rand::rngs::ThreadRng) -> &'a T { + &choices[rand_generator.gen_range(0..choices.len())] +} + +fn pick_random_easing_pair(rand_generator: &mut rand::rngs::ThreadRng) + -> (TextureTransitionOpacityEaser, TextureTransitionAspectRatioEaser) { + + use easing_fns::transition::{opacity, aspect_ratio}; + + let easing_pairs = [ + (opacity::LINEAR_BLENDED_FADE, aspect_ratio::LINEAR), + (opacity::BURST_BLENDED_FADE, aspect_ratio::LINEAR), + (opacity::FADE_OUT_THEN_FADE_IN, aspect_ratio::LINEAR), + + (opacity::LINEAR_BLENDED_BOUNCE, aspect_ratio::BOUNCE), + (opacity::BURST_BLENDED_BOUNCE, aspect_ratio::BOUNCE), + + (opacity::STRAIGHT_WAVY, aspect_ratio::STRAIGHT_WAVY), + (opacity::JITTER_WAVY, aspect_ratio::JITTER_WAVY) + ]; + + *pick_from_slice(&easing_pairs, rand_generator) +} + +pub fn update_as_texture_with_funky_remake_transition( + window_contents: &mut WindowContents, + texture_pool: &mut TexturePool, + texture_creation_info: &TextureCreationInfo, + duration: Duration, + rand_generator: &mut rand::rngs::ThreadRng, + get_fallback_texture_creation_info: fn() -> TextureCreationInfo<'static>, + mut intermediate_info: IntermediateTextureTransitionInfo) -> MaybeError { + + ////////// + + let path = |base| TextureCreationInfo::Path(Cow::Borrowed(base)); + + let all_intermediate_texture_creation_info = [ + path("assets/business_expert.jpg"), + path("assets/house_1.jpg"), + path("assets/house_2.jpg"), + + path("assets/bird.jpg"), + path("assets/brock.png"), + path("assets/dog.png"), + path("assets/horse_cop.png"), + path("assets/monks.png"), + path("assets/polar_board.png"), + path("assets/putin_kim.png"), + + path("assets/willem.png"), + path("assets/deer_1.png"), + path("assets/deer_2.png"), + path("assets/waltuh.png"), + path("assets/bird_boots.png"), + path("assets/lobster.png") + ]; + + ////////// + + // Randomly recurring to show intermediate textures before the final one + if intermediate_info.max_random_transitions != 0 && + rand_generator.gen_range(0.0..1.0) < intermediate_info.percent_chance_to_show_rand_intermediate_texture { + + let intermediate_texture_creation_info = pick_from_slice(&all_intermediate_texture_creation_info, rand_generator); + + let range = intermediate_info.rand_duration_range_for_intermediate; + let rand_duration_secs = rand_generator.gen_range(range.0..range.1); + let rand_duration_ms = (rand_duration_secs * 1000.0) as i64; + + intermediate_info.max_random_transitions -= 1; + + update_as_texture_with_funky_remake_transition( + window_contents, texture_pool, intermediate_texture_creation_info, + Duration::milliseconds(rand_duration_ms), + rand_generator, + get_fallback_texture_creation_info, + intermediate_info + )?; + } + + ////////// Making a remake transition + + let easers = pick_random_easing_pair(rand_generator); + + let remake_transition_info = RemakeTransitionInfo::new( + duration, easers.0, easers.1 + ); + + ////////// Updating + + window_contents.update_as_texture( + true, + texture_pool, + texture_creation_info, + Some(&remake_transition_info), + get_fallback_texture_creation_info + ) +} diff --git a/src/dashboard_defs/mod.rs b/src/dashboard_defs/mod.rs index d7158c1..905aba5 100644 --- a/src/dashboard_defs/mod.rs +++ b/src/dashboard_defs/mod.rs @@ -7,6 +7,7 @@ mod spinitron; mod easing_fns; mod shared_window_state; mod updatable_text_pattern; +mod funky_remake_transitions; pub mod error; pub mod themes; diff --git a/src/dashboard_defs/spinitron.rs b/src/dashboard_defs/spinitron.rs index c4857b4..a495b68 100644 --- a/src/dashboard_defs/spinitron.rs +++ b/src/dashboard_defs/spinitron.rs @@ -3,11 +3,10 @@ use std::borrow::Cow; use crate::{ dashboard_defs::{ easing_fns, + funky_remake_transitions, shared_window_state::SharedWindowState }, - spinitron::model::{SpinitronModelName, NUM_SPINITRON_MODEL_TYPES}, - texture::{ DisplayText, TextDisplayInfo, @@ -15,6 +14,7 @@ use crate::{ }, utility_types::{ + time::*, vec2f::Vec2f, generic_result::*, update_rate::UpdateRate, @@ -27,7 +27,9 @@ use crate::{ WindowContents, WindowUpdaterParams, PossibleWindowUpdater - } + }, + + spinitron::model::{SpinitronModelName, NUM_SPINITRON_MODEL_TYPES} }; struct SpinitronModelWindowState { @@ -87,7 +89,6 @@ pub fn make_spinitron_windows( ////////// - let texture_creation_info = if is_text_window { let model_text = spinitron_state.model_to_string(model_name); @@ -112,11 +113,26 @@ pub fn make_spinitron_windows( spinitron_state.get_cached_texture_creation_info(model_name) }; - params.window.get_contents_mut().update_as_texture( - true, + ////////// + + let default_duration = Duration::seconds(2); + + let intermediate_info = funky_remake_transitions::IntermediateTextureTransitionInfo { + percent_chance_to_show_rand_intermediate_texture: 0.3, + rand_duration_range_for_intermediate: (0.4, 1.2), + max_random_transitions: 10 + }; + + ////////// + + funky_remake_transitions::update_as_texture_with_funky_remake_transition( + params.window.get_contents_mut(), params.texture_pool, &texture_creation_info, - inner_shared_state.get_fallback_texture_creation_info + default_duration, + &mut inner_shared_state.rand_generator, + inner_shared_state.get_fallback_texture_creation_info, + intermediate_info ) } diff --git a/src/dashboard_defs/surprise.rs b/src/dashboard_defs/surprise.rs index 7ea6674..3a5e262 100644 --- a/src/dashboard_defs/surprise.rs +++ b/src/dashboard_defs/surprise.rs @@ -103,7 +103,7 @@ pub async fn make_surprise_window( local_hour >= surprise_info.local_hours_24_start.into() && local_hour <= surprise_info.local_hours_24_end.into(); - use rand::Rng; // TODO: can I use the system's rand generator instead? Less dependencies that way... + use rand::Rng; let rand_num = rand_generator.gen::<SurpriseAppearanceChance>(); in_acceptable_hour_range && rand_num < surprise_info.chance_of_appearing_when_updating diff --git a/src/dashboard_defs/themes/barebones.rs b/src/dashboard_defs/themes/barebones.rs index 7f6c4d7..6a36840 100644 --- a/src/dashboard_defs/themes/barebones.rs +++ b/src/dashboard_defs/themes/barebones.rs @@ -2,8 +2,8 @@ use sdl2::{render::BlendMode, ttf::{FontStyle, Hinting}}; use crate::{ themes::shared_utils::*, - texture::{FontInfo, TextureCreationInfo, TexturePool}, spinitron::{model::SpinitronModelName, state::SpinitronState}, + texture::{FontInfo, TextureCreationInfo, TexturePool, RemakeTransitionInfo}, utility_types::{ file_utils, @@ -21,6 +21,7 @@ use crate::{ }, dashboard_defs::{ + easing_fns, credit::make_credit_window, weather::make_weather_window, error::{make_error_window, ErrorState}, @@ -64,7 +65,7 @@ pub async fn make_dashboard( let main_windows_gap_size = 0.01; let theme_color_1 = ColorSDL::RGB(255, 133, 133); - let shared_update_rate = update_rate_creator.new_instance(15.0); + let shared_update_rate = update_rate_creator.new_instance(10.0); let api_keys: ApiKeys = file_utils::load_json_from_file("assets/api_keys.json").await?; ////////// Defining the Spinitron window extents @@ -313,7 +314,13 @@ pub async fn make_dashboard( &api_keys.twilio_auth_token, 11, Duration::days(5), - false + false, + + Some(RemakeTransitionInfo::new( + Duration::seconds(2), + easing_fns::transition::opacity::BURST_BLENDED_BOUNCE, + easing_fns::transition::aspect_ratio::BOUNCE + )) ), make_creation_info_for_static_texture_set(&background_static_texture_info), diff --git a/src/dashboard_defs/themes/retro_room.rs b/src/dashboard_defs/themes/retro_room.rs index ab46e27..4770b1d 100644 --- a/src/dashboard_defs/themes/retro_room.rs +++ b/src/dashboard_defs/themes/retro_room.rs @@ -2,8 +2,8 @@ use sdl2::{render::BlendMode, ttf::{FontStyle, Hinting}}; use crate::{ themes::shared_utils::*, - texture::{FontInfo, TextureCreationInfo, TexturePool}, spinitron::{model::SpinitronModelName, state::SpinitronState}, + texture::{FontInfo, TextureCreationInfo, TexturePool, RemakeTransitionInfo}, utility_types::{ file_utils, @@ -21,6 +21,7 @@ use crate::{ }, dashboard_defs::{ + easing_fns, credit::make_credit_window, weather::make_weather_window, error::{make_error_window, ErrorState}, @@ -309,7 +310,13 @@ pub async fn make_dashboard( &api_keys.twilio_auth_token, 3, Duration::days(5), - false + false, + + Some(RemakeTransitionInfo::new( + Duration::seconds(2), + easing_fns::transition::opacity::BURST_BLENDED_BOUNCE, + easing_fns::transition::aspect_ratio::BOUNCE + )) ), TextureCreationInfo::from_path_async("assets/alternative_text_bubble.png"), diff --git a/src/dashboard_defs/themes/standard.rs b/src/dashboard_defs/themes/standard.rs index 6df1b64..14e278c 100644 --- a/src/dashboard_defs/themes/standard.rs +++ b/src/dashboard_defs/themes/standard.rs @@ -2,8 +2,8 @@ use sdl2::{render::BlendMode, ttf::{FontStyle, Hinting}}; use crate::{ themes::shared_utils::*, - texture::{FontInfo, TextureCreationInfo, TexturePool}, spinitron::{model::SpinitronModelName, state::SpinitronState}, + texture::{FontInfo, TextureCreationInfo, TexturePool, RemakeTransitionInfo}, utility_types::{ file_utils, @@ -21,6 +21,7 @@ use crate::{ }, dashboard_defs::{ + easing_fns, credit::make_credit_window, weather::make_weather_window, error::{make_error_window, ErrorState}, @@ -315,7 +316,13 @@ pub async fn make_dashboard( &api_keys.twilio_auth_token, 6, Duration::days(5), - false + false, + + Some(RemakeTransitionInfo::new( + Duration::seconds(2), + easing_fns::transition::opacity::BURST_BLENDED_BOUNCE, + easing_fns::transition::aspect_ratio::BOUNCE + )) ), TextureCreationInfo::from_path_async("assets/text_bubble.png"), diff --git a/src/dashboard_defs/twilio.rs b/src/dashboard_defs/twilio.rs index 4620210..047d3ec 100644 --- a/src/dashboard_defs/twilio.rs +++ b/src/dashboard_defs/twilio.rs @@ -23,7 +23,7 @@ use crate::{ }, window_tree::{ColorSDL, Window, WindowContents, WindowUpdaterParams}, - texture::{FontInfo, DisplayText, TextDisplayInfo, TextureCreationInfo, TextureHandle, TexturePool} + texture::{FontInfo, DisplayText, TextDisplayInfo, TextureCreationInfo, TextureHandle, TexturePool, RemakeTransitionInfo} }; // TODO: split this file up into some smaller files @@ -42,6 +42,7 @@ impl TextureSubpoolManager { } fn request_slot(&mut self, texture_creation_info: &TextureCreationInfo, + maybe_remake_transition_info: Option<&RemakeTransitionInfo>, texture_pool: &mut TexturePool) -> GenericResult<TextureHandle> { assert!(self.subpool.len() <= self.max_size); @@ -52,7 +53,7 @@ impl TextureSubpoolManager { if !*is_used { // println!("(request) doing re-request, and setting {texture:?} to used"); *is_used = true; - texture_pool.remake_texture(texture_creation_info, texture, None)?; + texture_pool.remake_texture(texture_creation_info, texture, maybe_remake_transition_info)?; return Ok(texture.clone()); } } @@ -75,13 +76,14 @@ impl TextureSubpoolManager { fn re_request_slot(&mut self, incoming_texture: &TextureHandle, texture_creation_info: &TextureCreationInfo, + maybe_remake_transition_info: Option<&RemakeTransitionInfo>, texture_pool: &mut TexturePool) -> MaybeError { if let Some(is_used) = self.subpool.get(incoming_texture) { // println!("(re-request) checking {incoming_texture:?} for being used before"); assert!(is_used); // println!("(re-request) doing re-request for {incoming_texture:?}"); - texture_pool.remake_texture(texture_creation_info, incoming_texture, None) + texture_pool.remake_texture(texture_creation_info, incoming_texture, maybe_remake_transition_info) } else { panic!("Slot was not previously allocated in subpool!"); @@ -215,7 +217,8 @@ pub struct TwilioState { newly computed data. */ texture_subpool_manager: TextureSubpoolManager, id_to_texture_map: SyncedMessageMap<TextureHandle>, // TODO: integrate the subpool manager into this with the searching operations - historically_sorted_messages_by_id: Vec<MessageID> // TODO: avoid resorting with smart insertions and deletions? + historically_sorted_messages_by_id: Vec<MessageID>, // TODO: avoid resorting with smart insertions and deletions? + maybe_remake_transition_info: Option<RemakeTransitionInfo> } ////////// @@ -450,7 +453,8 @@ impl TwilioState { account_sid: &str, auth_token: &str, max_num_messages_in_history: usize, message_history_duration: Duration, - reveal_texter_identities: bool) -> GenericResult<Self> { + reveal_texter_identities: bool, + maybe_remake_transition_info: Option<RemakeTransitionInfo>) -> GenericResult<Self> { let data = TwilioStateData::new( account_sid, auth_token, max_num_messages_in_history, @@ -461,7 +465,8 @@ impl TwilioState { continually_updated: ContinuallyUpdated::new(&data, &(), "Twilio").await, texture_subpool_manager: TextureSubpoolManager::new(max_num_messages_in_history), id_to_texture_map: SyncedMessageMap::new(max_num_messages_in_history), - historically_sorted_messages_by_id: Vec::new() + historically_sorted_messages_by_id: Vec::new(), + maybe_remake_transition_info }) } @@ -511,7 +516,12 @@ impl TwilioState { if offshore_message_info.just_updated { // println!(">>> Update local texture"); update_texture_creation_info(offshore_message_info); - self.texture_subpool_manager.re_request_slot(local_texture, &texture_creation_info, texture_pool)?; + + self.texture_subpool_manager.re_request_slot( + local_texture, &texture_creation_info, + self.maybe_remake_transition_info.as_ref(), + texture_pool + )?; } }, @@ -519,7 +529,12 @@ impl TwilioState { // println!(">>> Allocate texture from base slot"); assert!(offshore_message_info.just_updated); update_texture_creation_info(offshore_message_info); - return Ok(Some(self.texture_subpool_manager.request_slot(&texture_creation_info, texture_pool)?)); + + return Ok(Some(self.texture_subpool_manager.request_slot( + &texture_creation_info, + self.maybe_remake_transition_info.as_ref(), + texture_pool + )?)); } } diff --git a/src/dashboard_defs/updatable_text_pattern.rs b/src/dashboard_defs/updatable_text_pattern.rs index 740aef9..f346d3f 100644 --- a/src/dashboard_defs/updatable_text_pattern.rs +++ b/src/dashboard_defs/updatable_text_pattern.rs @@ -82,8 +82,13 @@ pub fn make_window<IndividualState: UpdatableTextWindowMethods + Clone + 'static params.window.get_contents_mut() ); - texture_contents.update_as_texture(true, params.texture_pool, - &texture_creation_info, inner_shared_state.get_fallback_texture_creation_info) + texture_contents.update_as_texture( + true, + params.texture_pool, + &texture_creation_info, + None, + inner_shared_state.get_fallback_texture_creation_info + ) } ////////// diff --git a/src/dashboard_defs/weather.rs b/src/dashboard_defs/weather.rs index 8bc7ea9..2153e21 100644 --- a/src/dashboard_defs/weather.rs +++ b/src/dashboard_defs/weather.rs @@ -135,6 +135,7 @@ pub fn weather_updater_fn(params: WindowUpdaterParams) -> MaybeError { true, params.texture_pool, &texture_creation_info, + None, inner_shared_state.get_fallback_texture_creation_info ) } diff --git a/src/main.rs b/src/main.rs index ba2e41e..8c20cec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -106,7 +106,7 @@ macro_rules! build_dashboard_theme {( ////////// const STANDARD_BACKGROUND_COLOR: ColorSDL = ColorSDL::BLACK; -const MAX_REMAKE_TRANSITION_QUEUE_SIZE: usize = 5; // This is to avoid unbounded memory consumption +const MAX_REMAKE_TRANSITION_QUEUE_SIZE: usize = 10; // This is to avoid unbounded memory consumption #[tokio::main] async fn main() -> MaybeError { diff --git a/src/texture.rs b/src/texture.rs index 5c0d0a5..f3d1e94 100644 --- a/src/texture.rs +++ b/src/texture.rs @@ -119,7 +119,6 @@ impl<'a> DisplayText<'a> { ////////// /* - The first item, the function itself: Input: seed (some number of real-time fractional seconds), and if the text fits fully in the box. Output: scroll amount (range: [0, 1]), and if the text should wrap or not. @@ -154,9 +153,15 @@ pub type TextureTransitionAspectRatioEaser = fn(f64) -> f64; #[derive(Clone)] pub struct RemakeTransitionInfo { - pub duration: Duration, - pub opacity_easer: TextureTransitionOpacityEaser, - pub aspect_ratio_easer: TextureTransitionAspectRatioEaser + duration: Duration, + opacity_easer: TextureTransitionOpacityEaser, + aspect_ratio_easer: TextureTransitionAspectRatioEaser +} + +impl RemakeTransitionInfo { + pub fn new(duration: Duration, opacity_easer: TextureTransitionOpacityEaser, aspect_ratio_easer: TextureTransitionAspectRatioEaser) -> Self { + Self {duration, opacity_easer, aspect_ratio_easer} + } } ////////// @@ -799,14 +804,14 @@ impl<'a> TexturePool<'a> { ////////// TODO: implement these fully - pub fn set_color_mod_for(&mut self, handle: &TextureHandle, r: u8, g: u8, b: u8) { + pub fn set_color_mod_for(&mut self, _handle: &TextureHandle, _r: u8, _g: u8, _b: u8) { unimplemented!("Texture color mod setting is currently not supported! In the future, it will \ be supported by carrying it over for transitioning/remade textures."); // self.get_texture_from_handle_mut(handle).set_color_mod(r, g, b); } - pub fn set_alpha_mod_for(&mut self, handle: &TextureHandle, a: u8) { + pub fn set_alpha_mod_for(&mut self, _handle: &TextureHandle, _a: u8) { unimplemented!("Texture alpha mod setting is currently not supported! In the future, it will \ be supported by using it as a start/end interpolant for transitioning textures, \ and carrying it over for remade textures."); @@ -814,7 +819,7 @@ impl<'a> TexturePool<'a> { // self.get_texture_from_handle_mut(handle).set_alpha_mod(a); } - pub fn set_blend_mode_for(&mut self, handle: &TextureHandle, blend_mode: BlendMode) { + pub fn set_blend_mode_for(&mut self, handle: &TextureHandle, _blend_mode: BlendMode) { // TODO: specify a blend mode when making a transition? Or perhaps just do queueing logic internally here? if self.remake_transitions.get_from_handle(handle).is_some() { unimplemented!("Cannot set the blend mode during a remake transition! In The future, it will \ diff --git a/src/window_tree.rs b/src/window_tree.rs index cf32087..d35893e 100644 --- a/src/window_tree.rs +++ b/src/window_tree.rs @@ -1,14 +1,19 @@ use sdl2::{self, rect::FRect}; use crate::{ + texture::{ + TexturePool, + TextureHandle, + TextureCreationInfo, + RemakeTransitionInfo + }, + utility_types::{ vec2f::Vec2f, generic_result::*, dynamic_optional::DynamicOptional, - update_rate::{UpdateRate, FrameCounter} - }, - - texture::{TexturePool, TextureHandle, TextureCreationInfo} + update_rate::{FrameCounter, UpdateRate} + } }; ////////// These are some general utility types @@ -87,6 +92,7 @@ impl WindowContents { should_remake: bool, texture_pool: &mut TexturePool, creation_info: &TextureCreationInfo, + maybe_remake_transition_info: Option<&RemakeTransitionInfo>, get_fallback_texture_creation_info: fn() -> TextureCreationInfo<'static>) -> MaybeError { /* This is a macro for making or remaking a texture. If making or @@ -105,7 +111,14 @@ impl WindowContents { } let updated_texture = if let Self::Texture(prev_texture) = self { - if should_remake {try_to_make_or_remake_texture!(|a, b| texture_pool.remake_texture(a, b, None), "remake an existing", prev_texture)?} + if should_remake { + try_to_make_or_remake_texture!( + |a, b| texture_pool.remake_texture(a, b, maybe_remake_transition_info), + "remake an existing", + prev_texture + )? + } + prev_texture.clone() } else {