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