Skip to main content

pfx_play/world/
characters.rs

1use pfx_load::scene::Value;
2use pfx_physics::rigid::{Character, CharacterDesc};
3
4use super::{ObjectId, World};
5use crate::PlayError;
6use crate::characters::{self, Setting};
7
8impl World {
9    pub fn character(&mut self, id: ObjectId) -> Result<&mut Character, PlayError> {
10        let place = id.index();
11        if !self.characters.contains_key(&place) {
12            let name = self.name(id).to_string();
13            let desc = *self.roster.get(&name).ok_or_else(|| {
14                PlayError::Body(format!("object {name} has no [object.character]"))
15            })?;
16            if self.bodies.contains_key(&place) {
17                return Err(PlayError::Body(format!(
18                    "object {name} has a body; a character brings its own capsule"
19                )));
20            }
21            let feet = self.at(id);
22            let character = Character::spawn(&mut self.physics, desc, feet)
23                .map_err(|why| PlayError::Body(format!("character {name}: {why}")))?;
24            self.owners.insert(character.collider(), place);
25            self.characters.insert(place, character);
26        }
27        let objects = &self.objects;
28        self.characters.get_mut(&place).ok_or_else(|| {
29            PlayError::Body(format!("character {} did not spawn", objects[place].name))
30        })
31    }
32
33    pub fn set_character_desc(
34        &mut self,
35        id: ObjectId,
36        desc: CharacterDesc,
37    ) -> Result<(), PlayError> {
38        let name = self.name(id).to_string();
39        let place = id.index();
40        let refuse = |why: String| PlayError::Body(format!("character {name}: {why}"));
41        match self.characters.get_mut(&place) {
42            Some(character) => {
43                let old = character.collider();
44                character
45                    .set_desc(&mut self.physics, desc)
46                    .map_err(refuse)?;
47                let new = character.collider();
48                if new != old {
49                    self.owners.remove(&old);
50                    self.owners.insert(new, place);
51                }
52            }
53            None => desc.check().map_err(refuse)?,
54        }
55        self.roster.insert(name, desc);
56        Ok(())
57    }
58
59    pub fn character_of(&self, id: ObjectId) -> Option<&Character> {
60        self.characters.get(&id.index())
61    }
62
63    pub fn characters(&self) -> impl Iterator<Item = (ObjectId, &Character)> {
64        self.characters
65            .iter()
66            .map(|(place, character)| (ObjectId::from_index(*place), character))
67    }
68
69    pub fn character_desc(&self, id: ObjectId) -> Option<&CharacterDesc> {
70        self.roster.get(self.name(id))
71    }
72
73    pub fn remove_character(&mut self, id: ObjectId) -> bool {
74        match self.characters.remove(&id.index()) {
75            Some(character) => {
76                self.owners.remove(&character.collider());
77                character.remove(&mut self.physics)
78            }
79            None => false,
80        }
81    }
82
83    pub(crate) fn step_characters(&mut self) {
84        for character in self.characters.values_mut() {
85            character.step(&mut self.physics);
86        }
87    }
88
89    pub(crate) fn place_characters(&mut self) {
90        let placed: Vec<(usize, [f32; 3])> = self
91            .characters
92            .iter()
93            .map(|(place, character)| (*place, character.feet()))
94            .collect();
95        for (place, feet) in placed {
96            self.move_to(ObjectId::from_index(place), feet);
97        }
98    }
99
100    pub(crate) fn edit_character(
101        &mut self,
102        id: ObjectId,
103        key: &str,
104        value: &Value,
105    ) -> Result<(), String> {
106        let name = self.name(id).to_string();
107        let mut desc = *self
108            .roster
109            .get(&name)
110            .ok_or_else(|| format!("object {name} has no [object.character]"))?;
111        let setting = Setting::of_value(value).ok_or("not a value")?;
112        characters::set(&mut desc, key, &setting)?;
113        self.set_character_desc(id, desc)
114            .map_err(|error| error.to_string())?;
115        Ok(())
116    }
117}