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:
Sergio
2026-06-18 14:40:00 +00:00
parent e74800d9da
commit ccab39f140
202 changed files with 44034 additions and 1811 deletions
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "llimphi-widget-gauge"
version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
publish.workspace = true
description = "llimphi-widget-gauge — medidor radial (arco de 270°) con aguja y valor central. Para dashboards y stat panels donde el valor tiene un rango natural (0..max) y el contexto importa más que la cifra exacta."
[dependencies]
llimphi-ui = { workspace = true }
llimphi-theme = { workspace = true }
+111
View File
@@ -0,0 +1,111 @@
//! `llimphi-widget-gauge` — medidor radial.
//!
//! Arco de 270° (de 7:30 a 4:30, manecillas de reloj) con un track
//! gris fino y un arco activo del color `accent` que crece con el
//! valor. En el centro, una etiqueta opcional con el valor formateado.
//! Pensado para dashboards (CPU, RAM, throughput) y métricas con
//! contexto (lleno / vacío / objetivo).
#![forbid(unsafe_code)]
use llimphi_ui::llimphi_layout::taffy::{
prelude::{length, Size, Style},
AlignItems, JustifyContent,
};
use llimphi_ui::llimphi_raster::peniko::Color;
use llimphi_ui::llimphi_text::Alignment;
use llimphi_ui::View;
use llimphi_theme::Theme;
#[derive(Debug, Clone, Copy)]
pub struct GaugePalette {
pub track: Color,
pub active: Color,
pub fg: Color,
}
impl GaugePalette {
pub fn from_theme(t: &Theme) -> Self {
Self {
track: t.border,
active: t.accent,
fg: t.fg_text,
}
}
}
/// Render del gauge. `value` es la fracción 0..=1 que representa la
/// progresión del arco. `label` es texto centrado opcional.
pub fn gauge_view<Msg: Clone + 'static>(
value: f32,
size_px: f32,
label: Option<String>,
palette: &GaugePalette,
) -> View<Msg> {
let v = value.clamp(0.0, 1.0);
let track = palette.track;
let active = palette.active;
let mut node = View::new(Style {
size: Size { width: length(size_px), height: length(size_px) },
align_items: Some(AlignItems::Center),
justify_content: Some(JustifyContent::Center),
..Default::default()
})
.paint_with(move |scene, _ts, rect| {
paint_gauge(scene, rect, v, track, active);
});
if let Some(lbl) = label {
node = node.text_aligned(lbl, (size_px * 0.22).max(11.0), palette.fg, Alignment::Center);
}
node
}
fn paint_gauge(
scene: &mut llimphi_ui::llimphi_raster::vello::Scene,
rect: llimphi_ui::PaintRect,
value: f32,
track: Color,
active: Color,
) {
use llimphi_ui::llimphi_raster::kurbo::{Affine, Arc, Point, Stroke};
if rect.w <= 0.0 || rect.h <= 0.0 {
return;
}
let cx = (rect.x + rect.w * 0.5) as f64;
let cy = (rect.y + rect.h * 0.5) as f64;
let s = rect.w.min(rect.h) as f64;
let stroke_w = (s * 0.10).max(2.0);
let r = (s * 0.5) - stroke_w * 0.6;
// Arco completo (270° = 1.5π), empieza en 135° (7:30) y avanza
// sentido horario. En kurbo, `start_angle` está en radianes; CCW
// positivo. Tomamos start = 135° (back of bottom-left), sweep
// negativo para ir CW.
let start_deg = 135.0_f64;
let total_sweep_deg = -270.0_f64; // CW
let active_sweep_deg = total_sweep_deg * (value as f64);
let center = Point::new(cx, cy);
let radii = (r, r);
let track_arc = Arc {
center,
radii: radii.into(),
start_angle: start_deg.to_radians(),
sweep_angle: total_sweep_deg.to_radians(),
x_rotation: 0.0,
};
let stroke = Stroke::new(stroke_w).with_caps(llimphi_ui::llimphi_raster::kurbo::Cap::Round);
scene.stroke(&stroke, Affine::IDENTITY, track, None, &track_arc);
if value > 0.001 {
let active_arc = Arc {
center,
radii: radii.into(),
start_angle: start_deg.to_radians(),
sweep_angle: active_sweep_deg.to_radians(),
x_rotation: 0.0,
};
scene.stroke(&stroke, Affine::IDENTITY, active, None, &active_arc);
}
}