Compare commits

..

No commits in common. "39f52ddafcbdb741cf7bcf209049e1f3cb9d3ad7" and "47a73224c6650a595c24f8dfe7e2f12d3a1bdf52" have entirely different histories.

18 changed files with 274 additions and 817 deletions

386
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -74,4 +74,10 @@ lazy_static = "1.4.0"
clap = { version = "4.4.18", features = ["derive"] } clap = { version = "4.4.18", features = ["derive"] }
log = "0.4.20" log = "0.4.20"
log4rs = { version = "1.2.0", features = ["console_appender"] } log4rs = { version = "1.2.0", features = ["console_appender"] }
rhai = { version = "1.17.1", features = ["f32_float", "no_custom_syntax"] } rhai = { version = "1.17.0", features = [
"f32_float",
"only_i32",
"metadata",
"no_custom_syntax",
"no_closure",
] }

View File

@ -1,10 +1,8 @@
# Specific projects # Specific projects
## Now: ## Now:
- Clean up API (modules)
- Persistent variables
- Better planet icons
- Clean up scripting & errors - Clean up scripting & errors
- Fix radar
- Mouse colliders - Mouse colliders
- UI captures input? - UI captures input?
- No UI zoom scroll - No UI zoom scroll

View File

@ -32,46 +32,6 @@ fn init(state) {
Anchor::NorthEast Anchor::NorthEast
) )
); );
let radar_size = 150.0;
let radar_range = 4000.0;
add_sprite(
"radar",
"ui::radar",
Rect(
5.0, -5.0,
radar_size, radar_size,
Anchor::NorthWest,
Anchor::NorthWest
)
);
let init_pos = Rect(
(radar_size / 2.0 + 5),
(radar_size / -2.0 - 5),
3.5, 3.5,
Anchor::Center,
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));
add_sprite("radar.arrow", "ui::centerarrow", init_pos);
} }
fn event(state, event) { fn event(state, event) {
@ -93,209 +53,4 @@ fn step(state) {
state.player_ship().get_hull() state.player_ship().get_hull()
/ state.player_ship().get_total_hull() / state.player_ship().get_total_hull()
); );
// TODO: share variables with init();
let radar_size = 150.0;
let radar_range = 4000.0;
let hide_range = 0.85;
let shrink_distance = 20.0;
let p_pos = state.player_ship().get_pos();
// Radar arrow
{
let q = Vector(0.0, 0.0) - state.player_ship().get_pos();
let m = q.norm();
let angle = Vector(1.0, 0.0).clockwise_angle(q);
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",
Rect(
pos.x(), pos.y(),
5.0, 5.0,
Anchor::Center,
Anchor::NorthWest
)
);
sprite_set_angle("radar.arrow", angle - 90.0);
sprite_set_color(
"radar.arrow",
Color(
1.0, 1.0, 1.0,
clamp((m - 200.0) /400.0, 0.0, 1.0)
)
)
}
// Ships
{
for s in state.ships() {
let uid = s.get_uid();
let sprite_name = `radar.ship.${uid}`;
if (
!s.is_some() ||
s.is_dead() ||
s.is_landed()
){
if sprite_exists(sprite_name) {
remove_sprite(sprite_name);
}
continue;
}
let color = Color(0.2, 0.2, 0.2, 1.0);
if s.is_flying() {
color = s.get_faction_color()
}
let size_init = s.get_size() * (1.0 / 50.0);
let pos = s.get_pos();
let d = (pos - p_pos) / radar_range;
let m = d.norm() + (size_init / (2.0 * radar_size));
if m < hide_range {
let size = (hide_range - m) * size_init * shrink_distance;
if size > size_init {
size = size_init;
}
if size < 1.0 {
if sprite_exists(sprite_name) {
remove_sprite(sprite_name);
}
continue;
}
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(
sprite_name,
"ui::shipblip",
Rect(
pos.x(), pos.y(),
size, size,
Anchor::Center,
Anchor::NorthWest
)
);
} else {
sprite_set_rect(
sprite_name,
Rect(
pos.x(), pos.y(),
size, size,
Anchor::Center,
Anchor::NorthWest
)
);
}
sprite_set_color(sprite_name, color);
}
}
}
// System objects
{
for o in state.objects() {
let sprite_name = `radar.object.${o.get_label()}`;
if !o.is_some() {
if sprite_exists(sprite_name) {
remove_sprite(sprite_name);
}
continue;
}
let size_init = (o.get_size() / o.get_pos_z()) / (radar_range * (1.0 / 300.0));
let pos = o.get_pos();
let d = (pos - p_pos) / radar_range;
let m = d.norm() + (size_init / (2.0 * radar_size));
if m < hide_range {
let size = (hide_range - m) * size_init * shrink_distance;
if size > size_init {
size = size_init;
}
if size < 1.0 {
// Don't draw tiny sprites, they flicker
if sprite_exists(sprite_name) {
remove_sprite(sprite_name);
}
continue;
}
let pos = (
Vector(radar_size / 2.0 + 5.0, radar_size / -2.0 - 5.0)
+ (d * radar_size / 2.0)
);
if !sprite_exists(sprite_name) {
add_sprite(
sprite_name,
"ui::planetblip",
Rect(
pos.x(), pos.y(),
size, size,
Anchor::Center,
Anchor::NorthWest
)
);
} else {
sprite_set_rect(
sprite_name,
Rect(
pos.x(), pos.y(),
size, size,
Anchor::Center,
Anchor::NorthWest
)
);
}
}
}
}
// Window frame
{
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",
Rect(
(radar_size / 2.0 + 5) - dx,
(radar_size / -2.0 - 5) + dy,
3.5, 3.5,
Anchor::Center,
Anchor::NorthWest
)
);
sprite_set_rect("radar.frame.se",
Rect(
(radar_size / 2.0 + 5) - dx,
(radar_size / -2.0 - 5) - dy,
3.5, 3.5,
Anchor::Center,
Anchor::NorthWest
)
);
sprite_set_rect("radar.frame.sw",
Rect(
(radar_size / 2.0 + 5) + dx,
(radar_size / -2.0 - 5) - dy,
3.5, 3.5,
Anchor::Center,
Anchor::NorthWest
)
);
sprite_set_rect("radar.frame.nw",
Rect(
(radar_size / 2.0 + 5) + dx,
(radar_size / -2.0 - 5) + dy,
3.5, 3.5,
Anchor::Center,
Anchor::NorthWest
)
);
}
} }

