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<()> {
|
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 {
|
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<()> {
|
pub fn check<R: std::io::Read>(&self, r: &mut ReadStream<R>) -> ReadResult<()> {
|
||||||
let expected = self.start_pos + self.length as usize + 12usize;
|
let expected = self.start_pos + self.length as usize + 12usize;
|
||||||
if expected != r.pos {
|
if expected != r.pos {
|
||||||
|
|
|
@ -96,6 +96,7 @@ pub enum MapKind {
|
||||||
Diffuse = 1,
|
Diffuse = 1,
|
||||||
SelfIllum = 5,
|
SelfIllum = 5,
|
||||||
Opacity = 6,
|
Opacity = 6,
|
||||||
|
Reflect = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl gma::Serializable for MapKind {
|
impl gma::Serializable for MapKind {
|
||||||
|
@ -104,12 +105,15 @@ impl gma::Serializable for MapKind {
|
||||||
MapKind::Diffuse => w.emit("*MAP_DIFFUSE"),
|
MapKind::Diffuse => w.emit("*MAP_DIFFUSE"),
|
||||||
MapKind::SelfIllum => w.emit("*MAP_SELFILLUM"),
|
MapKind::SelfIllum => w.emit("*MAP_SELFILLUM"),
|
||||||
MapKind::Opacity => w.emit("*MAP_OPACITY"),
|
MapKind::Opacity => w.emit("*MAP_OPACITY"),
|
||||||
|
MapKind::Reflect => w.emit("*MAP_REFLECT"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
pub enum MapType {
|
pub enum MapType {
|
||||||
|
Explicit = 0,
|
||||||
|
Spherical = 1,
|
||||||
Screen = 4,
|
Screen = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,12 +185,14 @@ pub enum Shading {
|
||||||
#[derive(Debug, GMISerializable,GMASerializable)]
|
#[derive(Debug, GMISerializable,GMASerializable)]
|
||||||
pub enum Falloff {
|
pub enum Falloff {
|
||||||
In = 0,
|
In = 0,
|
||||||
|
InTwoSided = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
pub enum XPType {
|
pub enum XPType {
|
||||||
Other = 0,
|
Other = 0,
|
||||||
Filter = 1,
|
Filter = 1,
|
||||||
|
Additive = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
|
@ -274,11 +280,13 @@ pub struct ObjectList {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Object {
|
pub enum Object {
|
||||||
Geometry(GeometryObject),
|
Geometry(GeometryObject),
|
||||||
|
Camera(CameraObject),
|
||||||
Light(LightObject),
|
Light(LightObject),
|
||||||
AttachmentPoint(AttachmentPointObject),
|
AttachmentPoint(AttachmentPointObject),
|
||||||
ConstraintSolver(ConstraintSolverObject),
|
|
||||||
Simulation(SimulationObject),
|
Simulation(SimulationObject),
|
||||||
RBCollection(RBCollectionObject),
|
RBCollection(RBCollectionObject),
|
||||||
|
ConstraintSolver(ConstraintSolverObject),
|
||||||
|
AngularDashpot(AngularDashpotObject),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl gmi::Serializable for Object {
|
impl gmi::Serializable for Object {
|
||||||
|
@ -286,11 +294,13 @@ impl gmi::Serializable for Object {
|
||||||
let tlv = r.tlv()?;
|
let tlv = r.tlv()?;
|
||||||
let (res, check) = match (tlv.tag, tlv.flags) {
|
let (res, check) = match (tlv.tag, tlv.flags) {
|
||||||
(2, 4) => (Object::Geometry(r.read("geometry")?), false),
|
(2, 4) => (Object::Geometry(r.read("geometry")?), false),
|
||||||
|
(4, 2) => (Object::Camera(r.read("camera")?), false),
|
||||||
(5, 3) => (Object::Light(r.read("light")?), false),
|
(5, 3) => (Object::Light(r.read("light")?), false),
|
||||||
(21, 2) => (Object::AttachmentPoint(r.read("attachmentpoint")?), true),
|
(21, 2) => (Object::AttachmentPoint(r.read("attachmentpoint")?), true),
|
||||||
(42, 3) => (Object::ConstraintSolver(r.read("constraintsolver")?), false),
|
|
||||||
(30, 2) => (Object::Simulation(r.read("simulation")?), false),
|
(30, 2) => (Object::Simulation(r.read("simulation")?), false),
|
||||||
(31, 4) => (Object::RBCollection(r.read("rigidbodycollection")?), 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))),
|
_ => return Err(r.error(format!("unknown object type ({}, {})", tlv.tag, tlv.flags))),
|
||||||
};
|
};
|
||||||
if check {
|
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<()> {
|
fn write<W: io::Write, S: string::ToString>(&self, _name: S, w: &mut gma::WriteStream<W>) -> gma::WriteResult<()> {
|
||||||
match self {
|
match self {
|
||||||
Object::Geometry(o) => o.write("", w),
|
Object::Geometry(o) => o.write("", w),
|
||||||
|
Object::Camera(o) => o.write("", w),
|
||||||
Object::Light(o) => o.write("", w),
|
Object::Light(o) => o.write("", w),
|
||||||
Object::AttachmentPoint(o) => o.write("", w),
|
Object::AttachmentPoint(o) => o.write("", w),
|
||||||
Object::ConstraintSolver(o) => o.write("", w),
|
|
||||||
Object::Simulation(o) => o.write("", w),
|
Object::Simulation(o) => o.write("", w),
|
||||||
Object::RBCollection(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,
|
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)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
#[gmi_tagged(17, 2)]
|
#[gmi_tagged(17, 2)]
|
||||||
#[gma_name("NODE_TM")]
|
#[gma_name("NODE_TM")]
|
||||||
|
@ -612,6 +647,8 @@ pub enum LightType {
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
pub enum LightShadows {
|
pub enum LightShadows {
|
||||||
Off = 0,
|
Off = 0,
|
||||||
|
Mapped = 1,
|
||||||
|
Raytraced = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMASerializable)]
|
#[derive(Debug,GMASerializable)]
|
||||||
|
@ -648,14 +685,87 @@ pub struct ConstraintSolverObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
#[gmi_tagged(44, 2)]
|
#[gmi_tagged_nolen(44, 2)]
|
||||||
pub struct ConstraintList {
|
pub struct ConstraintList {
|
||||||
pub constraints: Vec<Constraint>,
|
pub constraints: Vec<Constraint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug)]
|
||||||
pub enum Constraint {
|
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)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
|
@ -796,6 +906,7 @@ impl gma::Serializable for NestedRigidBodyList {
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
pub enum GeoType {
|
pub enum GeoType {
|
||||||
Standard = 0,
|
Standard = 0,
|
||||||
|
Plane = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,GMISerializable,GMASerializable)]
|
#[derive(Debug,GMISerializable,GMASerializable)]
|
||||||
|
@ -818,3 +929,42 @@ impl gma::Serializable for DisabledCollisionPair {
|
||||||
self.a, self.b))
|
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! {
|
tlv_header = quote! {
|
||||||
let tlv = _r.tlv()?;
|
let tlv = _r.tlv()?;
|
||||||
if tlv.tag != #ty || tlv.flags != #flags {
|
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 {
|
if !tagged.nolen {
|
||||||
|
@ -109,7 +109,7 @@ pub fn gmi_serializable_macro(input: TokenStream) -> TokenStream {
|
||||||
let v: u32 = _r.read("value")?;
|
let v: u32 = _r.read("value")?;
|
||||||
let res = match v {
|
let res = match v {
|
||||||
#(#branches)*
|
#(#branches)*
|
||||||
_ => return Err(_r.error("unknown ")),
|
_ => return Err(_r.error(format!("unknown enum value {}", v))),
|
||||||
};
|
};
|
||||||
#tlv_footer
|
#tlv_footer
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
|
|
@ -1,8 +1,43 @@
|
||||||
fn main() -> std::io::Result<()> {
|
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 txt_gmfs = vec![
|
||||||
let gmf = gmflib::GMF::read_gmi(f).unwrap();
|
"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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue