rakata_formats/txi/
mod.rs1mod reader;
24mod writer;
25
26pub use reader::{
27 read_txi, read_txi_from_bytes, read_txi_from_bytes_with_options, read_txi_with_options,
28};
29pub use writer::{
30 write_txi, write_txi_to_vec, write_txi_to_vec_with_options, write_txi_with_options,
31};
32
33use thiserror::Error;
34
35use rakata_core::{DecodeTextError, EncodeTextError};
36
37use crate::binary::{DecodeBinary, EncodeBinary};
38
39const UPPER_LEFT_COORDS_COMMAND: &str = "upperleftcoords";
40const LOWER_RIGHT_COORDS_COMMAND: &str = "lowerrightcoords";
41const DECAL1_ALIAS: &str = "decal1";
42const DECAL_COMMAND: &str = "decal";
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
46pub struct TxiReadOptions {
47 pub compatibility_decal1_alias: bool,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
56pub struct TxiWriteOptions {}
57
58#[derive(Debug, Clone, PartialEq)]
60pub struct TxiCoordinate {
61 pub u: f32,
63 pub v: f32,
65 pub w: i32,
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct TxiDirective {
72 pub command: String,
76 pub arguments: String,
78}
79
80#[derive(Debug, Clone, PartialEq)]
82pub struct TxiCoordinateBlock {
83 pub command: String,
86 pub declared_count: usize,
88 pub coordinates: Vec<TxiCoordinate>,
90}
91
92#[derive(Debug, Clone, PartialEq)]
94pub enum TxiEntry {
95 Directive(TxiDirective),
97 CoordinateBlock(TxiCoordinateBlock),
99}
100
101#[derive(Debug, Clone, PartialEq, Default)]
103pub struct Txi {
104 pub entries: Vec<TxiEntry>,
106}
107
108impl Txi {
109 pub fn new() -> Self {
111 Self::default()
112 }
113
114 pub fn push_directive(
116 &mut self,
117 command: impl Into<String>,
118 arguments: impl Into<String>,
119 ) -> &mut Self {
120 self.entries.push(TxiEntry::Directive(TxiDirective {
121 command: command.into().to_ascii_lowercase(),
122 arguments: arguments.into(),
123 }));
124 self
125 }
126
127 pub fn push_coordinate_block(
129 &mut self,
130 command: impl Into<String>,
131 declared_count: usize,
132 coordinates: Vec<TxiCoordinate>,
133 ) -> &mut Self {
134 self.entries
135 .push(TxiEntry::CoordinateBlock(TxiCoordinateBlock {
136 command: command.into().to_ascii_lowercase(),
137 declared_count,
138 coordinates,
139 }));
140 self
141 }
142}
143
144impl DecodeBinary for Txi {
145 type Error = TxiError;
146
147 fn decode_binary(bytes: &[u8]) -> Result<Self, Self::Error> {
148 read_txi_from_bytes(bytes)
149 }
150}
151
152impl EncodeBinary for Txi {
153 type Error = TxiError;
154
155 fn encode_binary(&self) -> Result<Vec<u8>, Self::Error> {
156 write_txi_to_vec(self)
157 }
158}
159
160#[derive(Debug, Error)]
162pub enum TxiError {
163 #[error(transparent)]
165 Io(#[from] std::io::Error),
166 #[error("invalid TXI data: {0}")]
168 InvalidData(String),
169 #[error("TXI text encoding failed for {context}: {source}")]
171 TextEncoding {
172 context: String,
174 #[source]
176 source: EncodeTextError,
177 },
178 #[error("TXI text decoding failed for {context}: {source}")]
180 TextDecoding {
181 context: String,
183 #[source]
185 source: DecodeTextError,
186 },
187}