use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::str::FromStr;
pub mod error_types;
pub mod security;
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct ComponentErrorState {
pub has_error: bool,
pub error_message: Option<String>,
pub error_location: Option<String>,
}
impl ComponentErrorState {
pub fn clear() -> Self {
Self::default()
}
pub fn error(message: impl Into<String>, location: impl Into<String>) -> Self {
Self {
has_error: true,
error_message: Some(message.into()),
error_location: Some(location.into()),
}
}
}
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct KnowledgeState {
pub thoughts: Vec<String>,
pub actions: Vec<String>,
pub context: HashMap<String, String>,
pub last_query_results: Vec<KnowledgeId>,
#[serde(alias = "items")]
pub fragments: std::collections::HashMap<KnowledgeId, KnowledgeFragment>,
pub nodes: Vec<TemporalNode>,
pub edges: Vec<TemporalEdge>,
pub realm: Realm,
pub last_pointer_pos: [f32; 2],
pub pointer_velocity: [f32; 2],
pub odin_focus: Option<String>,
pub agent_attention: HashMap<String, f32>,
#[serde(skip)]
pub component_states: HashMap<u64, Arc<std::sync::RwLock<dyn std::any::Any + Send + Sync>>>,
}
impl KnowledgeState {
pub fn apply_decay(&mut self, decay_factor: f32) {
for node in &mut self.nodes {
node.weight *= decay_factor;
}
for state in self.component_states.values() {
if let Ok(mut lock) = state.write()
&& let Some(v) = lock.downcast_mut::<f32>()
{
*v = (*v * decay_factor).max(1.0);
}
}
}
pub fn reinforce(&mut self, node_ids: &[String], boost: f32) {
for node in &mut self.nodes {
if node_ids.contains(&node.id) {
node.weight += boost;
}
}
}
pub fn update_pointer(&mut self, new_pos: [f32; 2]) {
self.pointer_velocity = [
new_pos[0] - self.last_pointer_pos[0],
new_pos[1] - self.last_pointer_pos[1],
];
self.last_pointer_pos = new_pos;
}
}
pub type KnowledgeId = String;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeFragment {
pub id: String,
pub summary: String,
pub source: String,
pub created_at: u64,
pub accessed_count: u32,
pub content: Option<String>,
}
impl KnowledgeFragment {
pub fn new(id: String, summary: String, source: String) -> Self {
Self {
id,
summary,
source,
created_at: 0,
accessed_count: 0,
content: None,
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum MemoryLayer {
Episodic,
Semantic,
Procedural,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
pub enum Realm {
Midgard,
#[default]
Asgard,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalNode {
pub id: String,
pub fragment_id: KnowledgeId,
pub timestamp: u64,
pub layer: MemoryLayer,
pub weight: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalEdge {
pub source: String,
pub target: String,
pub relation: String,
pub weight: f32,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct AssetKey(pub String);
impl EnvKey for AssetKey {
type Value = Arc<dyn AssetManager>;
fn default_value() -> Self::Value {
Arc::new(DefaultAssetManager::new())
}
}
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum AssetState<T> {
Loading,
Ready(T),
Error(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum TokenValue {
Single { value: String },
Adaptive { light: String, dark: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YggdrasilTokens {
pub color: HashMap<String, TokenValue>,
pub font: HashMap<String, TokenValue>,
pub spacing: HashMap<String, TokenValue>,
pub radius: HashMap<String, TokenValue>,
pub shadow: HashMap<String, TokenValue>,
pub border: HashMap<String, TokenValue>,
pub anim: HashMap<String, TokenValue>,
pub bifrost: HashMap<String, TokenValue>,
pub gungnir: HashMap<String, TokenValue>,
pub mjolnir: HashMap<String, TokenValue>,
pub accessibility: HashMap<String, TokenValue>,
}
impl Default for YggdrasilTokens {
fn default() -> Self {
Self::new()
}
}
impl YggdrasilTokens {
pub fn new() -> Self {
Self {
color: HashMap::new(),
font: HashMap::new(),
spacing: HashMap::new(),
radius: HashMap::new(),
shadow: HashMap::new(),
border: HashMap::new(),
anim: HashMap::new(),
bifrost: HashMap::new(),
gungnir: HashMap::new(),
mjolnir: HashMap::new(),
accessibility: HashMap::new(),
}
}
pub fn get_color(&self, key: &str, is_dark: bool) -> Option<String> {
self.color.get(key).map(|token| match token {
TokenValue::Single { value } => value.clone(),
TokenValue::Adaptive { light, dark } => {
if is_dark {
dark.clone()
} else {
light.clone()
}
}
})
}
pub fn get<T: FromStr>(&self, category: &str, key: &str, is_dark: bool) -> Option<T> {
let map = match category {
"color" => &self.color,
"font" => &self.font,
"spacing" => &self.spacing,
"radius" => &self.radius,
"shadow" => &self.shadow,
"border" => &self.border,
"anim" => &self.anim,
"bifrost" => &self.bifrost,
"gungnir" => &self.gungnir,
"mjolnir" => &self.mjolnir,
"accessibility" => &self.accessibility,
_ => return None,
};
map.get(key).and_then(|token| match token {
TokenValue::Single { value } => value.parse().ok(),
TokenValue::Adaptive { light, dark } => {
let value = if is_dark { dark } else { light };
value.parse().ok()
}
})
}
}
pub trait View: Sized + Send {
type Body: View;
fn body(self) -> Self::Body;
fn render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
fn intrinsic_size(&self, _renderer: &mut dyn Renderer, _proposal: SizeProposal) -> Size {
Size::ZERO
}
fn layout(&self) -> Option<&dyn layout::LayoutView> {
None
}
fn flex_weight(&self) -> f32 {
0.0
}
fn modifier<M: ViewModifier>(self, m: M) -> ModifiedView<Self, M> {
ModifiedView::new(self, m)
}
fn bifrost(
self,
blur: f32,
saturation: f32,
opacity: f32,
) -> ModifiedView<Self, BifrostModifier> {
self.modifier(BifrostModifier {
blur,
saturation,
opacity,
})
}
fn gungnir(
self,
color: impl Into<String>,
radius: f32,
intensity: f32,
) -> ModifiedView<Self, GungnirModifier> {
self.modifier(GungnirModifier {
color: color.into(),
radius,
intensity,
})
}
fn mjolnir_slice(self, angle: f32, offset: f32) -> ModifiedView<Self, MjolnirSliceModifier> {
self.modifier(MjolnirSliceModifier { angle, offset })
}
fn mjolnir_shatter(
self,
pieces: u32,
force: f32,
) -> ModifiedView<Self, MjolnirShatterModifier> {
self.modifier(MjolnirShatterModifier { pieces, force })
}
fn bifrost_bridge(self, id: impl Into<String>) -> ModifiedView<Self, BifrostBridgeModifier> {
self.modifier(BifrostBridgeModifier { id: id.into() })
}
fn background(self, color: [f32; 4]) -> ModifiedView<Self, BackgroundModifier> {
self.modifier(BackgroundModifier { color })
}
fn padding(self, amount: f32) -> ModifiedView<Self, PaddingModifier> {
self.modifier(PaddingModifier { amount })
}
fn opacity(self, opacity: f32) -> ModifiedView<Self, OpacityModifier> {
self.modifier(OpacityModifier {
opacity: opacity.clamp(0.0, 1.0),
})
}
fn foreground_color(self, color: [f32; 4]) -> ModifiedView<Self, ForegroundColorModifier> {
self.modifier(ForegroundColorModifier { color })
}
fn frame(self, width: Option<f32>, height: Option<f32>) -> ModifiedView<Self, FrameModifier> {
self.modifier(FrameModifier { width, height })
}
fn flex(self, weight: f32) -> ModifiedView<Self, FlexModifier> {
self.modifier(FlexModifier { weight })
}
fn safe_area_padding(self) -> ModifiedView<Self, SafeAreaModifier> {
self.modifier(SafeAreaModifier { ignores: false })
}
fn ignores_safe_area(self) -> ModifiedView<Self, SafeAreaModifier> {
self.modifier(SafeAreaModifier { ignores: true })
}
fn clip_to_bounds(self) -> ModifiedView<Self, ClipModifier> {
self.modifier(ClipModifier)
}
fn border(self, color: [f32; 4], width: f32) -> ModifiedView<Self, BorderModifier> {
self.modifier(BorderModifier { color, width })
}
fn elevation(self, level: f32) -> ModifiedView<Self, ElevationModifier> {
self.modifier(ElevationModifier { level })
}
fn magnetic(self, radius: f32, intensity: f32) -> ModifiedView<Self, MagneticModifier> {
self.modifier(MagneticModifier { radius, intensity })
}
fn mani_glow(self, color: [f32; 4], radius: f32) -> ModifiedView<Self, ManiGlowModifier> {
self.modifier(ManiGlowModifier { color, radius })
}
fn memory_layer(self, layer: MemoryLayer) -> ModifiedView<Self, BifrostLayerModifier> {
self.modifier(BifrostLayerModifier { layer })
}
fn fafnir_evolve(self, id: u64) -> ModifiedView<Self, FafnirModifier> {
self.modifier(FafnirModifier { id })
}
fn mimir_intent(self) -> ModifiedView<Self, MimirIntentModifier> {
self.modifier(MimirIntentModifier)
}
fn kvasir_vibes(self, complexity: f32) -> ModifiedView<Self, KvasirVibeModifier> {
self.modifier(KvasirVibeModifier { complexity })
}
fn odins_eye(self) -> ModifiedView<Self, OdinsEyeModifier> {
self.modifier(OdinsEyeModifier)
}
fn on_appear<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, LifecycleModifier> {
self.modifier(LifecycleModifier {
on_appear: Some(Arc::new(action)),
on_disappear: None,
})
}
fn on_disappear<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, LifecycleModifier> {
self.modifier(LifecycleModifier {
on_appear: None,
on_disappear: Some(Arc::new(action)),
})
}
fn on_click<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, OnClickModifier> {
self.modifier(OnClickModifier {
action: Arc::new(action),
})
}
fn on_pointer_enter<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, OnPointerEnterModifier> {
self.modifier(OnPointerEnterModifier {
action: Arc::new(action),
})
}
fn on_pointer_leave<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, OnPointerLeaveModifier> {
self.modifier(OnPointerLeaveModifier {
action: Arc::new(action),
})
}
fn on_pointer_move<F: Fn(f32, f32) + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, OnPointerMoveModifier> {
self.modifier(OnPointerMoveModifier {
action: Arc::new(action),
})
}
fn on_pointer_down<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, OnPointerDownModifier> {
self.modifier(OnPointerDownModifier {
action: Arc::new(action),
})
}
fn on_pointer_up<F: Fn() + Send + Sync + 'static>(
self,
action: F,
) -> ModifiedView<Self, OnPointerUpModifier> {
self.modifier(OnPointerUpModifier {
action: Arc::new(action),
})
}
fn erase(self) -> AnyView
where
Self: Clone + 'static,
{
AnyView::new(self)
}
}
pub trait ErasedView: Send {
fn render_erased(&self, renderer: &mut dyn Renderer, rect: Rect);
fn name(&self) -> &'static str;
fn flex_weight_erased(&self) -> f32;
fn layout_erased(&self) -> Option<&dyn layout::LayoutView>;
fn clone_box(&self) -> Box<dyn ErasedView>;
}
impl<V: View + Clone + 'static> ErasedView for V {
fn render_erased(&self, renderer: &mut dyn Renderer, rect: Rect) {
self.render(renderer, rect);
}
fn name(&self) -> &'static str {
std::any::type_name::<V>()
}
fn flex_weight_erased(&self) -> f32 {
self.flex_weight()
}
fn layout_erased(&self) -> Option<&dyn layout::LayoutView> {
self.layout()
}
fn clone_box(&self) -> Box<dyn ErasedView> {
Box::new(self.clone())
}
}
pub struct MemoView<V, F> {
id: u64,
data_hash: u64,
builder: F,
_v: std::marker::PhantomData<V>,
}
impl<V: View, F: Fn() -> V + Send + Sync> MemoView<V, F> {
pub fn new(id: u64, data_hash: u64, builder: F) -> Self {
Self {
id,
data_hash,
builder,
_v: std::marker::PhantomData,
}
}
}
impl<V: View + 'static, F: Fn() -> V + Send + Sync + 'static> View for MemoView<V, F> {
type Body = Never;
fn body(self) -> Self::Body {
unreachable!("MemoView does not have a body")
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.memoize(self.id, self.data_hash, &|r| {
let view = (self.builder)();
view.render(r, rect);
});
}
}
pub struct AnyView {
inner: Box<dyn ErasedView>,
}
impl Clone for AnyView {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone_box(),
}
}
}
impl AnyView {
pub fn new<V: View + Clone + 'static>(view: V) -> Self {
Self {
inner: Box::new(view),
}
}
}
impl View for AnyView {
type Body = Never;
fn body(self) -> Self::Body {
unreachable!()
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.push_vnode(rect, self.inner.name());
self.inner.render_erased(renderer, rect);
renderer.pop_vnode();
}
fn flex_weight(&self) -> f32 {
self.inner.flex_weight_erased()
}
fn layout(&self) -> Option<&dyn layout::LayoutView> {
self.inner.layout_erased()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct BifrostBridgeModifier {
pub id: String,
}
impl ViewModifier for BifrostBridgeModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.register_shared_element(&self.id, rect);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MjolnirSliceModifier {
pub angle: f32,
pub offset: f32,
}
impl ViewModifier for MjolnirSliceModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
renderer.push_mjolnir_slice(self.angle, self.offset);
}
fn post_render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
renderer.pop_mjolnir_slice();
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MjolnirShatterModifier {
pub pieces: u32,
pub force: f32,
}
impl ViewModifier for MjolnirShatterModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let pieces = self.pieces.max(1);
for i in 0..pieces {
let progress = i as f32 / pieces as f32;
let next_progress = (i + 1) as f32 / pieces as f32;
let angle_start = progress * 360.0;
let angle_end = next_progress * 360.0;
renderer.push_mjolnir_slice(angle_start, 0.0);
renderer.push_mjolnir_slice(angle_end + 180.0, 0.0);
let mid_angle = (angle_start + angle_end) / 2.0;
let rad = mid_angle.to_radians();
let dx = rad.cos() * self.force;
let dy = rad.sin() * self.force;
let shard_rect = Rect {
x: rect.x + dx,
y: rect.y + dy,
..rect
};
view.render(renderer, shard_rect);
renderer.pop_mjolnir_slice();
renderer.pop_mjolnir_slice();
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BifrostModifier {
pub blur: f32,
pub saturation: f32,
pub opacity: f32,
}
impl ViewModifier for BifrostModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
if renderer.is_over_budget() {
renderer.bifrost(rect, self.blur * 0.5, self.saturation, self.opacity);
} else {
renderer.bifrost(rect, self.blur, self.saturation, self.opacity);
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BackgroundModifier {
pub color: [f32; 4],
}
impl ViewModifier for BackgroundModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.fill_rect(rect, self.color);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PaddingModifier {
pub amount: f32,
}
impl ViewModifier for PaddingModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn transform_rect(&self, rect: Rect) -> Rect {
Rect {
x: rect.x + self.amount,
y: rect.y + self.amount,
width: (rect.width - 2.0 * self.amount).max(0.0),
height: (rect.height - 2.0 * self.amount).max(0.0),
}
}
fn transform_proposal(&self, mut proposal: SizeProposal) -> SizeProposal {
if let Some(w) = proposal.width {
proposal.width = Some((w - 2.0 * self.amount).max(0.0));
}
if let Some(h) = proposal.height {
proposal.height = Some((h - 2.0 * self.amount).max(0.0));
}
proposal
}
fn transform_size(&self, mut size: Size) -> Size {
size.width += 2.0 * self.amount;
size.height += 2.0 * self.amount;
size
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct GungnirModifier {
pub color: String,
pub radius: f32,
pub intensity: f32,
}
impl ViewModifier for GungnirModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.stroke_rect(rect, [0.0, 1.0, 1.0, self.intensity], self.radius / 10.0);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GungnirPulseModifier {
pub color: [f32; 4],
pub radius: f32,
pub speed: f32,
}
impl ViewModifier for GungnirPulseModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
let time = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs_f32();
let intensity = (time * self.speed).sin() * 0.5 + 0.5;
let mut color = self.color;
color[3] *= intensity;
renderer.stroke_rect(rect, color, self.radius);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MagneticModifier {
pub radius: f32,
pub intensity: f32,
}
impl ViewModifier for MagneticModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let [px, py] = renderer.get_pointer_position();
let center_x = rect.x + rect.width / 2.0;
let center_y = rect.y + rect.height / 2.0;
let dx = px - center_x;
let dy = py - center_y;
let dist = (dx * dx + dy * dy).sqrt();
let mut offset_x = 0.0;
let mut offset_y = 0.0;
if dist < self.radius && dist > 0.0 {
let force = (1.0 - dist / self.radius) * self.intensity;
offset_x = dx * force;
offset_y = dy * force;
}
let magnetic_rect = Rect {
x: rect.x + offset_x,
y: rect.y + offset_y,
..rect
};
view.render(renderer, magnetic_rect);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ManiGlowModifier {
pub color: [f32; 4],
pub radius: f32,
}
impl ViewModifier for ManiGlowModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
if crate::load_system_state().realm == Realm::Asgard {
renderer.mani_glow(rect, self.color, self.radius);
}
view.render(renderer, rect);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BifrostLayerModifier {
pub layer: MemoryLayer,
}
impl ViewModifier for BifrostLayerModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let realm = crate::load_system_state().realm;
match self.layer {
MemoryLayer::Episodic => {
if realm == Realm::Asgard {
renderer.bifrost(rect, 40.0, 1.2, 0.7);
} else {
renderer.fill_rect(rect, [0.1, 0.12, 0.15, 0.8]);
}
}
MemoryLayer::Semantic => {
if realm == Realm::Asgard {
renderer.gungnir(rect, [1.0, 0.84, 0.0, 1.0], 15.0, 0.6);
} else {
renderer.stroke_rect(rect, [0.4, 0.4, 0.4, 1.0], 1.5);
}
}
MemoryLayer::Procedural => {
renderer.fill_rect(rect, [0.05, 0.05, 0.07, 0.95]);
let stroke_color = if realm == Realm::Asgard {
[0.3, 0.3, 0.3, 1.0]
} else {
[0.2, 0.2, 0.2, 1.0]
};
renderer.stroke_rect(rect, stroke_color, 2.0);
}
}
view.render(renderer, rect);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FafnirModifier {
pub id: u64,
}
impl ViewModifier for FafnirModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let state = crate::load_system_state();
let vitality = state
.get_component_state::<f32>(self.id)
.map(|v| *v.read().unwrap())
.unwrap_or(1.0);
let growth = (vitality - 1.0).clamp(0.0, 4.0);
let scale = 1.0 + growth * 0.12;
let glow_intensity = growth * 0.25;
let id = self.id;
renderer.register_handler(
"pointermove",
std::sync::Arc::new(move |_| {
crate::update_system_state(|s| {
let mut s = s.clone();
let v = s
.get_component_state::<f32>(id)
.map(|v| *v.read().unwrap())
.unwrap_or(1.0);
s.set_component_state(id, (v + 0.05).min(5.0)); s
});
}),
);
if scale > 1.01 {
renderer.push_transform([0.0, 0.0], [scale, scale], 0.0);
}
if glow_intensity > 0.1 && state.realm == Realm::Asgard {
renderer.gungnir(rect, [1.0, 0.84, 0.0, 1.0], 15.0 * vitality, glow_intensity);
}
view.render(renderer, rect);
if scale > 1.01 {
renderer.pop_transform();
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MimirIntentModifier;
impl ViewModifier for MimirIntentModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let state = crate::load_system_state();
let pos = state.last_pointer_pos;
let vel = state.pointer_velocity;
let center = [rect.x + rect.width / 2.0, rect.y + rect.height / 2.0];
let dx = center[0] - pos[0];
let dy = center[1] - pos[1];
let dot = vel[0] * dx + vel[1] * dy;
let speed_sq = vel[0] * vel[0] + vel[1] * vel[1];
let dist_sq = dx * dx + dy * dy;
if dot > 0.0 && dist_sq < 250.0 * 250.0 && speed_sq > 0.5 && state.realm == Realm::Asgard {
let intent_strength = (dot / (speed_sq.sqrt() * dist_sq.sqrt())).clamp(0.0, 1.0);
renderer.stroke_rect(rect, [0.0, 0.9, 1.0, 0.3 * intent_strength], 1.5);
}
view.render(renderer, rect);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct KvasirVibeModifier {
pub complexity: f32,
}
impl ViewModifier for KvasirVibeModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
if crate::load_system_state().realm == Realm::Asgard {
let t = renderer.elapsed_time();
let c = self.complexity.clamp(0.0, 1.0);
let blur = 20.0 + c * 40.0;
let turbulence_x = (t * (1.0 + c * 2.0)).sin() * 8.0 * c;
let turbulence_y = (t * (0.8 + c * 1.5)).cos() * 5.0 * c;
renderer.bifrost(
rect.offset(turbulence_x, turbulence_y),
blur,
0.8 + c * 0.4,
0.25,
);
if c > 0.2 {
let pulse = (t * (3.0 + c * 5.0)).sin().abs() * c;
let color = [0.0, 0.9, 1.0, 0.4 * pulse]; renderer.gungnir(rect, color, 12.0 + c * 24.0, 0.6 * pulse);
}
if c > 0.7 {
let instability = (t * 15.0).cos().abs() * (c - 0.7) * 3.3;
let warning_color = [1.0, 0.0, 0.4, 0.12 * instability];
renderer.fill_rect(rect, warning_color);
renderer.stroke_rect(rect, [1.0, 0.0, 0.2, 0.45 * instability], 1.8);
}
}
view.render(renderer, rect);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct OdinsEyeModifier;
impl ViewModifier for OdinsEyeModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let state = crate::load_system_state();
let t = renderer.elapsed_time();
view.render(renderer, rect);
if state.realm == Realm::Asgard {
let eye_pulse = (t * 0.5).sin().abs() * 0.05;
renderer.draw_radial_gradient(
rect,
[0.0, 0.6, 0.8, 0.08 + eye_pulse], [0.0, 0.0, 0.0, 0.0], );
let hugin_rect = Rect {
x: rect.x + 20.0,
y: rect.y + 40.0,
width: 200.0,
height: rect.height - 80.0,
};
renderer.draw_text(
"HUGIN: THOUGHT",
hugin_rect.x,
hugin_rect.y,
10.0,
[0.0, 1.0, 1.0, 0.6],
);
for (i, thought) in state.thoughts.iter().rev().take(10).enumerate() {
renderer.draw_text(
thought,
hugin_rect.x,
hugin_rect.y + 20.0 + i as f32 * 14.0,
9.0,
[1.0, 1.0, 1.0, 0.4],
);
}
let munin_rect = Rect {
x: rect.x + rect.width - 220.0,
y: rect.y + 40.0,
width: 200.0,
height: rect.height - 80.0,
};
renderer.draw_text(
"MUNIN: MEMORY",
munin_rect.x,
munin_rect.y,
10.0,
[1.0, 0.84, 0.0, 0.6],
);
for (i, node) in state.nodes.iter().take(10).enumerate() {
let opacity = (node.weight.min(1.0)) * 0.5;
renderer.draw_text(
&node.id,
munin_rect.x,
munin_rect.y + 20.0 + i as f32 * 14.0,
9.0,
[1.0, 1.0, 1.0, opacity],
);
}
if let Some(focus_id) = &state.odin_focus {
renderer.draw_text(
&format!("EYE FOCUS: {}", focus_id),
rect.x + rect.width / 2.0 - 50.0,
rect.y + 20.0,
12.0,
[0.0, 1.0, 1.0, 0.8],
);
renderer.gungnir(
Rect {
x: rect.x + rect.width / 2.0 - 1.0,
y: rect.y,
width: 2.0,
height: rect.height,
},
[0.0, 1.0, 1.0, 1.0],
20.0,
0.4,
);
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SleipnirParams {
pub stiffness: f32,
pub damping: f32,
pub mass: f32,
}
impl SleipnirParams {
pub fn snappy() -> Self {
Self {
stiffness: 230.0,
damping: 22.0,
mass: 1.0,
}
}
pub fn fluid() -> Self {
Self {
stiffness: 170.0,
damping: 26.0,
mass: 1.0,
}
}
pub fn heavy() -> Self {
Self {
stiffness: 90.0,
damping: 20.0,
mass: 1.0,
}
}
pub fn bouncy() -> Self {
Self {
stiffness: 190.0,
damping: 14.0,
mass: 1.0,
}
}
}
impl Default for SleipnirParams {
fn default() -> Self {
Self::fluid()
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
struct SolverState {
x: f32,
v: f32,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SleipnirSolver {
params: SleipnirParams,
target: f32,
state: SolverState,
}
impl SleipnirSolver {
pub fn new(params: SleipnirParams, target: f32, current: f32) -> Self {
Self {
params,
target,
state: SolverState { x: current, v: 0.0 },
}
}
pub fn tick(&mut self, dt: f32) -> f32 {
if dt <= 0.0 {
return self.state.x;
}
let mut remaining = dt;
let step = 1.0 / 120.0;
while remaining > 0.0 {
let d = remaining.min(step);
self.step(d);
remaining -= d;
}
self.state.x
}
fn step(&mut self, dt: f32) {
let a = self.evaluate(self.state, 0.0, SolverState { x: 0.0, v: 0.0 });
let b = self.evaluate(self.state, dt * 0.5, a);
let c = self.evaluate(self.state, dt * 0.5, b);
let d = self.evaluate(self.state, dt, c);
let dxdt = 1.0 / 6.0 * (a.x + 2.0 * (b.x + c.x) + d.x);
let dvdt = 1.0 / 6.0 * (a.v + 2.0 * (b.v + c.v) + d.v);
self.state.x += dxdt * dt;
self.state.v += dvdt * dt;
}
fn evaluate(&self, initial: SolverState, dt: f32, d: SolverState) -> SolverState {
let state = SolverState {
x: initial.x + d.x * dt,
v: initial.v + d.v * dt,
};
let force =
-self.params.stiffness * (state.x - self.target) - self.params.damping * state.v;
let mass = self.params.mass.max(0.001);
SolverState {
x: state.v,
v: force / mass,
}
}
pub fn is_settled(&self) -> bool {
(self.state.x - self.target).abs() < 0.001 && self.state.v.abs() < 0.001
}
pub fn set_target(&mut self, target: f32) {
self.target = target;
}
pub fn current_value(&self) -> f32 {
self.state.x
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SleipnirModifier {
pub id: u64,
pub target: f32,
pub params: SleipnirParams,
}
impl ViewModifier for SleipnirModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
let state = load_system_state();
let solver_lock_opt = state.get_component_state::<SleipnirSolver>(self.id);
let current_val;
if let Some(lock) = solver_lock_opt {
let mut solver = lock.write().unwrap();
solver.set_target(self.target);
current_val = solver.tick(renderer.delta_time());
if !solver.is_settled() {
renderer.request_redraw();
}
} else {
let solver = SleipnirSolver::new(
self.params,
self.target,
self.target, );
get_system_state().rcu(|old| {
let mut new_state = (**old).clone();
new_state.set_component_state(self.id, solver);
new_state
});
current_val = self.target;
}
renderer.push_transform([0.0, current_val], [1.0, 1.0], 0.0);
view.render(renderer, rect);
renderer.pop_transform();
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct TransformModifier {
pub translation: [f32; 2],
pub scale: [f32; 2],
pub rotation: f32,
}
impl Default for TransformModifier {
fn default() -> Self {
Self::new()
}
}
impl TransformModifier {
pub fn new() -> Self {
Self {
translation: [0.0, 0.0],
scale: [1.0, 1.0],
rotation: 0.0,
}
}
pub fn translate(mut self, x: f32, y: f32) -> Self {
self.translation = [x, y];
self
}
pub fn scale(mut self, x: f32, y: f32) -> Self {
self.scale = [x, y];
self
}
pub fn rotate(mut self, radians: f32) -> Self {
self.rotation = radians;
self
}
}
impl ViewModifier for TransformModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
renderer.push_transform(self.translation, self.scale, self.rotation);
view.render(renderer, rect);
renderer.pop_transform();
}
}
#[derive(Clone)]
pub struct LifecycleModifier {
pub on_appear: Option<Arc<dyn Fn() + Send + Sync>>,
pub on_disappear: Option<Arc<dyn Fn() + Send + Sync>>,
}
impl ViewModifier for LifecycleModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct OpacityModifier {
pub opacity: f32,
}
impl ViewModifier for OpacityModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
renderer.push_opacity(self.opacity);
}
fn post_render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
renderer.pop_opacity();
}
}
#[derive(Clone)]
pub struct OnClickModifier {
pub action: Arc<dyn Fn() + Send + Sync>,
}
impl ViewModifier for OnClickModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
let action = self.action.clone();
renderer.register_handler(
"pointerclick",
std::sync::Arc::new(move |event| {
if let Event::PointerClick { .. } = event {
(action)();
}
}),
);
}
}
#[derive(Clone)]
pub struct OnPointerEnterModifier {
pub action: Arc<dyn Fn() + Send + Sync>,
}
impl ViewModifier for OnPointerEnterModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
let action = self.action.clone();
renderer.register_handler(
"pointerenter",
std::sync::Arc::new(move |event| {
if let Event::PointerEnter = event {
(action)();
}
}),
);
}
}
#[derive(Clone)]
pub struct OnPointerLeaveModifier {
pub action: Arc<dyn Fn() + Send + Sync>,
}
impl ViewModifier for OnPointerLeaveModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
let action = self.action.clone();
renderer.register_handler(
"pointerleave",
std::sync::Arc::new(move |event| {
if let Event::PointerLeave = event {
(action)();
}
}),
);
}
}
#[derive(Clone)]
pub struct OnPointerMoveModifier {
pub action: Arc<dyn Fn(f32, f32) + Send + Sync>,
}
impl ViewModifier for OnPointerMoveModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
let action = self.action.clone();
renderer.register_handler(
"pointermove",
std::sync::Arc::new(move |event| {
if let Event::PointerMove { x, y } = event {
(action)(x, y);
}
}),
);
}
}
#[derive(Clone)]
pub struct OnPointerDownModifier {
pub action: Arc<dyn Fn() + Send + Sync>,
}
impl ViewModifier for OnPointerDownModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
let action = self.action.clone();
renderer.register_handler(
"pointerdown",
std::sync::Arc::new(move |event| {
if let Event::PointerDown { .. } = event {
(action)();
}
}),
);
}
}
#[derive(Clone)]
pub struct OnPointerUpModifier {
pub action: Arc<dyn Fn() + Send + Sync>,
}
impl ViewModifier for OnPointerUpModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
let action = self.action.clone();
renderer.register_handler(
"pointerup",
std::sync::Arc::new(move |event| {
if let Event::PointerUp { .. } = event {
(action)();
}
}),
);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ForegroundColorModifier {
pub color: [f32; 4],
}
impl ViewModifier for ForegroundColorModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ClipModifier;
impl ViewModifier for ClipModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.push_clip_rect(rect);
}
fn post_render(&self, renderer: &mut dyn Renderer, _rect: Rect) {
renderer.pop_clip_rect();
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BorderModifier {
pub color: [f32; 4],
pub width: f32,
}
impl ViewModifier for BorderModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.stroke_rect(rect, self.color, self.width);
}
}
#[doc(hidden)]
pub enum Never {}
impl View for Never {
type Body = Never;
fn body(self) -> Never {
unreachable!()
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct EmptyView;
impl View for EmptyView {
type Body = Never;
fn body(self) -> Self::Body {
unreachable!()
}
fn render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
fn intrinsic_size(&self, _renderer: &mut dyn Renderer, _proposal: SizeProposal) -> Size {
Size {
width: 0.0,
height: 0.0,
}
}
}
#[derive(Clone)]
pub struct ModifiedView<V, M> {
view: V,
modifier: M,
}
impl<V: View, M: ViewModifier> ModifiedView<V, M> {
#[doc(hidden)]
pub fn new(view: V, modifier: M) -> Self {
Self { view, modifier }
}
}
impl<V: View, M: ViewModifier> View for ModifiedView<V, M> {
type Body = ModifiedView<V::Body, M>;
fn body(self) -> Self::Body {
ModifiedView {
view: self.view.body(),
modifier: self.modifier.clone(),
}
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
self.modifier.render_view(&self.view, renderer, rect);
}
fn intrinsic_size(&self, renderer: &mut dyn Renderer, proposal: SizeProposal) -> Size {
self.modifier.measure_view(&self.view, renderer, proposal)
}
fn flex_weight(&self) -> f32 {
self.modifier.child_flex_weight(&self.view)
}
fn layout(&self) -> Option<&dyn layout::LayoutView> {
self.modifier.layout().or_else(|| self.view.layout())
}
}
pub trait ViewModifier: Send + Clone {
fn modify<V: View>(self, content: V) -> impl View;
fn render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
fn post_render(&self, _renderer: &mut dyn Renderer, _rect: Rect) {}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
self.render(renderer, rect);
let child_rect = self.transform_rect(rect);
view.render(renderer, child_rect);
self.post_render(renderer, rect);
}
fn transform_rect(&self, rect: Rect) -> Rect {
rect
}
fn transform_proposal(&self, proposal: SizeProposal) -> SizeProposal {
proposal
}
fn transform_size(&self, size: Size) -> Size {
size
}
fn measure_view<V: View>(
&self,
view: &V,
renderer: &mut dyn Renderer,
proposal: SizeProposal,
) -> Size {
let child_proposal = self.transform_proposal(proposal);
let child_size = view.intrinsic_size(renderer, child_proposal);
self.transform_size(child_size)
}
fn child_flex_weight<V: View>(&self, view: &V) -> f32 {
view.flex_weight()
}
fn layout(&self) -> Option<&dyn layout::LayoutView> {
None
}
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct TelemetryData {
pub frame_time_ms: f32,
pub p99_frame_time_ms: f32,
pub frame_jitter_ms: f32,
pub hardware_stall_detected: bool,
pub input_time_ms: f32,
pub state_flush_time_ms: f32,
pub layout_time_ms: f32,
pub draw_time_ms: f32,
pub gpu_submit_time_ms: f32,
pub draw_calls: u32,
pub vertices: u32,
pub berserker_rage: f32,
pub vram_usage_mb: f32,
pub vram_textures_mb: f32,
pub vram_buffers_mb: f32,
pub vram_pipelines_mb: f32,
pub vram_exhausted: bool,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct FrameBudget {
pub target_ms: f32,
pub allow_degradation: bool,
}
impl Default for FrameBudget {
fn default() -> Self {
Self {
target_ms: 16.0,
allow_degradation: true,
}
}
}
pub trait ElapsedTime {
fn elapsed_time(&self) -> f32;
fn delta_time(&self) -> f32;
}
pub trait Renderer: ElapsedTime + Send {
fn request_redraw(&mut self) {}
fn is_over_budget(&self) -> bool {
false
}
fn fill_rect(&mut self, rect: Rect, color: [f32; 4]);
fn fill_rounded_rect(&mut self, rect: Rect, radius: f32, color: [f32; 4]);
fn fill_ellipse(&mut self, rect: Rect, color: [f32; 4]);
fn draw_3d_cube(&mut self, _rect: Rect, _color: [f32; 4], _rotation: [f32; 3]) {}
fn stroke_rect(&mut self, rect: Rect, color: [f32; 4], stroke_width: f32);
fn stroke_rounded_rect(&mut self, rect: Rect, radius: f32, color: [f32; 4], stroke_width: f32);
fn stroke_ellipse(&mut self, rect: Rect, color: [f32; 4], stroke_width: f32);
fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: [f32; 4], stroke_width: f32);
fn fill_polygon(&mut self, _vertices: &[[f32; 2]], _color: [f32; 4]) {}
fn stroke_polygon(&mut self, _vertices: &[[f32; 2]], _color: [f32; 4], _stroke_width: f32) {}
fn draw_text(&mut self, text: &str, x: f32, y: f32, size: f32, color: [f32; 4]);
fn measure_text(&mut self, text: &str, size: f32) -> (f32, f32);
fn draw_texture(&mut self, _texture_id: u32, _rect: Rect) {}
fn draw_image(&mut self, _image_name: &str, _rect: Rect) {}
fn load_image(&mut self, _name: &str, _data: &[u8]) {}
fn prewarm_vram(&mut self, _assets: Vec<(String, Vec<u8>)>) {}
fn get_pointer_position(&self) -> [f32; 2] {
[0.0, 0.0]
}
fn upload_data_texture(&mut self, _id: &str, _data: &[f32], _width: u32, _height: u32) {}
fn draw_heatmap(&mut self, _texture_id: &str, _rect: Rect, _palette: &str) {}
fn draw_mesh(&mut self, _mesh: &Mesh, _color: [f32; 4], _transform: glam::Mat4) {}
fn draw_linear_gradient(
&mut self,
_rect: Rect,
_start_color: [f32; 4],
_end_color: [f32; 4],
_angle: f32,
) {
}
fn draw_radial_gradient(
&mut self,
_rect: Rect,
_inner_color: [f32; 4],
_outer_color: [f32; 4],
) {
}
fn draw_drop_shadow(
&mut self,
_rect: Rect,
_radius: f32,
_color: [f32; 4],
_blur: f32,
_spread: f32,
) {
}
fn stroke_dashed_rounded_rect(
&mut self,
_rect: Rect,
_radius: f32,
_color: [f32; 4],
_width: f32,
_dash: f32,
_gap: f32,
) {
}
fn draw_9slice(
&mut self,
_image_name: &str,
_rect: Rect,
_left: f32,
_top: f32,
_right: f32,
_bottom: f32,
) {
}
fn push_clip_rect(&mut self, _rect: Rect) {}
fn pop_clip_rect(&mut self) {}
fn current_clip_rect(&self) -> Rect {
Rect::new(-10000.0, -10000.0, 20000.0, 20000.0)
}
fn push_opacity(&mut self, _opacity: f32) {}
fn pop_opacity(&mut self) {}
fn set_theme(&mut self, _theme: ColorTheme) {}
fn set_rage(&mut self, _rage: f32) {}
fn set_berserker_mode(&mut self, _state: BerserkerMode) {}
fn trigger_shatter_event(&mut self, _origin: [f32; 2], _force: f32) {}
fn set_scene(&mut self, _scene: &str) {}
fn capture_png(&mut self) -> Vec<u8> {
Vec::new()
}
fn print(&mut self) {}
fn set_scene_preset(&mut self, _preset: u32) {}
fn bifrost(&mut self, _rect: Rect, _blur: f32, _saturation: f32, _opacity: f32) {}
fn gungnir(&mut self, _rect: Rect, _color: [f32; 4], _radius: f32, _intensity: f32) {}
fn mani_glow(&mut self, _rect: Rect, _color: [f32; 4], _radius: f32) {}
fn push_mjolnir_slice(&mut self, _angle: f32, _offset: f32) {}
fn pop_mjolnir_slice(&mut self) {}
fn memoize(&mut self, id: u64, data_hash: u64, render_fn: &dyn Fn(&mut dyn Renderer));
fn mjolnir_shatter(&mut self, _rect: Rect, _pieces: u32, _force: f32, _color: [f32; 4]) {}
fn mjolnir_fluid_shatter(&mut self, _rect: Rect, _pieces: u32, _force: f32, _color: [f32; 4]) {}
fn draw_mjolnir_bolt(&mut self, _from: [f32; 2], _to: [f32; 2], _color: [f32; 4]) {}
fn set_aria_role(&mut self, _role: &str) {}
fn set_aria_label(&mut self, _label: &str) {}
fn register_shared_element(&mut self, _id: &str, _rect: Rect) {}
fn set_key(&mut self, _key: &str) {}
fn get_telemetry(&self) -> TelemetryData {
TelemetryData::default()
}
fn push_shadow(&mut self, _radius: f32, _color: [f32; 4], _offset: [f32; 2]) {}
fn pop_shadow(&mut self) {}
fn push_vnode(&mut self, _rect: Rect, _name: &'static str) {}
fn pop_vnode(&mut self) {}
fn register_handler(
&mut self,
_event_type: &str,
_handler: std::sync::Arc<dyn Fn(Event) + Send + Sync>,
) {
}
fn set_z_index(&mut self, _z: f32) {}
fn get_z_index(&self) -> f32 {
0.0
}
fn load_svg(&mut self, _name: &str, _svg_data: &[u8]) {}
fn draw_svg(&mut self, _name: &str, _rect: Rect) {}
fn push_transform(&mut self, _translation: [f32; 2], _scale: [f32; 2], _rotation: f32) {}
fn pop_transform(&mut self) {}
fn query_layout(&self, _node_id: scene_graph::NodeId) -> Option<Rect> {
None
}
fn set_debug_layout(&mut self, _enabled: bool) {}
fn get_debug_layout(&self) -> bool {
false
}
}
pub mod accessibility {
pub fn relative_luminance(color: [f32; 4]) -> f32 {
let f = |c: f32| {
if c <= 0.03928 {
c / 12.92
} else {
((c + 0.055) / 1.055).powf(2.4)
}
};
0.2126 * f(color[0]) + 0.7152 * f(color[1]) + 0.0722 * f(color[2])
}
pub fn contrast_ratio(c1: [f32; 4], c2: [f32; 4]) -> f32 {
let l1 = relative_luminance(c1);
let l2 = relative_luminance(c2);
let (light, dark) = if l1 > l2 { (l1, l2) } else { (l2, l1) };
(light + 0.05) / (dark + 0.05)
}
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
)]
pub enum RenderTier {
Tier1GPU = 0,
Tier2GPU = 1,
Tier3Fallback = 2,
}
use bytemuck::{Pod, Zeroable};
#[repr(C)]
#[derive(Copy, Clone, Debug, Pod, Zeroable, serde::Serialize, serde::Deserialize)]
pub struct ColorTheme {
pub primary_neon: [f32; 4], pub shatter_neon: [f32; 4],
pub glass_base: [f32; 4],
pub glass_edge: [f32; 4],
pub rune_glow: [f32; 4],
pub ember_core: [f32; 4],
pub background_deep: [f32; 4],
pub mani_glow: [f32; 4], pub glass_blur_strength: f32,
pub shatter_edge_width: f32,
pub neon_bloom_radius: f32,
pub rune_opacity: f32,
}
impl ColorTheme {
pub fn asgard() -> Self {
Self {
primary_neon: [0.0, 1.0, 0.95, 1.2],
shatter_neon: [1.0, 0.0, 0.75, 1.5],
glass_base: [0.04, 0.04, 0.06, 0.82],
glass_edge: [0.0, 0.45, 0.55, 0.6],
rune_glow: [0.75, 0.98, 1.0, 0.9],
ember_core: [0.95, 0.12, 0.12, 1.0],
background_deep: [0.01, 0.01, 0.03, 1.0],
mani_glow: [0.7, 0.9, 1.0, 0.05],
glass_blur_strength: 0.6,
shatter_edge_width: 1.8,
neon_bloom_radius: 0.022,
rune_opacity: 0.55,
}
}
pub fn midgard() -> Self {
Self {
primary_neon: [0.2, 0.4, 0.6, 1.0], shatter_neon: [0.5, 0.5, 0.5, 1.0], glass_base: [0.1, 0.12, 0.15, 1.0], glass_edge: [0.3, 0.35, 0.4, 1.0], rune_glow: [0.8, 0.8, 0.8, 0.0], ember_core: [0.5, 0.5, 0.5, 1.0],
background_deep: [0.05, 0.05, 0.07, 1.0],
mani_glow: [0.0, 0.0, 0.0, 0.0], glass_blur_strength: 0.0, shatter_edge_width: 1.0,
neon_bloom_radius: 0.0,
rune_opacity: 0.0,
}
}
pub fn cyberpunk_viking() -> Self {
Self::asgard()
}
pub fn vibrant_glass() -> Self {
Self {
primary_neon: [0.0, 1.0, 0.95, 1.2],
shatter_neon: [1.0, 0.0, 0.75, 1.5],
glass_base: [0.55, 0.6, 0.7, 0.08], glass_edge: [0.7, 0.85, 1.0, 0.45], rune_glow: [0.75, 0.98, 1.0, 0.9],
ember_core: [1.0, 0.4, 0.1, 1.0],
background_deep: [0.05, 0.05, 0.1, 1.0],
mani_glow: [0.7, 0.9, 1.0, 0.05],
glass_blur_strength: 0.9,
shatter_edge_width: 1.8,
neon_bloom_radius: 0.022,
rune_opacity: 0.55,
}
}
}
impl Default for ColorTheme {
fn default() -> Self {
Self::vibrant_glass()
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Pod, Zeroable, serde::Serialize, serde::Deserialize)]
pub struct SceneUniforms {
pub view: glam::Mat4,
pub proj: glam::Mat4,
pub time: f32,
pub delta_time: f32,
pub resolution: [f32; 2],
pub mouse: [f32; 2],
pub mouse_velocity: [f32; 2],
pub shatter_origin: [f32; 2],
pub shatter_time: f32,
pub shatter_force: f32,
pub berzerker_rage: f32,
pub berzerker_mode: u32,
pub scroll_offset: f32,
pub scale_factor: f32,
pub scene_type: u32,
pub _pad: [f32; 3], }
pub const SCENE_AURORA: u32 = 0;
pub const SCENE_VOID: u32 = 1;
pub const SCENE_NEBULA: u32 = 2;
pub const SCENE_GLITCH: u32 = 3;
pub const SCENE_YGGDRASIL: u32 = 4;
impl SceneUniforms {
pub fn new(width: f32, height: f32) -> Self {
Self {
view: glam::Mat4::IDENTITY,
proj: glam::Mat4::orthographic_lh(0.0, width, height, 0.0, -100.0, 100.0),
time: 0.0,
delta_time: 0.016,
resolution: [width, height],
mouse: [0.5, 0.5],
mouse_velocity: [0.0, 0.0],
shatter_origin: [0.5, 0.5],
shatter_time: -100.0,
shatter_force: 0.0,
berzerker_rage: 0.0,
berzerker_mode: 0,
scroll_offset: 0.0,
scale_factor: 1.0,
scene_type: SCENE_AURORA,
_pad: [0.0; 3],
}
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Mesh {
pub vertices: Vec<[f32; 3]>,
pub normals: Vec<[f32; 3]>,
pub indices: Vec<u32>,
}
impl Mesh {
pub fn from_obj(data: &[u8]) -> anyhow::Result<Vec<Self>> {
let mut cursor = std::io::Cursor::new(data);
let (models, _) = tobj::load_obj_buf(&mut cursor, &tobj::LoadOptions::default(), |_| {
Ok((Vec::new(), Default::default()))
})?;
let mut meshes = Vec::new();
for m in models {
let mesh = m.mesh;
let vertices: Vec<[f32; 3]> = mesh
.positions
.chunks(3)
.map(|c| [c[0], c[1], c[2]])
.collect();
let normals = if mesh.normals.is_empty() {
vec![[0.0, 0.0, 1.0]; vertices.len()]
} else {
mesh.normals.chunks(3).map(|c| [c[0], c[1], c[2]]).collect()
};
meshes.push(Mesh {
vertices,
normals,
indices: mesh.indices,
});
}
Ok(meshes)
}
pub fn from_stl(data: &[u8]) -> anyhow::Result<Self> {
let mut cursor = std::io::Cursor::new(data);
let stl = stl_io::read_stl(&mut cursor)?;
let vertices: Vec<[f32; 3]> = stl.vertices.iter().map(|v| [v[0], v[1], v[2]]).collect();
let mut indices = Vec::new();
for face in stl.faces {
indices.push(face.vertices[0] as u32);
indices.push(face.vertices[1] as u32);
indices.push(face.vertices[2] as u32);
}
let normals = vec![[0.0, 0.0, 1.0]; vertices.len()];
Ok(Mesh {
vertices,
normals,
indices,
})
}
}
pub trait FrameRenderer<E = ()>: Renderer {
fn begin_frame(&mut self) -> E;
fn render_frame(&mut self) {
}
fn end_frame(&mut self, encoder: E);
}
use std::sync::Arc;
type SubscriberList<T> = Arc<std::sync::Mutex<Vec<Box<dyn Fn(&T) + Send + Sync>>>>;
#[derive(Clone)]
pub struct State<T: Clone + Send + Sync + 'static> {
swap: Arc<arc_swap::ArcSwap<T>>,
metadata_swap: Arc<arc_swap::ArcSwap<Option<agents::MutationMetadata>>>,
#[cfg(not(target_arch = "wasm32"))]
tvar: Arc<stm::TVar<T>>,
#[cfg(not(target_arch = "wasm32"))]
metadata_tvar: Arc<stm::TVar<Option<agents::MutationMetadata>>>,
subscribers: SubscriberList<T>,
version: Arc<std::sync::atomic::AtomicU64>,
resolution: agents::ConflictResolution,
}
impl<T: Clone + Send + Sync + 'static> State<T> {
pub fn new(value: T) -> Self {
#[cfg(not(target_arch = "wasm32"))]
let tvar = Arc::new(stm::TVar::new(value.clone()));
#[cfg(not(target_arch = "wasm32"))]
let metadata_tvar = Arc::new(stm::TVar::new(None));
Self {
swap: Arc::new(arc_swap::ArcSwap::from_pointee(value)),
metadata_swap: Arc::new(arc_swap::ArcSwap::new(Arc::new(None))),
#[cfg(not(target_arch = "wasm32"))]
tvar,
#[cfg(not(target_arch = "wasm32"))]
metadata_tvar,
subscribers: Arc::new(std::sync::Mutex::new(Vec::new())),
version: Arc::new(std::sync::atomic::AtomicU64::new(0)),
resolution: agents::ConflictResolution::default(),
}
}
pub fn with_resolution(mut self, resolution: agents::ConflictResolution) -> Self {
self.resolution = resolution;
self
}
pub fn get(&self) -> T {
(**self.swap.load()).clone()
}
pub fn set(&self, value: T) {
#[cfg(not(target_arch = "wasm32"))]
let (was_skipped, final_val, final_meta) = stm::atomically(|tx| {
let new_meta = agents::get_current_mutation_metadata();
let existing_meta = self.metadata_tvar.read(tx)?;
let mut skip = false;
if self.resolution == agents::ConflictResolution::PriorityWins
&& let (Some(new_m), Some(old_m)) = (new_meta, existing_meta)
&& new_m.priority < old_m.priority
{
skip = true;
}
if !skip {
self.tvar.write(tx, value.clone())?;
self.metadata_tvar.write(tx, new_meta)?;
Ok((false, value.clone(), new_meta))
} else {
Ok((true, self.tvar.read(tx)?, existing_meta))
}
});
#[cfg(target_arch = "wasm32")]
let (was_skipped, final_val, final_meta) =
(false, value, agents::get_current_mutation_metadata());
if was_skipped {
if let (Some(new_m), Some(old_m)) =
(agents::get_current_mutation_metadata(), final_meta)
{
agents::notify_conflict(agents::ConflictEvent {
agent_id: new_m.agent_id,
priority: new_m.priority,
existing_agent_id: old_m.agent_id,
existing_priority: old_m.priority,
timestamp_ms: new_m.timestamp_ms,
});
}
return;
}
self.swap.store(Arc::new(final_val.clone()));
self.metadata_swap.store(Arc::new(final_meta));
self.version
.fetch_add(1, std::sync::atomic::Ordering::Release);
let subs = Arc::clone(&self.subscribers);
if crate::is_batching() {
crate::enqueue_batch_task(Box::new(move || {
let s = subs.lock().unwrap();
for cb in s.iter() {
cb(&final_val);
}
}));
} else {
let s = subs.lock().unwrap();
for cb in s.iter() {
cb(&final_val);
}
}
}
pub fn mutate<F: Fn(&T) -> T>(&self, f: F) {
#[cfg(not(target_arch = "wasm32"))]
{
let (was_skipped, final_val, final_meta) = stm::atomically(|tx| {
let new_meta = agents::get_current_mutation_metadata();
let existing_meta = self.metadata_tvar.read(tx)?;
let mut skip = false;
if self.resolution == agents::ConflictResolution::PriorityWins
&& let (Some(new_m), Some(old_m)) = (new_meta, existing_meta)
&& new_m.priority < old_m.priority
{
skip = true;
}
if !skip {
let current = self.tvar.read(tx)?;
let next = f(¤t);
self.tvar.write(tx, next.clone())?;
self.metadata_tvar.write(tx, new_meta)?;
Ok((false, next, new_meta))
} else {
Ok((true, self.tvar.read(tx)?, existing_meta))
}
});
if was_skipped {
if let (Some(new_m), Some(old_m)) =
(agents::get_current_mutation_metadata(), final_meta)
{
agents::notify_conflict(agents::ConflictEvent {
agent_id: new_m.agent_id,
priority: new_m.priority,
existing_agent_id: old_m.agent_id,
existing_priority: old_m.priority,
timestamp_ms: new_m.timestamp_ms,
});
}
return;
}
self.swap.store(Arc::new(final_val.clone()));
self.metadata_swap.store(Arc::new(final_meta));
self.version
.fetch_add(1, std::sync::atomic::Ordering::Release);
let subs = Arc::clone(&self.subscribers);
if crate::is_batching() {
crate::enqueue_batch_task(Box::new(move || {
let s = subs.lock().unwrap();
for cb in s.iter() {
cb(&final_val);
}
}));
} else {
let s = subs.lock().unwrap();
for cb in s.iter() {
cb(&final_val);
}
}
}
#[cfg(target_arch = "wasm32")]
{
self.set(f(&self.get()));
}
}
pub fn version(&self) -> u64 {
self.version.load(std::sync::atomic::Ordering::Acquire)
}
pub fn subscribe<F: Fn(&T) + Send + Sync + 'static>(&self, callback: F) {
self.subscribers.lock().unwrap().push(Box::new(callback));
}
}
use crate::runtime::NodeStateSnapshot;
use std::sync::OnceLock;
use std::sync::atomic::{AtomicBool, Ordering};
pub static SYSTEM_STATE: OnceLock<Arc<arc_swap::ArcSwap<KnowledgeState>>> = OnceLock::new();
#[cfg(not(target_arch = "wasm32"))]
static KNOWLEDGE_TVAR: OnceLock<stm::TVar<KnowledgeState>> = OnceLock::new();
static IS_BATCHING: AtomicBool = AtomicBool::new(false);
pub static IS_RENDERING: AtomicBool = AtomicBool::new(false);
pub static LAYOUT_DIRTY: AtomicBool = AtomicBool::new(false);
type BatchQueue = OnceLock<std::sync::Mutex<Vec<Box<dyn FnOnce() + Send + Sync>>>>;
static BATCH_QUEUE: BatchQueue = OnceLock::new();
static STATE_WRITE_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(());
pub fn is_batching() -> bool {
IS_BATCHING.load(Ordering::Acquire)
}
pub fn is_rendering() -> bool {
IS_RENDERING.load(Ordering::Acquire)
}
pub fn begin_render_phase() {
IS_RENDERING.store(true, Ordering::Release);
}
pub fn end_render_phase() {
IS_RENDERING.store(false, Ordering::Release);
}
pub fn enqueue_batch_task(task: Box<dyn FnOnce() + Send + Sync>) {
let mut queue = BATCH_QUEUE
.get_or_init(|| std::sync::Mutex::new(Vec::new()))
.lock()
.unwrap();
queue.push(task);
}
pub fn batch<F: FnOnce()>(f: F) {
if IS_BATCHING.swap(true, Ordering::AcqRel) {
f();
return;
}
f();
IS_BATCHING.store(false, Ordering::Release);
let mut queue = BATCH_QUEUE
.get_or_init(|| std::sync::Mutex::new(Vec::new()))
.lock()
.unwrap();
let tasks: Vec<_> = queue.drain(..).collect();
drop(queue);
for task in tasks {
task();
}
}
pub fn get_system_state() -> Arc<arc_swap::ArcSwap<KnowledgeState>> {
SYSTEM_STATE
.get_or_init(|| Arc::new(arc_swap::ArcSwap::from_pointee(KnowledgeState::default())))
.clone()
}
pub fn load_system_state() -> arc_swap::Guard<Arc<KnowledgeState>> {
get_system_state().load()
}
pub fn update_system_state<F>(f: F)
where
F: Fn(&KnowledgeState) -> KnowledgeState,
{
let _lock = STATE_WRITE_MUTEX.lock().unwrap();
if is_rendering() {
log::warn!(
"LAYOUT THRASH DETECTED: System state mutated during render phase. This may trigger redundant layout passes and impact performance."
);
}
LAYOUT_DIRTY.store(true, Ordering::SeqCst);
let swap = get_system_state();
let current = swap.load();
let new_state = Arc::new(f(¤t));
swap.store(Arc::clone(&new_state));
#[cfg(not(target_arch = "wasm32"))]
{
let tvar = KNOWLEDGE_TVAR.get_or_init(|| stm::TVar::new((*new_state).clone()));
stm::atomically(|tx| tvar.write(tx, (*new_state).clone()));
}
}
pub fn transact_system_state<F>(f: F)
where
F: Fn(&KnowledgeState) -> KnowledgeState,
{
let _lock = STATE_WRITE_MUTEX.lock().unwrap();
#[cfg(not(target_arch = "wasm32"))]
{
if is_rendering() {
log::warn!(
"LAYOUT THRASH DETECTED: System state mutated during render phase. This may trigger redundant layout passes and impact performance."
);
}
let tvar = KNOWLEDGE_TVAR
.get_or_init(|| stm::TVar::new((**get_system_state().load()).clone()))
.clone();
let new_state = stm::atomically(move |tx| {
let current = tvar.read(tx)?;
let next = f(¤t);
tvar.write(tx, next.clone())?;
Ok(next)
});
get_system_state().store(Arc::new(new_state));
}
#[cfg(target_arch = "wasm32")]
{
if is_rendering() {
log::warn!(
"LAYOUT THRASH DETECTED: System state mutated during render phase. This may trigger redundant layout passes and impact performance."
);
}
update_system_state(f);
}
}
impl KnowledgeState {
pub fn new() -> Self {
Self::default()
}
pub fn set_component_state<T: 'static + Send + Sync>(&mut self, id: u64, state: T) {
self.component_states
.insert(id, Arc::new(std::sync::RwLock::new(state)));
}
pub fn get_component_state<T: 'static + Send + Sync>(
&self,
id: u64,
) -> Option<Arc<std::sync::RwLock<T>>> {
let lock = self.component_states.get(&id)?;
let any_ref = lock.read().ok()?;
if any_ref.is::<T>() {
drop(any_ref);
let cloned: Arc<std::sync::RwLock<dyn std::any::Any + Send + Sync>> = Arc::clone(lock);
Some(unsafe {
let raw = Arc::into_raw(cloned);
Arc::from_raw(raw as *const std::sync::RwLock<T>)
})
} else {
None
}
}
pub fn remember(&mut self, fragment: KnowledgeFragment) {
self.fragments.insert(fragment.id.clone(), fragment);
}
pub fn process_query(&mut self, query: &str) {
let query_lower = query.to_lowercase();
let mut results: Vec<(f32, String)> = self
.fragments
.iter()
.map(|(id, frag)| {
let mut score = 0.0;
if frag.summary.to_lowercase().contains(&query_lower) {
score += 1.0;
}
if frag.source.to_lowercase().contains(&query_lower) {
score += 0.5;
}
(score, id.clone())
})
.filter(|(score, _)| *score > 0.0)
.collect();
results.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
self.last_query_results = results.into_iter().map(|(_, id)| id).take(5).collect();
}
pub fn snapshot(&self) -> Vec<NodeStateSnapshot> {
let mut snapshots = Vec::new();
for frag in self.fragments.values() {
if let Ok(val) = serde_json::to_value(frag) {
snapshots.push(NodeStateSnapshot { id: 0, state: val });
}
}
snapshots
}
}
#[derive(Clone)]
pub struct Binding<T: Clone + Send + Sync + 'static> {
swap: Arc<arc_swap::ArcSwap<T>>,
#[cfg(not(target_arch = "wasm32"))]
tvar: Arc<stm::TVar<T>>,
version: Arc<std::sync::atomic::AtomicU64>,
}
impl<T: Clone + Send + Sync + 'static> Binding<T> {
pub fn from_state(state: &State<T>) -> Self {
Self {
swap: Arc::clone(&state.swap),
#[cfg(not(target_arch = "wasm32"))]
tvar: Arc::clone(&state.tvar),
version: Arc::clone(&state.version),
}
}
pub fn get(&self) -> T {
(**self.swap.load()).clone()
}
pub fn set(&self, value: T) {
self.swap.store(Arc::new(value.clone()));
#[cfg(not(target_arch = "wasm32"))]
{
let tvar = Arc::clone(&self.tvar);
let v = value.clone();
stm::atomically(move |tx| tvar.write(tx, v.clone()));
}
self.version
.fetch_add(1, std::sync::atomic::Ordering::Release);
}
pub fn version(&self) -> u64 {
self.version.load(std::sync::atomic::Ordering::Acquire)
}
}
#[cfg(not(target_arch = "wasm32"))]
pub fn transact_pair<A, B, F>(state_a: &State<A>, state_b: &State<B>, f: F)
where
A: Clone + Send + Sync + 'static,
B: Clone + Send + Sync + 'static,
F: Fn(&A, &B) -> (A, B),
{
let tvar_a = Arc::clone(&state_a.tvar);
let tvar_b = Arc::clone(&state_b.tvar);
let (new_a, new_b) = stm::atomically(move |tx| {
let a = tvar_a.read(tx)?;
let b = tvar_b.read(tx)?;
let (na, nb) = f(&a, &b);
tvar_a.write(tx, na.clone())?;
tvar_b.write(tx, nb.clone())?;
Ok((na, nb))
});
state_a.swap.store(Arc::new(new_a.clone()));
state_b.swap.store(Arc::new(new_b.clone()));
state_a
.version
.fetch_add(1, std::sync::atomic::Ordering::Release);
state_b
.version
.fetch_add(1, std::sync::atomic::Ordering::Release);
let subs_a = Arc::clone(&state_a.subscribers);
let subs_b = Arc::clone(&state_b.subscribers);
if crate::is_batching() {
crate::enqueue_batch_task(Box::new(move || {
{
let s = subs_a.lock().unwrap();
for cb in s.iter() {
cb(&new_a);
}
}
{
let s = subs_b.lock().unwrap();
for cb in s.iter() {
cb(&new_b);
}
}
}));
} else {
{
let s = subs_a.lock().unwrap();
for cb in s.iter() {
cb(&new_a);
}
}
{
let s = subs_b.lock().unwrap();
for cb in s.iter() {
cb(&new_b);
}
}
}
}
use std::any::TypeId;
use std::sync::Mutex;
pub(crate) static ENVIRONMENT: OnceLock<
Mutex<HashMap<TypeId, Box<dyn std::any::Any + Send + Sync>>>,
> = OnceLock::new();
pub trait EnvKey: 'static + Send + Sync {
type Value: Clone + Send + Sync + 'static;
fn default_value() -> Self::Value;
}
pub struct YggdrasilKey;
impl EnvKey for YggdrasilKey {
type Value = YggdrasilTokens;
fn default_value() -> Self::Value {
default_tokens()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Appearance {
Light,
Dark,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Orientation {
Horizontal,
Vertical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum Alignment {
#[default]
Center,
Leading,
Trailing,
Top,
Bottom,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum Distribution {
#[default]
Fill,
Center,
Leading,
Trailing,
SpaceBetween,
SpaceAround,
SpaceEvenly,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Color {
pub r: f32,
pub g: f32,
pub b: f32,
pub a: f32,
}
impl Color {
pub const BLACK: Color = Color {
r: 0.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
pub const WHITE: Color = Color {
r: 1.0,
g: 1.0,
b: 1.0,
a: 1.0,
};
pub const TRANSPARENT: Color = Color {
r: 0.0,
g: 0.0,
b: 0.0,
a: 0.0,
};
pub const RED: Color = Color {
r: 1.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
pub const GREEN: Color = Color {
r: 0.0,
g: 1.0,
b: 0.0,
a: 1.0,
};
pub const BLUE: Color = Color {
r: 0.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
pub const VIKING_GOLD: Color = Color {
r: 1.0,
g: 0.84,
b: 0.0,
a: 1.0,
};
pub const MAGENTA_LIQUID: Color = Color {
r: 1.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
pub const TACTICAL_OBSIDIAN: Color = Color {
r: 0.05,
g: 0.05,
b: 0.07,
a: 1.0,
};
pub fn relative_luminance(&self) -> f32 {
fn res(c: f32) -> f32 {
if c <= 0.03928 {
c / 12.92
} else {
((c + 0.055) / 1.055).powf(2.4)
}
}
0.2126 * res(self.r) + 0.7152 * res(self.g) + 0.0722 * res(self.b)
}
pub fn contrast_ratio(&self, other: &Color) -> f32 {
let l1 = self.relative_luminance();
let l2 = other.relative_luminance();
if l1 > l2 {
(l1 + 0.05) / (l2 + 0.05)
} else {
(l2 + 0.05) / (l1 + 0.05)
}
}
pub const CYAN: Color = Color {
r: 0.0,
g: 1.0,
b: 1.0,
a: 1.0,
};
pub const YELLOW: Color = Color {
r: 1.0,
g: 1.0,
b: 0.0,
a: 1.0,
};
pub const MAGENTA: Color = Color {
r: 1.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
pub const GRAY: Color = Color {
r: 0.5,
g: 0.5,
b: 0.5,
a: 1.0,
};
pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
Self { r, g, b, a }
}
pub fn as_array(&self) -> [f32; 4] {
[self.r, self.g, self.b, self.a]
}
}
impl View for Color {
type Body = Never;
fn body(self) -> Self::Body {
unreachable!()
}
fn render(&self, renderer: &mut dyn Renderer, rect: Rect) {
renderer.fill_rect(rect, self.as_array());
}
}
pub struct AppearanceKey;
impl EnvKey for AppearanceKey {
type Value = Appearance;
fn default_value() -> Self::Value {
Appearance::Dark }
}
pub struct StyleResolver;
impl StyleResolver {
pub fn color(key: &str) -> String {
let tokens = Environment::<YggdrasilKey>::new().get();
let appearance = Environment::<AppearanceKey>::new().get();
let is_dark = appearance == Appearance::Dark;
tokens
.get_color(key, is_dark)
.unwrap_or_else(|| "#FF00FF".to_string()) }
pub fn get<T: FromStr>(category: &str, key: &str) -> Option<T> {
let tokens = Environment::<YggdrasilKey>::new().get();
let appearance = Environment::<AppearanceKey>::new().get();
let is_dark = appearance == Appearance::Dark;
tokens.get(category, key, is_dark)
}
}
pub fn default_tokens() -> YggdrasilTokens {
let mut tokens = YggdrasilTokens::new();
tokens.color.insert(
"background".to_string(),
TokenValue::Single {
value: "#000000".to_string(), },
);
tokens.color.insert(
"primary".to_string(),
TokenValue::Single {
value: "#00FFFF".to_string(), },
);
tokens.color.insert(
"secondary".to_string(),
TokenValue::Single {
value: "#FF00FF".to_string(), },
);
tokens.color.insert(
"surface".to_string(),
TokenValue::Adaptive {
light: "#FFFFFF".to_string(),
dark: "#121212".to_string(),
},
);
tokens.color.insert(
"text".to_string(),
TokenValue::Adaptive {
light: "#000000".to_string(),
dark: "#FFFFFF".to_string(),
},
);
tokens.bifrost.insert(
"blur".to_string(),
TokenValue::Single {
value: "25.0".to_string(),
},
);
tokens.bifrost.insert(
"saturation".to_string(),
TokenValue::Single {
value: "1.2".to_string(),
},
);
tokens.bifrost.insert(
"opacity".to_string(),
TokenValue::Single {
value: "0.65".to_string(),
},
);
tokens.gungnir.insert(
"intensity".to_string(),
TokenValue::Single {
value: "1.0".to_string(),
},
);
tokens.gungnir.insert(
"radius".to_string(),
TokenValue::Single {
value: "15.0".to_string(),
},
);
tokens.mjolnir.insert(
"clip_angle".to_string(),
TokenValue::Single {
value: "12.0".to_string(),
},
);
tokens.mjolnir.insert(
"border_width".to_string(),
TokenValue::Single {
value: "2.0".to_string(),
},
);
tokens.anim.insert(
"stiffness".to_string(),
TokenValue::Single {
value: "170.0".to_string(),
},
);
tokens.anim.insert(
"damping".to_string(),
TokenValue::Single {
value: "26.0".to_string(),
},
);
tokens.anim.insert(
"mass".to_string(),
TokenValue::Single {
value: "1.0".to_string(),
},
);
tokens.accessibility.insert(
"reduce_motion".to_string(),
TokenValue::Single {
value: "false".to_string(),
},
);
tokens
}
pub struct Environment<K: EnvKey> {
_marker: std::marker::PhantomData<K>,
}
impl<K: EnvKey> Default for Environment<K> {
fn default() -> Self {
Self::new()
}
}
impl<K: EnvKey> Environment<K> {
pub fn new() -> Self {
Self {
_marker: std::marker::PhantomData,
}
}
pub fn get(&self) -> K::Value {
if let Some(env_store) = ENVIRONMENT.get() {
let env_lock = env_store.lock().unwrap();
if let Some(val) = env_lock.get(&std::any::TypeId::of::<K>()) {
if let Some(typed_val) = val.downcast_ref::<K::Value>() {
return typed_val.clone();
} else {
log::warn!(
"Environment: Downcast failed for key type {:?}",
std::any::type_name::<K>()
);
}
} else {
log::debug!(
"Environment: Key not found: {:?}. Returning default.",
std::any::type_name::<K>()
);
}
} else {
log::debug!(
"Environment: Store not initialized. Key: {:?}. Returning default.",
std::any::type_name::<K>()
);
}
K::default_value()
}
}
pub mod env {
pub fn insert<K: super::EnvKey>(value: K::Value) {
let store = super::ENVIRONMENT
.get_or_init(|| std::sync::Mutex::new(std::collections::HashMap::new()));
let mut env_map = store.lock().unwrap();
env_map.insert(std::any::TypeId::of::<K>(), Box::new(value));
}
pub fn remove<K: super::EnvKey>() {
if let Some(store) = super::ENVIRONMENT.get() {
let mut env_map = store.lock().unwrap();
env_map.remove(&std::any::TypeId::of::<K>());
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Size {
pub width: f32,
pub height: f32,
}
impl Size {
pub const ZERO: Self = Self {
width: 0.0,
height: 0.0,
};
pub fn new(width: f32, height: f32) -> Self {
Self { width, height }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct EdgeInsets {
pub top: f32,
pub leading: f32,
pub bottom: f32,
pub trailing: f32,
}
impl EdgeInsets {
pub fn all(value: f32) -> Self {
Self {
top: value,
leading: value,
bottom: value,
trailing: value,
}
}
pub fn vertical(value: f32) -> Self {
Self {
top: value,
leading: 0.0,
bottom: value,
trailing: 0.0,
}
}
pub fn horizontal(value: f32) -> Self {
Self {
top: 0.0,
leading: value,
bottom: 0.0,
trailing: value,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FrameModifier {
pub width: Option<f32>,
pub height: Option<f32>,
}
impl Default for FrameModifier {
fn default() -> Self {
Self::new()
}
}
impl FrameModifier {
pub fn new() -> Self {
Self {
width: None,
height: None,
}
}
pub fn width(mut self, width: f32) -> Self {
self.width = Some(width);
self
}
pub fn height(mut self, height: f32) -> Self {
self.height = Some(height);
self
}
pub fn size(mut self, width: f32, height: f32) -> Self {
self.width = Some(width);
self.height = Some(height);
self
}
}
impl ViewModifier for FrameModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FlexModifier {
pub weight: f32,
}
impl ViewModifier for FlexModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn child_flex_weight<V: View>(&self, _view: &V) -> f32 {
self.weight
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct OffsetModifier {
pub x: f32,
pub y: f32,
}
impl OffsetModifier {
pub fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
}
impl ViewModifier for OffsetModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ZIndexModifier {
pub z_index: i32,
}
impl ZIndexModifier {
pub fn new(z_index: i32) -> Self {
Self { z_index }
}
}
impl ViewModifier for ZIndexModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct LayoutConstraints {
pub min_width: Option<f32>,
pub max_width: Option<f32>,
pub min_height: Option<f32>,
pub max_height: Option<f32>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LayoutModifier {
pub constraints: LayoutConstraints,
}
impl LayoutModifier {
pub fn new(constraints: LayoutConstraints) -> Self {
Self { constraints }
}
}
impl ViewModifier for LayoutModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SafeAreaModifier {
pub ignores: bool,
}
impl ViewModifier for SafeAreaModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ElevationModifier {
pub level: f32,
}
impl ViewModifier for ElevationModifier {
fn modify<V: View>(self, content: V) -> impl View {
ModifiedView::new(content, self)
}
fn render_view<V: View>(&self, view: &V, renderer: &mut dyn Renderer, rect: Rect) {
if self.level > 0.0 {
let radius = self.level * 2.0;
let offset_y = self.level * 0.5;
let shadow_color = [0.0, 0.0, 0.0, 0.3];
renderer.push_shadow(radius, shadow_color, [0.0, offset_y]);
view.render(renderer, rect);
renderer.pop_shadow();
} else {
view.render(renderer, rect);
}
}
}
pub mod layout {
use super::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LayoutKey {
pub view_hash: u64,
pub generation: u64,
}
pub struct LayoutCache {
pub safe_area: SafeArea,
size_cache: HashMap<(u64, u32, u32), Size>, generation: u64,
}
impl Default for LayoutCache {
fn default() -> Self {
Self::new()
}
}
impl LayoutCache {
pub fn new() -> Self {
Self {
safe_area: SafeArea::default(),
size_cache: HashMap::new(),
generation: 0,
}
}
pub fn generation(&self) -> u64 {
self.generation
}
pub fn invalidate(&mut self) {
self.generation = self.generation.wrapping_add(1);
}
pub fn is_valid(&self, key: LayoutKey, current_gen: u64) -> bool {
key.generation == current_gen && key.generation == self.generation
}
pub fn clear(&mut self) {
self.safe_area = SafeArea::default();
self.size_cache.clear();
}
pub fn get_size(&self, view_hash: u64, proposal: SizeProposal) -> Option<Size> {
let pw = (proposal.width.unwrap_or(-1.0) * 100.0) as u32;
let ph = (proposal.height.unwrap_or(-1.0) * 100.0) as u32;
self.size_cache.get(&(view_hash, pw, ph)).copied()
}
pub fn set_size(&mut self, view_hash: u64, proposal: SizeProposal, size: Size) {
let pw = (proposal.width.unwrap_or(-1.0) * 100.0) as u32;
let ph = (proposal.height.unwrap_or(-1.0) * 100.0) as u32;
self.size_cache.insert((view_hash, pw, ph), size);
}
pub fn invalidate_view(&mut self, view_hash: u64) {
self.size_cache.retain(|&(hash, _, _), _| hash != view_hash);
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SizeProposal {
pub width: Option<f32>,
pub height: Option<f32>,
}
impl SizeProposal {
pub fn unspecified() -> Self {
Self {
width: None,
height: None,
}
}
pub fn width(width: f32) -> Self {
Self {
width: Some(width),
height: None,
}
}
pub fn height(height: f32) -> Self {
Self {
width: None,
height: Some(height),
}
}
pub fn tight(width: f32, height: f32) -> Self {
Self {
width: Some(width),
height: Some(height),
}
}
pub fn new(width: Option<f32>, height: Option<f32>) -> Self {
Self { width, height }
}
}
pub trait LayoutView: Send {
fn size_that_fits(
&self,
proposal: SizeProposal,
subviews: &[&dyn LayoutView],
cache: &mut LayoutCache,
) -> Size;
fn place_subviews(
&self,
bounds: Rect,
subviews: &mut [&mut dyn LayoutView],
cache: &mut LayoutCache,
);
fn flex_weight(&self) -> f32 {
0.0
}
fn debug_layout(&self, indent: usize) -> String {
let prefix = " ".repeat(indent);
format!("{}LayoutView", prefix)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
pub struct EdgeInsets {
pub top: f32,
pub leading: f32,
pub bottom: f32,
pub trailing: f32,
}
impl EdgeInsets {
pub fn new(top: f32, leading: f32, bottom: f32, trailing: f32) -> Self {
Self {
top,
leading,
bottom,
trailing,
}
}
pub fn all(value: f32) -> Self {
Self {
top: value,
leading: value,
bottom: value,
trailing: value,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
pub struct SafeArea {
pub insets: EdgeInsets,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Rect {
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
}
impl Rect {
pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
Self {
x,
y,
width,
height,
}
}
pub fn inset(&self, amount: f32) -> Self {
Self {
x: self.x + amount,
y: self.y + amount,
width: (self.width - amount * 2.0).max(0.0),
height: (self.height - amount * 2.0).max(0.0),
}
}
pub fn offset(&self, dx: f32, dy: f32) -> Self {
Self {
x: self.x + dx,
y: self.y + dy,
..*self
}
}
pub fn zero() -> Self {
Self {
x: 0.0,
y: 0.0,
width: 0.0,
height: 0.0,
}
}
pub fn contains(&self, x: f32, y: f32) -> bool {
x >= self.x && x <= self.x + self.width && y >= self.y && y <= self.y + self.height
}
pub fn size(&self) -> Size {
Size {
width: self.width,
height: self.height,
}
}
pub fn split_horizontal(&self, n: usize) -> Vec<Rect> {
if n == 0 {
return vec![];
}
let item_width = self.width / n as f32;
(0..n)
.map(|i| Rect {
x: self.x + i as f32 * item_width,
y: self.y,
width: item_width,
height: self.height,
})
.collect()
}
pub fn split_vertical(&self, n: usize) -> Vec<Rect> {
if n == 0 {
return vec![];
}
let item_height = self.height / n as f32;
(0..n)
.map(|i| Rect {
x: self.x,
y: self.y + i as f32 * item_height,
width: self.width,
height: item_height,
})
.collect()
}
}
}
pub use layout::{LayoutCache, LayoutKey, LayoutView, Rect, SizeProposal};
pub mod agents;
pub mod animation;
pub mod gpu;
pub mod material;
pub mod runtime;
pub mod scene_graph;
pub mod sdf_shadow;
pub use scene_graph::{NodeId, bifrost_registry};
pub trait AssetManager: Send + Sync {
fn load_image(&self, url: &str) -> AssetState<Arc<Vec<u8>>>;
fn preload_image(&self, url: &str);
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum Event {
PointerDown {
x: f32,
y: f32,
button: u32,
},
PointerUp {
x: f32,
y: f32,
button: u32,
},
PointerMove {
x: f32,
y: f32,
},
PointerClick {
x: f32,
y: f32,
button: u32,
},
PointerEnter,
PointerLeave,
PointerWheel {
x: f32,
y: f32,
delta_x: f32,
delta_y: f32,
},
PointerDoubleClick {
x: f32,
y: f32,
button: u32,
},
DragStart {
x: f32,
y: f32,
button: u32,
},
DragMove {
x: f32,
y: f32,
},
DragEnd {
x: f32,
y: f32,
},
KeyDown {
key: String,
},
KeyUp {
key: String,
},
FocusIn,
FocusOut,
Copy,
Cut,
Paste(String),
Ime(String),
TouchStart {
x: f32,
y: f32,
touch_id: u64,
},
TouchMove {
x: f32,
y: f32,
touch_id: u64,
},
TouchEnd {
x: f32,
y: f32,
touch_id: u64,
},
}
impl Event {
pub fn name(&self) -> &'static str {
match self {
Self::PointerDown { .. } => "pointerdown",
Self::PointerUp { .. } => "pointerup",
Self::PointerMove { .. } => "pointermove",
Self::PointerClick { .. } => "pointerclick",
Self::PointerEnter => "pointerenter",
Self::PointerLeave => "pointerleave",
Self::PointerWheel { .. } => "pointerwheel",
Self::PointerDoubleClick { .. } => "pointerdoubleclick",
Self::DragStart { .. } => "dragstart",
Self::DragMove { .. } => "dragmove",
Self::DragEnd { .. } => "dragend",
Self::KeyDown { .. } => "keydown",
Self::KeyUp { .. } => "keyup",
Self::FocusIn => "focusin",
Self::FocusOut => "focusout",
Self::Copy => "copy",
Self::Cut => "cut",
Self::Paste(_) => "paste",
Self::Ime(_) => "ime",
Self::TouchStart { .. } => "touchstart",
Self::TouchMove { .. } => "touchmove",
Self::TouchEnd { .. } => "touchend",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EventResponse {
Handled,
Ignored,
}
pub struct DefaultAssetManager {
cache: AssetCache,
}
type AssetCache = Arc<arc_swap::ArcSwap<HashMap<String, AssetState<Arc<Vec<u8>>>>>>;
impl Default for DefaultAssetManager {
fn default() -> Self {
Self::new()
}
}
impl DefaultAssetManager {
pub fn new() -> Self {
Self {
cache: Arc::new(arc_swap::ArcSwap::from_pointee(HashMap::new())),
}
}
}
impl AssetManager for DefaultAssetManager {
fn load_image(&self, url: &str) -> AssetState<Arc<Vec<u8>>> {
if let Some(state) = self.cache.load().get(url) {
return state.clone();
}
self.cache.rcu(|map| {
let mut m = (**map).clone();
m.entry(url.to_string()).or_insert(AssetState::Loading);
m
});
AssetState::Loading
}
fn preload_image(&self, _url: &str) {}
}
use std::future::Future;
pub struct Suspense<T: Clone + Send + Sync + 'static> {
inner: State<AssetState<T>>,
}
impl<T: Clone + Send + Sync + 'static> Default for Suspense<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Clone + Send + Sync + 'static> Suspense<T> {
pub fn new() -> Self {
Self {
inner: State::new(AssetState::Loading),
}
}
pub fn new_async<F>(future: F) -> Self
where
F: Future<Output = Result<T, String>> + Send + 'static,
{
let suspense = Self::new();
let suspense_clone = suspense.clone();
#[cfg(not(target_arch = "wasm32"))]
{
if let Ok(handle) = tokio::runtime::Handle::try_current() {
handle.spawn(async move {
let result = future.await;
match result {
Ok(val) => suspense_clone.inner.set(AssetState::Ready(val)),
Err(err) => suspense_clone.inner.set(AssetState::Error(err)),
}
});
} else {
std::thread::spawn(move || {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(async {
let result = future.await;
match result {
Ok(val) => suspense_clone.inner.set(AssetState::Ready(val)),
Err(err) => suspense_clone.inner.set(AssetState::Error(err)),
}
});
});
}
}
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
{
wasm_bindgen_futures::spawn_local(async move {
let result = future.await;
match result {
Ok(val) => suspense_clone.inner.set(AssetState::Ready(val)),
Err(err) => suspense_clone.inner.set(AssetState::Error(err)),
}
});
}
suspense
}
pub fn ready(value: T) -> Self {
Self {
inner: State::new(AssetState::Ready(value)),
}
}
pub fn error(message: impl Into<String>) -> Self {
Self {
inner: State::new(AssetState::Error(message.into())),
}
}
pub fn get(&self) -> AssetState<T> {
self.inner.get()
}
pub fn get_ref(&self) -> AssetState<T> {
self.inner.get()
}
pub fn is_loading(&self) -> bool {
matches!(self.get(), AssetState::Loading)
}
pub fn is_ready(&self) -> bool {
matches!(self.get(), AssetState::Ready(_))
}
pub fn is_error(&self) -> bool {
matches!(self.get(), AssetState::Error(_))
}
pub fn ready_value(&self) -> Option<T> {
match self.get() {
AssetState::Ready(value) => Some(value),
_ => None,
}
}
pub fn error_message(&self) -> Option<String> {
match self.get() {
AssetState::Error(message) => Some(message),
_ => None,
}
}
pub fn subscribe<F: Fn(&AssetState<T>) + Send + Sync + 'static>(&self, callback: F) {
self.inner.subscribe(callback)
}
pub fn inner_state(&self) -> &State<AssetState<T>> {
&self.inner
}
}
impl<T: Clone + Send + Sync + 'static> Clone for Suspense<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T: Clone + Send + Sync + 'static> From<T> for Suspense<T> {
fn from(value: T) -> Self {
Self::ready(value)
}
}
impl<T: Clone + Send + Sync + 'static> From<Result<T, String>> for Suspense<T> {
fn from(result: Result<T, String>) -> Self {
match result {
Ok(value) => Self::ready(value),
Err(error) => Self::error(error),
}
}
}
#[cfg(test)]
mod phase1_test;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BerserkerMode {
Normal,
Rage, Frenzy, GodMode, }
pub trait Seer: Send + Sync {
fn predict(&self, context: &str) -> String;
fn whispers(&self) -> Vec<String>;
}