Skip to main content

rpfm_lib/files/rigidmodel/materials/
rope.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11use super::*;
12
13//---------------------------------------------------------------------------//
14//                            Implementation
15//---------------------------------------------------------------------------//
16
17/// Rope materials of version 6 RigidModels: the default material, followed by the rope as a chain of nodes.
18///
19/// There's one link fewer than nodes, and the file doesn't store their count.
20impl Material {
21    pub fn read_rope<R: ReadBytes>(data: &mut R, version: u32) -> Result<Self> {
22        let mut material = Self::read_default(data, version)?;
23
24        let node_count = data.read_u32()?;
25        let rope = &mut material.rope;
26        rope.attachments = Vector4::new(data.read_i32()?, data.read_i32()?, data.read_i32()?, data.read_i32()?);
27        rope.uk_1 = data.read_f32()?;
28        rope.uk_2 = data.read_u32()?;
29
30        rope.nodes = Vec::with_capacity(node_count as usize);
31        for _ in 0..node_count {
32            rope.nodes.push(RopeNode {
33                position: Vector3::new(data.read_f32()?, data.read_f32()?, data.read_f32()?),
34                weight: data.read_f32()?,
35                uk_1: data.read_f32()?,
36            });
37        }
38
39        let link_count = node_count.saturating_sub(1);
40        rope.links = Vec::with_capacity(link_count as usize);
41        for _ in 0..link_count {
42            rope.links.push(RopeLink {
43                node_a: data.read_u32()?,
44                node_b: data.read_u32()?,
45                length: data.read_f32()?,
46            });
47        }
48
49        Ok(material)
50    }
51
52    pub fn write_rope<W: WriteBytes>(&self, buffer: &mut W, version: u32) -> Result<()> {
53        let rope = &self.rope;
54        if rope.links.len() != rope.nodes.len().saturating_sub(1) {
55            return Err(RLibError::EncodingRigidModelRopeLinkCountMismatch(rope.nodes.len(), rope.links.len()));
56        }
57
58        self.write_default(buffer, version)?;
59
60        buffer.write_u32(rope.nodes.len() as u32)?;
61        for attachment in rope.attachments.iter() {
62            buffer.write_i32(*attachment)?;
63        }
64        buffer.write_f32(rope.uk_1)?;
65        buffer.write_u32(rope.uk_2)?;
66
67        for node in &rope.nodes {
68            buffer.write_f32(node.position.x)?;
69            buffer.write_f32(node.position.y)?;
70            buffer.write_f32(node.position.z)?;
71            buffer.write_f32(node.weight)?;
72            buffer.write_f32(node.uk_1)?;
73        }
74
75        for link in &rope.links {
76            buffer.write_u32(link.node_a)?;
77            buffer.write_u32(link.node_b)?;
78            buffer.write_f32(link.length)?;
79        }
80
81        Ok(())
82    }
83}