79 lines
1.8 KiB
Rust
79 lines
1.8 KiB
Rust
|
use tiny_skia::Pixmap;
|
||
|
|
||
|
use crate::{
|
||
|
render::{Renderer, RendererLimits},
|
||
|
system::System,
|
||
|
value::{Ref, Reticle, Value, Vec2},
|
||
|
vm::{Exception, Vm},
|
||
|
};
|
||
|
|
||
|
#[derive(Debug, Clone, Copy)]
|
||
|
pub struct Trampoline {
|
||
|
pub value: Value,
|
||
|
}
|
||
|
|
||
|
// NOTE: This must be kept in sync with haku.js.
|
||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||
|
#[repr(u8)]
|
||
|
pub enum Cont {
|
||
|
Scribble,
|
||
|
Dotter,
|
||
|
}
|
||
|
|
||
|
impl Trampoline {
|
||
|
pub fn new(init: Value) -> Self {
|
||
|
Self { value: init }
|
||
|
}
|
||
|
|
||
|
pub fn cont(&self, vm: &Vm) -> Cont {
|
||
|
let Some((_, refv)) = vm.get_ref_value(self.value) else {
|
||
|
return Cont::Scribble;
|
||
|
};
|
||
|
|
||
|
match refv {
|
||
|
Ref::Reticle(_) => Cont::Dotter,
|
||
|
_ => Cont::Scribble,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn scribble(
|
||
|
&mut self,
|
||
|
vm: &Vm,
|
||
|
pixmap: &mut Pixmap,
|
||
|
translation: Vec2,
|
||
|
limits: &RendererLimits,
|
||
|
) -> Result<(), Exception> {
|
||
|
let mut renderer = Renderer::new(&mut *pixmap, limits);
|
||
|
renderer.translate(translation.x, translation.y);
|
||
|
renderer.render(vm, self.value)
|
||
|
}
|
||
|
|
||
|
pub fn dotter(
|
||
|
&mut self,
|
||
|
vm: &mut Vm,
|
||
|
system: &System,
|
||
|
from: Vec2,
|
||
|
to: Vec2,
|
||
|
num: f32,
|
||
|
) -> Result<(), Exception> {
|
||
|
let (_, vref) = vm.get_ref_value(self.value).expect("value must be a ref");
|
||
|
let &Ref::Reticle(Reticle::Dotter {
|
||
|
draw: Value::Ref(draw_id),
|
||
|
}) = vref
|
||
|
else {
|
||
|
panic!("value must be a dotter reticle");
|
||
|
};
|
||
|
|
||
|
let dotter = vm.create_ref(Ref::Closure(system.create_dotter(
|
||
|
from.into(),
|
||
|
to.into(),
|
||
|
num,
|
||
|
)))?;
|
||
|
|
||
|
let value = vm.run(system, draw_id, &[Value::Ref(dotter)])?;
|
||
|
self.value = value;
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|