use crate::engine::ecs::ComponentId;
use crate::engine::ecs::component::Component;
use crate::engine::graphics::TextureHandle;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CatEngineTextureFormat {
Rgba8,
DdsBc7,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TextureSource {
Uri(String),
Handle(TextureHandle),
}
impl CatEngineTextureFormat {
pub fn from_uri(uri: &str) -> Self {
let raw_path_str = uri.strip_prefix("file://").unwrap_or(uri);
let ext = Path::new(raw_path_str)
.extension()
.and_then(|e| e.to_str())
.unwrap_or("");
if ext.eq_ignore_ascii_case("dds") {
CatEngineTextureFormat::DdsBc7
} else {
CatEngineTextureFormat::Rgba8
}
}
}
#[derive(Debug, Clone)]
pub struct TextureComponent {
pub source: TextureSource,
pub format: CatEngineTextureFormat,
pub render_image: Option<String>,
}
impl TextureComponent {
pub fn new(uri: impl Into<String>) -> Self {
let uri = uri.into();
let format = CatEngineTextureFormat::from_uri(&uri);
Self {
source: TextureSource::Uri(uri),
format,
render_image: None,
}
}
pub fn unresolved() -> Self {
Self {
source: TextureSource::Uri(String::new()),
format: CatEngineTextureFormat::Rgba8,
render_image: None,
}
}
pub fn with_uri(uri: impl Into<String>) -> Self {
Self::new(uri)
}
pub fn render_image(selector: impl Into<String>) -> Self {
Self {
source: TextureSource::Uri(String::new()),
format: CatEngineTextureFormat::Rgba8,
render_image: Some(selector.into()),
}
}
pub fn from_handle(handle: TextureHandle) -> Self {
Self {
source: TextureSource::Handle(handle),
format: CatEngineTextureFormat::Rgba8,
render_image: None,
}
}
pub fn from_png(uri: impl Into<String>) -> Self {
let mut c = Self::new(uri);
c.format = CatEngineTextureFormat::Rgba8;
c
}
pub fn from_dds(uri: impl Into<String>) -> Self {
let mut c = Self::new(uri);
c.format = CatEngineTextureFormat::DdsBc7;
c
}
pub fn refresh_format_from_uri(&mut self) {
if let TextureSource::Uri(uri) = &self.source {
self.format = CatEngineTextureFormat::from_uri(uri);
}
}
pub fn uri(&self) -> Option<&str> {
match &self.source {
TextureSource::Uri(s) if !s.is_empty() => Some(s.as_str()),
TextureSource::Handle(_) => None,
TextureSource::Uri(_) => None,
}
}
}
impl Component for TextureComponent {
fn name(&self) -> &'static str {
"texture"
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn init(&mut self, emit: &mut dyn crate::engine::ecs::SignalEmitter, component: ComponentId) {
emit.push_intent_now(
component,
crate::engine::ecs::IntentValue::RegisterTexture {
component_ids: vec![component],
},
);
}
fn to_mms_ast(
&self,
_world: &crate::engine::ecs::World,
) -> crate::scripting::ast::ComponentExpression {
use crate::engine::ecs::component::ce_helpers::*;
if let Some(selector) = &self.render_image {
return ce_call("Texture", "render_image", vec![s(selector)]);
}
match (&self.source, self.format) {
(TextureSource::Uri(uri), _) if uri.is_empty() => ce("Texture"),
(TextureSource::Uri(uri), CatEngineTextureFormat::DdsBc7) => {
ce_call("Texture", "from_dds", vec![s(uri)])
}
(TextureSource::Uri(uri), CatEngineTextureFormat::Rgba8) => {
ce_call("Texture", "with_uri", vec![s(uri)])
}
(TextureSource::Handle(_), _) => ce("Texture"),
}
}
}