pukram-server/src/chara.rs

119 lines
4.0 KiB
Rust

use chara::CharacterDefinition;
use maud::{Markup, html};
pub fn render_character(name: &str, def: &CharacterDefinition, relative_path: &str) -> Markup {
html! {
style { (CHARACTER_CSS) }
div.customizer-container {
div.character-container {
@for layer in &def.layers {
img.character-layer
id=(format!("{name}-{}-layer", layer.internal_name))
src=(layer.entries.first().map(|e| format!("/{relative_path}/{}", e.path)).unwrap_or_default())
style=(format!("display: {};",
if layer.entries.first().is_some_and(|e| !e.path.is_empty()) {
"block"
} else {
"none"
}
));
}
}
div.controls-column {
@for layer in &def.layers {
@if let Some(display_name) = &layer.display_name {
div.layer-group {
div.layer-title { (display_name) }
div.layer-options {
@for (i, entry) in layer.entries.iter().enumerate() {
label.option {
input type="radio"
name=(format!("{name}-{}", layer.internal_name))
value=(if entry.path.is_empty() {
String::new()
} else {
format!("/{relative_path}/{}", entry.path)
})
checked[i==0]
onchange=(format!(
"var img=document.getElementById('{name}-{}-layer');{}",
layer.internal_name,
if entry.path.is_empty() {
"img.style.display='none';"
} else {
"img.src=this.value;img.style.display='block';"
}
));
(entry.name)
}
}
}
}
}
}
}
}
}
}
const CHARACTER_CSS: &str = r"
.customizer-container { display: flex; gap: 20px; margin-top: 20px; }
.character-container {
position: relative;
width: 300px;
height: 400px;
border: 2px solid #ddd;
border-radius: 10px;
background-color: white;
flex-shrink: 0;
}
.character-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
}
.controls-column {
flex-grow: 1;
display: flex;
flex-direction: column;
gap: 15px;
}
.layer-group {
background-color: white;
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.layer-title {
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
.layer-options {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 8px;
}
.option {
display: flex;
align-items: center;
}
.option input {
margin-right: 8px;
}
.back-link {
display: inline-block;
margin-bottom: 15px;
color: #333;
text-decoration: none;
}
.back-link:hover {
text-decoration: underline;
}
";