use std::borrow::Cow;
pub fn display_name_for_type(short_type_name: &str) -> Cow<'static, str> {
if let Some(name) = builtin_display_name(short_type_name) {
Cow::Borrowed(name)
} else {
Cow::Owned(prettify_camel_case(short_type_name))
}
}
pub fn display_name_for_modifier(m: &dyn bevy_hanabi::Modifier) -> Cow<'static, str> {
let short = m.as_reflect().reflect_short_type_path();
if short == "SetAttributeModifier"
&& let Some(sam) = m
.as_reflect()
.downcast_ref::<bevy_hanabi::SetAttributeModifier>()
{
return Cow::Owned(format!("Set Attribute ({})", sam.attribute.name()));
}
display_name_for_type(short)
}
fn builtin_display_name(short: &str) -> Option<&'static str> {
Some(match short {
"SetPositionCircleModifier" => "Set Position (Circle)",
"SetPositionSphereModifier" => "Set Position (Sphere)",
"SetPositionCone3dModifier" => "Set Position (Cone)",
"SetVelocityCircleModifier" => "Set Velocity (Circle)",
"SetVelocitySphereModifier" => "Set Velocity (Sphere)",
"SetVelocityTangentModifier" => "Set Velocity (Tangent)",
"SetAttributeModifier" => "Set Attribute",
"InheritAttributeModifier" => "Inherit Attribute",
"AccelModifier" => "Acceleration",
"RadialAccelModifier" => "Radial Acceleration",
"TangentAccelModifier" => "Tangential Acceleration",
"LinearDragModifier" => "Linear Drag",
"ConformToSphereModifier" => "Conform To Sphere",
"KillSphereModifier" => "Kill (Sphere)",
"KillAabbModifier" => "Kill (AABB)",
"EmitSpawnEventModifier" => "Emit Spawn Event",
"SetColorModifier" => "Set Color",
"ColorOverLifetimeModifier" => "Color Over Lifetime",
"SetSizeModifier" => "Set Size",
"SizeOverLifetimeModifier" => "Size Over Lifetime",
"ScreenSpaceSizeModifier" => "Screen-Space Size",
"ParticleTextureModifier" => "Particle Texture",
"FlipbookModifier" => "Flipbook",
"OrientModifier" => "Orient",
"RoundModifier" => "Round",
_ => return None,
})
}
fn prettify_camel_case(name: &str) -> String {
let trimmed = name.strip_suffix("Modifier").unwrap_or(name);
if trimmed.is_empty() {
return name.to_string();
}
let mut out = String::with_capacity(trimmed.len() + 4);
let chars: Vec<char> = trimmed.chars().collect();
for (i, &c) in chars.iter().enumerate() {
if i > 0 {
let prev = chars[i - 1];
let next = chars.get(i + 1).copied();
let boundary = (!prev.is_uppercase() && c.is_uppercase())
|| (prev.is_uppercase()
&& c.is_uppercase()
&& matches!(next, Some(n) if n.is_lowercase()));
if boundary {
out.push(' ');
}
}
out.push(c);
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn curated_names() {
assert_eq!(
display_name_for_type("SetPositionSphereModifier"),
"Set Position (Sphere)"
);
assert_eq!(
display_name_for_type("ColorOverLifetimeModifier"),
"Color Over Lifetime"
);
assert_eq!(display_name_for_type("KillAabbModifier"), "Kill (AABB)");
}
#[test]
fn fallback_prettifies_unknown() {
assert_eq!(display_name_for_type("MyCustomModifier"), "My Custom");
assert_eq!(display_name_for_type("FooBar"), "Foo Bar");
assert_eq!(display_name_for_type("HTTPRequestModifier"), "HTTP Request");
}
}