all ra2 stock files with corresponding _txt are parsed
parent
13c9fe6678
commit
e4c810ab06
|
@ -36,9 +36,10 @@ impl Atom for f32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serializable for [f32; 3] {
|
||||
impl<const N: usize> Serializable for [f32; N] {
|
||||
fn write<W: std::io::Write, S: std::string::ToString>(&self, name: S, w: &mut WriteStream<W>) -> WriteResult<()> {
|
||||
w.emit(&format!("{} {:.6}\t{:.6}\t{:.6}", name.to_string(), self[0], self[1], self[2]))
|
||||
let fields = self.iter().map(|v| format!("{:.6}", v)).collect::<Vec<String>>().join("\t");
|
||||
w.emit(&format!("{} {}", name.to_string(), fields))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,13 +186,6 @@ pub struct TLV {
|
|||
}
|
||||
|
||||
impl TLV {
|
||||
pub fn error<S: std::string::ToString>(&self, msg: S) -> ReadError {
|
||||
ReadError {
|
||||
msg: msg.to_string(),
|
||||
stack: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check<R: std::io::Read>(&self, r: &mut ReadStream<R>) -> ReadResult<()> {
|
||||
let expected = self.start_pos + self.length as usize + 12usize;
|
||||
if expected != r.pos {
|
||||
|
|
|
@ -96,6 +96,7 @@ pub enum MapKind {
|
|||
Diffuse = 1,
|
||||
SelfIllum = 5,
|
||||
Opacity = 6,
|
||||
Reflect = 9,
|
||||
}
|
||||
|
||||
impl gma::Serializable for MapKind {
|
||||
|
@ -104,12 +105,15 @@ impl gma::Serializable for MapKind {
|
|||
MapKind::Diffuse => w.emit("*MAP_DIFFUSE"),
|
||||
MapKind::SelfIllum => w.emit("*MAP_SELFILLUM"),
|
||||
MapKind::Opacity => w.emit("*MAP_OPACITY"),
|
||||
MapKind::Reflect => w.emit("*MAP_REFLECT"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub enum MapType {
|
||||
Explicit = 0,
|
||||
Spherical = 1,
|
||||
Screen = 4,
|
||||
}
|
||||
|
||||
|
@ -181,12 +185,14 @@ pub enum Shading {
|
|||
#[derive(Debug, GMISerializable,GMASerializable)]
|
||||
pub enum Falloff {
|
||||
In = 0,
|
||||
InTwoSided = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub enum XPType {
|
||||
Other = 0,
|
||||
Filter = 1,
|
||||
Additive = 3,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
|
@ -274,11 +280,13 @@ pub struct ObjectList {
|
|||
#[derive(Debug)]
|
||||
pub enum Object {
|
||||
Geometry(GeometryObject),
|
||||
Camera(CameraObject),
|
||||
Light(LightObject),
|
||||
AttachmentPoint(AttachmentPointObject),
|
||||
ConstraintSolver(ConstraintSolverObject),
|
||||
Simulation(SimulationObject),
|
||||
RBCollection(RBCollectionObject),
|
||||
ConstraintSolver(ConstraintSolverObject),
|
||||
AngularDashpot(AngularDashpotObject),
|
||||
}
|
||||
|
||||
impl gmi::Serializable for Object {
|
||||
|
@ -286,11 +294,13 @@ impl gmi::Serializable for Object {
|
|||
let tlv = r.tlv()?;
|
||||
let (res, check) = match (tlv.tag, tlv.flags) {
|
||||
(2, 4) => (Object::Geometry(r.read("geometry")?), false),
|
||||
(4, 2) => (Object::Camera(r.read("camera")?), false),
|
||||
(5, 3) => (Object::Light(r.read("light")?), false),
|
||||
(21, 2) => (Object::AttachmentPoint(r.read("attachmentpoint")?), true),
|
||||
(42, 3) => (Object::ConstraintSolver(r.read("constraintsolver")?), false),
|
||||
(30, 2) => (Object::Simulation(r.read("simulation")?), false),
|
||||
(31, 4) => (Object::RBCollection(r.read("rigidbodycollection")?), false),
|
||||
(42, 3) => (Object::ConstraintSolver(r.read("constraintsolver")?), false),
|
||||
(49, 2) => (Object::AngularDashpot(r.read("angulardashpot")?), false),
|
||||
_ => return Err(r.error(format!("unknown object type ({}, {})", tlv.tag, tlv.flags))),
|
||||
};
|
||||
if check {
|
||||
|
@ -304,11 +314,13 @@ impl gma::Serializable for Object {
|
|||
fn write<W: io::Write, S: string::ToString>(&self, _name: S, w: &mut gma::WriteStream<W>) -> gma::WriteResult<()> {
|
||||
match self {
|
||||
Object::Geometry(o) => o.write("", w),
|
||||
Object::Camera(o) => o.write("", w),
|
||||
Object::Light(o) => o.write("", w),
|
||||
Object::AttachmentPoint(o) => o.write("", w),
|
||||
Object::ConstraintSolver(o) => o.write("", w),
|
||||
Object::Simulation(o) => o.write("", w),
|
||||
Object::RBCollection(o) => o.write("", w),
|
||||
Object::ConstraintSolver(o) => o.write("", w),
|
||||
Object::AngularDashpot(o) => o.write("", w),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -327,6 +339,29 @@ pub struct GeometryObject {
|
|||
pub mesh: Mesh,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
#[gma_name("CAMERA")]
|
||||
pub struct CameraObject {
|
||||
#[gma_name("NODE_NAME")]
|
||||
pub name: String,
|
||||
#[gma_name("NODE_TM")]
|
||||
pub tm1: TransformMatrix,
|
||||
#[gma_name("NODE_TM")]
|
||||
pub tm2: Option<TransformMatrix>,
|
||||
pub type_: CameraType,
|
||||
pub hither: f32,
|
||||
pub yon: f32,
|
||||
pub near: f32,
|
||||
pub far: f32,
|
||||
pub fov: f32,
|
||||
pub tdist: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub enum CameraType {
|
||||
Target = 0,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
#[gmi_tagged(17, 2)]
|
||||
#[gma_name("NODE_TM")]
|
||||
|
@ -612,6 +647,8 @@ pub enum LightType {
|
|||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub enum LightShadows {
|
||||
Off = 0,
|
||||
Mapped = 1,
|
||||
Raytraced = 2,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMASerializable)]
|
||||
|
@ -648,14 +685,87 @@ pub struct ConstraintSolverObject {
|
|||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
#[gmi_tagged(44, 2)]
|
||||
#[gmi_tagged_nolen(44, 2)]
|
||||
pub struct ConstraintList {
|
||||
pub constraints: Vec<Constraint>,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
#[derive(Debug)]
|
||||
pub enum Constraint {
|
||||
Foo = 1,
|
||||
Hinge(HingeConstraint),
|
||||
PointToPoint(PointToPointConstraint),
|
||||
}
|
||||
|
||||
impl gmi::Serializable for Constraint {
|
||||
fn read<R: io::Read>(r: &mut gmi::ReadStream<R>) -> gmi::ReadResult<Self> {
|
||||
let tlv = r.tlv()?;
|
||||
let (res, check) = match (tlv.tag, tlv.flags) {
|
||||
(47, 2) => (Constraint::Hinge(r.read("hinge")?), false),
|
||||
(53, 2) => (Constraint::PointToPoint(r.read("pointtopoint")?), false),
|
||||
_ => return Err(r.error(format!("unknown constraint type ({}, {})", tlv.tag, tlv.flags))),
|
||||
};
|
||||
if check {
|
||||
tlv.check(r)?;
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl gma::Serializable for Constraint {
|
||||
fn write<W: io::Write, S: string::ToString>(&self, _name: S, w: &mut gma::WriteStream<W>) -> gma::WriteResult<()> {
|
||||
match self {
|
||||
Constraint::Hinge(o) => o.write("", w),
|
||||
Constraint::PointToPoint(o) => o.write("", w),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub struct HingeConstraint {
|
||||
#[gma_name("NODE_NAME")]
|
||||
pub name: String,
|
||||
pub tm: TransformMatrix,
|
||||
#[gma_name("BODY1")]
|
||||
pub body1: String,
|
||||
#[gma_name("BODY2")]
|
||||
pub body2: String,
|
||||
#[gma_name("POINT")]
|
||||
pub point: [f32; 3],
|
||||
#[gma_name("SPIN_AXIS")]
|
||||
pub spin_axis: [f32; 3],
|
||||
#[gma_name("IS_LIMITED")]
|
||||
pub is_limited: u8,
|
||||
#[gma_name("FRICTION")]
|
||||
pub friction: f32,
|
||||
#[gma_name("ANGLE_LIMITS")]
|
||||
pub angle_limits: [f32; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub struct PointToPointConstraint {
|
||||
#[gma_name("NODE_NAME")]
|
||||
pub name: String,
|
||||
pub tm: TransformMatrix,
|
||||
#[gma_name("BODY1")]
|
||||
pub body1: String,
|
||||
#[gma_name("BODY2")]
|
||||
pub body2: String,
|
||||
pub points: PTPPoints,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable)]
|
||||
pub struct PTPPoints {
|
||||
a: Point,
|
||||
b: Point,
|
||||
}
|
||||
|
||||
impl gma::Serializable for PTPPoints {
|
||||
fn write<W: io::Write, S: string::ToString>(&self, _name: S, w: &mut gma::WriteStream<W>) -> gma::WriteResult<()> {
|
||||
w.emit("*POINT 1")?;
|
||||
w.emit(&format!("(\t{:.6}\t{:.6}\t{:.6}\t)", self.a.x, self.a.y, self.a.z))?;
|
||||
w.emit(&format!("(\t{:.6}\t{:.6}\t{:.6}\t)", self.b.x, self.b.y, self.b.z))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
|
@ -796,6 +906,7 @@ impl gma::Serializable for NestedRigidBodyList {
|
|||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
pub enum GeoType {
|
||||
Standard = 0,
|
||||
Plane = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
|
@ -818,3 +929,42 @@ impl gma::Serializable for DisabledCollisionPair {
|
|||
self.a, self.b))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||
#[gma_name("GMID_HAVOK_ANGULAR_DASHPOT")]
|
||||
pub struct AngularDashpotObject {
|
||||
#[gma_name("NODE_NAME")]
|
||||
pub name: String,
|
||||
pub tm: TransformMatrix,
|
||||
#[gma_name("BODY1")]
|
||||
pub body1: String,
|
||||
#[gma_name("BODY2")]
|
||||
pub body2: String,
|
||||
#[gma_name("STRENGTH")]
|
||||
pub strength: f32,
|
||||
#[gma_name("DAMPING")]
|
||||
pub damping: f32,
|
||||
#[gma_name("ALLOW_INTERPENETRATIONS")]
|
||||
pub allow_interpenetrations: u8,
|
||||
#[gma_name("QUATERNION")]
|
||||
pub quaternion: Quaternion,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Quaternion([f32; 4]);
|
||||
|
||||
impl gmi::Serializable for Quaternion {
|
||||
fn read<R: io::Read>(r: &mut gmi::ReadStream<R>) -> gmi::ReadResult<Self> {
|
||||
<[f32; 4]>::read(r).map(|el| Quaternion(el))
|
||||
}
|
||||
}
|
||||
|
||||
impl gma::Serializable for Quaternion {
|
||||
fn write<W: io::Write, S: string::ToString>(&self, name: S, w: &mut gma::WriteStream<W>) -> gma::WriteResult<()> {
|
||||
w.emit(&name.to_string())?;
|
||||
let values = self.0.iter().map(|v| format!("{:.6}", v)).collect::<Vec<_>>().join("\t");
|
||||
w.emit(&format!("(\t{}\t)", values))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ pub fn gmi_serializable_macro(input: TokenStream) -> TokenStream {
|
|||
tlv_header = quote! {
|
||||
let tlv = _r.tlv()?;
|
||||
if tlv.tag != #ty || tlv.flags != #flags {
|
||||
return Err(tlv.error(format!("unsupported tag/flags (wanted {}/{}, got {}/{})", #ty, #flags, tlv.tag, tlv.flags)));
|
||||
return Err(_r.error(format!("unsupported tag/flags (wanted {}/{}, got {}/{})", #ty, #flags, tlv.tag, tlv.flags)));
|
||||
}
|
||||
};
|
||||
if !tagged.nolen {
|
||||
|
@ -109,7 +109,7 @@ pub fn gmi_serializable_macro(input: TokenStream) -> TokenStream {
|
|||
let v: u32 = _r.read("value")?;
|
||||
let res = match v {
|
||||
#(#branches)*
|
||||
_ => return Err(_r.error("unknown ")),
|
||||
_ => return Err(_r.error(format!("unknown enum value {}", v))),
|
||||
};
|
||||
#tlv_footer
|
||||
Ok(res)
|
||||
|
|
|
@ -1,8 +1,43 @@
|
|||
fn main() -> std::io::Result<()> {
|
||||
let f = std::fs::File::open("/home/q3k/Games/RA2/Robot Arena 2 v1.4/Arenas/box/boxarena.gmf")?;
|
||||
let gmf = gmflib::GMF::read_gmi(f).unwrap();
|
||||
let txt_gmfs = vec![
|
||||
"Arenas/practice arena/practice_arena_txt.gmf",
|
||||
"Arenas/octagon/octagon_txt.gmf",
|
||||
"Arenas/parkinglot/parkinglot_txt.gmf",
|
||||
"Arenas/flextop/flextop_txt.gmf",
|
||||
"Arenas/barrels/barrels_txt.gmf",
|
||||
"Arenas/cones/cones_txt.gmf",
|
||||
"Arenas/skull/skull_txt.gmf",
|
||||
"Arenas/crates/crates_txt.gmf",
|
||||
"Arenas/bridge/bridge_txt.gmf",
|
||||
"Arenas/cinderblocks/blocks_txt.gmf",
|
||||
"Arenas/event_results/event_results_txt.gmf",
|
||||
"Arenas/compressor/compressor_txt.gmf",
|
||||
"Arenas/hilltop/hilltop_txt.gmf",
|
||||
"Arenas/kingofhill/king_txt.gmf",
|
||||
"Arenas/electric/electric_txt.gmf",
|
||||
"Arenas/half/half_txt.gmf",
|
||||
"Arenas/box/boxarena_txt.gmf",
|
||||
"Arenas/tabletop/clawtop_txt.gmf",
|
||||
"Arenas/ramps/ramps_txt.gmf",
|
||||
"UI/botlab/AP_box_selected_txt.gmf",
|
||||
"UI/botlab/heading_arrow_txt.gmf",
|
||||
"UI/botlab/AP_box_unselected_txt.gmf",
|
||||
"Components/cannon/cannon_txt.gmf",
|
||||
];
|
||||
|
||||
gmf.write_gma(std::io::stdout()).unwrap();
|
||||
for txt_gmf_path in txt_gmfs.iter() {
|
||||
let txt_gmf_path = "/home/q3k/Games/RA2/Robot Arena 2 v1.4/".to_string() + txt_gmf_path;
|
||||
let gmf_path = txt_gmf_path.replace("_txt.gmf", ".gmf");
|
||||
println!("Testing {} vs {}...", txt_gmf_path, gmf_path);
|
||||
|
||||
let f = std::fs::File::open(gmf_path).unwrap();
|
||||
let gmf = gmflib::GMF::read_gmi(f).unwrap();
|
||||
}
|
||||
|
||||
//let f = std::fs::File::open("/home/q3k/Games/RA2/Robot Arena 2 v1.4/Arenas/barrels/barrels.gmf")?;
|
||||
//let gmf = gmflib::GMF::read_gmi(f).unwrap();
|
||||
|
||||
//gmf.write_gma(std::io::stdout()).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue