refresh: stack al día (vello 0.7 / wgpu 27 / parley 0.6) + motor 3D voxel
Re-sincroniza las fuentes desde el monorepo (estaba en vello 0.5/wgpu 24 y con la estructura vieja de eventloop) y suma el 3D: - bump del workspace a vello 0.7 / wgpu 27 / parley 0.6, + accesskit 0.24 / accesskit_winit 0.33 / vello_hybrid 0.0.9. - nuevos crates: llimphi-3d (voxels ray-march + mallas en un depth compartido, montable dentro de un View 2D vía set_viewport+scissor) y llimphi-voxel (world-gen, personajes, director de escenas) + shared/foreign-vox (puente .vox). - README: sección "Not just 2D — a 3D voxel engine" + GIF (docs/llimphi_voxel.gif). - excluido modules/allichay (arrastra deps fuera del alcance del front-door). - cargo check --workspace: verde. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,29 @@ pub fn button_view<Msg: Clone + 'static>(
|
||||
)
|
||||
}
|
||||
|
||||
/// Tinte de la onda de ripple derivado de la paleta: el color de texto
|
||||
/// (`fg`, normalmente claro sobre el botón dark) a alpha bajo, así contrasta
|
||||
/// con el fondo y se adapta al theme sin añadir un campo a [`ButtonPalette`].
|
||||
fn ripple_ink(palette: &ButtonPalette) -> Color {
|
||||
let c = palette.fg.components;
|
||||
Color { components: [c[0], c[1], c[2], 0.22], ..palette.fg }
|
||||
}
|
||||
|
||||
/// Como [`button_view`] pero con feedback **ripple/InkWell**: al presionarlo
|
||||
/// emite la salpicadura Material (círculo que se expande desde el punto del
|
||||
/// tap y se desvanece, recortado al contorno del botón). `key` debe ser
|
||||
/// **estable y único** entre los botones vivos del frame (índice del botón,
|
||||
/// hash de su acción) — es lo que enlaza la onda retenida con este botón entre
|
||||
/// frames. El tinte sale de la paleta ([`ripple_ink`]).
|
||||
pub fn button_ripple<Msg: Clone + 'static>(
|
||||
label: impl Into<String>,
|
||||
key: u64,
|
||||
palette: &ButtonPalette,
|
||||
on_click: Msg,
|
||||
) -> View<Msg> {
|
||||
button_view(label, palette, on_click).ripple(key, ripple_ink(palette))
|
||||
}
|
||||
|
||||
/// Variante con `Style` y alineación de texto explícitos — útil cuando
|
||||
/// la app necesita un botón con dimensiones particulares o el texto a
|
||||
/// la izquierda.
|
||||
@@ -89,6 +112,11 @@ pub fn button_styled<Msg: Clone + 'static>(
|
||||
palette: &ButtonPalette,
|
||||
on_click: Msg,
|
||||
) -> View<Msg> {
|
||||
let label: String = label.into();
|
||||
// Semántica accesible: rol Button + el texto visible como nombre. Si el
|
||||
// caller le pasó un label vacío (botones puramente icónicos), igual sale
|
||||
// como Button — lo correcto es agregarle un aria_label propio desde fuera.
|
||||
let aria = label.clone();
|
||||
// Gloss superior: gradient blanco alpha 28 → 0 sobre la mitad de
|
||||
// arriba. `paint_with` corre entre el fill (que respeta hover_fill)
|
||||
// y el texto, así que la luz se suma al color de base sin sustituirlo
|
||||
@@ -119,6 +147,23 @@ pub fn button_styled<Msg: Clone + 'static>(
|
||||
.with_stops([top, bot].as_slice());
|
||||
scene.fill(Fill::NonZero, Affine::IDENTITY, &gradient, None, &rr);
|
||||
})
|
||||
.text_aligned(label.into(), 13.0, palette.fg, text_alignment)
|
||||
.text_aligned(label, 13.0, palette.fg, text_alignment)
|
||||
.role(llimphi_ui::Role::Button)
|
||||
.aria_label(aria)
|
||||
.on_click(on_click)
|
||||
.cursor(llimphi_ui::Cursor::Pointer)
|
||||
}
|
||||
|
||||
/// Como [`button_styled`] pero con feedback **ripple/InkWell** (ver
|
||||
/// [`button_ripple`] para la semántica de `key`).
|
||||
pub fn button_styled_ripple<Msg: Clone + 'static>(
|
||||
label: impl Into<String>,
|
||||
key: u64,
|
||||
style: Style,
|
||||
text_alignment: Alignment,
|
||||
palette: &ButtonPalette,
|
||||
on_click: Msg,
|
||||
) -> View<Msg> {
|
||||
button_styled(label, style, text_alignment, palette, on_click)
|
||||
.ripple(key, ripple_ink(palette))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user