This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 5.1 kB View raw
1#![allow(unused)] 2 3use std::sync::Mutex; 4 5use once_cell::sync::Lazy; 6use rand::SeedableRng; 7use rand::rngs::SmallRng; 8use wasm_bindgen::prelude::wasm_bindgen; 9use wasm_bindgen::{JsValue, UnwrapThrowExt}; 10 11use crate::{ 12 Canvas, Color, ColorMapping, Fill, Filter, Layer, Object, Point, 13 SVGRenderable, 14}; 15 16use super::LayerWeb; 17 18static WEB_CANVAS: Lazy<Mutex<Canvas>> = 19 Lazy::new(|| Mutex::new(Canvas::default_settings())); 20 21pub(super) static mut RNG: Lazy<SmallRng> = 22 Lazy::new(|| SmallRng::seed_from_u64(0xCAFE)); 23 24pub(super) fn canvas() -> std::sync::MutexGuard<'static, Canvas> { 25 WEB_CANVAS.lock().unwrap() 26} 27 28// Can't bind Color.name directly, see https://github.com/rustwasm/wasm-bindgen/issues/1715 29#[wasm_bindgen] 30pub fn color_name(c: Color) -> String { 31 c.name() 32} 33 34#[wasm_bindgen] 35extern "C" { 36 #[wasm_bindgen(js_namespace = console)] 37 pub fn log(s: &str); 38} 39 40macro_rules! console_log { 41 ($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string())) 42} 43 44#[wasm_bindgen] 45pub fn render_image(opacity: f32, color: Color) -> Result<(), JsValue> { 46 let mut canvas = Canvas::with_colors(ColorMapping { 47 black: "#ffffff".into(), 48 white: "#ffffff".into(), 49 red: "#cf0a2b".into(), 50 green: "#22e753".into(), 51 blue: "#2734e6".into(), 52 yellow: "#f8e21e".into(), 53 orange: "#f05811".into(), 54 purple: "#6a24ec".into(), 55 brown: "#a05634".into(), 56 pink: "#e92e76".into(), 57 gray: "#81a0a8".into(), 58 cyan: "#4fecec".into(), 59 }); 60 61 *WEB_CANVAS.lock().unwrap() = canvas; 62 render_canvas_at(String::from("body")); 63 64 Ok(()) 65} 66 67#[wasm_bindgen] 68pub fn map_to_midi_controller() {} 69 70#[wasm_bindgen] 71pub fn render_canvas_into(selector: String) { 72 append_new_div_inside(render_canvas(), selector) 73} 74 75#[wasm_bindgen] 76pub fn render_canvas_at(selector: String) { 77 replace_content_with(render_canvas(), selector); 78} 79 80#[wasm_bindgen] 81pub enum MidiEvent { 82 Note, 83 ControlChange, 84} 85 86#[wasm_bindgen] 87pub struct MidiEventData([u8; 3]); 88 89#[wasm_bindgen] 90pub struct MidiPitch(u8); 91 92#[wasm_bindgen] 93impl MidiPitch { 94 pub fn octave(&self) -> u8 { 95 self.0 / 12 96 } 97} 98 99pub struct Percentage(pub f32); 100 101impl From<u8> for Percentage { 102 fn from(value: u8) -> Self { 103 Self(value as f32 / 127.0) 104 } 105} 106 107pub enum MidiMessage { 108 NoteOn(MidiPitch, Percentage), 109 NoteOff(MidiPitch), 110 PedalOn, 111 PedalOff, 112 ControlChange(u8, Percentage), 113} 114 115impl From<(MidiEvent, MidiEventData)> for MidiMessage { 116 fn from(value: (MidiEvent, MidiEventData)) -> Self { 117 match value { 118 (MidiEvent::Note, MidiEventData([pitch, velocity, _])) => { 119 if velocity == 0 { 120 MidiMessage::NoteOff(MidiPitch(pitch)) 121 } else { 122 MidiMessage::NoteOn(MidiPitch(pitch), velocity.into()) 123 } 124 } 125 (MidiEvent::ControlChange, MidiEventData([64, value, _])) => { 126 if value == 0 { 127 MidiMessage::PedalOff 128 } else { 129 MidiMessage::PedalOn 130 } 131 } 132 (MidiEvent::ControlChange, MidiEventData([_, controller, value])) => { 133 MidiMessage::ControlChange(controller, value.into()) 134 } 135 } 136 } 137} 138 139#[wasm_bindgen] 140pub fn render_canvas() -> String { 141 let can = canvas(); 142 can.render_to_svg( 143 can.colormap.clone(), 144 can.cell_size, 145 can.object_sizes, 146 "web_root_canvas", 147 ) 148 .unwrap_throw() 149 .to_string() 150} 151 152#[wasm_bindgen] 153pub fn set_palette(palette: ColorMapping) { 154 canvas().colormap = palette; 155} 156 157#[wasm_bindgen] 158pub fn get_layer(name: &str) -> Result<LayerWeb, JsValue> { 159 match canvas().layer(name) { 160 Ok(layer) => Ok(LayerWeb { 161 name: layer.name.clone(), 162 }), 163 Err(_) => Err(JsValue::from_str("Layer not found")), 164 } 165} 166 167#[wasm_bindgen] 168pub fn random_linelikes(name: &str) -> LayerWeb { 169 unsafe { 170 #[allow(static_mut_refs)] 171 let layer = canvas().random_linelikes(&mut RNG, name); 172 } 173 LayerWeb { 174 name: name.to_string(), 175 } 176} 177 178fn document() -> web_sys::Document { 179 let window = web_sys::window().expect_throw("no global `window` exists"); 180 window 181 .document() 182 .expect_throw("should have a document on window") 183} 184 185fn query_selector(selector: String) -> web_sys::Element { 186 document() 187 .query_selector(&selector) 188 .expect_throw(&format!("selector '{}' not found", selector)) 189 .expect_throw( 190 "could not get the element, but is was found (shouldn't happen)", 191 ) 192} 193 194pub(super) fn append_new_div_inside(content: String, selector: String) { 195 let output = document().create_element("div").unwrap(); 196 output.set_class_name("frame"); 197 output.set_inner_html(&content); 198 query_selector(selector).append_child(&output).unwrap(); 199} 200 201pub(super) fn replace_content_with(content: String, selector: String) { 202 query_selector(selector).set_inner_html(&content); 203}