View File

@ -6,7 +6,7 @@ pub(crate) mod syntax {
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use galactica_packer::SpriteAtlas; use galactica_packer::SpriteAtlas;
use galactica_util::rhai_error_to_anyhow; use galactica_util::rhai_error_to_anyhow;
use rhai::{Engine, OptimizationLevel}; use rhai::Engine;
use serde::Deserialize; use serde::Deserialize;
use std::{ use std::{
collections::HashMap, collections::HashMap,
@ -61,9 +61,7 @@ pub(crate) mod syntax {
} }
}; };
let mut engine = Engine::new_raw(); let engine = Engine::new();
engine.set_optimization_level(OptimizationLevel::Full);
engine.set_max_expr_depths(0, 0);
let mut ui_scenes = HashMap::new(); let mut ui_scenes = HashMap::new();
for (n, p) in self.ui_scene { for (n, p) in self.ui_scene {
ui_scenes.insert( ui_scenes.insert(

View File

@ -126,12 +126,9 @@ pub struct SystemObject {
/// If true, ships may land on this object /// If true, ships may land on this object
pub landable: bool, pub landable: bool,
/// The pretty display name of this object /// The display name of this object
pub name: Option<String>, pub name: Option<String>,
/// The system-unique label of this object
pub label: String,
/// The description of this object (shown on landed ui) /// The description of this object (shown on landed ui)
pub desc: Option<String>, pub desc: Option<String>,
@ -262,7 +259,6 @@ impl crate::Build for System {
} }
objects.push(SystemObject { objects.push(SystemObject {
label: label.clone(),
sprite: sprite_handle, sprite: sprite_handle,
image: image_handle, image: image_handle,
pos: resolve_position(&system.object, &obj, cycle_detector) pos: resolve_position(&system.object, &obj, cycle_detector)

View File

@ -33,4 +33,3 @@ bytemuck = { workspace = true }
glyphon = { workspace = true } glyphon = { workspace = true }
log = { workspace = true } log = { workspace = true }
rhai = { workspace = true } rhai = { workspace = true }
rapier2d = { workspace = true }

View File

@ -3,7 +3,7 @@ use rhai::{CustomType, TypeBuilder};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Color { pub struct Color {
val: Vector4<f32>, pub val: Vector4<f32>,
} }
impl Color { impl Color {

View File

@ -1,28 +0,0 @@
use rhai::{CustomType, TypeBuilder};
#[derive(Debug, Clone)]
pub struct SceneConfig {
pub show_phys: bool,
pub show_starfield: bool,
}
impl SceneConfig {
pub fn new() -> Self {
Self {
show_phys: false,
show_starfield: false,
}
}
}
impl CustomType for SceneConfig {
fn build(mut builder: TypeBuilder<Self>) {
builder
.with_name("SceneConfig")
.with_fn("SceneConfig", Self::new)
.with_fn("show_phys", |s: &mut Self, x: bool| s.show_phys = x)
.with_fn("show_starfield", |s: &mut Self, x: bool| {
s.show_starfield = x
});
}
}

View File

@ -3,14 +3,12 @@ mod color;
mod event; mod event;
mod rect; mod rect;
mod state; mod state;
mod vector;
pub use anchor::*; pub use anchor::*;
pub use color::*; pub use color::*;
pub use event::*; pub use event::*;
pub use rect::*; pub use rect::*;
pub use state::*; pub use state::*;
pub use vector::*;
use rhai::{exported_module, Engine}; use rhai::{exported_module, Engine};
@ -19,7 +17,6 @@ pub fn register_into_engine(engine: &mut Engine) {
// Helpers // Helpers
.build_type::<Rect>() .build_type::<Rect>()
.build_type::<Color>() .build_type::<Color>()
.build_type::<UiVector>()
// State // State
.build_type::<State>() .build_type::<State>()
.build_type::<ShipState>() .build_type::<ShipState>()

View File

@ -1,16 +1,13 @@
use galactica_content::{Ship, SystemObject, SystemObjectHandle}; use galactica_content::{Ship, SystemObject, SystemObjectHandle};
use galactica_system::{ use galactica_system::{
data::{self}, data::{self, ShipData},
phys::{objects::PhysShip, PhysSimShipHandle}, phys::PhysSimShipHandle,
}; };
use galactica_util::to_degrees;
use log::error; use log::error;
use rapier2d::dynamics::RigidBody; use rhai::{CustomType, TypeBuilder};
use rhai::{Array, CustomType, Dynamic, ImmutableString, TypeBuilder};
use std::sync::Arc; use std::sync::Arc;
use super::{Color, UiVector}; use crate::RenderInput;
use crate::{RenderInput, RenderState};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ShipState { pub struct ShipState {
@ -18,6 +15,10 @@ pub struct ShipState {
input: Arc<RenderInput>, input: Arc<RenderInput>,
} }
// TODO: remove this
unsafe impl Send for ShipState {}
unsafe impl Sync for ShipState {}
impl ShipState { impl ShipState {
fn get_content(&mut self) -> &Ship { fn get_content(&mut self) -> &Ship {
let ship = self let ship = self
@ -29,27 +30,18 @@ impl ShipState {
self.input.ct.get_ship(handle) self.input.ct.get_ship(handle)
} }
fn get_ship(&mut self) -> &PhysShip { fn get_data(&mut self) -> &ShipData {
let ship = self let ship = self
.input .input
.phys_img .phys_img
.get_ship(self.ship.as_ref().unwrap()) .get_ship(self.ship.as_ref().unwrap())
.unwrap(); .unwrap();
&ship.ship ship.ship.get_data()
}
fn get_body(&mut self) -> &RigidBody {
let ship = self
.input
.phys_img
.get_ship(self.ship.as_ref().unwrap())
.unwrap();
&ship.rigidbody
} }
fn landed_on(&mut self) -> SystemObjectState { fn landed_on(&mut self) -> SystemObjectState {
let input = self.input.clone(); let input = self.input.clone();
match self.get_ship().get_data().get_state() { match self.get_data().get_state() {
data::ShipState::Landed { target } => { data::ShipState::Landed { target } => {
return SystemObjectState { return SystemObjectState {
input, input,
@ -71,48 +63,31 @@ impl CustomType for ShipState {
builder builder
.with_name("ShipState") .with_name("ShipState")
.with_fn("is_some", |s: &mut Self| s.ship.is_some()) .with_fn("is_some", |s: &mut Self| s.ship.is_some())
.with_fn("is_dead", |s: &mut Self| { .with_fn("is_dead", |s: &mut Self| s.get_data().get_state().is_dead())
s.get_ship().get_data().get_state().is_dead()
})
.with_fn("is_landed", |s: &mut Self| { .with_fn("is_landed", |s: &mut Self| {
s.get_ship().get_data().get_state().is_landed() s.get_data().get_state().is_landed()
}) })
.with_fn("is_landing", |s: &mut Self| { .with_fn("is_landing", |s: &mut Self| {
s.get_ship().get_data().get_state().is_landing() s.get_data().get_state().is_landing()
}) })
.with_fn("is_flying", |s: &mut Self| { .with_fn("is_flying", |s: &mut Self| {
s.get_ship().get_data().get_state().is_flying() s.get_data().get_state().is_flying()
}) })
.with_fn("is_unlanding", |s: &mut Self| { .with_fn("is_unlanding", |s: &mut Self| {
s.get_ship().get_data().get_state().is_unlanding() s.get_data().get_state().is_unlanding()
}) })
.with_fn("is_collapsing", |s: &mut Self| { .with_fn("is_collapsing", |s: &mut Self| {
s.get_ship().get_data().get_state().is_collapsing() s.get_data().get_state().is_collapsing()
}) })
.with_fn("name", |s: &mut Self| s.get_content().name.clone()) .with_fn("name", |s: &mut Self| s.get_content().name.clone())
.with_fn("thumbnail", |s: &mut Self| s.get_content().thumb) .with_fn("thumbnail", |s: &mut Self| s.get_content().thumb)
.with_fn("landed_on", |s: &mut Self| s.landed_on()) .with_fn("landed_on", |s: &mut Self| s.landed_on())
.with_fn("get_shields", |s: &mut Self| { .with_fn("get_shields", |s: &mut Self| s.get_data().get_shields())
s.get_ship().get_data().get_shields()
})
.with_fn("get_total_shields", |s: &mut Self| { .with_fn("get_total_shields", |s: &mut Self| {
s.get_ship().get_data().get_outfits().get_total_shields() s.get_data().get_outfits().get_total_shields()
}) })
.with_fn("get_total_hull", |s: &mut Self| s.get_content().hull) .with_fn("get_total_hull", |s: &mut Self| s.get_content().hull)
.with_fn("get_hull", |s: &mut Self| { .with_fn("get_hull", |s: &mut Self| s.get_data().get_hull());
s.get_ship().get_data().get_hull()
})
.with_fn("get_size", |s: &mut Self| s.get_content().size)
.with_fn("get_uid", |s: &mut Self| format!("{}", s.get_ship().uid))
.with_fn("get_pos", |s: &mut Self| {
let t = s.get_body().translation();
UiVector::new(t.x, t.y)
})
.with_fn("get_faction_color", |s: &mut Self| {
let h = s.get_ship().get_data().get_faction();
let c = s.input.ct.get_faction(h).color;
Color::new(c[0], c[1], c[2], 1.0)
});
} }
} }
@ -122,6 +97,10 @@ pub struct SystemObjectState {
input: Arc<RenderInput>, input: Arc<RenderInput>,
} }
// TODO: remove this
unsafe impl Send for SystemObjectState {}
unsafe impl Sync for SystemObjectState {}
impl SystemObjectState { impl SystemObjectState {
fn get_content(&mut self) -> &SystemObject { fn get_content(&mut self) -> &SystemObject {
self.input.ct.get_system_object(self.object.unwrap()) self.input.ct.get_system_object(self.object.unwrap())
@ -167,30 +146,13 @@ impl CustomType for SystemObjectState {
"".to_string() "".to_string()
} }
}) })
.with_fn("is_some", |s: &mut Self| s.object.is_some()) .with_fn("is_some", |s: &mut Self| s.object.is_some());
.with_fn("==", |a: &mut Self, b: Self| a.object == b.object)
.with_fn("get_size", |s: &mut Self| s.get_content().size)
.with_fn("get_label", |s: &mut Self| {
ImmutableString::from(&s.get_content().label)
})
.with_fn("get_angle", |s: &mut Self| {
to_degrees(s.get_content().angle)
})
.with_fn("get_pos", |s: &mut Self| {
let t = s.get_content().pos;
UiVector::new(t.x, t.y)
})
.with_fn("get_pos_z", |s: &mut Self| {
let t = s.get_content().pos;
t.z
});
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct State { pub struct State {
input: Arc<RenderInput>, input: Arc<RenderInput>,
window_aspect: f32,
} }
// TODO: remove this // TODO: remove this
@ -198,11 +160,8 @@ unsafe impl Send for State {}
unsafe impl Sync for State {} unsafe impl Sync for State {}
impl State { impl State {
pub fn new(state: &RenderState, input: Arc<RenderInput>) -> Self { pub fn new(input: Arc<RenderInput>) -> Self {
Self { Self { input }
input,
window_aspect: state.window_aspect,
}
} }
pub fn player_ship(&mut self) -> ShipState { pub fn player_ship(&mut self) -> ShipState {
@ -211,39 +170,12 @@ impl State {
ship: self.input.player.ship.map(|x| PhysSimShipHandle(x)), ship: self.input.player.ship.map(|x| PhysSimShipHandle(x)),
} }
} }
pub fn ships(&mut self) -> Array {
let mut a = Array::new();
for s in self.input.phys_img.iter_ships() {
a.push(Dynamic::from(ShipState {
input: self.input.clone(),
ship: Some(PhysSimShipHandle(s.ship.collider)),
}));
}
return a;
}
pub fn objects(&mut self) -> Array {
let mut a = Array::new();
let s = self.input.current_system;
for o in &self.input.ct.get_system(s).objects {
a.push(Dynamic::from(SystemObjectState {
input: self.input.clone(),
object: Some(o.handle),
}));
}
return a;
}
} }
impl CustomType for State { impl CustomType for State {
fn build(mut builder: TypeBuilder<Self>) { fn build(mut builder: TypeBuilder<Self>) {
builder builder
.with_name("State") .with_name("State")
.with_fn("player_ship", Self::player_ship) .with_fn("player_ship", Self::player_ship);
.with_fn("ships", Self::ships)
.with_fn("objects", Self::objects)
.with_fn("window_aspect", |s: &mut Self| s.window_aspect)
.with_fn("camera_zoom", |s: &mut Self| s.input.camera_zoom);
} }
} }

View File

@ -1,47 +0,0 @@
use galactica_util::{clockwise_angle, to_degrees, to_radians};
use nalgebra::{Rotation2, Vector2};
use rhai::{CustomType, TypeBuilder};
#[derive(Debug, Clone)]
pub struct UiVector {
val: Vector2<f32>,
}
impl UiVector {
pub fn new(x: f32, y: f32) -> Self {
Self {
val: Vector2::new(x, y),
}
}
pub fn rotate(&mut self, angle: f32) -> Self {
return UiVector {
val: Rotation2::new(to_radians(angle)) * self.val,
};
}
pub fn clockwise_angle(&mut self, other: UiVector) -> f32 {
return to_degrees(clockwise_angle(&self.val, &other.val));
}
}
impl CustomType for UiVector {
fn build(mut builder: TypeBuilder<Self>) {
builder
.with_name("Vector")
.with_fn("Vector", Self::new)
.with_fn("rotate", Self::rotate)
.with_fn("clockwise_angle", Self::clockwise_angle)
.with_fn("+", |a: UiVector, b: UiVector| UiVector {
val: a.val + b.val,
})
.with_fn("-", |a: UiVector, b: UiVector| UiVector {
val: a.val - b.val,
})
.with_fn("/", |s: &mut Self, x: f32| UiVector { val: s.val / x })
.with_fn("*", |s: &mut Self, x: f32| UiVector { val: s.val * x })
.with_fn("x", |s: &mut Self| s.val.x)
.with_fn("y", |s: &mut Self| s.val.y)
.with_fn("norm", |s: &mut Self| s.val.magnitude());
}
}

View File

@ -4,10 +4,7 @@ use galactica_system::phys::PhysSimShipHandle;
use galactica_util::rhai_error_to_anyhow; use galactica_util::rhai_error_to_anyhow;
use glyphon::{cosmic_text::Align, FamilyOwned, FontSystem, Style, Weight}; use glyphon::{cosmic_text::Align, FamilyOwned, FontSystem, Style, Weight};
use log::{debug, error}; use log::{debug, error};
use rhai::{ use rhai::{Dynamic, Engine, ImmutableString, Scope};
packages::{BasicArrayPackage, BasicStringPackage, LogicPackage, MoreStringPackage, Package},
Dynamic, Engine, ImmutableString, Scope,
};
use std::{cell::RefCell, num::NonZeroU32, rc::Rc, sync::Arc}; use std::{cell::RefCell, num::NonZeroU32, rc::Rc, sync::Arc};
use super::{ use super::{
@ -34,18 +31,6 @@ impl UiScriptExecutor {
let elements = Rc::new(RefCell::new(UiState::new(ct.clone(), state))); let elements = Rc::new(RefCell::new(UiState::new(ct.clone(), state)));
let mut engine = Engine::new_raw(); let mut engine = Engine::new_raw();
// Required for array iteration
// We may need to add more packages here later.
engine.register_global_module(BasicArrayPackage::new().as_shared_module());
engine.register_global_module(LogicPackage::new().as_shared_module());
engine.register_global_module(BasicStringPackage::new().as_shared_module());
engine.register_global_module(MoreStringPackage::new().as_shared_module());
engine.set_max_expr_depths(0, 0);
// Enables custom operators
engine.set_fast_operators(false);
api::register_into_engine(&mut engine); api::register_into_engine(&mut engine);
Self::register_api( Self::register_api(
ct.clone(), ct.clone(),
@ -68,7 +53,7 @@ impl UiScriptExecutor {
} }
/// Change the current scene /// Change the current scene
pub fn set_scene(&mut self, state: &RenderState, input: Arc<RenderInput>) -> Result<()> { pub fn set_scene(&mut self, input: Arc<RenderInput>) -> Result<()> {
let current_scene = (*self.state).borrow().get_scene().clone(); let current_scene = (*self.state).borrow().get_scene().clone();
if self.last_scene == current_scene { if self.last_scene == current_scene {
return Ok(()); return Ok(());
@ -100,7 +85,7 @@ impl UiScriptExecutor {
.get(current_scene.as_ref().unwrap().as_str()) .get(current_scene.as_ref().unwrap().as_str())
.unwrap(), .unwrap(),
"init", "init",
(State::new(state, input.clone()),), (State::new(input.clone()),),
), ),
) )
.with_context(|| format!("while running `init()`")) .with_context(|| format!("while running `init()`"))
@ -119,7 +104,7 @@ impl UiScriptExecutor {
.borrow_mut() .borrow_mut()
.set_scene(ImmutableString::from(&ct.get_config().start_ui_scene)); .set_scene(ImmutableString::from(&ct.get_config().start_ui_scene));
} }
self.set_scene(state, input.clone())?; self.set_scene(input.clone())?;
let current_scene = (*self.state).borrow().get_scene().clone(); let current_scene = (*self.state).borrow().get_scene().clone();
(*self.state).borrow_mut().step(state, input.clone()); (*self.state).borrow_mut().step(state, input.clone());
@ -136,7 +121,7 @@ impl UiScriptExecutor {
&mut self.scope, &mut self.scope,
ast, ast,
"step", "step",
(State::new(state, input.clone()),), (State::new(input.clone()),),
)) ))
.with_context(|| format!("while calling `step()`")) .with_context(|| format!("while calling `step()`"))
.with_context(|| format!("in ui scene `{}`", current_scene.as_ref().unwrap()))?; .with_context(|| format!("in ui scene `{}`", current_scene.as_ref().unwrap()))?;
@ -169,7 +154,7 @@ impl UiScriptExecutor {
.get(current_scene.as_ref().unwrap().as_str()) .get(current_scene.as_ref().unwrap().as_str())
.unwrap(), .unwrap(),
"event", "event",
(State::new(state, input.clone()), PlayerShipStateEvent {}), (State::new(input.clone()), PlayerShipStateEvent {}),
), ),
) )
.with_context(|| format!("while handling player state change event")) .with_context(|| format!("while handling player state change event"))
@ -229,7 +214,7 @@ impl UiScriptExecutor {
.get(current_scene.as_ref().unwrap().as_str()) .get(current_scene.as_ref().unwrap().as_str())
.unwrap(), .unwrap(),
"event", "event",
(State::new(state, input.clone()), event_arg.clone()), (State::new(input.clone()), event_arg.clone()),
), ),
) )
.with_context(|| format!("while handling event `{:?}`", event_arg)) .with_context(|| format!("while handling event `{:?}`", event_arg))
@ -237,7 +222,6 @@ impl UiScriptExecutor {
} }
} }
self.scope.rewind(0);
return Ok(()); return Ok(());
} }
} }
@ -269,12 +253,6 @@ impl UiScriptExecutor {
let mut ui_state = c.borrow_mut(); let mut ui_state = c.borrow_mut();
ui_state.config.show_starfield = b; 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 // Sprites
@ -285,6 +263,7 @@ impl UiScriptExecutor {
"add_sprite", "add_sprite",
move |name: ImmutableString, sprite: ImmutableString, rect: Rect| { move |name: ImmutableString, sprite: ImmutableString, rect: Rect| {
let mut ui_state = c.borrow_mut(); let mut ui_state = c.borrow_mut();
let len = ui_state.len();
let sprite_handle = ct.get_sprite_handle(sprite.as_str()); let sprite_handle = ct.get_sprite_handle(sprite.as_str());
if sprite_handle.is_none() { if sprite_handle.is_none() {
@ -292,35 +271,16 @@ impl UiScriptExecutor {
return; return;
} }
if ui_state.elements.contains_key(&name) { ui_state.names.insert(name.clone(), len);
error!("tried to make a sprite using an existing name `{name}`"); ui_state.elements.push(UiElement::Sprite(Sprite::new(
return;
}
ui_state.names.push(name.clone());
ui_state.elements.insert(
name.clone(),
UiElement::Sprite(Sprite::new(
&ct, &ct,
name.clone(), name.clone(),
sprite_handle.unwrap(), sprite_handle.unwrap(),
rect, 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 c = s.clone();
let ct = ct_src.clone(); let ct = ct_src.clone();
engine.register_fn( engine.register_fn(
@ -339,7 +299,7 @@ impl UiScriptExecutor {
} }
_ => { _ => {
error!("called `sprite_set_mask` on an invalid name `{name}`") error!("called `set_sprite_mask` on an invalid name `{name}`")
} }
} }
}, },
@ -379,51 +339,6 @@ impl UiScriptExecutor {
} }
}, },
); );
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 // Textboxes
@ -439,24 +354,17 @@ impl UiScriptExecutor {
rect: Rect, rect: Rect,
color: Color| { color: Color| {
let mut ui_state = c.borrow_mut(); let mut ui_state = c.borrow_mut();
let len = ui_state.len();
if ui_state.elements.contains_key(&name) { ui_state.names.insert(name.clone(), len);
error!("tried to make a textbox using an existing name `{name}`"); ui_state.elements.push(UiElement::Text(TextBox::new(
return;
}
ui_state.names.push(name.clone());
ui_state.elements.insert(
name.clone(),
UiElement::Text(TextBox::new(
&mut font.borrow_mut(), &mut font.borrow_mut(),
name.clone(), name.clone(),
font_size, font_size,
line_height, line_height,
rect, rect,
color, color,
)), )));
);
}, },
); );
@ -628,23 +536,16 @@ impl UiScriptExecutor {
// TODO: fix ugly spaces // TODO: fix ugly spaces
move |name: ImmutableString, stroke: f32, color: Color, rect: Rect| { move |name: ImmutableString, stroke: f32, color: Color, rect: Rect| {
let mut ui_state = c.borrow_mut(); let mut ui_state = c.borrow_mut();
let len = ui_state.len();
if ui_state.elements.contains_key(&name) { ui_state.names.insert(name.clone(), len);
error!("tried to make a radialbar using an existing name `{name}`"); ui_state.elements.push(UiElement::RadialBar(RadialBar::new(
return;
}
ui_state.names.push(name.clone());
ui_state.elements.insert(
name.clone(),
UiElement::RadialBar(RadialBar::new(
name.clone(), name.clone(),
stroke, stroke,
color, color,
rect, rect,
1.0, 1.0,
)), )));
);
}, },
); );

View File

@ -23,8 +23,8 @@ pub(crate) struct UiConfig {
} }
pub(crate) struct UiState { pub(crate) struct UiState {
pub elements: HashMap<ImmutableString, UiElement>, pub names: HashMap<ImmutableString, usize>,
pub names: Vec<ImmutableString>, pub elements: Vec<UiElement>,
pub ct: Arc<Content>, pub ct: Arc<Content>,
current_scene: Option<ImmutableString>, current_scene: Option<ImmutableString>,
@ -42,8 +42,8 @@ impl UiState {
pub fn new(ct: Arc<Content>, state: &mut RenderState) -> Self { pub fn new(ct: Arc<Content>, state: &mut RenderState) -> Self {
Self { Self {
ct, ct,
elements: HashMap::new(), names: HashMap::new(),
names: Vec::new(), elements: Vec::new(),
current_scene: None, current_scene: None,
show_timings: true, show_timings: true,
@ -79,15 +79,15 @@ impl UiState {
*/ */
pub fn get_mut_by_idx(&mut self, idx: usize) -> Option<&mut UiElement> { pub fn get_mut_by_idx(&mut self, idx: usize) -> Option<&mut UiElement> {
let name = self.names.get(idx); self.elements.get_mut(idx)
if name.is_none() {
return None;
}
self.elements.get_mut(name.unwrap())
} }
pub fn get_mut_by_name(&mut self, name: &ImmutableString) -> Option<&mut UiElement> { pub fn get_mut_by_name(&mut self, name: &ImmutableString) -> Option<&mut UiElement> {
self.elements.get_mut(name) let idx = self.names.get(name);
if idx.is_none() {
return None;
}
self.get_mut_by_idx(*idx.unwrap())
} }
pub fn get_scene(&self) -> &Option<ImmutableString> { pub fn get_scene(&self) -> &Option<ImmutableString> {
@ -124,7 +124,7 @@ impl<'a> UiState {
v.push(self.fps_indicator.get_textarea(input, window)) v.push(self.fps_indicator.get_textarea(input, window))
} }
for t in self.elements.values() { for t in self.elements.iter() {
match &t { match &t {
UiElement::Text(x) => v.push(x.get_textarea(input, window)), UiElement::Text(x) => v.push(x.get_textarea(input, window)),
_ => {} _ => {}

View File

@ -1,9 +1,5 @@
use super::super::api::Rect; use super::super::api::Rect;
use crate::{ use crate::{ui::event::Event, vertexbuffer::types::UiInstance, RenderInput, RenderState};
ui::{api::Color, event::Event},
vertexbuffer::types::UiInstance,
RenderInput, RenderState,
};
use galactica_content::{Content, SpriteAutomaton, SpriteHandle}; use galactica_content::{Content, SpriteAutomaton, SpriteHandle};
use galactica_util::to_radians; use galactica_util::to_radians;
use rhai::ImmutableString; use rhai::ImmutableString;
@ -13,12 +9,8 @@ pub struct Sprite {
pub anim: SpriteAutomaton, pub anim: SpriteAutomaton,
pub name: ImmutableString, pub name: ImmutableString,
/// Sprite angle, in degrees
angle: f32,
rect: Rect, rect: Rect,
mask: Option<SpriteHandle>, mask: Option<SpriteHandle>,
color: Color,
/// If true, ignore mouse events until click is released /// If true, ignore mouse events until click is released
waiting_for_release: bool, waiting_for_release: bool,
@ -32,8 +24,6 @@ impl Sprite {
name, name,
anim: SpriteAutomaton::new(&ct, sprite), anim: SpriteAutomaton::new(&ct, sprite),
rect, rect,
angle: 0.0,
color: Color::new(1.0, 1.0, 1.0, 1.0),
mask: None, mask: None,
has_mouse: false, has_mouse: false,
has_click: false, has_click: false,
@ -45,18 +35,6 @@ impl Sprite {
self.mask = mask; self.mask = mask;
} }
pub fn set_angle(&mut self, angle: f32) {
self.angle = angle;
}
pub fn set_rect(&mut self, rect: Rect) {
self.rect = rect;
}
pub fn set_color(&mut self, color: Color) {
self.color = color;
}
pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) { pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) {
let rect = self let rect = self
.rect .rect
@ -68,9 +46,9 @@ impl Sprite {
state.push_ui_buffer(UiInstance { state.push_ui_buffer(UiInstance {
position: rect.pos.into(), position: rect.pos.into(),
angle: to_radians(90.0 + self.angle), angle: to_radians(90.0),
dim: rect.dim.into(), dim: rect.dim.into(),
color: self.color.as_array(), color: [1.0, 1.0, 1.0, 1.0],
texture_index: anim_state.texture_index(), texture_index: anim_state.texture_index(),
texture_fade: anim_state.fade, texture_fade: anim_state.fade,
mask_index: self mask_index: self

View File

@ -6,15 +6,7 @@ mod physsim;
mod physwrapper; mod physwrapper;
mod stepresources; mod stepresources;
use std::sync::atomic::{AtomicU64, Ordering};
pub use physimage::*; pub use physimage::*;
pub use physsim::{PhysSim, PhysSimShipHandle}; pub use physsim::{PhysSim, PhysSimShipHandle};
pub use physwrapper::PhysWrapper; pub use physwrapper::PhysWrapper;
pub use stepresources::*; pub use stepresources::*;
/// A unique id given to each physics object
static PHYS_UID: AtomicU64 = AtomicU64::new(0);
fn get_phys_id() -> u64 {
PHYS_UID.fetch_add(1, Ordering::Relaxed)
}

View File

@ -14,7 +14,6 @@ use super::{autopilot, collapse::ShipCollapseSequence, controller::ShipControlle
use crate::{ use crate::{
data::{ShipAutoPilot, ShipData, ShipPersonality, ShipState}, data::{ShipAutoPilot, ShipData, ShipPersonality, ShipState},
phys::{ phys::{
get_phys_id,
objects::{PhysEffect, PhysProjectile}, objects::{PhysEffect, PhysProjectile},
physsim::NewObjects, physsim::NewObjects,
PhysImage, PhysSimShipHandle, PhysStepResources, PhysWrapper, PhysImage, PhysSimShipHandle, PhysStepResources, PhysWrapper,
@ -24,9 +23,6 @@ use crate::{
/// A ship instance in the physics system /// A ship instance in the physics system
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PhysShip { pub struct PhysShip {
/// This ship's unique id
pub uid: u64,
/// This ship's physics handle /// This ship's physics handle
pub rigid_body: RigidBodyHandle, pub rigid_body: RigidBodyHandle,
@ -75,7 +71,6 @@ impl PhysShip {
) -> Self { ) -> Self {
let ship_ct = ct.get_ship(handle); let ship_ct = ct.get_ship(handle);
PhysShip { PhysShip {
uid: get_phys_id(),
anim: SpriteAutomaton::new(ct, ship_ct.sprite), anim: SpriteAutomaton::new(ct, ship_ct.sprite),
rigid_body, rigid_body,
collider, collider,

View File

@ -13,11 +13,6 @@ pub fn to_radians(degrees: f32) -> f32 {
return (degrees / 360.0) * std::f32::consts::TAU; return (degrees / 360.0) * std::f32::consts::TAU;
} }
/// Convert an angle in radians to degrees
pub fn to_degrees(radians: f32) -> f32 {
return (radians / std::f32::consts::TAU) * 360.0;
}
/// Compute the clockwise angle between two vectors /// Compute the clockwise angle between two vectors
/// Returns a value in [-pi, pi] /// Returns a value in [-pi, pi]
pub fn clockwise_angle(a: &Vector2<f32>, b: &Vector2<f32>) -> f32 { pub fn clockwise_angle(a: &Vector2<f32>, b: &Vector2<f32>) -> f32 {