Improved system parser
parent
4f0d77eeea
commit
fd94cd6701
|
@ -4,14 +4,25 @@ name = "12 Autumn above"
|
||||||
|
|
||||||
[object.star]
|
[object.star]
|
||||||
sprite = "star::star"
|
sprite = "star::star"
|
||||||
center = [0.0, 0.0]
|
position = [0.0, 0.0]
|
||||||
size = 50
|
size = 1000
|
||||||
parallax = 1.0
|
parallax = 20.0
|
||||||
|
|
||||||
|
|
||||||
[object.earth]
|
[object.earth]
|
||||||
sprite = "planet::earth"
|
sprite = "planet::earth"
|
||||||
center = "star"
|
position.center = "star"
|
||||||
radius = 1000
|
position.radius = 4000
|
||||||
angle = 0
|
position.angle = 0
|
||||||
size = 100
|
size = 1000
|
||||||
parallax = 1.0
|
parallax = 10.0
|
||||||
|
|
||||||
|
|
||||||
|
[object.luna]
|
||||||
|
sprite = "planet::luna"
|
||||||
|
position.center = "earth"
|
||||||
|
position.radius = 1600
|
||||||
|
position.angle = 135
|
||||||
|
size = 500
|
||||||
|
angle = -45
|
||||||
|
parallax = 7.8
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use cgmath::{Deg, Point2};
|
use cgmath::{Deg, Point2};
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use crate::physics::{Pfloat, Polar};
|
use crate::physics::{Pfloat, Polar};
|
||||||
|
|
||||||
|
@ -24,25 +24,37 @@ pub(in crate::content) mod toml {
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
pub sprite: String,
|
pub sprite: String,
|
||||||
pub center: Center,
|
pub position: Position,
|
||||||
|
|
||||||
pub size: Pfloat,
|
pub size: Pfloat,
|
||||||
pub parallax: Pfloat,
|
pub parallax: Pfloat,
|
||||||
|
|
||||||
#[serde(default)]
|
pub radius: Option<Pfloat>,
|
||||||
|
pub angle: Option<Pfloat>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Position {
|
||||||
|
Polar(PolarCoords),
|
||||||
|
Cartesian(Coordinates),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct PolarCoords {
|
||||||
|
pub center: Coordinates,
|
||||||
pub radius: Pfloat,
|
pub radius: Pfloat,
|
||||||
#[serde(default)]
|
|
||||||
pub angle: Pfloat,
|
pub angle: Pfloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum Center {
|
pub enum Coordinates {
|
||||||
Label(String),
|
Label(String),
|
||||||
Coords([Pfloat; 2]),
|
Coords([Pfloat; 2]),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Center {
|
impl ToString for Coordinates {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::Label(s) => s.to_owned(),
|
Self::Label(s) => s.to_owned(),
|
||||||
|
@ -61,25 +73,57 @@ pub struct System {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
pub sprite: String,
|
pub sprite: String,
|
||||||
pub position: Polar,
|
pub position: Point2<f32>,
|
||||||
pub size: Pfloat,
|
pub size: Pfloat,
|
||||||
pub parallax: Pfloat,
|
pub parallax: Pfloat,
|
||||||
|
pub angle: Deg<Pfloat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_center(
|
fn resolve_coordinates(
|
||||||
|
objects: &HashMap<String, toml::Object>,
|
||||||
|
cor: &toml::Coordinates,
|
||||||
|
mut cycle_detector: HashSet<String>,
|
||||||
|
) -> Result<Point2<f32>> {
|
||||||
|
match cor {
|
||||||
|
toml::Coordinates::Coords(c) => Ok((*c).into()),
|
||||||
|
toml::Coordinates::Label(l) => {
|
||||||
|
if cycle_detector.contains(l) {
|
||||||
|
bail!(
|
||||||
|
"Found coordinate cycle: `{}`",
|
||||||
|
cycle_detector.iter().fold(String::new(), |sum, a| {
|
||||||
|
if sum.is_empty() {
|
||||||
|
a.to_string()
|
||||||
|
} else {
|
||||||
|
sum + " -> " + a
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cycle_detector.insert(l.to_owned());
|
||||||
|
|
||||||
|
let p = match objects.get(l) {
|
||||||
|
Some(p) => p,
|
||||||
|
None => bail!("Could not resolve coordinate label `{l}`"),
|
||||||
|
};
|
||||||
|
Ok(resolve_position(&objects, &p, cycle_detector)
|
||||||
|
.with_context(|| format!("In object {:#?}", l))?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_position(
|
||||||
objects: &HashMap<String, toml::Object>,
|
objects: &HashMap<String, toml::Object>,
|
||||||
obj: &toml::Object,
|
obj: &toml::Object,
|
||||||
) -> Option<Point2<f32>> {
|
cycle_detector: HashSet<String>,
|
||||||
match &obj.center {
|
) -> Result<Point2<f32>> {
|
||||||
toml::Center::Label(s) => Some(
|
match &obj.position {
|
||||||
Polar {
|
toml::Position::Cartesian(c) => Ok(resolve_coordinates(objects, c, cycle_detector)?),
|
||||||
center: resolve_center(&objects, objects.get(s)?)?,
|
toml::Position::Polar(p) => Ok(Polar {
|
||||||
radius: obj.radius,
|
center: resolve_coordinates(&objects, &p.center, cycle_detector)?,
|
||||||
angle: Deg(obj.angle),
|
radius: p.radius,
|
||||||
}
|
angle: Deg(p.angle),
|
||||||
.to_cartesian(),
|
}
|
||||||
),
|
.to_cartesian()),
|
||||||
toml::Center::Coords(v) => Some((*v).into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,26 +132,16 @@ impl System {
|
||||||
let mut objects = Vec::new();
|
let mut objects = Vec::new();
|
||||||
|
|
||||||
for (label, obj) in &value.object {
|
for (label, obj) in &value.object {
|
||||||
let center = match resolve_center(&value.object, obj) {
|
let mut cycle_detector = HashSet::new();
|
||||||
Some(v) => v,
|
cycle_detector.insert(label.to_owned());
|
||||||
None => {
|
|
||||||
bail!(
|
|
||||||
"could not resolve center label `{}` in `object.{}`",
|
|
||||||
obj.center.to_string(),
|
|
||||||
label
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
objects.push(Object {
|
objects.push(Object {
|
||||||
sprite: obj.sprite.clone(),
|
sprite: obj.sprite.clone(),
|
||||||
position: Polar {
|
position: resolve_position(&value.object, &obj, cycle_detector)
|
||||||
center,
|
.with_context(|| format!("In object {:#?}", label))?,
|
||||||
radius: obj.radius,
|
|
||||||
angle: Deg(obj.angle),
|
|
||||||
},
|
|
||||||
size: obj.size,
|
size: obj.size,
|
||||||
parallax: obj.parallax,
|
parallax: obj.parallax,
|
||||||
|
angle: Deg(obj.angle.unwrap_or(0.0)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,16 @@ pub struct Doodad {
|
||||||
pub pos: Point2<Pfloat>,
|
pub pos: Point2<Pfloat>,
|
||||||
pub parallax: Pfloat,
|
pub parallax: Pfloat,
|
||||||
pub size: Pfloat,
|
pub size: Pfloat,
|
||||||
|
pub angle: Deg<Pfloat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spriteable for Doodad {
|
impl Spriteable for Doodad {
|
||||||
fn get_sprite(&self) -> Sprite {
|
fn get_sprite(&self) -> Sprite {
|
||||||
return Sprite {
|
return Sprite {
|
||||||
texture: self.sprite.clone(),
|
texture: self.sprite.clone(),
|
||||||
pos: self.pos,
|
|
||||||
angle: Deg(0.0),
|
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
|
pos: self.pos,
|
||||||
|
angle: self.angle,
|
||||||
size: self.size,
|
size: self.size,
|
||||||
parallax: self.parallax,
|
parallax: self.parallax,
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,10 +50,11 @@ impl System {
|
||||||
|
|
||||||
for o in &ct.objects {
|
for o in &ct.objects {
|
||||||
s.bodies.push(Doodad {
|
s.bodies.push(Doodad {
|
||||||
pos: o.position.to_cartesian(),
|
pos: o.position,
|
||||||
sprite: SpriteTexture(o.sprite.to_owned()),
|
sprite: SpriteTexture(o.sprite.to_owned()),
|
||||||
size: o.size,
|
size: o.size,
|
||||||
parallax: o.parallax,
|
parallax: o.parallax,
|
||||||
|
angle: o.angle,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue