use getset::*;
use rand::Rng;
use serde_derive::{Serialize, Deserialize};
use crate::binary::{ReadBytes, WriteBytes};
use crate::error::{Result, RLibError};
use crate::files::{Bmd, bmd::ToLayer, Decodeable, EncodeableExtraData, Encodeable};
use super::DecodeableExtraData;
mod v4;
#[derive(Default, PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub struct TreeList {
serialise_version: u16,
tree_list: Vec<BattleTreeItemVector>,
}
#[derive(Default, PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub struct BattleTreeItemVector {
key: String,
value: Vec<BattleTreeItem>,
}
#[derive(PartialEq, Clone, Debug, Getters, MutGetters, Setters, Serialize, Deserialize)]
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub struct BattleTreeItem {
id: u64,
x: f32,
y: f32,
z: f32,
rotation: u8,
scale: f32,
flags: u8,
}
impl Decodeable for TreeList {
fn decode<R: ReadBytes>(data: &mut R, extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
let mut decoded = Self::default();
decoded.serialise_version = data.read_u16()?;
match decoded.serialise_version {
4 => decoded.read_v4(data, extra_data)?,
_ => return Err(RLibError::DecodingFastBinUnsupportedVersion(String::from("TreeList"), decoded.serialise_version)),
}
Ok(decoded)
}
}
impl Encodeable for TreeList {
fn encode<W: WriteBytes>(&mut self, buffer: &mut W, extra_data: &Option<EncodeableExtraData>) -> Result<()> {
buffer.write_u16(self.serialise_version)?;
match self.serialise_version {
4 => self.write_v4(buffer, extra_data)?,
_ => return Err(RLibError::EncodingFastBinUnsupportedVersion(String::from("TreeList"), self.serialise_version)),
}
Ok(())
}
}
impl Default for BattleTreeItem {
fn default() -> Self {
Self {
id: rand::thread_rng().gen::<u64>(),
x: f32::default(),
y: f32::default(),
z: f32::default(),
rotation: u8::default(),
scale: f32::default(),
flags: u8::default(),
}
}
}
impl ToLayer for TreeList {
fn to_layer(&self, _parent: &Bmd) -> Result<String> {
let mut layer = String::new();
for item_vector in self.tree_list() {
for item in item_vector.value() {
layer.push_str(&format!("
<entity id=\"{:x}\">",
item.id())
);
layer.push_str(&format!("
<ECVegetation key=\"{}\" legacy_random_rotation=\"true\"/>",
item_vector.key(),
));
layer.push_str(&format!("
<ECTransform position=\"{:.5} {:.5} {:.5}\" rotation=\"{:.5} {:.5} {:.5}\" scale=\"{:.5} {:.5} {:.5}\" pivot=\"0 0 0\"/>",
item.x(),
item.y(),
item.z(),
0,
*item.rotation() as f32 * 1.40625, 0,
item.scale(),
item.scale(),
item.scale(),
));
layer.push_str("
<ECTerrainClamp active=\"false\" clamp_to_sea_level=\"false\" terrain_oriented=\"false\" fit_height_to_terrain=\"false\"/>");
layer.push_str("
</entity>"
);
}
}
Ok(layer)
}
}