From a817ad0d0fcccf8db8fa749ec06f5d6bcc38d541 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 5 Feb 2024 10:12:15 -0800 Subject: [PATCH] API cleanup --- TODO.md | 4 +- content/ui/flying.rhai | 86 ++-- content/ui/landed.rhai | 36 +- content/ui/outfitter.rhai | 74 +-- crates/render/src/ui/api/functions/conf.rs | 27 ++ crates/render/src/ui/api/functions/mod.rs | 11 + .../render/src/ui/api/functions/radialbar.rs | 48 ++ crates/render/src/ui/api/functions/sprite.rs | 169 +++++++ crates/render/src/ui/api/functions/textbox.rs | 226 +++++++++ crates/render/src/ui/api/functions/ui.rs | 19 + .../render/src/ui/api/{ => helpers}/anchor.rs | 0 .../render/src/ui/api/{ => helpers}/color.rs | 0 crates/render/src/ui/api/helpers/mod.rs | 4 + .../render/src/ui/api/{ => helpers}/rect.rs | 2 +- .../render/src/ui/api/{ => helpers}/vector.rs | 0 crates/render/src/ui/api/mod.rs | 50 +- crates/render/src/ui/executor.rs | 436 +----------------- 17 files changed, 650 insertions(+), 542 deletions(-) create mode 100644 crates/render/src/ui/api/functions/conf.rs create mode 100644 crates/render/src/ui/api/functions/mod.rs create mode 100644 crates/render/src/ui/api/functions/radialbar.rs create mode 100644 crates/render/src/ui/api/functions/sprite.rs create mode 100644 crates/render/src/ui/api/functions/textbox.rs create mode 100644 crates/render/src/ui/api/functions/ui.rs rename crates/render/src/ui/api/{ => helpers}/anchor.rs (100%) rename crates/render/src/ui/api/{ => helpers}/color.rs (100%) create mode 100644 crates/render/src/ui/api/helpers/mod.rs rename crates/render/src/ui/api/{ => helpers}/rect.rs (99%) rename crates/render/src/ui/api/{ => helpers}/vector.rs (100%) diff --git a/TODO.md b/TODO.md index 0a6886c..9ab947f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,10 +1,10 @@ # Specific projects ## Now: -- Clean up API (modules) +- Clean up state api - Persistent variables - Better planet icons -- Clean up scripting & errors +- Clean up scripting errors - Mouse colliders - UI captures input? - No UI zoom scroll diff --git a/content/ui/flying.rhai b/content/ui/flying.rhai index b5ff892..e03d074 100644 --- a/content/ui/flying.rhai +++ b/content/ui/flying.rhai @@ -1,9 +1,9 @@ fn init(state) { - conf_set_starfield(true); - conf_set_phys(true); + conf::show_starfield(true); + conf::show_phys(true); - add_sprite( + sprite::add( "ring", "ui::status", Rect( @@ -13,7 +13,7 @@ fn init(state) { ) ); - add_radialbar( + radialbar::add( "shield", 2.5, Color(0.3, 0.6, 0.8, 1.0), Rect( @@ -23,7 +23,7 @@ fn init(state) { ) ); - add_radialbar( + radialbar::add( "hull", 2.5, Color(0.8, 0.7, 0.5, 1.0), Rect( @@ -40,7 +40,7 @@ fn init(state) { let radar_size = 150.0; let radar_range = 4000.0; - add_sprite( + sprite::add( "radar", "ui::radar", Rect( @@ -59,25 +59,25 @@ fn init(state) { Anchor::NorthWest ); - add_sprite("radar.frame.ne", "ui::radarframe", init_pos); - add_sprite("radar.frame.se", "ui::radarframe", init_pos); - add_sprite("radar.frame.sw", "ui::radarframe", init_pos); - add_sprite("radar.frame.nw", "ui::radarframe", init_pos); - sprite_set_angle("radar.frame.se", 90.0); - sprite_set_angle("radar.frame.sw", 180.0); - sprite_set_angle("radar.frame.nw", 270.0); - sprite_set_color("radar.frame.ne", Color(0.3, 0.3, 0.3, 1.0)); - sprite_set_color("radar.frame.se", Color(0.3, 0.3, 0.3, 1.0)); - sprite_set_color("radar.frame.sw", Color(0.3, 0.3, 0.3, 1.0)); - sprite_set_color("radar.frame.nw", Color(0.3, 0.3, 0.3, 1.0)); + sprite::add("radar.frame.ne", "ui::radarframe", init_pos); + sprite::add("radar.frame.se", "ui::radarframe", init_pos); + sprite::add("radar.frame.sw", "ui::radarframe", init_pos); + sprite::add("radar.frame.nw", "ui::radarframe", init_pos); + sprite::set_angle("radar.frame.se", 90.0); + sprite::set_angle("radar.frame.sw", 180.0); + sprite::set_angle("radar.frame.nw", 270.0); + sprite::set_color("radar.frame.ne", Color(0.3, 0.3, 0.3, 1.0)); + sprite::set_color("radar.frame.se", Color(0.3, 0.3, 0.3, 1.0)); + sprite::set_color("radar.frame.sw", Color(0.3, 0.3, 0.3, 1.0)); + sprite::set_color("radar.frame.nw", Color(0.3, 0.3, 0.3, 1.0)); - add_sprite("radar.arrow", "ui::centerarrow", init_pos); + sprite::add("radar.arrow", "ui::centerarrow", init_pos); } fn event(state, event) { if type_of(event) == "PlayerShipStateEvent" { if state.player_ship().is_landed() { - go_to_scene("landed"); + ui::go_to_scene("landed"); return; } return; @@ -85,11 +85,11 @@ fn event(state, event) { } fn step(state) { - radialbar_set_val("shield", + radialbar::set_val("shield", state.player_ship().get_shields() / state.player_ship().get_total_shields() ); - radialbar_set_val("hull", + radialbar::set_val("hull", state.player_ship().get_hull() / state.player_ship().get_total_hull() ); @@ -110,7 +110,7 @@ fn step(state) { let position = Vector(5.0 + (radar_size / 2.0), -5.0 - (radar_size / 2.0)); let rot = Vector(0.915 * (radar_size / 2.0), 0.0); let pos = position + rot.rotate(angle); - sprite_set_rect("radar.arrow", + sprite::set_rect("radar.arrow", Rect( pos.x(), pos.y(), 5.0, 5.0, @@ -118,8 +118,8 @@ fn step(state) { Anchor::NorthWest ) ); - sprite_set_angle("radar.arrow", angle - 90.0); - sprite_set_color( + sprite::set_angle("radar.arrow", angle - 90.0); + sprite::set_color( "radar.arrow", Color( 1.0, 1.0, 1.0, @@ -139,8 +139,8 @@ fn step(state) { s.is_dead() || s.is_landed() ){ - if sprite_exists(sprite_name) { - remove_sprite(sprite_name); + if sprite::exists(sprite_name) { + sprite::remove(sprite_name); } continue; } @@ -161,8 +161,8 @@ fn step(state) { size = size_init; } if size < 1.0 { - if sprite_exists(sprite_name) { - remove_sprite(sprite_name); + if sprite::exists(sprite_name) { + sprite::remove(sprite_name); } continue; } @@ -170,8 +170,8 @@ fn step(state) { let pos = Vector(radar_size / 2.0 + 5.0, radar_size / -2.0 - 5.0); pos = pos + (d * radar_size / 2.0); - if !sprite_exists(sprite_name) { - add_sprite( + if !sprite::exists(sprite_name) { + sprite::add( sprite_name, "ui::shipblip", Rect( @@ -182,7 +182,7 @@ fn step(state) { ) ); } else { - sprite_set_rect( + sprite::set_rect( sprite_name, Rect( pos.x(), pos.y(), @@ -192,7 +192,7 @@ fn step(state) { ) ); } - sprite_set_color(sprite_name, color); + sprite::set_color(sprite_name, color); } } } @@ -203,8 +203,8 @@ fn step(state) { let sprite_name = `radar.object.${o.get_label()}`; if !o.is_some() { - if sprite_exists(sprite_name) { - remove_sprite(sprite_name); + if sprite::exists(sprite_name) { + sprite::remove(sprite_name); } continue; } @@ -220,8 +220,8 @@ fn step(state) { } if size < 1.0 { // Don't draw tiny sprites, they flicker - if sprite_exists(sprite_name) { - remove_sprite(sprite_name); + if sprite::exists(sprite_name) { + sprite::remove(sprite_name); } continue; } @@ -231,8 +231,8 @@ fn step(state) { + (d * radar_size / 2.0) ); - if !sprite_exists(sprite_name) { - add_sprite( + if !sprite::exists(sprite_name) { + sprite::add( sprite_name, "ui::planetblip", Rect( @@ -243,7 +243,7 @@ fn step(state) { ) ); } else { - sprite_set_rect( + sprite::set_rect( sprite_name, Rect( pos.x(), pos.y(), @@ -261,7 +261,7 @@ fn step(state) { { let dx = (((state.camera_zoom() / 2.0) * state.window_aspect()) / radar_range) * (radar_size / 2.0); let dy = ((state.camera_zoom() / 2.0) / radar_range) * (radar_size / 2.0); - sprite_set_rect("radar.frame.ne", + sprite::set_rect("radar.frame.ne", Rect( (radar_size / 2.0 + 5) - dx, (radar_size / -2.0 - 5) + dy, @@ -270,7 +270,7 @@ fn step(state) { Anchor::NorthWest ) ); - sprite_set_rect("radar.frame.se", + sprite::set_rect("radar.frame.se", Rect( (radar_size / 2.0 + 5) - dx, (radar_size / -2.0 - 5) - dy, @@ -279,7 +279,7 @@ fn step(state) { Anchor::NorthWest ) ); - sprite_set_rect("radar.frame.sw", + sprite::set_rect("radar.frame.sw", Rect( (radar_size / 2.0 + 5) + dx, (radar_size / -2.0 - 5) - dy, @@ -288,7 +288,7 @@ fn step(state) { Anchor::NorthWest ) ); - sprite_set_rect("radar.frame.nw", + sprite::set_rect("radar.frame.nw", Rect( (radar_size / 2.0 + 5) + dx, (radar_size / -2.0 - 5) + dy, diff --git a/content/ui/landed.rhai b/content/ui/landed.rhai index 884c031..82b2724 100644 --- a/content/ui/landed.rhai +++ b/content/ui/landed.rhai @@ -1,10 +1,10 @@ fn init(state) { let player = state.player_ship(); - conf_set_starfield(true); - conf_set_phys(false); + conf::show_starfield(true); + conf::show_phys(false); - add_sprite( + sprite::add( "button", "ui::planet::button", Rect( @@ -14,7 +14,7 @@ fn init(state) { ) ); - add_sprite( + sprite::add( "landscape", { if player.is_landed() { @@ -29,9 +29,9 @@ fn init(state) { Anchor::Center ) ); - sprite_set_mask("landscape", "ui::landscapemask"); + sprite::set_mask("landscape", "ui::landscapemask"); - add_sprite( + sprite::add( "frame", "ui::planet", Rect( @@ -42,7 +42,7 @@ fn init(state) { ); - add_textbox( + textbox::add( "title", 10.0, 10.0, Rect( -70.79, 138.0, 59.867, 10.0, @@ -51,14 +51,14 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_align_center("title"); - textbox_font_serif("title"); - textbox_weight_bold("title"); + textbox::align_center("title"); + textbox::font_serif("title"); + textbox::weight_bold("title"); if player.is_landed() { - textbox_set_text("title", player.landed_on().name()); + textbox::set_text("title", player.landed_on().name()); } - add_textbox( + textbox::add( "desc", 7.5, 8.0, Rect( -178.92, -20.3, 343.0, 81.467, @@ -67,9 +67,9 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_sans("desc"); + textbox::font_sans("desc"); if player.is_landed() { - textbox_set_text("desc", player.landed_on().desc()); + textbox::set_text("desc", player.landed_on().desc()); } } @@ -78,9 +78,9 @@ fn event(state, event) { let element = event.element(); if element == "button" { if event.is_enter() { - sprite_take_edge("button", "on:top", 0.1); + sprite::take_edge("button", "on:top", 0.1); } else { - sprite_take_edge("button", "off:top", 0.1); + sprite::take_edge("button", "off:top", 0.1); } } return; @@ -94,7 +94,7 @@ fn event(state, event) { let element = event.element(); if element == "button" { - go_to_scene("outfitter"); + ui::go_to_scene("outfitter"); return; } return; @@ -102,7 +102,7 @@ fn event(state, event) { if type_of(event) == "PlayerShipStateEvent" { if !state.player_ship().is_landed() { - go_to_scene("flying"); + ui::go_to_scene("flying"); return; } return; diff --git a/content/ui/outfitter.rhai b/content/ui/outfitter.rhai index 4b63a56..c92b112 100644 --- a/content/ui/outfitter.rhai +++ b/content/ui/outfitter.rhai @@ -1,9 +1,9 @@ fn init(state) { - conf_set_starfield(true); - conf_set_phys(false); + conf::show_starfield(true); + conf::show_phys(false); - add_sprite( + sprite::add( "se_box", "ui::outfitterbox", Rect( @@ -13,7 +13,7 @@ fn init(state) { ) ); - add_textbox( + textbox::add( "exit_text", 10.0, 10.0, Rect( 122.71, 48.0, 51.0, 12.0, @@ -22,11 +22,11 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_serif("exit_text"); - textbox_align_center("exit_text"); - textbox_set_text("exit_text", "Exit"); + textbox::font_serif("exit_text"); + textbox::align_center("exit_text"); + textbox::set_text("exit_text", "Exit"); - add_sprite( + sprite::add( "exit_button", "ui::button", Rect( @@ -38,7 +38,7 @@ fn init(state) { - add_sprite( + sprite::add( "ship_bg", "ui::outfitter-ship-bg", Rect( @@ -48,7 +48,7 @@ fn init(state) { ) ); - add_sprite( + sprite::add( "ship_thumb", "icon::gypsum", Rect( @@ -58,7 +58,7 @@ fn init(state) { ) ); - add_textbox( + textbox::add( "ship_name", 10.0, 10.0, Rect( 111.0, -167.27, 145.0, 10.0, @@ -67,11 +67,11 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_serif("ship_name"); - textbox_align_center("ship_name"); - textbox_set_text("ship_name", "Hyperion"); + textbox::font_serif("ship_name"); + textbox::align_center("ship_name"); + textbox::set_text("ship_name", "Hyperion"); - add_textbox( + textbox::add( "ship_type", 7.0, 8.5, Rect( 111.0, -178.0, 145.0, 8.5, @@ -80,14 +80,14 @@ fn init(state) { ), Color(0.7, 0.7, 0.7, 1.0) ); - textbox_font_sans("ship_type"); - textbox_align_center("ship_type"); + textbox::font_sans("ship_type"); + textbox::align_center("ship_type"); if state.player_ship().is_some() { - textbox_set_text("ship_type", state.player_ship().name()); + textbox::set_text("ship_type", state.player_ship().name()); } - add_textbox( + textbox::add( "ship_stats", 7.0, 8.5, Rect( 38.526, -192.332, 144.948, 154.5, @@ -96,11 +96,11 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_mono("ship_stats"); - textbox_set_text("ship_stats", "Earth"); + textbox::font_mono("ship_stats"); + textbox::set_text("ship_stats", "Earth"); - add_sprite( + sprite::add( "outfit_bg", "ui::outfitter-outfit-bg", Rect( @@ -110,7 +110,7 @@ fn init(state) { ) ); - add_sprite( + sprite::add( "outfit_thumb", "icon::engine", Rect( @@ -120,7 +120,7 @@ fn init(state) { ) ); - add_textbox( + textbox::add( "outfit_name", 16.0, 16.0, Rect( -312.0, -20.0, 200.0, 16.0, @@ -129,11 +129,11 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_serif("outfit_name"); - textbox_weight_bold("outfit_name"); - textbox_set_text("outfit_name", "Earth"); + textbox::font_serif("outfit_name"); + textbox::weight_bold("outfit_name"); + textbox::set_text("outfit_name", "Earth"); - add_textbox( + textbox::add( "outfit_desc", 7.0, 8.5, Rect( -166.0, -219.0, 260.0, 78.0, @@ -142,11 +142,11 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_serif("outfit_desc"); - textbox_set_text("outfit_desc", "Earth"); + textbox::font_serif("outfit_desc"); + textbox::set_text("outfit_desc", "Earth"); - add_textbox( + textbox::add( "outfit_stats", 7.0, 8.5, Rect( -295.0, -271.0, 164.0, 216.0, @@ -155,8 +155,8 @@ fn init(state) { ), Color(1.0, 1.0, 1.0, 1.0) ); - textbox_font_mono("outfit_stats"); - textbox_set_text("outfit_stats", "Earth"); + textbox::font_mono("outfit_stats"); + textbox::set_text("outfit_stats", "Earth"); } @@ -166,9 +166,9 @@ fn event(state, event) { let element = event.element(); if element == "exit_button" { if event.is_enter() { - sprite_take_edge("exit_button", "on:top", 0.1); + sprite::take_edge("exit_button", "on:top", 0.1); } else { - sprite_take_edge("exit_button", "off:top", 0.1); + sprite::take_edge("exit_button", "off:top", 0.1); } } return; @@ -182,7 +182,7 @@ fn event(state, event) { let element = event.element(); if element == "exit_button" { - go_to_scene("landed"); + ui::go_to_scene("landed"); return; } return; @@ -190,7 +190,7 @@ fn event(state, event) { if type_of(event) == "PlayerShipStateEvent" { if !state.player_ship().is_landed() { - go_to_scene("flying"); + ui::go_to_scene("flying"); return; } return; diff --git a/crates/render/src/ui/api/functions/conf.rs b/crates/render/src/ui/api/functions/conf.rs new file mode 100644 index 0000000..322f6d3 --- /dev/null +++ b/crates/render/src/ui/api/functions/conf.rs @@ -0,0 +1,27 @@ +use rhai::{FnNamespace, FuncRegistration, Module}; +use std::{cell::RefCell, rc::Rc}; + +use crate::ui::UiState; + +pub fn build_conf_module(state_src: Rc>) -> Module { + let mut module = Module::new(); + module.set_id("GalacticaConfModule"); + + let state = state_src.clone(); + let _ = FuncRegistration::new("show_phys") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |b: bool| { + let mut ui_state = state.borrow_mut(); + ui_state.config.show_phys = b; + }); + + let state = state_src.clone(); + let _ = FuncRegistration::new("show_starfield") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |b: bool| { + let mut ui_state = state.borrow_mut(); + ui_state.config.show_starfield = b; + }); + + return module; +} diff --git a/crates/render/src/ui/api/functions/mod.rs b/crates/render/src/ui/api/functions/mod.rs new file mode 100644 index 0000000..be7b3a5 --- /dev/null +++ b/crates/render/src/ui/api/functions/mod.rs @@ -0,0 +1,11 @@ +mod conf; +mod radialbar; +mod sprite; +mod textbox; +mod ui; + +pub use conf::build_conf_module; +pub use radialbar::build_radialbar_module; +pub use sprite::build_sprite_module; +pub use textbox::build_textbox_module; +pub use ui::build_ui_module; diff --git a/crates/render/src/ui/api/functions/radialbar.rs b/crates/render/src/ui/api/functions/radialbar.rs new file mode 100644 index 0000000..f725ad5 --- /dev/null +++ b/crates/render/src/ui/api/functions/radialbar.rs @@ -0,0 +1,48 @@ +use log::error; +use rhai::{FnNamespace, FuncRegistration, ImmutableString, Module}; +use std::{cell::RefCell, rc::Rc}; + +use super::super::{Color, Rect}; +use crate::ui::{elements::RadialBar, UiElement, UiState}; + +pub fn build_radialbar_module(state_src: Rc>) -> Module { + let mut module = Module::new(); + module.set_id("GalacticaRadialbarModule"); + + let state = state_src.clone(); + let _ = FuncRegistration::new("add") + .with_namespace(FnNamespace::Internal) + .set_into_module( + &mut module, + // TODO: fix ugly spaces + move |name: ImmutableString, stroke: f32, color: Color, rect: Rect| { + let mut ui_state = state.borrow_mut(); + + if ui_state.elements.contains_key(&name) { + error!("tried to make a radialbar using an existing name `{name}`"); + return; + } + + ui_state.names.push(name.clone()); + ui_state.elements.insert( + name.clone(), + UiElement::RadialBar(RadialBar::new(name.clone(), stroke, color, rect, 1.0)), + ); + }, + ); + + let state = state_src.clone(); + let _ = FuncRegistration::new("set_val") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString, val: f32| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::RadialBar(x)) => x.set_val(val), + _ => { + error!("called `radialbar_set_val` on an invalid name `{name}`") + } + } + }); + + return module; +} diff --git a/crates/render/src/ui/api/functions/sprite.rs b/crates/render/src/ui/api/functions/sprite.rs new file mode 100644 index 0000000..e27135e --- /dev/null +++ b/crates/render/src/ui/api/functions/sprite.rs @@ -0,0 +1,169 @@ +use galactica_content::{resolve_edge_as_edge, Content}; +use log::error; +use rhai::{FnNamespace, FuncRegistration, ImmutableString, Module}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; + +use crate::ui::{elements::Sprite, UiElement, UiState}; + +use super::super::{Color, Rect}; + +pub fn build_sprite_module(ct_src: Arc, state_src: Rc>) -> Module { + let mut module = Module::new(); + module.set_id("GalacticaSpriteModule"); + + let state = state_src.clone(); + let ct = ct_src.clone(); + let _ = FuncRegistration::new("add") + .with_namespace(FnNamespace::Internal) + .set_into_module( + &mut module, + move |name: ImmutableString, sprite: ImmutableString, rect: Rect| { + let mut ui_state = state.borrow_mut(); + + let sprite_handle = ct.get_sprite_handle(sprite.as_str()); + if sprite_handle.is_none() { + error!("made a sprite using an invalid source `{sprite}`"); + return; + } + + if ui_state.elements.contains_key(&name) { + error!("tried to make a sprite using an existing name `{name}`"); + return; + } + + ui_state.names.push(name.clone()); + ui_state.elements.insert( + name.clone(), + UiElement::Sprite(Sprite::new(&ct, name.clone(), sprite_handle.unwrap(), rect)), + ); + }, + ); + + let state = state_src.clone(); + let _ = FuncRegistration::new("remove") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + if ui_state.elements.contains_key(&name) { + ui_state.elements.remove(&name).unwrap(); + ui_state.names.retain(|x| *x != name); + } else { + error!("called `sprite::remove` on an invalid name `{name}`") + } + }); + + let state = state_src.clone(); + let ct = ct_src.clone(); + let _ = FuncRegistration::new("set_mask") + .with_namespace(FnNamespace::Internal) + .set_into_module( + &mut module, + move |name: ImmutableString, mask: ImmutableString| { + let mut ui_state = state.borrow_mut(); + + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Sprite(x)) => { + let m = ct.get_sprite_handle(mask.as_str()); + if m.is_none() { + error!("called `set_sprite_mask` with an invalid mask `{mask}`"); + return; + } + x.set_mask(m) + } + + _ => { + error!("called `sprite::set_mask` on an invalid name `{name}`") + } + } + }, + ); + + let state = state_src.clone(); + let ct = ct_src.clone(); + let _ = FuncRegistration::new("take_edge") + .with_namespace(FnNamespace::Internal) + .set_into_module( + &mut module, + move |name: ImmutableString, edge_name: ImmutableString, duration: f32| { + let mut ui_state = state.borrow_mut(); + + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Sprite(x)) => { + let sprite_handle = x.anim.get_sprite(); + let sprite = &ct.get_sprite(sprite_handle); + + let edge = resolve_edge_as_edge(edge_name.as_str(), duration, |x| { + sprite.get_section_handle_by_name(x) + }); + let edge = match edge { + Err(_) => { + error!( + "called `sprite::take_edge` on an invalid edge `{}` on sprite `{}`", + edge_name, sprite.name + ); + return; + } + Ok(s) => s, + }; + + x.anim.jump_to(&ct, edge); + } + _ => { + error!("called `sprite::take_edge` on an invalid name `{name}`") + } + } + }, + ); + + let state = state_src.clone(); + let _ = FuncRegistration::new("set_angle") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString, x: f32| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Sprite(s)) => s.set_angle(x), + _ => { + error!("called `sprite::set_angle` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let _ = FuncRegistration::new("set_rect") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString, x: Rect| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Sprite(s)) => s.set_rect(x), + _ => { + error!("called `sprite::set_rect` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let _ = FuncRegistration::new("set_color") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString, x: Color| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Sprite(s)) => s.set_color(x), + _ => { + error!("called `sprite::set_color` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let _ = FuncRegistration::new("exists") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Sprite(_)) => true, + _ => false, + } + }); + + return module; +} diff --git a/crates/render/src/ui/api/functions/textbox.rs b/crates/render/src/ui/api/functions/textbox.rs new file mode 100644 index 0000000..a021aa3 --- /dev/null +++ b/crates/render/src/ui/api/functions/textbox.rs @@ -0,0 +1,226 @@ +use glyphon::{cosmic_text::Align, FamilyOwned, FontSystem, Style, Weight}; +use log::error; +use rhai::{FnNamespace, FuncRegistration, ImmutableString, Module}; +use std::{cell::RefCell, rc::Rc}; + +use super::super::{Color, Rect}; +use crate::ui::{elements::TextBox, UiElement, UiState}; + +pub fn build_textbox_module( + font_src: Rc>, + state_src: Rc>, +) -> Module { + let mut module = Module::new(); + module.set_id("GalacticaTextboxModule"); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("add") + .with_namespace(FnNamespace::Internal) + .set_into_module( + &mut module, + // TODO: fix ugly spaces + move |name: ImmutableString, + font_size: f32, + line_height: f32, + rect: Rect, + color: Color| { + let mut ui_state = state.borrow_mut(); + + if ui_state.elements.contains_key(&name) { + error!("tried to make a textbox using an existing name `{name}`"); + return; + } + + ui_state.names.push(name.clone()); + ui_state.elements.insert( + name.clone(), + UiElement::Text(TextBox::new( + &mut font.borrow_mut(), + name.clone(), + font_size, + line_height, + rect, + color, + )), + ); + }, + ); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("set_text") + .with_namespace(FnNamespace::Internal) + .set_into_module( + &mut module, + move |name: ImmutableString, text: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_text(&mut font.borrow_mut(), text.as_str()), + _ => { + error!("called `textbox::set_text` on an invalid name `{name}`") + } + } + }, + ); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("align_left") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Left), + _ => { + error!("called `textbox::align_left` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("align_right") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Right), + _ => { + error!("called `textbox::align_right` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("align_justify") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Justified), + _ => { + error!("called `textbox::align_justify` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("align_center") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Center), + _ => { + error!("called `textbox::align_center` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("weight_bold") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_weight(&mut font.borrow_mut(), Weight::BOLD), + _ => { + error!("called `textbox::weight_bold` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("weight_normal") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_weight(&mut font.borrow_mut(), Weight::NORMAL), + _ => { + error!("called `textbox::weight_normal` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("font_serif") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_font(&mut font.borrow_mut(), FamilyOwned::Serif), + _ => { + error!("called `textbox::font_serif` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("font_sans") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => { + x.set_font(&mut font.borrow_mut(), FamilyOwned::SansSerif) + } + _ => { + error!("called `textbox::font_sans` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("font_mono") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => { + x.set_font(&mut font.borrow_mut(), FamilyOwned::Monospace) + } + _ => { + error!("called `textbox::font_mono` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("style_normal") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_style(&mut font.borrow_mut(), Style::Normal), + _ => { + error!("called `textbox::style_normal` on an invalid name `{name}`") + } + } + }); + + let state = state_src.clone(); + let font = font_src.clone(); + let _ = FuncRegistration::new("style_italic") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |name: ImmutableString| { + let mut ui_state = state.borrow_mut(); + match ui_state.get_mut_by_name(&name) { + Some(UiElement::Text(x)) => x.set_style(&mut font.borrow_mut(), Style::Italic), + _ => { + error!("called `textbox::style_italic` on an invalid name `{name}`") + } + } + }); + + return module; +} diff --git a/crates/render/src/ui/api/functions/ui.rs b/crates/render/src/ui/api/functions/ui.rs new file mode 100644 index 0000000..7b9c413 --- /dev/null +++ b/crates/render/src/ui/api/functions/ui.rs @@ -0,0 +1,19 @@ +use rhai::{FnNamespace, FuncRegistration, ImmutableString, Module}; +use std::{cell::RefCell, rc::Rc}; + +use crate::ui::UiState; + +pub fn build_ui_module(state_src: Rc>) -> Module { + let mut module = Module::new(); + module.set_id("GalacticaUiModule"); + + let state = state_src.clone(); + let _ = FuncRegistration::new("go_to_scene") + .with_namespace(FnNamespace::Internal) + .set_into_module(&mut module, move |scene: ImmutableString| { + let mut ui_state = state.borrow_mut(); + ui_state.set_scene(scene); + }); + + return module; +} diff --git a/crates/render/src/ui/api/anchor.rs b/crates/render/src/ui/api/helpers/anchor.rs similarity index 100% rename from crates/render/src/ui/api/anchor.rs rename to crates/render/src/ui/api/helpers/anchor.rs diff --git a/crates/render/src/ui/api/color.rs b/crates/render/src/ui/api/helpers/color.rs similarity index 100% rename from crates/render/src/ui/api/color.rs rename to crates/render/src/ui/api/helpers/color.rs diff --git a/crates/render/src/ui/api/helpers/mod.rs b/crates/render/src/ui/api/helpers/mod.rs new file mode 100644 index 0000000..b15e2e5 --- /dev/null +++ b/crates/render/src/ui/api/helpers/mod.rs @@ -0,0 +1,4 @@ +pub mod anchor; +pub mod color; +pub mod rect; +pub mod vector; diff --git a/crates/render/src/ui/api/rect.rs b/crates/render/src/ui/api/helpers/rect.rs similarity index 99% rename from crates/render/src/ui/api/rect.rs rename to crates/render/src/ui/api/helpers/rect.rs index ab8ab51..59bad45 100644 --- a/crates/render/src/ui/api/rect.rs +++ b/crates/render/src/ui/api/helpers/rect.rs @@ -2,7 +2,7 @@ use nalgebra::{Point2, Vector2}; use rhai::{CustomType, TypeBuilder}; use winit::{dpi::LogicalSize, window::Window}; -use super::Anchor; +use super::anchor::Anchor; use crate::{RenderInput, RenderState}; #[derive(Debug, Clone)] diff --git a/crates/render/src/ui/api/vector.rs b/crates/render/src/ui/api/helpers/vector.rs similarity index 100% rename from crates/render/src/ui/api/vector.rs rename to crates/render/src/ui/api/helpers/vector.rs diff --git a/crates/render/src/ui/api/mod.rs b/crates/render/src/ui/api/mod.rs index 8934310..fe37744 100644 --- a/crates/render/src/ui/api/mod.rs +++ b/crates/render/src/ui/api/mod.rs @@ -1,20 +1,25 @@ -mod anchor; -mod color; mod event; -mod rect; +mod functions; +mod helpers; mod state; -mod vector; -pub use anchor::*; -pub use color::*; pub use event::*; -pub use rect::*; +use glyphon::FontSystem; +pub use helpers::{anchor::*, color::*, rect::*, vector::*}; +use log::debug; pub use state::*; -pub use vector::*; -use rhai::{exported_module, Engine}; +use super::UiState; +use galactica_content::Content; +use rhai::{exported_module, Dynamic, Engine}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; -pub fn register_into_engine(engine: &mut Engine) { +pub fn register_into_engine( + engine: &mut Engine, + ct_src: Arc, + font_src: Rc>, + state_src: Rc>, +) { engine // Helpers .build_type::() @@ -31,4 +36,29 @@ pub fn register_into_engine(engine: &mut Engine) { // Bigger modules .register_type_with_name::("Anchor") .register_static_module("Anchor", exported_module!(anchor_mod).into()); + + // Extra functions + engine.register_fn("print", move |d: Dynamic| { + debug!("{:?}", d); + }); + engine.register_fn("clamp", move |x: f32, l: f32, h: f32| x.clamp(l, h)); + + // Modules + engine.register_static_module( + "sprite", + functions::build_sprite_module(ct_src.clone(), state_src.clone()).into(), + ); + engine.register_static_module( + "textbox", + functions::build_textbox_module(font_src.clone(), state_src.clone()).into(), + ); + engine.register_static_module( + "radialbar", + functions::build_radialbar_module(state_src.clone()).into(), + ); + engine.register_static_module("ui", functions::build_ui_module(state_src.clone()).into()); + engine.register_static_module( + "conf", + functions::build_conf_module(state_src.clone()).into(), + ); } diff --git a/crates/render/src/ui/executor.rs b/crates/render/src/ui/executor.rs index 317a02d..8337d8a 100644 --- a/crates/render/src/ui/executor.rs +++ b/crates/render/src/ui/executor.rs @@ -1,9 +1,8 @@ use anyhow::{Context, Result}; -use galactica_content::{resolve_edge_as_edge, Content}; +use galactica_content::Content; use galactica_system::phys::PhysSimShipHandle; use galactica_util::rhai_error_to_anyhow; -use glyphon::{cosmic_text::Align, FamilyOwned, FontSystem, Style, Weight}; -use log::{debug, error}; +use log::debug; use rhai::{ packages::{BasicArrayPackage, BasicStringPackage, LogicPackage, MoreStringPackage, Package}, Dynamic, Engine, ImmutableString, Scope, @@ -11,8 +10,7 @@ use rhai::{ use std::{cell::RefCell, num::NonZeroU32, rc::Rc, sync::Arc}; use super::{ - api::{self, Color, MouseClickEvent, MouseHoverEvent, PlayerShipStateEvent, Rect}, - elements::{RadialBar, Sprite, TextBox}, + api::{self, MouseClickEvent, MouseHoverEvent, PlayerShipStateEvent}, event::Event, UiConfig, UiElement, UiState, }; @@ -46,12 +44,11 @@ impl UiScriptExecutor { // Enables custom operators engine.set_fast_operators(false); - api::register_into_engine(&mut engine); - Self::register_api( + api::register_into_engine( + &mut engine, ct.clone(), state.text_font_system.clone(), elements.clone(), - &mut engine, ); Self { @@ -241,426 +238,3 @@ impl UiScriptExecutor { return Ok(()); } } - -// API -impl UiScriptExecutor { - pub fn register_api( - ct_src: Arc, - font_src: Rc>, - s: Rc>, - engine: &mut Engine, - ) { - // Utilities - { - let c = s.clone(); - engine.register_fn("go_to_scene", move |scene: ImmutableString| { - let mut ui_state = c.borrow_mut(); - ui_state.set_scene(scene); - }); - - let c = s.clone(); - engine.register_fn("conf_set_phys", move |b: bool| { - let mut ui_state = c.borrow_mut(); - ui_state.config.show_phys = b; - }); - - let c = s.clone(); - engine.register_fn("conf_set_starfield", move |b: bool| { - let mut ui_state = c.borrow_mut(); - ui_state.config.show_starfield = b; - }); - - engine.register_fn("print", move |d: Dynamic| { - debug!("{:?}", d); - }); - - engine.register_fn("clamp", move |x: f32, l: f32, h: f32| x.clamp(l, h)); - } - - // Sprites - { - let c = s.clone(); - let ct = ct_src.clone(); - engine.register_fn( - "add_sprite", - move |name: ImmutableString, sprite: ImmutableString, rect: Rect| { - let mut ui_state = c.borrow_mut(); - - let sprite_handle = ct.get_sprite_handle(sprite.as_str()); - if sprite_handle.is_none() { - error!("made a sprite using an invalid source `{sprite}`"); - return; - } - - if ui_state.elements.contains_key(&name) { - error!("tried to make a sprite using an existing name `{name}`"); - return; - } - - ui_state.names.push(name.clone()); - ui_state.elements.insert( - name.clone(), - UiElement::Sprite(Sprite::new( - &ct, - name.clone(), - sprite_handle.unwrap(), - rect, - )), - ); - }, - ); - - let c = s.clone(); - engine.register_fn("remove_sprite", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - if ui_state.elements.contains_key(&name) { - ui_state.elements.remove(&name).unwrap(); - ui_state.names.retain(|x| *x != name); - } else { - error!("called `remove_sprite` on an invalid name `{name}`") - } - }); - - let c = s.clone(); - let ct = ct_src.clone(); - engine.register_fn( - "sprite_set_mask", - move |name: ImmutableString, mask: ImmutableString| { - let mut ui_state = c.borrow_mut(); - - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Sprite(x)) => { - let m = ct.get_sprite_handle(mask.as_str()); - if m.is_none() { - error!("called `set_sprite_mask` with an invalid mask `{mask}`"); - return; - } - x.set_mask(m) - } - - _ => { - error!("called `sprite_set_mask` on an invalid name `{name}`") - } - } - }, - ); - - let c = s.clone(); - let ct = ct_src.clone(); - engine.register_fn( - "sprite_take_edge", - move |name: ImmutableString, edge_name: ImmutableString, duration: f32| { - let mut ui_state = c.borrow_mut(); - - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Sprite(x)) => { - let sprite_handle = x.anim.get_sprite(); - let sprite = &ct.get_sprite(sprite_handle); - - let edge = resolve_edge_as_edge(edge_name.as_str(), duration, |x| { - sprite.get_section_handle_by_name(x) - }); - let edge = match edge { - Err(_) => { - error!( - "called `sprite_take_edge` on an invalid edge `{}` on sprite `{}`", - edge_name, sprite.name - ); - return; - } - Ok(s) => s, - }; - - x.anim.jump_to(&ct, edge); - } - _ => { - error!("called `sprite_take_edge` on an invalid name `{name}`") - } - } - }, - ); - - let c = s.clone(); - engine.register_fn("sprite_set_angle", move |name: ImmutableString, x: f32| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Sprite(s)) => s.set_angle(x), - _ => { - error!("called `sprite_set_angle` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - engine.register_fn("sprite_set_rect", move |name: ImmutableString, x: Rect| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Sprite(s)) => s.set_rect(x), - _ => { - error!("called `sprite_set_rect` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - engine.register_fn( - "sprite_set_color", - move |name: ImmutableString, x: Color| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Sprite(s)) => s.set_color(x), - _ => { - error!("called `sprite_set_color` on an invalid name `{name}`") - } - } - }, - ); - - let c = s.clone(); - engine.register_fn("sprite_exists", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Sprite(_)) => true, - _ => false, - } - }); - } - - // Textboxes - { - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn( - "add_textbox", - // TODO: fix ugly spaces - move |name: ImmutableString, - font_size: f32, - line_height: f32, - rect: Rect, - color: Color| { - let mut ui_state = c.borrow_mut(); - - if ui_state.elements.contains_key(&name) { - error!("tried to make a textbox using an existing name `{name}`"); - return; - } - - ui_state.names.push(name.clone()); - ui_state.elements.insert( - name.clone(), - UiElement::Text(TextBox::new( - &mut font.borrow_mut(), - name.clone(), - font_size, - line_height, - rect, - color, - )), - ); - }, - ); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn( - "textbox_set_text", - move |name: ImmutableString, text: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => { - x.set_text(&mut font.borrow_mut(), text.as_str()) - } - _ => { - error!("called `textbox_set_text` on an invalid name `{name}`") - } - } - }, - ); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_align_left", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Left), - _ => { - error!("called `textbox_align_left` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_align_right", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Right), - _ => { - error!("called `textbox_align_right` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_align_justify", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => { - x.set_align(&mut font.borrow_mut(), Align::Justified) - } - _ => { - error!("called `textbox_align_justify` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_align_center", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => x.set_align(&mut font.borrow_mut(), Align::Center), - _ => { - error!("called `textbox_align_center` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_weight_bold", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => x.set_weight(&mut font.borrow_mut(), Weight::BOLD), - _ => { - error!("called `textbox_weight_bold` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_weight_normal", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => { - x.set_weight(&mut font.borrow_mut(), Weight::NORMAL) - } - _ => { - error!("called `textbox_weight_normal` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_font_serif", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => { - x.set_font(&mut font.borrow_mut(), FamilyOwned::Serif) - } - _ => { - error!("called `textbox_font_serif` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_font_sans", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => { - x.set_font(&mut font.borrow_mut(), FamilyOwned::SansSerif) - } - _ => { - error!("called `textbox_font_sans` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_font_mono", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => { - x.set_font(&mut font.borrow_mut(), FamilyOwned::Monospace) - } - _ => { - error!("called `textbox_font_mono` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_style_normal", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => x.set_style(&mut font.borrow_mut(), Style::Normal), - _ => { - error!("called `textbox_style_normal` on an invalid name `{name}`") - } - } - }); - - let c = s.clone(); - let font = font_src.clone(); - engine.register_fn("textbox_style_italic", move |name: ImmutableString| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::Text(x)) => x.set_style(&mut font.borrow_mut(), Style::Italic), - _ => { - error!("called `textbox_style_italic` on an invalid name `{name}`") - } - } - }); - } - - // Radialbars - { - let c = s.clone(); - engine.register_fn( - "add_radialbar", - // TODO: fix ugly spaces - move |name: ImmutableString, stroke: f32, color: Color, rect: Rect| { - let mut ui_state = c.borrow_mut(); - - if ui_state.elements.contains_key(&name) { - error!("tried to make a radialbar using an existing name `{name}`"); - return; - } - - ui_state.names.push(name.clone()); - ui_state.elements.insert( - name.clone(), - UiElement::RadialBar(RadialBar::new( - name.clone(), - stroke, - color, - rect, - 1.0, - )), - ); - }, - ); - - let c = s.clone(); - engine.register_fn( - "radialbar_set_val", - move |name: ImmutableString, val: f32| { - let mut ui_state = c.borrow_mut(); - match ui_state.get_mut_by_name(&name) { - Some(UiElement::RadialBar(x)) => x.set_val(val), - _ => { - error!("called `radialbar_set_val` on an invalid name `{name}`") - } - } - }, - ); - } - } -}