Skip to main content

oxygengine_visual_novel/
character.rs

1use crate::{Color, Position, Scale};
2use anim::{animation::Interpolation, transition::Transition};
3use core::{prefab::Prefab, Scalar};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7pub type CharacterStyle = Transition<String>;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Character {
11    name: String,
12    /// {style name: image name}
13    pub styles: HashMap<String, String>,
14    #[serde(default)]
15    style: CharacterStyle,
16    #[serde(default)]
17    visibility: Interpolation<Scalar>,
18    #[serde(default)]
19    name_color: Interpolation<Color>,
20    /// position in screen space percentage.
21    #[serde(default)]
22    position: Interpolation<Position>,
23    /// alignment tells where in the image space pivot is located (percentage of image size).
24    #[serde(default)]
25    alignment: Interpolation<Position>,
26    #[serde(default)]
27    rotation: Interpolation<Scalar>,
28    #[serde(default)]
29    scale: Interpolation<Scale>,
30    #[serde(skip)]
31    pub(crate) dirty: bool,
32}
33
34impl Prefab for Character {
35    fn post_from_prefab(&mut self) {
36        self.dirty = true;
37    }
38}
39
40impl Default for Character {
41    fn default() -> Self {
42        Self {
43            name: Default::default(),
44            styles: Default::default(),
45            style: Default::default(),
46            visibility: Interpolation::instant(1.0),
47            name_color: Interpolation::instant((1.0, 1.0, 1.0).into()),
48            position: Default::default(),
49            alignment: Default::default(),
50            rotation: Default::default(),
51            scale: Interpolation::instant((1.0, 1.0).into()),
52            dirty: true,
53        }
54    }
55}
56
57impl Character {
58    pub fn new(name: &str) -> Self {
59        Self {
60            name: name.to_owned(),
61            ..Default::default()
62        }
63    }
64
65    pub fn initialize(&mut self) {
66        self.style.end();
67        self.visibility.end();
68        self.name_color.end();
69        self.position.end();
70        self.alignment.end();
71        self.rotation.end();
72        self.scale.end();
73    }
74
75    pub fn is_dirty(&self) -> bool {
76        self.dirty
77            || self.style.in_progress()
78            || self.visibility.in_progress()
79            || self.name_color.in_progress()
80            || self.position.in_progress()
81            || self.alignment.in_progress()
82            || self.rotation.in_progress()
83            || self.scale.in_progress()
84    }
85
86    pub fn rebuild(&mut self) {
87        self.dirty = true;
88    }
89
90    pub fn name(&self) -> &str {
91        &self.name
92    }
93
94    pub fn set_name(&mut self, value: String) {
95        self.name = value;
96        self.dirty = true;
97    }
98
99    /// (style name, image name)
100    pub fn styles(&self) -> impl Iterator<Item = (&str, &str)> {
101        self.styles.iter().map(|(k, v)| (k.as_str(), v.as_str()))
102    }
103
104    /// (from style, phase, to style)
105    pub fn style(&self) -> (&str, Scalar, &str) {
106        let from = self.style.from().as_str();
107        let to = self.style.to().as_str();
108        let phase = self.style.phase();
109        (from, phase, to)
110    }
111
112    pub fn style_transition(&self) -> &CharacterStyle {
113        &self.style
114    }
115
116    pub fn style_transition_mut(&mut self) -> &mut CharacterStyle {
117        &mut self.style
118    }
119
120    pub fn set_style(&mut self, value: String) {
121        self.style.set(value);
122        self.style.playing = true;
123    }
124
125    pub fn visibility(&self) -> Scalar {
126        self.visibility.value()
127    }
128
129    pub fn visibility_anim(&self) -> &Interpolation<Scalar> {
130        &self.visibility
131    }
132
133    pub fn visibility_anim_mut(&mut self) -> &mut Interpolation<Scalar> {
134        &mut self.visibility
135    }
136
137    pub fn set_visibility(&mut self, value: Scalar) {
138        self.visibility.set(value);
139        self.visibility.playing = true;
140    }
141
142    pub fn hide(&mut self) {
143        self.set_visibility(0.0);
144    }
145
146    pub fn show(&mut self) {
147        self.set_visibility(1.0);
148    }
149
150    pub fn name_color(&self) -> Color {
151        self.name_color.value()
152    }
153
154    pub fn name_color_anim(&self) -> &Interpolation<Color> {
155        &self.name_color
156    }
157
158    pub fn name_color_anim_mut(&mut self) -> &mut Interpolation<Color> {
159        &mut self.name_color
160    }
161
162    pub fn set_name_color(&mut self, value: Color) {
163        self.name_color.set(value);
164        self.name_color.playing = true;
165    }
166
167    pub fn position(&self) -> Position {
168        self.position.value()
169    }
170
171    pub fn position_anim(&self) -> &Interpolation<Position> {
172        &self.position
173    }
174
175    pub fn position_anim_mut(&mut self) -> &mut Interpolation<Position> {
176        &mut self.position
177    }
178
179    pub fn set_position(&mut self, value: Position) {
180        self.position.set(value);
181        self.position.playing = true;
182    }
183
184    pub fn alignment(&self) -> Position {
185        self.alignment.value()
186    }
187
188    pub fn alignment_anim(&self) -> &Interpolation<Position> {
189        &self.alignment
190    }
191
192    pub fn alignment_anim_mut(&mut self) -> &mut Interpolation<Position> {
193        &mut self.alignment
194    }
195
196    pub fn set_alignment(&mut self, value: Position) {
197        self.alignment.set(value);
198        self.alignment.playing = true;
199    }
200
201    pub fn rotation(&self) -> Scalar {
202        self.rotation.value()
203    }
204
205    pub fn rotation_anim(&self) -> &Interpolation<Scalar> {
206        &self.rotation
207    }
208
209    pub fn rotation_anim_mut(&mut self) -> &mut Interpolation<Scalar> {
210        &mut self.rotation
211    }
212
213    pub fn set_rotation(&mut self, value: Scalar) {
214        self.rotation.set(value);
215        self.rotation.playing = true;
216    }
217
218    pub fn scale(&self) -> Scale {
219        self.scale.value()
220    }
221
222    pub fn scale_anim(&self) -> &Interpolation<Scale> {
223        &self.scale
224    }
225
226    pub fn scale_anim_mut(&mut self) -> &mut Interpolation<Scale> {
227        &mut self.scale
228    }
229
230    pub fn set_scale(&mut self, value: Scale) {
231        self.scale.set(value);
232        self.scale.playing = true;
233    }
234
235    pub fn process(&mut self, delta_time: Scalar) {
236        self.dirty = false;
237        self.style.process(delta_time);
238        self.visibility.process(delta_time);
239        self.name_color.process(delta_time);
240        self.position.process(delta_time);
241        self.alignment.process(delta_time);
242        self.rotation.process(delta_time);
243        self.scale.process(delta_time);
244    }
245}