Compare commits
No commits in common. "39f52ddafcbdb741cf7bcf209049e1f3cb9d3ad7" and "47a73224c6650a595c24f8dfe7e2f12d3a1bdf52" have entirely different histories.
39f52ddafc
...
47a73224c6
386
Cargo.lock
generated
386
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -74,4 +74,10 @@ lazy_static = "1.4.0"
|
||||
clap = { version = "4.4.18", features = ["derive"] }
|
||||
log = "0.4.20"
|
||||
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",
|
||||
] }
|
||||
|
4
TODO.md
4
TODO.md
@ -1,10 +1,8 @@
|
||||
# Specific projects
|
||||
|
||||
## Now:
|
||||
- Clean up API (modules)
|
||||
- Persistent variables
|
||||
- Better planet icons
|
||||
- Clean up scripting & errors
|
||||
- Fix radar
|
||||
- Mouse colliders
|
||||
- UI captures input?
|
||||
- No UI zoom scroll
|
||||
|
@ -32,46 +32,6 @@ fn init(state) {
|
||||
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) {
|
||||
@ -93,209 +53,4 @@ fn step(state) {
|
||||
state.player_ship().get_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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ pub(crate) mod syntax {
|
||||
use anyhow::{bail, Context, Result};
|
||||
use galactica_packer::SpriteAtlas;
|
||||
use galactica_util::rhai_error_to_anyhow;
|
||||
use rhai::{Engine, OptimizationLevel};
|
||||
use rhai::Engine;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -61,9 +61,7 @@ pub(crate) mod syntax {
|
||||
}
|
||||
};
|
||||
|
||||
let mut engine = Engine::new_raw();
|
||||
engine.set_optimization_level(OptimizationLevel::Full);
|
||||
engine.set_max_expr_depths(0, 0);
|
||||
let engine = Engine::new();
|
||||
let mut ui_scenes = HashMap::new();
|
||||
for (n, p) in self.ui_scene {
|
||||
ui_scenes.insert(
|
||||
|
@ -126,12 +126,9 @@ pub struct SystemObject {
|
||||
/// If true, ships may land on this object
|
||||
pub landable: bool,
|
||||
|
||||
/// The pretty display name of this object
|
||||
/// The display name of this object
|
||||
pub name: Option<String>,
|
||||
|
||||
/// The system-unique label of this object
|
||||
pub label: String,
|
||||
|
||||
/// The description of this object (shown on landed ui)
|
||||
pub desc: Option<String>,
|
||||
|
||||
@ -262,7 +259,6 @@ impl crate::Build for System {
|
||||
}
|
||||
|
||||
objects.push(SystemObject {
|
||||
label: label.clone(),
|
||||
sprite: sprite_handle,
|
||||
image: image_handle,
|
||||
pos: resolve_position(&system.object, &obj, cycle_detector)
|
||||
|
@ -33,4 +33,3 @@ bytemuck = { workspace = true }
|
||||
glyphon = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rhai = { workspace = true }
|
||||
rapier2d = { workspace = true }
|
||||
|
@ -3,7 +3,7 @@ use rhai::{CustomType, TypeBuilder};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Color {
|
||||
val: Vector4<f32>,
|
||||
pub val: Vector4<f32>,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
@ -3,14 +3,12 @@ mod color;
|
||||
mod event;
|
||||
mod rect;
|
||||
mod state;
|
||||
mod vector;
|
||||
|
||||
pub use anchor::*;
|
||||
pub use color::*;
|
||||
pub use event::*;
|
||||
pub use rect::*;
|
||||
pub use state::*;
|
||||
pub use vector::*;
|
||||
|
||||
use rhai::{exported_module, Engine};
|
||||
|
||||
@ -19,7 +17,6 @@ pub fn register_into_engine(engine: &mut Engine) {
|
||||
// Helpers
|
||||
.build_type::<Rect>()
|
||||
.build_type::<Color>()
|
||||
.build_type::<UiVector>()
|
||||
// State
|
||||
.build_type::<State>()
|
||||
.build_type::<ShipState>()
|
||||
|
@ -1,16 +1,13 @@
|
||||
use galactica_content::{Ship, SystemObject, SystemObjectHandle};
|
||||
use galactica_system::{
|
||||
data::{self},
|
||||
phys::{objects::PhysShip, PhysSimShipHandle},
|
||||
data::{self, ShipData},
|
||||
phys::PhysSimShipHandle,
|
||||
};
|
||||
use galactica_util::to_degrees;
|
||||
use log::error;
|
||||
use rapier2d::dynamics::RigidBody;
|
||||
use rhai::{Array, CustomType, Dynamic, ImmutableString, TypeBuilder};
|
||||
use rhai::{CustomType, TypeBuilder};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{Color, UiVector};
|
||||
use crate::{RenderInput, RenderState};
|
||||
use crate::RenderInput;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ShipState {
|
||||
@ -18,6 +15,10 @@ pub struct ShipState {
|
||||
input: Arc<RenderInput>,
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
unsafe impl Send for ShipState {}
|
||||
unsafe impl Sync for ShipState {}
|
||||
|
||||
impl ShipState {
|
||||
fn get_content(&mut self) -> &Ship {
|
||||
let ship = self
|
||||
@ -29,27 +30,18 @@ impl ShipState {
|
||||
self.input.ct.get_ship(handle)
|
||||
}
|
||||
|
||||
fn get_ship(&mut self) -> &PhysShip {
|
||||
fn get_data(&mut self) -> &ShipData {
|
||||
let ship = self
|
||||
.input
|
||||
.phys_img
|
||||
.get_ship(self.ship.as_ref().unwrap())
|
||||
.unwrap();
|
||||
&ship.ship
|
||||
}
|
||||
|
||||
fn get_body(&mut self) -> &RigidBody {
|
||||
let ship = self
|
||||
.input
|
||||
.phys_img
|
||||
.get_ship(self.ship.as_ref().unwrap())
|
||||
.unwrap();
|
||||
&ship.rigidbody
|
||||
ship.ship.get_data()
|
||||
}
|
||||
|
||||
fn landed_on(&mut self) -> SystemObjectState {
|
||||
let input = self.input.clone();
|
||||
match self.get_ship().get_data().get_state() {
|
||||
match self.get_data().get_state() {
|
||||
data::ShipState::Landed { target } => {
|
||||
return SystemObjectState {
|
||||
input,
|
||||
@ -71,48 +63,31 @@ impl CustomType for ShipState {
|
||||
builder
|
||||
.with_name("ShipState")
|
||||
.with_fn("is_some", |s: &mut Self| s.ship.is_some())
|
||||
.with_fn("is_dead", |s: &mut Self| {
|
||||
s.get_ship().get_data().get_state().is_dead()
|
||||
})
|
||||
.with_fn("is_dead", |s: &mut Self| s.get_data().get_state().is_dead())
|
||||
.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| {
|
||||
s.get_ship().get_data().get_state().is_landing()
|
||||
s.get_data().get_state().is_landing()
|
||||
})
|
||||
.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| {
|
||||
s.get_ship().get_data().get_state().is_unlanding()
|
||||
s.get_data().get_state().is_unlanding()
|
||||
})
|
||||
.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("thumbnail", |s: &mut Self| s.get_content().thumb)
|
||||
.with_fn("landed_on", |s: &mut Self| s.landed_on())
|
||||
.with_fn("get_shields", |s: &mut Self| {
|
||||
s.get_ship().get_data().get_shields()
|
||||
})
|
||||
.with_fn("get_shields", |s: &mut Self| s.get_data().get_shields())
|
||||
.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_hull", |s: &mut Self| {
|
||||
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)
|
||||
});
|
||||
.with_fn("get_hull", |s: &mut Self| s.get_data().get_hull());
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,6 +97,10 @@ pub struct SystemObjectState {
|
||||
input: Arc<RenderInput>,
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
unsafe impl Send for SystemObjectState {}
|
||||
unsafe impl Sync for SystemObjectState {}
|
||||
|
||||
impl SystemObjectState {
|
||||
fn get_content(&mut self) -> &SystemObject {
|
||||
self.input.ct.get_system_object(self.object.unwrap())
|
||||
@ -167,30 +146,13 @@ impl CustomType for SystemObjectState {
|
||||
"".to_string()
|
||||
}
|
||||
})
|
||||
.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
|
||||
});
|
||||
.with_fn("is_some", |s: &mut Self| s.object.is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct State {
|
||||
input: Arc<RenderInput>,
|
||||
window_aspect: f32,
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
@ -198,11 +160,8 @@ unsafe impl Send for State {}
|
||||
unsafe impl Sync for State {}
|
||||
|
||||
impl State {
|
||||
pub fn new(state: &RenderState, input: Arc<RenderInput>) -> Self {
|
||||
Self {
|
||||
input,
|
||||
window_aspect: state.window_aspect,
|
||||
}
|
||||
pub fn new(input: Arc<RenderInput>) -> Self {
|
||||
Self { input }
|
||||
}
|
||||
|
||||
pub fn player_ship(&mut self) -> ShipState {
|
||||
@ -211,39 +170,12 @@ impl State {
|
||||
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 {
|
||||
fn build(mut builder: TypeBuilder<Self>) {
|
||||
builder
|
||||
.with_name("State")
|
||||
.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);
|
||||
.with_fn("player_ship", Self::player_ship);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -4,10 +4,7 @@ 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 rhai::{
|
||||
packages::{BasicArrayPackage, BasicStringPackage, LogicPackage, MoreStringPackage, Package},
|
||||
Dynamic, Engine, ImmutableString, Scope,
|
||||
};
|
||||
use rhai::{Dynamic, Engine, ImmutableString, Scope};
|
||||
use std::{cell::RefCell, num::NonZeroU32, rc::Rc, sync::Arc};
|
||||
|
||||
use super::{
|
||||
@ -34,18 +31,6 @@ impl UiScriptExecutor {
|
||||
let elements = Rc::new(RefCell::new(UiState::new(ct.clone(), state)));
|
||||
|
||||
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);
|
||||
Self::register_api(
|
||||
ct.clone(),
|
||||
@ -68,7 +53,7 @@ impl UiScriptExecutor {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
if self.last_scene == current_scene {
|
||||
return Ok(());
|
||||
@ -100,7 +85,7 @@ impl UiScriptExecutor {
|
||||
.get(current_scene.as_ref().unwrap().as_str())
|
||||
.unwrap(),
|
||||
"init",
|
||||
(State::new(state, input.clone()),),
|
||||
(State::new(input.clone()),),
|
||||
),
|
||||
)
|
||||
.with_context(|| format!("while running `init()`"))
|
||||
@ -119,7 +104,7 @@ impl UiScriptExecutor {
|
||||
.borrow_mut()
|
||||
.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();
|
||||
|
||||
(*self.state).borrow_mut().step(state, input.clone());
|
||||
@ -136,7 +121,7 @@ impl UiScriptExecutor {
|
||||
&mut self.scope,
|
||||
ast,
|
||||
"step",
|
||||
(State::new(state, input.clone()),),
|
||||
(State::new(input.clone()),),
|
||||
))
|
||||
.with_context(|| format!("while calling `step()`"))
|
||||
.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())
|
||||
.unwrap(),
|
||||
"event",
|
||||
(State::new(state, input.clone()), PlayerShipStateEvent {}),
|
||||
(State::new(input.clone()), PlayerShipStateEvent {}),
|
||||
),
|
||||
)
|
||||
.with_context(|| format!("while handling player state change event"))
|
||||
@ -229,7 +214,7 @@ impl UiScriptExecutor {
|
||||
.get(current_scene.as_ref().unwrap().as_str())
|
||||
.unwrap(),
|
||||
"event",
|
||||
(State::new(state, input.clone()), event_arg.clone()),
|
||||
(State::new(input.clone()), event_arg.clone()),
|
||||
),
|
||||
)
|
||||
.with_context(|| format!("while handling event `{:?}`", event_arg))
|
||||
@ -237,7 +222,6 @@ impl UiScriptExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
self.scope.rewind(0);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -269,12 +253,6 @@ impl UiScriptExecutor {
|
||||
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
|
||||
@ -285,6 +263,7 @@ impl UiScriptExecutor {
|
||||
"add_sprite",
|
||||
move |name: ImmutableString, sprite: ImmutableString, rect: Rect| {
|
||||
let mut ui_state = c.borrow_mut();
|
||||
let len = ui_state.len();
|
||||
|
||||
let sprite_handle = ct.get_sprite_handle(sprite.as_str());
|
||||
if sprite_handle.is_none() {
|
||||
@ -292,35 +271,16 @@ impl UiScriptExecutor {
|
||||
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(
|
||||
ui_state.names.insert(name.clone(), len);
|
||||
ui_state.elements.push(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(
|
||||
@ -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
|
||||
@ -439,24 +354,17 @@ impl UiScriptExecutor {
|
||||
rect: Rect,
|
||||
color: Color| {
|
||||
let mut ui_state = c.borrow_mut();
|
||||
let len = ui_state.len();
|
||||
|
||||
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(
|
||||
ui_state.names.insert(name.clone(), len);
|
||||
ui_state.elements.push(UiElement::Text(TextBox::new(
|
||||
&mut font.borrow_mut(),
|
||||
name.clone(),
|
||||
font_size,
|
||||
line_height,
|
||||
rect,
|
||||
color,
|
||||
)),
|
||||
);
|
||||
)));
|
||||
},
|
||||
);
|
||||
|
||||
@ -628,23 +536,16 @@ impl UiScriptExecutor {
|
||||
// TODO: fix ugly spaces
|
||||
move |name: ImmutableString, stroke: f32, color: Color, rect: Rect| {
|
||||
let mut ui_state = c.borrow_mut();
|
||||
let len = ui_state.len();
|
||||
|
||||
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(
|
||||
ui_state.names.insert(name.clone(), len);
|
||||
ui_state.elements.push(UiElement::RadialBar(RadialBar::new(
|
||||
name.clone(),
|
||||
stroke,
|
||||
color,
|
||||
rect,
|
||||
1.0,
|
||||
)),
|
||||
);
|
||||
)));
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -23,8 +23,8 @@ pub(crate) struct UiConfig {
|
||||
}
|
||||
|
||||
pub(crate) struct UiState {
|
||||
pub elements: HashMap<ImmutableString, UiElement>,
|
||||
pub names: Vec<ImmutableString>,
|
||||
pub names: HashMap<ImmutableString, usize>,
|
||||
pub elements: Vec<UiElement>,
|
||||
|
||||
pub ct: Arc<Content>,
|
||||
current_scene: Option<ImmutableString>,
|
||||
@ -42,8 +42,8 @@ impl UiState {
|
||||
pub fn new(ct: Arc<Content>, state: &mut RenderState) -> Self {
|
||||
Self {
|
||||
ct,
|
||||
elements: HashMap::new(),
|
||||
names: Vec::new(),
|
||||
names: HashMap::new(),
|
||||
elements: Vec::new(),
|
||||
|
||||
current_scene: None,
|
||||
show_timings: true,
|
||||
@ -79,15 +79,15 @@ impl UiState {
|
||||
*/
|
||||
|
||||
pub fn get_mut_by_idx(&mut self, idx: usize) -> Option<&mut UiElement> {
|
||||
let name = self.names.get(idx);
|
||||
if name.is_none() {
|
||||
return None;
|
||||
}
|
||||
self.elements.get_mut(name.unwrap())
|
||||
self.elements.get_mut(idx)
|
||||
}
|
||||
|
||||
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> {
|
||||
@ -124,7 +124,7 @@ impl<'a> UiState {
|
||||
v.push(self.fps_indicator.get_textarea(input, window))
|
||||
}
|
||||
|
||||
for t in self.elements.values() {
|
||||
for t in self.elements.iter() {
|
||||
match &t {
|
||||
UiElement::Text(x) => v.push(x.get_textarea(input, window)),
|
||||
_ => {}
|
||||
|
@ -1,9 +1,5 @@
|
||||
use super::super::api::Rect;
|
||||
use crate::{
|
||||
ui::{api::Color, event::Event},
|
||||
vertexbuffer::types::UiInstance,
|
||||
RenderInput, RenderState,
|
||||
};
|
||||
use crate::{ui::event::Event, vertexbuffer::types::UiInstance, RenderInput, RenderState};
|
||||
use galactica_content::{Content, SpriteAutomaton, SpriteHandle};
|
||||
use galactica_util::to_radians;
|
||||
use rhai::ImmutableString;
|
||||
@ -13,12 +9,8 @@ pub struct Sprite {
|
||||
pub anim: SpriteAutomaton,
|
||||
pub name: ImmutableString,
|
||||
|
||||
/// Sprite angle, in degrees
|
||||
angle: f32,
|
||||
|
||||
rect: Rect,
|
||||
mask: Option<SpriteHandle>,
|
||||
color: Color,
|
||||
|
||||
/// If true, ignore mouse events until click is released
|
||||
waiting_for_release: bool,
|
||||
@ -32,8 +24,6 @@ impl Sprite {
|
||||
name,
|
||||
anim: SpriteAutomaton::new(&ct, sprite),
|
||||
rect,
|
||||
angle: 0.0,
|
||||
color: Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
mask: None,
|
||||
has_mouse: false,
|
||||
has_click: false,
|
||||
@ -45,18 +35,6 @@ impl Sprite {
|
||||
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) {
|
||||
let rect = self
|
||||
.rect
|
||||
@ -68,9 +46,9 @@ impl Sprite {
|
||||
|
||||
state.push_ui_buffer(UiInstance {
|
||||
position: rect.pos.into(),
|
||||
angle: to_radians(90.0 + self.angle),
|
||||
angle: to_radians(90.0),
|
||||
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_fade: anim_state.fade,
|
||||
mask_index: self
|
||||
|
@ -6,15 +6,7 @@ mod physsim;
|
||||
mod physwrapper;
|
||||
mod stepresources;
|
||||
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
pub use physimage::*;
|
||||
pub use physsim::{PhysSim, PhysSimShipHandle};
|
||||
pub use physwrapper::PhysWrapper;
|
||||
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)
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ use super::{autopilot, collapse::ShipCollapseSequence, controller::ShipControlle
|
||||
use crate::{
|
||||
data::{ShipAutoPilot, ShipData, ShipPersonality, ShipState},
|
||||
phys::{
|
||||
get_phys_id,
|
||||
objects::{PhysEffect, PhysProjectile},
|
||||
physsim::NewObjects,
|
||||
PhysImage, PhysSimShipHandle, PhysStepResources, PhysWrapper,
|
||||
@ -24,9 +23,6 @@ use crate::{
|
||||
/// A ship instance in the physics system
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PhysShip {
|
||||
/// This ship's unique id
|
||||
pub uid: u64,
|
||||
|
||||
/// This ship's physics handle
|
||||
pub rigid_body: RigidBodyHandle,
|
||||
|
||||
@ -75,7 +71,6 @@ impl PhysShip {
|
||||
) -> Self {
|
||||
let ship_ct = ct.get_ship(handle);
|
||||
PhysShip {
|
||||
uid: get_phys_id(),
|
||||
anim: SpriteAutomaton::new(ct, ship_ct.sprite),
|
||||
rigid_body,
|
||||
collider,
|
||||
|
@ -13,11 +13,6 @@ pub fn to_radians(degrees: f32) -> f32 {
|
||||
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
|
||||
/// Returns a value in [-pi, pi]
|
||||
pub fn clockwise_angle(a: &Vector2<f32>, b: &Vector2<f32>) -> f32 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user