Added a few rhai API utilities

master
Mark 2024-02-02 22:27:34 -08:00
parent 5e9f2dd159
commit 7d681268b9
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
7 changed files with 396 additions and 0 deletions

View File

@ -0,0 +1,38 @@
mod rect;
mod sprite;
mod spritebuilder;
mod state;
mod textboxbuilder;
mod util;
use rhai::{exported_module, Engine};
pub fn register_into_engine(engine: &mut Engine) {
engine
.build_type::<State>()
.build_type::<Rect>()
.build_type::<SpriteElement>()
.build_type::<SpriteBuilder>()
.build_type::<TextBoxBuilder>()
.register_type_with_name::<SpriteAnchor>("SpriteAnchor")
.register_static_module("SpriteAnchor", exported_module!(spriteanchor_mod).into())
.register_type_with_name::<TextBoxFont>("TextBoxFont")
.register_static_module(
"TextBoxFont",
exported_module!(util::textboxfont_mod).into(),
)
.register_type_with_name::<TextBoxJustify>("TextBoxJustify")
.register_static_module(
"TextBoxJustify",
exported_module!(textboxjustify_mod).into(),
)
.register_type_with_name::<SceneAction>("SceneAction")
.register_static_module("SceneAction", exported_module!(sceneaction_mod).into());
}
pub use rect::*;
pub use sprite::*;
pub use spritebuilder::*;
pub use state::*;
pub use textboxbuilder::*;
pub use util::*;

View File

@ -0,0 +1,126 @@
use nalgebra::{Point2, Vector2};
use rhai::{CustomType, TypeBuilder};
use winit::dpi::LogicalSize;
use super::SpriteAnchor;
use crate::{RenderInput, RenderState};
#[derive(Debug, Clone)]
pub struct Rect {
pub pos: Point2<f32>,
pub dim: Vector2<f32>,
pub anchor_self: SpriteAnchor,
pub anchor_parent: SpriteAnchor,
}
impl Rect {
pub fn new(
x: f32,
y: f32,
w: f32,
h: f32,
anchor_self: SpriteAnchor,
anchor_parent: SpriteAnchor,
) -> Self {
Self {
pos: Point2::new(x, y),
dim: Vector2::new(w, h),
anchor_self,
anchor_parent,
}
}
pub fn to_centered(&self, state: &RenderState, ui_scale: f32) -> CenteredRect {
let w: LogicalSize<f32> = state.window_size.to_logical(state.window.scale_factor());
let w = Vector2::new(w.width, w.height);
let mut pos = self.pos * ui_scale;
let dim = self.dim * ui_scale;
// Origin
match self.anchor_parent {
SpriteAnchor::Center => {}
SpriteAnchor::NorthWest => {
pos += Vector2::new(-w.x, w.y) / 2.0;
}
SpriteAnchor::SouthWest => {
pos += Vector2::new(-w.x, -w.y) / 2.0;
}
SpriteAnchor::NorthEast => {
pos += Vector2::new(w.x, w.y) / 2.0;
}
SpriteAnchor::SouthEast => {
pos += Vector2::new(w.x, -w.y) / 2.0;
}
}
// Offset for self dimensions
match self.anchor_self {
SpriteAnchor::Center => {}
SpriteAnchor::NorthWest => {
pos += Vector2::new(dim.x, -dim.y) / 2.0;
}
SpriteAnchor::NorthEast => {
pos += Vector2::new(-dim.x, -dim.y) / 2.0;
}
SpriteAnchor::SouthWest => {
pos += Vector2::new(dim.x, dim.y) / 2.0;
}
SpriteAnchor::SouthEast => {
pos += Vector2::new(-dim.x, dim.y) / 2.0;
}
};
return CenteredRect { pos, dim };
}
}
impl CustomType for Rect {
fn build(mut builder: TypeBuilder<Self>) {
builder.with_name("Rect").with_fn("Rect", Self::new);
}
}
/// Represents a rectangular region, in absolute coordinates relative to the screen center.
#[derive(Debug, Clone, Copy)]
pub(crate) struct CenteredRect {
/// The position of the top-left corner of this rectangle, in fractional units.
/// (0.0 is left edge of sprite, 1.0 is right edge)
pub pos: Point2<f32>,
/// The width and height of this rectangle, in fractional units.
/// 1.0 will be as tall as the sprite, 0.5 will be half as tall
pub dim: Vector2<f32>,
}
impl CenteredRect {
pub fn contains_point(&self, pt: Point2<f32>) -> bool {
let ne = self.pos + Vector2::new(-self.dim.x, self.dim.y) / 2.0;
let sw = self.pos + Vector2::new(self.dim.x, -self.dim.y) / 2.0;
return (pt.y < ne.y && pt.y > sw.y) && (pt.x > ne.x && pt.x < sw.x);
}
pub fn contains_mouse(&self, input: &RenderInput, state: &RenderState) -> bool {
let fac = state.window.scale_factor() as f32;
let window_size = Vector2::new(
state.window_size.width as f32 / fac,
state.window_size.height as f32 / fac,
);
let pos = input.player.input.get_mouse_pos();
let mouse_pos = Point2::new(
pos.x / fac - window_size.x / 2.0,
window_size.y / 2.0 - pos.y / fac,
);
return self.contains_point(mouse_pos);
}
}

View File

@ -0,0 +1,61 @@
use galactica_content::{resolve_edge_as_edge, Content};
use log::error;
use rhai::{CustomType, TypeBuilder};
use std::{cell::RefCell, rc::Rc};
use crate::ui::util::Sprite;
#[derive(Debug, Clone)]
pub struct SpriteElement {
pub sprite: Rc<RefCell<Sprite>>,
pub ct: Rc<Content>,
}
unsafe impl Send for SpriteElement {}
unsafe impl Sync for SpriteElement {}
impl SpriteElement {
pub fn new(ct: Rc<Content>, sprite: Rc<RefCell<Sprite>>) -> Self {
Self { ct, sprite }
}
// This MUST be &mut, or rhai won't recognize it.
pub fn has_name(&mut self, s: String) -> bool {
self.sprite.as_ref().borrow().name == s
}
pub fn take_edge(&mut self, edge_name: &str, duration: f32) {
let sprite_handle = self.sprite.as_ref().borrow().anim.get_sprite();
let sprite = self.ct.get_sprite(sprite_handle);
let edge = resolve_edge_as_edge(edge_name, duration, |x| {
sprite.get_section_handle_by_name(x)
});
let edge = match edge {
Err(x) => {
error!(
"UI script reference invalid section `{}` in sprite `{}`, skipping",
edge_name, sprite.name
);
error!("error: {:?}", x);
return;
}
Ok(s) => s,
};
self.sprite
.as_ref()
.borrow_mut()
.anim
.jump_to(&self.ct, edge);
}
}
impl CustomType for SpriteElement {
fn build(mut builder: TypeBuilder<Self>) {
builder
.with_name("SpriteElement")
.with_fn("has_name", Self::has_name)
.with_fn("take_edge", Self::take_edge);
}
}

View File

@ -0,0 +1,35 @@
use rhai::{CustomType, TypeBuilder};
use super::Rect;
#[derive(Debug, Clone)]
pub struct SpriteBuilder {
pub name: String,
pub rect: Rect,
pub sprite: String,
pub mask: Option<String>,
}
impl SpriteBuilder {
pub fn new(name: String, sprite: String, rect: Rect) -> Self {
Self {
name,
rect,
sprite,
mask: None,
}
}
pub fn set_mask(&mut self, mask: String) {
self.mask = Some(mask);
}
}
impl CustomType for SpriteBuilder {
fn build(mut builder: TypeBuilder<Self>) {
builder
.with_name("SpriteBuilder")
.with_fn("SpriteBuilder", Self::new)
.with_fn("set_mask", Self::set_mask);
}
}

View File

@ -0,0 +1,7 @@
use rhai::{CustomType, TypeBuilder};
#[derive(Debug, Clone, CustomType)]
pub struct State {
pub planet_landscape: String,
pub planet_name: String,
}

View File

@ -0,0 +1,48 @@
use rhai::{CustomType, TypeBuilder};
use super::{Rect, TextBoxFont, TextBoxJustify};
#[derive(Debug, Clone)]
pub struct TextBoxBuilder {
pub name: String,
pub font_size: f32,
pub line_height: f32,
pub font: TextBoxFont,
pub justify: TextBoxJustify,
pub rect: Rect,
pub text: String,
}
impl TextBoxBuilder {
pub fn new(
name: String,
font_size: f32,
line_height: f32,
font: TextBoxFont,
justify: TextBoxJustify,
rect: Rect,
) -> Self {
Self {
name,
font_size,
line_height,
font,
justify,
rect,
text: String::new(),
}
}
pub fn set_text(&mut self, text: String) {
self.text = text
}
}
impl CustomType for TextBoxBuilder {
fn build(mut builder: TypeBuilder<Self>) {
builder
.with_name("TextBoxBuilder")
.with_fn("TextBoxBuilder", Self::new)
.with_fn("set_text", Self::set_text);
}
}

View File

@ -0,0 +1,81 @@
use rhai::plugin::*;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum SpriteAnchor {
Center,
NorthWest,
SouthWest,
NorthEast,
SouthEast,
}
#[export_module]
pub mod spriteanchor_mod {
#[allow(non_upper_case_globals)]
pub const Center: SpriteAnchor = SpriteAnchor::Center;
#[allow(non_upper_case_globals)]
pub const NorthWest: SpriteAnchor = SpriteAnchor::NorthWest;
#[allow(non_upper_case_globals)]
pub const NorthEast: SpriteAnchor = SpriteAnchor::NorthEast;
#[allow(non_upper_case_globals)]
pub const SouthWest: SpriteAnchor = SpriteAnchor::SouthWest;
#[allow(non_upper_case_globals)]
pub const SouthEast: SpriteAnchor = SpriteAnchor::SouthEast;
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum TextBoxFont {
Serif,
SansSerif,
Monospace,
}
#[export_module]
pub mod textboxfont_mod {
#[allow(non_upper_case_globals)]
pub const Serif: TextBoxFont = TextBoxFont::Serif;
#[allow(non_upper_case_globals)]
pub const SansSerif: TextBoxFont = TextBoxFont::SansSerif;
#[allow(non_upper_case_globals)]
pub const Monospace: TextBoxFont = TextBoxFont::Monospace;
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum TextBoxJustify {
Center,
Left,
}
#[export_module]
pub mod textboxjustify_mod {
#[allow(non_upper_case_globals)]
pub const Center: TextBoxJustify = TextBoxJustify::Center;
#[allow(non_upper_case_globals)]
pub const Left: TextBoxJustify = TextBoxJustify::Left;
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum SceneAction {
None,
SceneOutfitter,
SceneLanded,
}
#[export_module]
pub mod sceneaction_mod {
#[allow(non_upper_case_globals)]
pub const None: SceneAction = SceneAction::None;
#[allow(non_upper_case_globals)]
pub const SceneOutfitter: SceneAction = SceneAction::SceneOutfitter;
#[allow(non_upper_case_globals)]
pub const SceneLanded: SceneAction = SceneAction::SceneLanded;
}