mod bindings {
use js_sys::{Array, JsString, Promise};
use wasm_bindgen::JsValue;
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen(module = "/resources/web-renderer/renderer.js")]
extern "C" {
pub fn get_delta_time_ms() -> JsValue;
pub fn window_dimensions() -> Array;
pub fn init_html_root();
pub fn text_measuring_function(
string: JsString,
id: JsValue,
size: JsValue,
line_height: JsValue,
letter_spacing: JsValue,
) -> Array;
pub fn get_mouse_position() -> Array;
pub fn mouse_button_down(n: usize) -> JsValue;
pub fn get_mouse_wheel_move_v() -> JsValue;
pub fn keyDown(keyCode: JsValue) -> JsValue;
pub fn readChar() -> JsValue;
pub fn hasInput() -> JsValue;
pub fn getPressedKeys() -> Array;
pub fn loadFont(id: JsValue, url: JsValue) -> Promise;
pub fn get_custom_element_html(element_id: JsValue) -> JsValue;
pub fn get_custom_element_properties(element_id: JsValue, selector: JsValue) -> JsValue;
pub async fn waitForNextFrame();
pub fn beginFrame();
pub fn endFrame(usedElementIds: JsValue);
pub fn getOrCreateHostElement(
id: JsValue,
tagName: JsValue,
extraStyle: JsValue,
applyStyleCallback: JsValue,
) -> JsValue;
pub fn appendToCurrentContainer(element: JsValue);
pub fn scissorStackPush(container: JsValue, globalX: f64, globalY: f64);
pub fn scissorStackPop();
}
}
pub(crate) mod primitives {
use crate::web_functions::*;
use cotis_defaults::element_configs::text_config::TextConfig;
use cotis_utils::interactivity::keyboard::KeyboardKey;
use cotis_utils::interactivity::mouse;
use cotis_utils::math::Dimensions;
use js_sys::{Array, JsString, Promise};
use wasm_bindgen::JsCast;
use wasm_bindgen::JsValue;
pub fn get_delta_time_ms() -> f32 {
let delta: JsValue = bindings::get_delta_time_ms();
let delta = delta.as_f64().unwrap_or(0.0) as f32;
delta / 1000.0 }
pub(crate) fn window_dimensions() -> (f32, f32) {
let array = bindings::window_dimensions();
let width: f32 = array.get(0).as_f64().unwrap_or(0.0) as f32;
let height: f32 = array.get(1).as_f64().unwrap_or(0.0) as f32;
(width, height)
}
pub fn text_measuring_function(s: &str, config: &TextConfig) -> Dimensions {
let js_string: JsString = JsString::from(s);
let array = bindings::text_measuring_function(
js_string,
JsValue::from(config.font_id),
JsValue::from(config.font_size),
JsValue::from(config.line_height),
JsValue::from(config.letter_spacing),
);
let width: f32 = array.get(0).as_f64().unwrap_or(0.0) as f32;
let height: f32 = array.get(1).as_f64().unwrap_or(0.0) as f32;
Dimensions { width, height }
}
pub fn get_mouse_position() -> (f32, f32) {
let array = bindings::get_mouse_position();
let x: f32 = array.get(0).as_f64().unwrap_or(0.0) as f32;
let y: f32 = array.get(1).as_f64().unwrap_or(0.0) as f32;
(x, y)
}
pub fn mouse_button_down(n: mouse::MouseButton) -> bool {
let true_n = match n {
mouse::MouseButton::MouseButtonLeft => 0,
mouse::MouseButton::MouseButtonRight => 2,
mouse::MouseButton::MouseButtonMiddle => 1,
_ => return false,
};
let res = bindings::mouse_button_down(true_n);
res.as_bool().unwrap_or(false)
}
pub fn get_mouse_wheel_move_v() -> (f32, f32) {
let value: JsValue = bindings::get_mouse_wheel_move_v();
let x: f32 = 0.0f32;
let y: f32 = value.as_f64().unwrap_or(0.0) as f32;
(x, y)
}
#[allow(dead_code)]
pub fn key_down(key_code: &KeyboardKey) -> bool {
let key_code = match key_code {
KeyboardKey::KeyNull => "Null",
KeyboardKey::KeyApostrophe => "Quote",
KeyboardKey::KeyComma => "Comma",
KeyboardKey::KeyMinus => "Minus",
KeyboardKey::KeyPeriod => "Period",
KeyboardKey::KeySlash => "Slash",
KeyboardKey::KeyZero => "Digit0",
KeyboardKey::KeyOne => "Digit1",
KeyboardKey::KeyTwo => "Digit2",
KeyboardKey::KeyThree => "Digit3",
KeyboardKey::KeyFour => "Digit4",
KeyboardKey::KeyFive => "Digit5",
KeyboardKey::KeySix => "Digit6",
KeyboardKey::KeySeven => "Digit7",
KeyboardKey::KeyEight => "Digit8",
KeyboardKey::KeyNine => "Digit9",
KeyboardKey::KeySemicolon => "Semicolon",
KeyboardKey::KeyEqual => "Equal",
KeyboardKey::KeyA => "KeyA",
KeyboardKey::KeyB => "KeyB",
KeyboardKey::KeyC => "KeyC",
KeyboardKey::KeyD => "KeyD",
KeyboardKey::KeyE => "KeyE",
KeyboardKey::KeyF => "KeyF",
KeyboardKey::KeyG => "KeyG",
KeyboardKey::KeyH => "KeyH",
KeyboardKey::KeyI => "KeyI",
KeyboardKey::KeyJ => "KeyJ",
KeyboardKey::KeyK => "KeyK",
KeyboardKey::KeyL => "KeyL",
KeyboardKey::KeyM => "KeyM",
KeyboardKey::KeyN => "KeyN",
KeyboardKey::KeyO => "KeyO",
KeyboardKey::KeyP => "KeyP",
KeyboardKey::KeyQ => "KeyQ",
KeyboardKey::KeyR => "KeyR",
KeyboardKey::KeyS => "KeyS",
KeyboardKey::KeyT => "KeyT",
KeyboardKey::KeyU => "KeyU",
KeyboardKey::KeyV => "KeyV",
KeyboardKey::KeyW => "KeyW",
KeyboardKey::KeyX => "KeyX",
KeyboardKey::KeyY => "KeyY",
KeyboardKey::KeyZ => "KeyZ",
KeyboardKey::KeyLeftBracket => "BracketLeft",
KeyboardKey::KeyBackslash => "Backslash",
KeyboardKey::KeyRightBracket => "BracketRight",
KeyboardKey::KeyGrave => "Backquote",
KeyboardKey::KeySpace => "Space",
KeyboardKey::KeyEscape => "Escape",
KeyboardKey::KeyEnter => "Enter",
KeyboardKey::KeyTab => "Tab",
KeyboardKey::KeyBackspace => "Backspace",
KeyboardKey::KeyInsert => "Insert",
KeyboardKey::KeyDelete => "Delete",
KeyboardKey::KeyRight => "ArrowRight",
KeyboardKey::KeyLeft => "ArrowLeft",
KeyboardKey::KeyDown => "ArrowDown",
KeyboardKey::KeyUp => "ArrowUp",
KeyboardKey::KeyPageUp => "PageUp",
KeyboardKey::KeyPageDown => "PageDown",
KeyboardKey::KeyHome => "Home",
KeyboardKey::KeyEnd => "End",
KeyboardKey::KeyCapsLock => "CapsLock",
KeyboardKey::KeyScrollLock => "ScrollLock",
KeyboardKey::KeyNumLock => "NumLock",
KeyboardKey::KeyPrintScreen => "PrintScreen",
KeyboardKey::KeyPause => "Pause",
KeyboardKey::KeyF1 => "F1",
KeyboardKey::KeyF2 => "F2",
KeyboardKey::KeyF3 => "F3",
KeyboardKey::KeyF4 => "F4",
KeyboardKey::KeyF5 => "F5",
KeyboardKey::KeyF6 => "F6",
KeyboardKey::KeyF7 => "F7",
KeyboardKey::KeyF8 => "F8",
KeyboardKey::KeyF9 => "F9",
KeyboardKey::KeyF10 => "F10",
KeyboardKey::KeyF11 => "F11",
KeyboardKey::KeyF12 => "F12",
KeyboardKey::KeyLeftShift => "ShiftLeft",
KeyboardKey::KeyLeftControl => "ControlLeft",
KeyboardKey::KeyLeftAlt => "AltLeft",
KeyboardKey::KeyLeftSuper => "MetaLeft",
KeyboardKey::KeyRightShift => "ShiftRight",
KeyboardKey::KeyRightControl => "ControlRight",
KeyboardKey::KeyRightAlt => "AltRight",
KeyboardKey::KeyRightSuper => "MetaRight",
KeyboardKey::KeyKbMenu => "ContextMenu",
KeyboardKey::KeyKp0 => "Numpad0",
KeyboardKey::KeyKp1 => "Numpad1",
KeyboardKey::KeyKp2 => "Numpad2",
KeyboardKey::KeyKp3 => "Numpad3",
KeyboardKey::KeyKp4 => "Numpad4",
KeyboardKey::KeyKp5 => "Numpad5",
KeyboardKey::KeyKp6 => "Numpad6",
KeyboardKey::KeyKp7 => "Numpad7",
KeyboardKey::KeyKp8 => "Numpad8",
KeyboardKey::KeyKp9 => "Numpad9",
KeyboardKey::KeyKpDecimal => "NumpadDecimal",
KeyboardKey::KeyKpDivide => "NumpadDivide",
KeyboardKey::KeyKpMultiply => "NumpadMultiply",
KeyboardKey::KeyKpSubtract => "NumpadSubtract",
KeyboardKey::KeyKpAdd => "NumpadAdd",
KeyboardKey::KeyKpEnter => "NumpadEnter",
KeyboardKey::KeyKpEqual => "NumpadEqual",
KeyboardKey::KeyBack => "BrowserBack",
KeyboardKey::KeyMenu => "BrowserMenu",
KeyboardKey::KeyVolumeUp => "AudioVolumeUp",
KeyboardKey::KeyVolumeDown => "AudioVolumeDown",
};
let value: JsValue = bindings::keyDown(JsValue::from_str(key_code));
value.as_bool().unwrap()
}
#[allow(dead_code)]
pub fn get_next_char() -> Option<char> {
let has_input: JsValue = bindings::hasInput();
match has_input.as_bool() {
Some(false) => {
return None;
}
None => {
return None;
}
Some(true) => {}
}
let new_char: JsValue = bindings::readChar();
match new_char.as_string() {
None => None,
Some(c) => Some(c.chars().next()?),
}
}
#[allow(dead_code)]
pub fn get_pressed_keys() -> Vec<String> {
let values: Array = bindings::getPressedKeys();
let mut res: Vec<String> = vec![];
for value in values {
let value: JsValue = value;
res.push(value.as_string().unwrap());
}
res
}
pub fn load_font(url: &str, id: usize) {
let _: Promise =
bindings::loadFont(JsValue::from_str(&id.to_string()), JsValue::from_str(url));
}
pub async fn wait_for_next_frame() {
bindings::waitForNextFrame().await;
}
pub fn get_custom_element_html(element_id: u64) -> Option<String> {
bindings::get_custom_element_html(JsValue::from_f64(element_id as f64)).as_string()
}
pub fn get_custom_element_properties(
element_id: u64,
selector: Option<&str>,
) -> Option<String> {
let selector = selector.map(JsValue::from_str).unwrap_or(JsValue::NULL);
bindings::get_custom_element_properties(JsValue::from_f64(element_id as f64), selector)
.as_string()
}
pub fn begin_frame() {
bindings::beginFrame();
}
pub fn end_frame(used_element_ids: &js_sys::Set) {
bindings::endFrame(used_element_ids.into());
}
pub fn get_or_create_host_element(
id: &str,
tag_name: &str,
extra_style: Option<&str>,
apply_style_fn: &js_sys::Function,
) -> web_sys::Element {
let extra_style_js = extra_style.map(JsValue::from_str).unwrap_or(JsValue::NULL);
bindings::getOrCreateHostElement(
JsValue::from_str(id),
JsValue::from_str(tag_name),
extra_style_js,
apply_style_fn.into(),
)
.unchecked_into()
}
pub fn append_to_current_container(element: &web_sys::Element) {
bindings::appendToCurrentContainer(element.into());
}
pub fn scissor_stack_push(container: &web_sys::Element, global_x: f64, global_y: f64) {
bindings::scissorStackPush(container.into(), global_x, global_y);
}
pub fn scissor_stack_pop() {
bindings::scissorStackPop();
}
}