-
-
Save ethereumdegen/0b2c99677e710d32ae494dd7e735e6f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use crate::file_system_interaction::asset_loading::TextureAssets; | |
use bevy::{prelude::*, utils::HashMap}; | |
use bevy_asset_loader::mapped::AssetFileName; | |
pub struct TextureAtlasCombined { | |
pub layout: Handle<TextureAtlasLayout>, | |
pub image: Handle<Image>, | |
} | |
#[derive(Resource, Default)] | |
pub(crate) struct TextureAtlasAssets { | |
pub(crate) gui_pixel_icons_atlas: Option<TextureAtlasCombined>, | |
pub(crate) ability_icons_atlas: Option<TextureAtlasCombined>, | |
pub(crate) item_icons_atlas: Option<TextureAtlasCombined>, | |
// pub(crate) particles_atlas: Option<Handle<TextureAtlas>>, | |
} | |
impl TextureAtlasAssets { | |
pub fn build ( | |
mut commands: Commands, | |
texture_assets: Res<TextureAssets>, | |
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>, | |
mut images: ResMut<Assets<Image>>, | |
) { | |
// Assume defaults for padding and sampling, adjust as needed | |
let padding = Some(UVec2::new(2, 2)); | |
//let sampling = Some(ImageSampler::linear()); | |
let gui_pixel_icons_atlas = build_texture_atlas( | |
&texture_assets.gui_pixel_icons, | |
Some(Vec2::new(2048., 2048.)), | |
padding, | |
&mut texture_atlases, | |
&mut images, | |
); | |
let ability_icons_atlas = build_texture_atlas( | |
&texture_assets.ability_icons, | |
Some(Vec2::new(2048., 2048.)), | |
padding, | |
&mut texture_atlases, | |
&mut images, | |
); | |
let item_icons_atlas = build_texture_atlas( | |
&texture_assets.item_icons, | |
Some(Vec2::new(2048., 2048.)), | |
padding, | |
&mut texture_atlases, | |
&mut images, | |
); | |
// Store the handles in new resource | |
commands.insert_resource(TextureAtlasAssets { | |
gui_pixel_icons_atlas: Some(gui_pixel_icons_atlas), | |
ability_icons_atlas: Some(ability_icons_atlas), | |
item_icons_atlas: Some(item_icons_atlas), | |
}); | |
} | |
} | |
pub fn get_index_for_subtexture_by_name( | |
texture_atlas_handle: &Handle<TextureAtlasLayout>, | |
texture_atlases: &Res<Assets<TextureAtlasLayout>>, | |
image_handles_map: &HashMap<AssetFileName, Handle<Image>>, | |
texture_name: &String, | |
) -> Option<usize> { | |
if let Some(atlas) = texture_atlases.get(texture_atlas_handle) { | |
if let Some(image_handle) = image_handles_map.get(texture_name.as_str()) { | |
return atlas.get_texture_index(image_handle); | |
} | |
} | |
//self.index_registry.get(texture_name) .copied() //why do we need to do plus 1 ? | |
None | |
} | |
pub fn build_texture_atlas( | |
handles: &HashMap<AssetFileName, Handle<Image>>, | |
max_size: Option<Vec2>, | |
padding: Option<UVec2>, | |
// textures: &mut ResMut<Assets<Image>>, | |
texture_atlases: &mut ResMut<Assets<TextureAtlasLayout>>, | |
images: &mut ResMut<Assets<Image>>, | |
) -> TextureAtlasCombined { | |
let mut texture_atlas_builder = TextureAtlasBuilder::default() | |
.max_size(max_size.unwrap_or(Vec2::new(2048., 2048.))) | |
.padding(padding.unwrap_or(UVec2::ZERO)); | |
// let mut texture_atlas_index_registry: TextureAtlasIndexRegistry = HashMap::new(); | |
for (icon_name, handle) in handles.iter() { | |
if let Some(texture) = images.get(handle) { | |
texture_atlas_builder.add_texture(Some(handle.clone_weak().into()), texture); | |
// texture_atlas_index_registry.insert(icon_name.clone(), index) ; | |
// println!("register atlas image {:?} {:?}", icon_name,index); | |
} else { | |
panic!( | |
"Texture handle did not resolve to an `Image` asset: {:?}", | |
icon_name | |
); | |
// continue; | |
} | |
} | |
let (texture_atlas, image) = texture_atlas_builder | |
.finish() | |
.expect("Failed to build texture atlas."); | |
let texture_atlas_handle = texture_atlases.add(texture_atlas); | |
let image_handle = images.add(image); | |
TextureAtlasCombined { | |
layout: texture_atlas_handle, | |
image: image_handle, | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use bevy::ecs::system::EntityCommands; | |
use bevy::ecs::system::EntityCommand; | |
use bevy::prelude::*; | |
use crate::{ | |
file_system_interaction::{ | |
ability_type::AbilityType, | |
asset_loading::{AbilitySystemTypeAssets, ItemSystemTypeAssets, TextureAssets}, | |
item_type::ItemType, | |
texture_atlas::{get_index_for_subtexture_by_name, TextureAtlasAssets}, | |
}, | |
ui::{element_linker::LinkedUiElement, inventory_menu::InventoryUiEquipmentSlot}, | |
}; | |
pub(crate) fn ui_icons_plugin(app: &mut App) { | |
app.add_systems( | |
Update, | |
update_icons_from_source.run_if(any_with_component::<UiIconComponent>), | |
); | |
} | |
#[derive(Component, Default)] | |
pub struct UiIconComponent { | |
pub icon_source: Option<UiIconSource>, | |
} | |
impl UiIconComponent { | |
pub fn new (icon_source: Option<UiIconSource> ) -> Self { | |
Self { | |
icon_source | |
} | |
} | |
} | |
struct SetIconSource(Option<UiIconSource>); | |
impl EntityCommand for SetIconSource { | |
fn apply(self, entity: Entity, world: &mut World) { | |
if let Some(mut ui_icon_comp) = world.entity_mut(entity).get_mut::<UiIconComponent>() { | |
ui_icon_comp.icon_source = self.0 ; | |
} | |
} | |
} | |
pub trait UiIconComponentCommands<'a> { | |
fn set_icon_source(&'a mut self, src: Option<UiIconSource> ) -> &mut EntityCommands<'a>; | |
} | |
impl<'a> UiIconComponentCommands<'a> for EntityCommands<'a> { | |
fn set_icon_source(&'a mut self, src: Option<UiIconSource>) -> &mut EntityCommands<'a> { | |
self.add(SetIconSource(src)) | |
} | |
} | |
pub enum UiIconSource { | |
AbilityType(String), | |
ItemType(String), | |
GuiPixelIcon(String) | |
} | |
/* | |
rebuild this in a more generic way with traits and having access to World? trait returns string and needs resources from World to compute ? ..? | |
*/ | |
fn update_icons_from_source( | |
mut image_node_query: Query< | |
(&mut Visibility, &mut TextureAtlas, &mut UiImage, &UiIconComponent), | |
Changed<UiIconComponent>, | |
>, | |
ability_system_type_assets: Res<AbilitySystemTypeAssets>, | |
item_system_type_assets: Res<ItemSystemTypeAssets>, | |
item_types: Res<Assets<ItemType>>, | |
ability_types: Res<Assets<AbilityType>>, | |
texture_atlases: Res<Assets<TextureAtlasLayout>>, | |
texture_atlas_assets: Res<TextureAtlasAssets>, | |
images: Res<TextureAssets>, | |
) { | |
//render equipped stuff like weapons that are on you !! | |
for (mut _visibility, mut tex_atlas, mut ui_image, ui_icon_comp) in image_node_query.iter_mut() { | |
let Some(icon_source) = &ui_icon_comp.icon_source else { | |
let icons_atlas = &texture_atlas_assets.gui_pixel_icons_atlas.as_ref().unwrap(); | |
let icons_handles_map = &images.gui_pixel_icons; | |
//set to blank icon | |
let Some(image_index) = get_index_for_subtexture_by_name( | |
&icons_atlas.layout, | |
&texture_atlases, | |
&icons_handles_map, | |
&"icon_transparent.png".to_string(), | |
) else { | |
warn!("could not set icon source (None) to icon_transparent"); | |
continue; | |
}; | |
tex_atlas.layout = icons_atlas.layout.clone(); | |
tex_atlas.index = image_index; | |
ui_image.texture = icons_atlas.image.clone(); | |
continue; | |
}; | |
let icon_name = match &icon_source { | |
UiIconSource::ItemType(item_type_name) => { | |
if let Some(item_type_handle) = item_system_type_assets | |
.item_types | |
.get(item_type_name.as_str()) | |
{ | |
if let Some(item_type) = item_types.get(item_type_handle) { | |
if let Some(equipment_item_icon_name) = &item_type.icon_texture { | |
Some(equipment_item_icon_name.clone()) | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
} | |
UiIconSource::AbilityType(ability_type_name) => { | |
if let Some(ability_type_handle) = ability_system_type_assets | |
.ability_types | |
.get(ability_type_name.as_str()) | |
{ | |
if let Some(ability_type) = ability_types.get(ability_type_handle) { | |
if let Some(ability_icon_name) = &ability_type.icon_texture { | |
Some(ability_icon_name.clone()) | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
} else { | |
None | |
} | |
}, | |
UiIconSource::GuiPixelIcon(icon_name) => Some(icon_name.clone()) | |
}; | |
let Some(icon_name) = icon_name else { continue }; | |
let icons_handles_map = match &icon_source { | |
UiIconSource::ItemType(_) => Some(&images.item_icons), | |
UiIconSource::AbilityType(_) => Some(&images.ability_icons), | |
UiIconSource::GuiPixelIcon(_) => Some(&images.gui_pixel_icons), | |
}; | |
let Some(icons_handles_map) = icons_handles_map else { | |
continue; | |
}; | |
let texture_atlas = match &icon_source { | |
UiIconSource::ItemType(_) => texture_atlas_assets.item_icons_atlas.as_ref().unwrap() , | |
UiIconSource::AbilityType(_) => texture_atlas_assets.ability_icons_atlas.as_ref().unwrap() , | |
UiIconSource::GuiPixelIcon(_) => texture_atlas_assets.gui_pixel_icons_atlas.as_ref().unwrap(), | |
}; | |
let Some(image_index) = get_index_for_subtexture_by_name( | |
&texture_atlas.layout, | |
&texture_atlases, | |
&icons_handles_map, | |
&icon_name, | |
) else { | |
continue; | |
}; | |
ui_image.texture = texture_atlas.image.clone(); | |
tex_atlas.layout = texture_atlas.layout.clone(); | |
tex_atlas.index = image_index; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment