Added a few rhai API utilities
parent
5e9f2dd159
commit
7d681268b9
|
@ -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::*;
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
use rhai::{CustomType, TypeBuilder};
|
||||
|
||||
#[derive(Debug, Clone, CustomType)]
|
||||
pub struct State {
|
||||
pub planet_landscape: String,
|
||||
pub planet_name: String,
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue