summaryrefslogtreecommitdiff
path: root/engine/src/material.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/material.rs')
-rw-r--r--engine/src/material.rs99
1 files changed, 92 insertions, 7 deletions
diff --git a/engine/src/material.rs b/engine/src/material.rs
index 5f77950..ae0751b 100644
--- a/engine/src/material.rs
+++ b/engine/src/material.rs
@@ -1,4 +1,14 @@
-use crate::asset::{Asset, Handle as AssetHandle};
+use ecs::sole::Single;
+
+use crate::asset::{
+ Asset,
+ Assets,
+ Dependency as AssetDependency,
+ Event as AssetEvent,
+ Events as AssetEvents,
+ Handle as AssetHandle,
+ Label as AssetLabel,
+};
use crate::builder;
use crate::color::{Color, Rgb};
use crate::ecs::Component;
@@ -18,6 +28,7 @@ pub struct Material
pub diffuse_map: Option<AssetHandle<Texture>>,
pub specular_map: Option<AssetHandle<Texture>>,
pub shininess: f32,
+ pub loading_textures: Vec<(LoadingTextureName, AssetLabel<'static>)>,
}
impl Material
@@ -46,12 +57,26 @@ impl Default for Material
impl Asset for Material
{
- fn dependencies(&self) -> impl Iterator<Item = crate::asset::Dependency<'_>>
+ fn dependencies(&self) -> impl Iterator<Item = AssetDependency<'_>>
{
- [].into_iter()
+ self.loading_textures.iter().map(|(_, texture_label)| {
+ AssetDependency::new::<Texture>(AssetLabel {
+ path: (&*texture_label.path).into(),
+ name: texture_label.name.as_deref().map(Into::into),
+ })
+ })
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum LoadingTextureName
+{
+ AmbientMap,
+ DiffuseMap,
+ SpecularMap,
+}
+
/// [`Material`] builder.
#[derive(Debug, Clone)]
pub struct Builder
@@ -63,6 +88,7 @@ pub struct Builder
diffuse_map: Option<AssetHandle<Texture>>,
specular_map: Option<AssetHandle<Texture>>,
shininess: f32,
+ loading_textures: Vec<(LoadingTextureName, AssetLabel<'static>)>,
}
impl Builder
@@ -78,6 +104,7 @@ impl Builder
diffuse_map: None,
specular_map: None,
shininess: 32.0,
+ loading_textures: Vec::with_capacity(3),
}
}
@@ -130,6 +157,17 @@ impl Builder
}
#[must_use]
+ pub fn loading_texture(
+ mut self,
+ name: LoadingTextureName,
+ asset_label: AssetLabel<'static>,
+ ) -> Self
+ {
+ self.loading_textures.push((name, asset_label));
+ self
+ }
+
+ #[must_use]
pub fn shininess(mut self, shininess: f32) -> Self
{
self.shininess = shininess;
@@ -138,11 +176,8 @@ impl Builder
}
/// Builds a new [`Material`].
- ///
- /// # Panics
- /// Will panic if no ambient map, diffuse map or specular map is set.
#[must_use]
- pub const fn build(self) -> Material
+ pub fn build(self) -> Material
{
Material {
ambient: self.ambient,
@@ -152,6 +187,7 @@ impl Builder
diffuse_map: self.diffuse_map,
specular_map: self.specular_map,
shininess: self.shininess,
+ loading_textures: self.loading_textures,
}
}
}
@@ -210,3 +246,52 @@ impl Default for FlagsBuilder
Self::new()
}
}
+
+pub(crate) fn set_stored_materials_texture_handles(
+ mut assets: Single<Assets>,
+ asset_events: Single<AssetEvents>,
+)
+{
+ let assets = assets.get_mut().unwrap();
+ let asset_events = asset_events.get().unwrap();
+
+ for AssetEvent::Stored(asset_id, ..) in asset_events.iter_last_tick() {
+ let asset_handle = AssetHandle::<Material>::from_id(*asset_id);
+
+ if !assets.is_loaded_and_has_type(&asset_handle) {
+ continue;
+ }
+
+ let Some(material_textures) = assets.get(&asset_handle).map(|mat| {
+ mat.loading_textures
+ .iter()
+ .map(|(tex_name, tex_label)| {
+ (
+ *tex_name,
+ assets.get_handle_to_loaded::<Texture>(tex_label.clone()),
+ )
+ })
+ .collect::<Vec<_>>()
+ }) else {
+ unreachable!();
+ };
+
+ let Some(material) = assets.get_mut(&asset_handle) else {
+ unreachable!();
+ };
+
+ for (tex_name, tex_asset) in material_textures {
+ let Some(tex_asset) = tex_asset else {
+ unreachable!();
+ };
+
+ let dst = match tex_name {
+ LoadingTextureName::AmbientMap => &mut material.ambient_map,
+ LoadingTextureName::DiffuseMap => &mut material.diffuse_map,
+ LoadingTextureName::SpecularMap => &mut material.specular_map,
+ };
+
+ *dst = Some(tex_asset);
+ }
+ }
+}