use crate::{
parsers::{parse_color, parse_property},
Color, TiledValue, Vec2,
};
use serde::{Deserialize, Deserializer};
use std::collections::HashMap;
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Object {
pub gid: Option<u32>,
pub id: Option<u32>,
pub name: String,
#[serde(rename(deserialize = "type"), default)]
pub custom_type: String,
pub rotation: f32,
pub height: f32,
pub width: f32,
#[serde(default)]
pub x: f32,
#[serde(default)]
pub y: f32,
#[serde(deserialize_with = "parse_property", default)]
pub properties: HashMap<String, TiledValue>,
#[serde(flatten)]
pub object_type: ObjectType,
}
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Text {
pub flags: u8,
#[serde(deserialize_with = "parse_color", default)]
pub color: Color,
pub text: String,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ObjectType {
Ellipse,
Point,
Polygon(Vec<Vec2<i32>>),
PolyLine(Vec<Vec2<i32>>),
Text(Text),
Template(String),
None,
}
impl ObjectType {
pub fn is_none(&self) -> bool {
*self == ObjectType::None
}
pub fn is_some(&self) -> bool {
*self != ObjectType::None
}
}
impl<'de> Deserialize<'de> for ObjectType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(rename_all = "lowercase")]
enum Helper {
Ellipse(bool),
Point(bool),
Polygon(Vec<Vec2<i32>>),
Polyline(Vec<Vec2<i32>>),
Text {
bold: bool,
#[serde(deserialize_with = "parse_color", default)]
color: Color,
italic: bool,
text: String,
wrap: bool,
},
}
let v = serde_json::Value::deserialize(deserializer)?;
if let Ok(m) = Helper::deserialize(&v) {
return match m {
Helper::Ellipse(b) => {
if b {
Ok(ObjectType::Ellipse)
} else {
Ok(ObjectType::None)
}
}
Helper::Point(b) => {
if b {
Ok(ObjectType::Point)
} else {
Ok(ObjectType::None)
}
}
Helper::Polygon(data) => Ok(ObjectType::Polygon(data)),
Helper::Polyline(data) => Ok(ObjectType::PolyLine(data)),
Helper::Text {
bold,
color,
italic,
text,
wrap,
} => {
let mut flags = 0u8;
if bold {
flags |= 1
}
if italic {
flags |= 2
}
if wrap {
flags |= 4
}
Ok(ObjectType::Text(Text { flags, color, text }))
}
};
}
Ok(ObjectType::None)
}
}