1use super::cache::{
2 FigureKey, FigureModelEntryFuture, ModelEntryFuture, TerrainModelEntryFuture, ToolKey,
3};
4use common::{
5 assets::{
6 self, AssetCache, AssetExt, AssetHandle, BoxedError, Concatenate, DotVox, MultiRon,
7 ReloadWatcher, SharedString,
8 },
9 comp::{
10 arthropod::{self, BodyType as ABodyType, Species as ASpecies},
11 biped_large::{self, BodyType as BLBodyType, Species as BLSpecies},
12 biped_small,
13 bird_large::{self, BodyType as BLABodyType, Species as BLASpecies},
14 bird_medium::{self, BodyType as BMBodyType, Species as BMSpecies},
15 body,
16 crustacean::{self, BodyType as CBodyType, Species as CSpecies},
17 dragon::{self, BodyType as DBodyType, Species as DSpecies},
18 fish_medium::{self, BodyType as FMBodyType, Species as FMSpecies},
19 fish_small::{self, BodyType as FSBodyType, Species as FSSpecies},
20 golem::{self, BodyType as GBodyType, Species as GSpecies},
21 humanoid::{self, Body, BodyType, EyeColor, Skin, Species},
22 item::item_key::ItemKey,
23 object,
24 quadruped_low::{self, BodyType as QLBodyType, Species as QLSpecies},
25 quadruped_medium::{self, BodyType as QMBodyType, Species as QMSpecies},
26 quadruped_small::{self, BodyType as QSBodyType, Species as QSSpecies},
27 ship::{
28 self,
29 figuredata::{ShipSpec, VoxelCollider},
30 },
31 theropod::{self, BodyType as TBodyType, Species as TSpecies},
32 },
33 figure::{Cell, DynaUnionizer, MatCell, MatSegment, Material, Segment},
34 terrain::Block,
35 vol::{IntoFullPosIterator, ReadVol},
36 volumes::dyna::Dyna,
37};
38use hashbrown::HashMap;
39use serde::{Deserialize, Deserializer};
40use std::{fmt, hash::Hash};
41use tracing::{error, warn};
42use vek::*;
43
44pub type BoneMeshes = (Segment, Vec3<f32>);
45
46const DEFAULT_INDEX: u32 = 0;
47
48fn load_segment(mesh_name: &str) -> Segment {
49 let full_specifier: String = ["voxygen.voxel.", mesh_name].concat();
50 Segment::from_vox_model_index(
51 &DotVox::load_expect(&full_specifier).read().0,
52 DEFAULT_INDEX as usize,
53 )
54}
55fn graceful_load_vox(mesh_name: &str) -> AssetHandle<DotVox> {
56 let full_specifier: String = ["voxygen.voxel.", mesh_name].concat();
57 graceful_load_vox_fullspec(&full_specifier)
58}
59fn graceful_load_vox_fullspec(full_specifier: &str) -> AssetHandle<DotVox> {
60 match DotVox::load(full_specifier) {
61 Ok(dot_vox) => dot_vox,
62 Err(_) => {
63 error!(?full_specifier, "Could not load vox file for figure");
64 DotVox::load_expect("voxygen.voxel.not_found")
65 },
66 }
67}
68fn graceful_load_segment(mesh_name: &str, model_index: u32) -> Segment {
69 Segment::from_vox_model_index(&graceful_load_vox(mesh_name).read().0, model_index as usize)
70}
71fn graceful_load_segment_fullspec(full_specifier: &str, model_index: u32) -> Segment {
72 Segment::from_vox_model_index(
73 &graceful_load_vox_fullspec(full_specifier).read().0,
74 model_index as usize,
75 )
76}
77fn graceful_load_segment_flipped(mesh_name: &str, flipped: bool, model_index: u32) -> Segment {
78 Segment::from_vox(
79 &graceful_load_vox(mesh_name).read().0,
80 flipped,
81 model_index as usize,
82 )
83}
84fn graceful_load_mat_segment(mesh_name: &str, model_index: u32) -> MatSegment {
85 MatSegment::from_vox_model_index(&graceful_load_vox(mesh_name).read().0, model_index as usize)
86}
87fn graceful_load_mat_segment_flipped(mesh_name: &str, model_index: u32) -> MatSegment {
88 MatSegment::from_vox(
89 &graceful_load_vox(mesh_name).read().0,
90 true,
91 model_index as usize,
92 )
93}
94
95pub fn load_mesh(mesh_name: &str, position: Vec3<f32>) -> BoneMeshes {
96 (load_segment(mesh_name), position)
97}
98
99pub fn recolor_grey(rgb: Rgb<u8>, color: Rgb<u8>) -> Rgb<u8> {
100 use common::util::{linear_to_srgb, srgb_to_linear_fast};
101
102 const BASE_GREY: f32 = 178.0;
103 if rgb.r == rgb.g && rgb.g == rgb.b {
104 let c1 = srgb_to_linear_fast(rgb.map(|e| e as f32 / BASE_GREY));
105 let c2 = srgb_to_linear_fast(color.map(|e| e as f32 / 255.0));
106
107 linear_to_srgb(c1 * c2).map(|e| (e.clamp(0.0, 1.0) * 255.0) as u8)
108 } else {
109 rgb
110 }
111}
112
113pub trait BodySpec: Sized {
115 type Spec;
116 type Manifests: Send + Sync + Clone;
119 type Extra: Send + Sync;
120 type BoneMesh;
121 type ModelEntryFuture<const N: usize>: ModelEntryFuture<N>;
122
123 fn load_spec() -> Result<Self::Manifests, assets::Error>;
125
126 fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher;
128
129 fn bone_meshes(
137 key: &FigureKey<Self>,
138 manifests: &Self::Manifests,
139 extra: Self::Extra,
140 ) -> [Option<Self::BoneMesh>; 16]; }
142
143macro_rules! make_vox_spec {
144 (
145 $body:ty,
146 struct $Spec:ident { $( $(+)? $field:ident: $ty:ty = $asset_path:literal),* $(,)? },
147 |$self_pat:pat, $spec_pat:pat_param| $bone_meshes:block $(,)?
148 ) => {
149 #[derive(Clone)]
150 pub struct $Spec {
151 $( $field: AssetHandle<MultiRon<$ty>>, )*
152 }
153
154 impl assets::Asset for $Spec {
155 fn load(_: &AssetCache, _: &SharedString) -> Result<Self, BoxedError> {
156 Ok($Spec {
157 $( $field: AssetExt::load($asset_path)?, )*
158 })
159 }
160 }
161
162 impl BodySpec for $body {
163 type Spec = $Spec;
164 type Manifests = AssetHandle<Self::Spec>;
165 type Extra = ();
166 type BoneMesh = BoneMeshes;
167 type ModelEntryFuture<const N: usize> = FigureModelEntryFuture<N>;
168
169 fn load_spec() -> Result<Self::Manifests, assets::Error> {
170 Self::Spec::load("")
171 }
172
173 fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher { manifests.reload_watcher() }
174
175 fn bone_meshes(
176 $self_pat: &FigureKey<Self>,
177 manifests: &Self::Manifests,
178 _: Self::Extra,
179 ) -> [Option<BoneMeshes>; anim::MAX_BONE_COUNT] {
180 let $spec_pat = &*manifests.read();
181 $bone_meshes
182 }
183 }
184 }
185}
186macro_rules! impl_concatenate_for_wrapper {
187 ($name:ty) => {
188 impl Concatenate for $name {
189 fn concatenate(self, b: Self) -> Self { Self(self.0.concatenate(b.0)) }
190 }
191 };
192}
193
194#[derive(Deserialize)]
197struct VoxSpec<T>(String, [T; 3], #[serde(default)] u32);
198
199#[derive(Deserialize)]
200struct VoxSimple(String);
201
202impl Default for VoxSimple {
203 fn default() -> Self { VoxSimple("armor.empty".to_string()) }
204}
205
206#[derive(Deserialize)]
207struct VoxMirror(String, bool);
208
209impl Default for VoxMirror {
210 fn default() -> Self { VoxMirror("armor.empty".to_string(), false) }
211}
212
213#[derive(Deserialize)]
214struct ArmorVoxSpec {
215 vox_spec: VoxSpec<f32>,
216 color: Option<[u8; 3]>,
217}
218
219#[derive(Deserialize)]
220#[expect(dead_code)]
221enum ModularComponentSpec {
222 Damage((String, [i32; 3])),
224 Held((String, [f32; 3], [i32; 3])),
226}
227
228#[derive(Deserialize)]
230struct SidedArmorVoxSpec {
231 left: ArmorVoxSpec,
232 right: ArmorVoxSpec,
233 #[expect(dead_code)]
235 color: Option<[u8; 3]>,
236}
237
238#[derive(Deserialize)]
240struct HumColorSpec {
241 hair_colors: humanoid::species::PureCases<Vec<(u8, u8, u8)>>,
242 eye_colors_light: humanoid::eye_color::PureCases<(u8, u8, u8)>,
243 eye_colors_dark: humanoid::eye_color::PureCases<(u8, u8, u8)>,
244 eye_white: (u8, u8, u8),
245 skin_colors_plain: humanoid::skin::PureCases<(u8, u8, u8)>,
246 skin_colors_light: humanoid::skin::PureCases<(u8, u8, u8)>,
247 skin_colors_dark: humanoid::skin::PureCases<(u8, u8, u8)>,
248}
249
250impl HumColorSpec {
251 fn hair_color(&self, species: Species, val: u8) -> (u8, u8, u8) {
252 species
253 .elim_case_pure(&self.hair_colors)
254 .get(val as usize)
255 .copied()
256 .unwrap_or((0, 0, 0))
257 }
258
259 fn color_segment(
260 &self,
261 mat_segment: MatSegment,
262 skin: Skin,
263 hair_color: (u8, u8, u8),
264 eye_color: EyeColor,
265 ) -> Segment {
266 mat_segment.to_segment(|mat| {
268 match mat {
269 Material::Skin => *skin.elim_case_pure(&self.skin_colors_plain),
270 Material::SkinDark => *skin.elim_case_pure(&self.skin_colors_dark),
271 Material::SkinLight => *skin.elim_case_pure(&self.skin_colors_light),
272 Material::Hair => hair_color,
273 Material::EyeLight => *eye_color.elim_case_pure(&self.eye_colors_light),
275 Material::EyeDark => *eye_color.elim_case_pure(&self.eye_colors_dark),
276 Material::EyeWhite => self.eye_white,
277 }
278 .into()
279 })
280 }
281}
282
283impl Concatenate for HumColorSpec {
284 fn concatenate(self, _b: Self) -> Self { todo!("Can't concatenate HumColorSpec") }
285}
286
287#[derive(Deserialize)]
289struct HumHeadSubSpec {
290 offset: [f32; 3], head: VoxSpec<i32>,
292 eyes: Vec<Option<VoxSpec<i32>>>,
293 hair: Vec<Option<VoxSpec<i32>>>,
294 beard: Vec<Option<VoxSpec<i32>>>,
295 accessory: Vec<Option<VoxSpec<i32>>>,
296}
297#[derive(Deserialize)]
298struct HumHeadSpec(HashMap<(Species, BodyType), HumHeadSubSpec>);
299
300impl HumHeadSpec {
301 fn mesh_head(
302 &self,
303 body: &Body,
304 color_spec: &HumColorSpec,
305 helmet: Option<(Segment, Vec3<i32>)>,
306 ) -> BoneMeshes {
307 let spec = match self.0.get(&(body.species, body.body_type)) {
308 Some(spec) => spec,
309 None => {
310 error!(
311 ?body.species,
312 ?body.body_type,
313 "No head specification exists for the combination of species and body"
314 );
315 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
316 },
317 };
318
319 let hair_color = color_spec.hair_color(body.species, body.hair_color);
320 let hair_rgb = hair_color.into();
321 let skin_rgb = body.species.skin_color(body.skin);
322 let eye_rgb = body.species.eye_color(body.eye_color);
323
324 let bare_head = graceful_load_mat_segment(&spec.head.0, spec.head.2);
326
327 let eyes = match spec.eyes.get(body.eyes as usize) {
328 Some(Some(spec)) => Some((
329 color_spec.color_segment(
330 graceful_load_mat_segment(&spec.0, spec.2)
331 .map_rgb(|rgb| recolor_grey(rgb, hair_rgb)),
332 skin_rgb,
333 hair_color,
334 eye_rgb,
335 ),
336 Vec3::from(spec.1),
337 )),
338 Some(None) => None,
339 None => {
340 warn!("No specification for these eyes: {:?}", body.eyes);
341 None
342 },
343 };
344 let hair = match spec.hair.get(body.hair_style as usize) {
345 Some(Some(spec)) => Some((
346 graceful_load_segment(&spec.0, spec.2).map_rgb(|rgb| recolor_grey(rgb, hair_rgb)),
347 Vec3::from(spec.1),
348 )),
349 Some(None) => None,
350 None => {
351 warn!("No specification for hair style {}", body.hair_style);
352 None
353 },
354 };
355 let beard = match spec.beard.get(body.beard as usize) {
356 Some(Some(spec)) => Some((
357 graceful_load_segment(&spec.0, spec.2).map_rgb(|rgb| recolor_grey(rgb, hair_rgb)),
358 Vec3::from(spec.1),
359 )),
360 Some(None) => None,
361 None => {
362 warn!("No specification for this beard: {:?}", body.beard);
363 None
364 },
365 };
366 let accessory = match spec.accessory.get(body.accessory as usize) {
367 Some(Some(spec)) => Some((graceful_load_segment(&spec.0, spec.2), Vec3::from(spec.1))),
368 Some(None) => None,
369 None => {
370 warn!("No specification for this accessory: {:?}", body.accessory);
371 None
372 },
373 };
374
375 let (head, origin_offset) = DynaUnionizer::new()
376 .add(
377 color_spec.color_segment(bare_head, skin_rgb, hair_color, eye_rgb),
378 spec.head.1.into(),
379 )
380 .maybe_add(eyes)
381 .maybe_add(hair)
382 .maybe_add(beard)
383 .maybe_add(accessory)
384 .maybe_add(helmet)
385 .unify_with(|v, old_v| {
386 if old_v.attr().is_not_overridable() {
387 old_v
388 } else if v.attr().is_hollow() {
389 Cell::Empty
390 } else {
391 v
392 }
393 });
394 (
395 head,
396 Vec3::from(spec.offset) + origin_offset.map(|e| -(e as f32)),
397 )
398 }
399}
400impl_concatenate_for_wrapper!(HumHeadSpec);
401
402#[derive(Deserialize)]
406struct ArmorVoxSpecMap<K, S>
407where
408 K: Hash + Eq,
409{
410 default: S,
411 map: HashMap<K, S>,
412}
413impl<K: Hash + Eq, S> Concatenate for ArmorVoxSpecMap<K, S> {
414 fn concatenate(self, b: Self) -> Self {
415 Self {
416 default: self.default,
417 map: self.map.concatenate(b.map),
418 }
419 }
420}
421#[derive(Deserialize)]
422struct HumArmorShoulderSpec(ArmorVoxSpecMap<String, SidedArmorVoxSpec>);
423impl_concatenate_for_wrapper!(HumArmorShoulderSpec);
424#[derive(Deserialize)]
425struct HumArmorChestSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
426impl_concatenate_for_wrapper!(HumArmorChestSpec);
427#[derive(Deserialize)]
428struct HumArmorHandSpec(ArmorVoxSpecMap<String, SidedArmorVoxSpec>);
429impl_concatenate_for_wrapper!(HumArmorHandSpec);
430#[derive(Deserialize)]
431struct HumArmorBeltSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
432impl_concatenate_for_wrapper!(HumArmorBeltSpec);
433#[derive(Deserialize)]
434struct HumArmorBackSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
435impl_concatenate_for_wrapper!(HumArmorBackSpec);
436#[derive(Deserialize)]
437struct HumArmorPantsSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
438impl_concatenate_for_wrapper!(HumArmorPantsSpec);
439#[derive(Deserialize)]
440struct HumArmorFootSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
441impl_concatenate_for_wrapper!(HumArmorFootSpec);
442#[derive(Deserialize)]
443struct HumMainWeaponSpec(HashMap<ToolKey, ArmorVoxSpec>);
444impl_concatenate_for_wrapper!(HumMainWeaponSpec);
445#[derive(Deserialize)]
446struct HumArmorLanternSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
447impl_concatenate_for_wrapper!(HumArmorLanternSpec);
448#[derive(Deserialize)]
449struct HumArmorGliderSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
450impl_concatenate_for_wrapper!(HumArmorGliderSpec);
451#[derive(Deserialize)]
452struct HumArmorHeadSpec(ArmorVoxSpecMap<(Species, BodyType, String), ArmorVoxSpec>);
453impl_concatenate_for_wrapper!(HumArmorHeadSpec);
454#[derive(Deserialize)]
455struct HumArmorTabardSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
456impl_concatenate_for_wrapper!(HumArmorTabardSpec);
457
458make_vox_spec!(
459 Body,
460 struct HumSpec {
461 color: HumColorSpec = "voxygen.voxel.humanoid_color_manifest",
462 head: HumHeadSpec = "voxygen.voxel.humanoid_head_manifest",
463 armor_shoulder: HumArmorShoulderSpec = "voxygen.voxel.humanoid_armor_shoulder_manifest",
464 armor_chest: HumArmorChestSpec = "voxygen.voxel.humanoid_armor_chest_manifest",
465 armor_hand: HumArmorHandSpec = "voxygen.voxel.humanoid_armor_hand_manifest",
466 armor_belt: HumArmorBeltSpec = "voxygen.voxel.humanoid_armor_belt_manifest",
467 armor_back: HumArmorBackSpec = "voxygen.voxel.humanoid_armor_back_manifest",
468 armor_pants: HumArmorPantsSpec = "voxygen.voxel.humanoid_armor_pants_manifest",
469 armor_foot: HumArmorFootSpec = "voxygen.voxel.humanoid_armor_foot_manifest",
470 main_weapon: HumMainWeaponSpec = "voxygen.voxel.biped_weapon_manifest",
471 armor_lantern: HumArmorLanternSpec = "voxygen.voxel.humanoid_lantern_manifest",
472 armor_glider: HumArmorGliderSpec = "voxygen.voxel.humanoid_glider_manifest",
473 armor_head: HumArmorHeadSpec = "voxygen.voxel.humanoid_armor_head_manifest",
474 },
477 |FigureKey {
478 body,
479 item_key: _,
480 extra,
481 },
482 spec| {
483 const DEFAULT_LOADOUT: super::cache::CharacterCacheKey = super::cache::CharacterCacheKey {
484 third_person: None,
485 tool: None,
486 lantern: None,
487 glider: None,
488 hand: None,
489 foot: None,
490 head: None,
491 };
492
493 let loadout = extra.as_deref().unwrap_or(&DEFAULT_LOADOUT);
495 let third_person = loadout.third_person.as_ref();
496 let tool = loadout.tool.as_ref();
497 let lantern = loadout.lantern.as_deref();
498 let glider = loadout.glider.as_deref();
499 let hand = loadout.hand.as_ref();
500 let foot = loadout.foot.as_deref();
501
502 let color = &spec.color.read().0;
503
504 [
505 third_person.map(|_| {
506 spec.head.read().0.mesh_head(
507 body,
508 color,
509 spec.armor_head
510 .read()
511 .0
512 .load_head(body, loadout.head.as_deref()),
513 )
514 }),
515 third_person.map(|loadout| {
516 spec.armor_chest
517 .read()
518 .0
519 .mesh_chest(body, color, loadout.chest.as_deref())
520 }),
521 third_person.map(|loadout| {
522 spec.armor_belt
523 .read()
524 .0
525 .mesh_belt(body, color, loadout.belt.as_deref())
526 }),
527 third_person.map(|loadout| {
528 spec.armor_back
529 .read()
530 .0
531 .mesh_back(body, color, loadout.back.as_deref())
532 }),
533 third_person.map(|loadout| {
534 spec.armor_pants
535 .read()
536 .0
537 .mesh_pants(body, color, loadout.pants.as_deref())
538 }),
539 hand.map(|hand| {
540 spec.armor_hand
541 .read()
542 .0
543 .mesh_left_hand(body, color, hand.as_deref())
544 }),
545 hand.map(|hand| {
546 spec.armor_hand
547 .read()
548 .0
549 .mesh_right_hand(body, color, hand.as_deref())
550 }),
551 Some(spec.armor_foot.read().0.mesh_left_foot(body, color, foot)),
552 Some(spec.armor_foot.read().0.mesh_right_foot(body, color, foot)),
553 third_person.map(|loadout| {
554 spec.armor_shoulder.read().0.mesh_left_shoulder(
555 body,
556 color,
557 loadout.shoulder.as_deref(),
558 )
559 }),
560 third_person.map(|loadout| {
561 spec.armor_shoulder.read().0.mesh_right_shoulder(
562 body,
563 color,
564 loadout.shoulder.as_deref(),
565 )
566 }),
567 Some(spec.armor_glider.read().0.mesh_glider(body, color, glider)),
568 tool.and_then(|tool| tool.active.as_ref())
569 .map(|tool| spec.main_weapon.read().0.mesh_main_weapon(tool, false)),
570 tool.and_then(|tool| tool.second.as_ref())
571 .map(|tool| spec.main_weapon.read().0.mesh_main_weapon(tool, true)),
572 Some(
573 spec.armor_lantern
574 .read()
575 .0
576 .mesh_lantern(body, color, lantern),
577 ),
578 Some(mesh_hold()),
579 ]
580 },
581);
582
583impl HumArmorShoulderSpec {
585 fn mesh_shoulder(
586 &self,
587 body: &Body,
588 color_spec: &HumColorSpec,
589 shoulder: Option<&str>,
590 flipped: bool,
591 ) -> BoneMeshes {
592 let spec = if let Some(shoulder) = shoulder {
593 match self.0.map.get(shoulder) {
594 Some(spec) => spec,
595 None => {
596 error!(?shoulder, "No shoulder specification exists");
597 return load_mesh("not_found", Vec3::new(-3.0, -3.5, 0.1));
598 },
599 }
600 } else {
601 &self.0.default
602 };
603
604 let mut shoulder_segment = color_spec.color_segment(
605 if flipped {
606 graceful_load_mat_segment_flipped(&spec.left.vox_spec.0, spec.left.vox_spec.2)
607 } else {
608 graceful_load_mat_segment(&spec.right.vox_spec.0, spec.right.vox_spec.2)
609 },
610 body.species.skin_color(body.skin),
611 color_spec.hair_color(body.species, body.hair_color),
612 body.species.eye_color(body.eye_color),
613 );
614
615 let offset = if flipped {
621 spec.left.vox_spec.1
622 } else {
623 spec.right.vox_spec.1
624 };
625
626 if let Some(color) = if flipped {
627 spec.left.color
628 } else {
629 spec.right.color
630 } {
631 let shoulder_color = Vec3::from(color);
632 shoulder_segment =
633 shoulder_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(shoulder_color)));
634 }
635
636 (shoulder_segment, Vec3::from(offset))
637 }
638
639 fn mesh_left_shoulder(
640 &self,
641 body: &Body,
642 color_spec: &HumColorSpec,
643 shoulder: Option<&str>,
644 ) -> BoneMeshes {
645 self.mesh_shoulder(body, color_spec, shoulder, true)
646 }
647
648 fn mesh_right_shoulder(
649 &self,
650 body: &Body,
651 color_spec: &HumColorSpec,
652 shoulder: Option<&str>,
653 ) -> BoneMeshes {
654 self.mesh_shoulder(body, color_spec, shoulder, false)
655 }
656}
657impl HumArmorChestSpec {
659 fn mesh_chest(
660 &self,
661 body: &Body,
662 color_spec: &HumColorSpec,
663 chest: Option<&str>,
664 ) -> BoneMeshes {
665 let spec = if let Some(chest) = chest {
666 match self.0.map.get(chest) {
667 Some(spec) => spec,
668 None => {
669 error!(?chest, "No chest specification exists");
670 return load_mesh("not_found", Vec3::new(-7.0, -3.5, 2.0));
671 },
672 }
673 } else {
674 &self.0.default
675 };
676
677 let color = |mat_segment| {
678 color_spec.color_segment(
679 mat_segment,
680 body.species.skin_color(body.skin),
681 color_spec.hair_color(body.species, body.hair_color),
682 body.species.eye_color(body.eye_color),
683 )
684 };
685
686 let bare_chest = graceful_load_mat_segment("armor.empty", DEFAULT_INDEX);
687
688 let mut chest_armor = graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2);
689
690 if let Some(color) = spec.color {
691 let chest_color = Vec3::from(color);
692 chest_armor = chest_armor.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(chest_color)));
693 }
694
695 let chest = DynaUnionizer::new()
696 .add(color(bare_chest), Vec3::new(0, 0, 0))
697 .add(color(chest_armor), Vec3::new(0, 0, 0))
698 .unify()
699 .0;
700
701 (chest, Vec3::from(spec.vox_spec.1))
702 }
703}
704impl HumArmorHandSpec {
706 fn mesh_hand(
707 &self,
708 body: &Body,
709 color_spec: &HumColorSpec,
710 hand: Option<&str>,
711 flipped: bool,
712 ) -> BoneMeshes {
713 let spec = if let Some(hand) = hand {
714 match self.0.map.get(hand) {
715 Some(spec) => spec,
716 None => {
717 error!(?hand, "No hand specification exists");
718 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
719 },
720 }
721 } else {
722 &self.0.default
723 };
724
725 let mut hand_segment = color_spec.color_segment(
726 if flipped {
727 graceful_load_mat_segment_flipped(&spec.left.vox_spec.0, spec.left.vox_spec.2)
728 } else {
729 graceful_load_mat_segment(&spec.right.vox_spec.0, spec.right.vox_spec.2)
730 },
731 body.species.skin_color(body.skin),
732 color_spec.hair_color(body.species, body.hair_color),
733 body.species.eye_color(body.eye_color),
734 );
735
736 let offset = if flipped {
737 spec.left.vox_spec.1
738 } else {
739 spec.right.vox_spec.1
740 };
741
742 if let Some(color) = if flipped {
743 spec.left.color
744 } else {
745 spec.right.color
746 } {
747 let hand_color = Vec3::from(color);
748 hand_segment = hand_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(hand_color)));
749 }
750
751 (hand_segment, Vec3::from(offset))
752 }
753
754 fn mesh_left_hand(
755 &self,
756 body: &Body,
757 color_spec: &HumColorSpec,
758 hand: Option<&str>,
759 ) -> BoneMeshes {
760 self.mesh_hand(body, color_spec, hand, true)
761 }
762
763 fn mesh_right_hand(
764 &self,
765 body: &Body,
766 color_spec: &HumColorSpec,
767 hand: Option<&str>,
768 ) -> BoneMeshes {
769 self.mesh_hand(body, color_spec, hand, false)
770 }
771}
772impl HumArmorBeltSpec {
774 fn mesh_belt(&self, body: &Body, color_spec: &HumColorSpec, belt: Option<&str>) -> BoneMeshes {
775 let spec = if let Some(belt) = belt {
776 match self.0.map.get(belt) {
777 Some(spec) => spec,
778 None => {
779 error!(?belt, "No belt specification exists");
780 return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0));
781 },
782 }
783 } else {
784 &self.0.default
785 };
786
787 let mut belt_segment = color_spec.color_segment(
788 graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2),
789 body.species.skin_color(body.skin),
790 color_spec.hair_color(body.species, body.hair_color),
791 body.species.eye_color(body.eye_color),
792 );
793
794 if let Some(color) = spec.color {
795 let belt_color = Vec3::from(color);
796 belt_segment = belt_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(belt_color)));
797 }
798
799 (belt_segment, Vec3::from(spec.vox_spec.1))
800 }
801}
802impl HumArmorBackSpec {
804 fn mesh_back(&self, body: &Body, color_spec: &HumColorSpec, back: Option<&str>) -> BoneMeshes {
805 let spec = if let Some(back) = back {
806 match self.0.map.get(back) {
807 Some(spec) => spec,
808 None => {
809 error!(?back, "No back specification exists");
810 return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0));
811 },
812 }
813 } else {
814 &self.0.default
815 };
816
817 let mut back_segment = color_spec.color_segment(
818 graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2),
819 body.species.skin_color(body.skin),
820 color_spec.hair_color(body.species, body.hair_color),
821 body.species.eye_color(body.eye_color),
822 );
823 if let Some(color) = spec.color {
824 let back_color = Vec3::from(color);
825 back_segment = back_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(back_color)));
826 }
827
828 (back_segment, Vec3::from(spec.vox_spec.1))
829 }
830}
831impl HumArmorPantsSpec {
833 fn mesh_pants(
834 &self,
835 body: &Body,
836 color_spec: &HumColorSpec,
837 pants: Option<&str>,
838 ) -> BoneMeshes {
839 let spec = if let Some(pants) = pants {
840 match self.0.map.get(pants) {
841 Some(spec) => spec,
842 None => {
843 error!(?pants, "No pants specification exists");
844 return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0));
845 },
846 }
847 } else {
848 &self.0.default
849 };
850
851 let color = |mat_segment| {
852 color_spec.color_segment(
853 mat_segment,
854 body.species.skin_color(body.skin),
855 color_spec.hair_color(body.species, body.hair_color),
856 body.species.eye_color(body.eye_color),
857 )
858 };
859
860 let bare_pants = graceful_load_mat_segment("armor.empty", DEFAULT_INDEX);
861
862 let mut pants_armor = graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2);
863
864 if let Some(color) = spec.color {
865 let pants_color = Vec3::from(color);
866 pants_armor = pants_armor.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(pants_color)));
867 }
868
869 let pants = DynaUnionizer::new()
870 .add(color(bare_pants), Vec3::new(0, 0, 0))
871 .add(color(pants_armor), Vec3::new(0, 0, 0))
872 .unify()
873 .0;
874
875 (pants, Vec3::from(spec.vox_spec.1))
876 }
877}
878impl HumArmorFootSpec {
880 fn mesh_foot(
881 &self,
882 body: &Body,
883 color_spec: &HumColorSpec,
884 foot: Option<&str>,
885 flipped: bool,
886 ) -> BoneMeshes {
887 let spec = if let Some(foot) = foot {
888 match self.0.map.get(foot) {
889 Some(spec) => spec,
890 None => {
891 error!(?foot, "No foot specification exists");
892 return load_mesh("not_found", Vec3::new(-2.5, -3.5, -9.0));
893 },
894 }
895 } else {
896 &self.0.default
897 };
898
899 let mut foot_segment = color_spec.color_segment(
900 if flipped {
901 graceful_load_mat_segment_flipped(&spec.vox_spec.0, spec.vox_spec.2)
902 } else {
903 graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2)
904 },
905 body.species.skin_color(body.skin),
906 color_spec.hair_color(body.species, body.hair_color),
907 body.species.eye_color(body.eye_color),
908 );
909
910 if let Some(color) = spec.color {
911 let foot_color = Vec3::from(color);
912 foot_segment = foot_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(foot_color)));
913 }
914
915 (foot_segment, Vec3::from(spec.vox_spec.1))
916 }
917
918 fn mesh_left_foot(
919 &self,
920 body: &Body,
921 color_spec: &HumColorSpec,
922 foot: Option<&str>,
923 ) -> BoneMeshes {
924 self.mesh_foot(body, color_spec, foot, true)
925 }
926
927 fn mesh_right_foot(
928 &self,
929 body: &Body,
930 color_spec: &HumColorSpec,
931 foot: Option<&str>,
932 ) -> BoneMeshes {
933 self.mesh_foot(body, color_spec, foot, false)
934 }
935}
936
937impl HumMainWeaponSpec {
938 fn mesh_main_weapon(&self, tool: &ToolKey, flipped: bool) -> BoneMeshes {
939 let not_found = |tool: &ToolKey| {
940 error!(?tool, "No tool/weapon specification exists");
941 load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0))
942 };
943
944 let spec = match self.0.get(tool) {
945 Some(spec) => spec,
946 None => return not_found(tool),
947 };
948
949 let tool_kind_segment =
950 graceful_load_segment_flipped(&spec.vox_spec.0, flipped, spec.vox_spec.2);
951 let mut offset = Vec3::from(spec.vox_spec.1);
952
953 if flipped {
954 offset.x = 0.0 - offset.x - (tool_kind_segment.sz.x as f32);
955 }
956
957 (tool_kind_segment, offset)
958 }
959}
960
961impl HumArmorLanternSpec {
963 fn mesh_lantern(
964 &self,
965 body: &Body,
966 color_spec: &HumColorSpec,
967 lantern: Option<&str>,
968 ) -> BoneMeshes {
969 let spec = if let Some(kind) = lantern {
970 match self.0.map.get(kind) {
971 Some(spec) => spec,
972 None => {
973 error!(?kind, "No lantern specification exists");
974 return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0));
975 },
976 }
977 } else {
978 &self.0.default
979 };
980
981 let mut lantern_segment = color_spec.color_segment(
982 graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2),
983 body.species.skin_color(body.skin),
984 color_spec.hair_color(body.species, body.hair_color),
985 body.species.eye_color(body.eye_color),
986 );
987 if let Some(color) = spec.color {
988 let lantern_color = Vec3::from(color);
989 lantern_segment =
990 lantern_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(lantern_color)));
991 }
992
993 (lantern_segment, Vec3::from(spec.vox_spec.1))
994 }
995}
996impl HumArmorHeadSpec {
997 fn load_head(&self, body: &Body, head: Option<&str>) -> Option<(Segment, Vec3<i32>)> {
998 if let Some(spec) = self
999 .0
1000 .map
1001 .get(&(body.species, body.body_type, head?.to_string()))
1002 {
1003 let segment = graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2);
1004 let segment = if let Some(color) = spec.color {
1005 let color = Vec3::from(color);
1006 segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(color)))
1007 } else {
1008 segment
1009 };
1010 Some((segment, Vec3::<f32>::from(spec.vox_spec.1).as_()))
1011 } else {
1012 warn!("No specification for this head: {:?}", head);
1013 None
1014 }
1015 }
1016}
1017
1018impl HumArmorTabardSpec {
1019 #[expect(dead_code)]
1021 fn mesh_tabard(
1022 &self,
1023 body: &Body,
1024 color_spec: &HumColorSpec,
1025 tabard: Option<&str>,
1026 ) -> BoneMeshes {
1027 let spec = if let Some(tabard) = tabard {
1028 match self.0.map.get(tabard) {
1029 Some(spec) => spec,
1030 None => {
1031 error!(?tabard, "No tabard specification exists");
1032 return load_mesh("not_found", Vec3::new(-5.0, -3.5, 1.0));
1033 },
1034 }
1035 } else {
1036 &self.0.default
1037 };
1038
1039 let color = |mat_segment| {
1040 color_spec.color_segment(
1041 mat_segment,
1042 body.species.skin_color(body.skin),
1043 color_spec.hair_color(body.species, body.hair_color),
1044 body.species.eye_color(body.eye_color),
1045 )
1046 };
1047
1048 let bare_tabard = graceful_load_mat_segment("armor.empty", DEFAULT_INDEX);
1049
1050 let mut tabard_armor = graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2);
1051
1052 if let Some(color) = spec.color {
1053 let tabard_color = Vec3::from(color);
1054 tabard_armor = tabard_armor.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(tabard_color)));
1055 }
1056
1057 let tabard = DynaUnionizer::new()
1058 .add(color(bare_tabard), Vec3::new(0, 0, 0))
1059 .add(color(tabard_armor), Vec3::new(0, 0, 0))
1060 .unify()
1061 .0;
1062
1063 (tabard, Vec3::from(spec.vox_spec.1))
1064 }
1065}
1066impl HumArmorGliderSpec {
1067 fn mesh_glider(
1068 &self,
1069 body: &Body,
1070 color_spec: &HumColorSpec,
1071 glider: Option<&str>,
1072 ) -> BoneMeshes {
1073 let spec = if let Some(kind) = glider {
1074 match self.0.map.get(kind) {
1075 Some(spec) => spec,
1076 None => {
1077 error!(?kind, "No glider specification exists");
1078 return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0));
1079 },
1080 }
1081 } else {
1082 &self.0.default
1083 };
1084
1085 let mut glider_segment = color_spec.color_segment(
1086 graceful_load_mat_segment(&spec.vox_spec.0, spec.vox_spec.2),
1087 body.species.skin_color(body.skin),
1088 color_spec.hair_color(body.species, body.hair_color),
1089 body.species.eye_color(body.eye_color),
1090 );
1091 if let Some(color) = spec.color {
1092 let glider_color = Vec3::from(color);
1093 glider_segment =
1094 glider_segment.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(glider_color)));
1095 }
1096
1097 (glider_segment, Vec3::from(spec.vox_spec.1))
1098 }
1099}
1100
1101fn mesh_hold() -> BoneMeshes {
1102 load_mesh(
1103 "weapon.projectile.simple-arrow",
1104 Vec3::new(-0.5, -6.0, -1.5),
1105 )
1106}
1107
1108#[derive(Deserialize)]
1110struct QuadrupedSmallCentralSpec(HashMap<(QSSpecies, QSBodyType), SidedQSCentralVoxSpec>);
1111impl_concatenate_for_wrapper!(QuadrupedSmallCentralSpec);
1112
1113#[derive(Deserialize, Default)]
1114#[serde(default)]
1115struct SidedQSCentralVoxSpec {
1116 head: QuadrupedSmallCentralSubSpec,
1117 chest: QuadrupedSmallCentralSubSpec,
1118 tail: QuadrupedSmallCentralSubSpec,
1119}
1120#[derive(Deserialize, Default)]
1121struct QuadrupedSmallCentralSubSpec {
1122 offset: [f32; 3], central: VoxSimple,
1124 #[serde(default)]
1125 model_index: u32,
1126}
1127
1128#[derive(Deserialize)]
1129struct QuadrupedSmallLateralSpec(HashMap<(QSSpecies, QSBodyType), SidedQSLateralVoxSpec>);
1130impl_concatenate_for_wrapper!(QuadrupedSmallLateralSpec);
1131
1132#[derive(Deserialize, Default)]
1133#[serde(default)]
1134struct SidedQSLateralVoxSpec {
1135 left_front: QuadrupedSmallLateralSubSpec,
1136 right_front: QuadrupedSmallLateralSubSpec,
1137 left_back: QuadrupedSmallLateralSubSpec,
1138 right_back: QuadrupedSmallLateralSubSpec,
1139}
1140#[derive(Deserialize, Default)]
1141struct QuadrupedSmallLateralSubSpec {
1142 offset: [f32; 3], lateral: VoxSimple,
1144 #[serde(default)]
1145 model_index: u32,
1146}
1147
1148make_vox_spec!(
1149 quadruped_small::Body,
1150 struct QuadrupedSmallSpec {
1151 central: QuadrupedSmallCentralSpec = "voxygen.voxel.quadruped_small_central_manifest",
1152 lateral: QuadrupedSmallLateralSpec = "voxygen.voxel.quadruped_small_lateral_manifest",
1153 },
1154 |FigureKey { body, extra, .. }, spec| {
1155 let third_person = extra
1156 .as_ref()
1157 .and_then(|loadout| loadout.third_person.as_ref());
1158
1159 [
1160 third_person.map(|_| {
1161 spec.central
1162 .read()
1163 .0
1164 .mesh_head(body.species, body.body_type)
1165 }),
1166 Some(
1167 spec.central
1168 .read()
1169 .0
1170 .mesh_chest(body.species, body.body_type),
1171 ),
1172 Some(
1173 spec.lateral
1174 .read()
1175 .0
1176 .mesh_foot_fl(body.species, body.body_type),
1177 ),
1178 Some(
1179 spec.lateral
1180 .read()
1181 .0
1182 .mesh_foot_fr(body.species, body.body_type),
1183 ),
1184 Some(
1185 spec.lateral
1186 .read()
1187 .0
1188 .mesh_foot_bl(body.species, body.body_type),
1189 ),
1190 Some(
1191 spec.lateral
1192 .read()
1193 .0
1194 .mesh_foot_br(body.species, body.body_type),
1195 ),
1196 Some(
1197 spec.central
1198 .read()
1199 .0
1200 .mesh_tail(body.species, body.body_type),
1201 ),
1202 None,
1203 None,
1204 None,
1205 None,
1206 None,
1207 None,
1208 None,
1209 None,
1210 None,
1211 ]
1212 },
1213);
1214
1215impl QuadrupedSmallCentralSpec {
1216 fn mesh_head(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1217 let spec = match self.0.get(&(species, body_type)) {
1218 Some(spec) => spec,
1219 None => {
1220 error!(
1221 "No head specification exists for the combination of {:?} and {:?}",
1222 species, body_type
1223 );
1224 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1225 },
1226 };
1227 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
1228
1229 (central, Vec3::from(spec.head.offset))
1230 }
1231
1232 fn mesh_chest(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1233 let spec = match self.0.get(&(species, body_type)) {
1234 Some(spec) => spec,
1235 None => {
1236 error!(
1237 "No chest specification exists for the combination of {:?} and {:?}",
1238 species, body_type
1239 );
1240 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1241 },
1242 };
1243 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
1244
1245 (central, Vec3::from(spec.chest.offset))
1246 }
1247
1248 fn mesh_tail(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1249 let spec = match self.0.get(&(species, body_type)) {
1250 Some(spec) => spec,
1251 None => {
1252 error!(
1253 "No tail specification exists for the combination of {:?} and {:?}",
1254 species, body_type
1255 );
1256 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1257 },
1258 };
1259 let central = graceful_load_segment(&spec.tail.central.0, spec.tail.model_index);
1260
1261 (central, Vec3::from(spec.tail.offset))
1262 }
1263}
1264
1265impl QuadrupedSmallLateralSpec {
1266 fn mesh_foot_fl(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1267 let spec = match self.0.get(&(species, body_type)) {
1268 Some(spec) => spec,
1269 None => {
1270 error!(
1271 "No leg specification exists for the combination of {:?} and {:?}",
1272 species, body_type
1273 );
1274 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1275 },
1276 };
1277 let lateral = graceful_load_segment_flipped(
1278 &spec.left_front.lateral.0,
1279 true,
1280 spec.left_front.model_index,
1281 );
1282
1283 (lateral, Vec3::from(spec.left_front.offset))
1284 }
1285
1286 fn mesh_foot_fr(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1287 let spec = match self.0.get(&(species, body_type)) {
1288 Some(spec) => spec,
1289 None => {
1290 error!(
1291 "No leg specification exists for the combination of {:?} and {:?}",
1292 species, body_type
1293 );
1294 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1295 },
1296 };
1297 let lateral =
1298 graceful_load_segment(&spec.right_front.lateral.0, spec.right_front.model_index);
1299
1300 (lateral, Vec3::from(spec.right_front.offset))
1301 }
1302
1303 fn mesh_foot_bl(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1304 let spec = match self.0.get(&(species, body_type)) {
1305 Some(spec) => spec,
1306 None => {
1307 error!(
1308 "No leg specification exists for the combination of {:?} and {:?}",
1309 species, body_type
1310 );
1311 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1312 },
1313 };
1314 let lateral = graceful_load_segment_flipped(
1315 &spec.left_back.lateral.0,
1316 true,
1317 spec.left_back.model_index,
1318 );
1319
1320 (lateral, Vec3::from(spec.left_back.offset))
1321 }
1322
1323 fn mesh_foot_br(&self, species: QSSpecies, body_type: QSBodyType) -> BoneMeshes {
1324 let spec = match self.0.get(&(species, body_type)) {
1325 Some(spec) => spec,
1326 None => {
1327 error!(
1328 "No leg specification exists for the combination of {:?} and {:?}",
1329 species, body_type
1330 );
1331 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1332 },
1333 };
1334 let lateral =
1335 graceful_load_segment(&spec.right_back.lateral.0, spec.right_back.model_index);
1336
1337 (lateral, Vec3::from(spec.right_back.offset))
1338 }
1339}
1340
1341#[derive(Deserialize)]
1343struct QuadrupedMediumCentralSpec(HashMap<(QMSpecies, QMBodyType), SidedQMCentralVoxSpec>);
1344impl_concatenate_for_wrapper!(QuadrupedMediumCentralSpec);
1345
1346#[derive(Deserialize, Default)]
1347#[serde(default)]
1348struct SidedQMCentralVoxSpec {
1349 head: QuadrupedMediumCentralSubSpec,
1350 neck: QuadrupedMediumCentralSubSpec,
1351 jaw: QuadrupedMediumCentralSubSpec,
1352 ears: QuadrupedMediumCentralSubSpec,
1353 torso_front: QuadrupedMediumCentralSubSpec,
1354 torso_back: QuadrupedMediumCentralSubSpec,
1355 tail: QuadrupedMediumCentralSubSpec,
1356}
1357#[derive(Deserialize, Default)]
1358struct QuadrupedMediumCentralSubSpec {
1359 offset: [f32; 3], central: VoxSimple,
1361 #[serde(default)]
1362 model_index: u32,
1363}
1364
1365#[derive(Deserialize)]
1366struct QuadrupedMediumLateralSpec(HashMap<(QMSpecies, QMBodyType), SidedQMLateralVoxSpec>);
1367impl_concatenate_for_wrapper!(QuadrupedMediumLateralSpec);
1368
1369#[derive(Deserialize, Default)]
1370#[serde(default)]
1371struct SidedQMLateralVoxSpec {
1372 leg_fl: QuadrupedMediumLateralSubSpec,
1373 leg_fr: QuadrupedMediumLateralSubSpec,
1374 leg_bl: QuadrupedMediumLateralSubSpec,
1375 leg_br: QuadrupedMediumLateralSubSpec,
1376 foot_fl: QuadrupedMediumLateralSubSpec,
1377 foot_fr: QuadrupedMediumLateralSubSpec,
1378 foot_bl: QuadrupedMediumLateralSubSpec,
1379 foot_br: QuadrupedMediumLateralSubSpec,
1380}
1381#[derive(Deserialize, Default)]
1382struct QuadrupedMediumLateralSubSpec {
1383 offset: [f32; 3], lateral: VoxSimple,
1385 #[serde(default)]
1386 model_index: u32,
1387}
1388
1389make_vox_spec!(
1390 quadruped_medium::Body,
1391 struct QuadrupedMediumSpec {
1392 central: QuadrupedMediumCentralSpec = "voxygen.voxel.quadruped_medium_central_manifest",
1393 lateral: QuadrupedMediumLateralSpec = "voxygen.voxel.quadruped_medium_lateral_manifest",
1394 },
1395 |FigureKey { body, extra, .. }, spec| {
1396 let third_person = extra
1397 .as_ref()
1398 .and_then(|loadout| loadout.third_person.as_ref());
1399
1400 [
1401 third_person.map(|_| {
1402 spec.central
1403 .read()
1404 .0
1405 .mesh_head(body.species, body.body_type)
1406 }),
1407 third_person.map(|_| {
1408 spec.central
1409 .read()
1410 .0
1411 .mesh_neck(body.species, body.body_type)
1412 }),
1413 third_person.map(|_| spec.central.read().0.mesh_jaw(body.species, body.body_type)),
1414 Some(
1415 spec.central
1416 .read()
1417 .0
1418 .mesh_tail(body.species, body.body_type),
1419 ),
1420 Some(
1421 spec.central
1422 .read()
1423 .0
1424 .mesh_torso_front(body.species, body.body_type),
1425 ),
1426 Some(
1427 spec.central
1428 .read()
1429 .0
1430 .mesh_torso_back(body.species, body.body_type),
1431 ),
1432 third_person.map(|_| {
1433 spec.central
1434 .read()
1435 .0
1436 .mesh_ears(body.species, body.body_type)
1437 }),
1438 Some(
1439 spec.lateral
1440 .read()
1441 .0
1442 .mesh_leg_fl(body.species, body.body_type),
1443 ),
1444 Some(
1445 spec.lateral
1446 .read()
1447 .0
1448 .mesh_leg_fr(body.species, body.body_type),
1449 ),
1450 Some(
1451 spec.lateral
1452 .read()
1453 .0
1454 .mesh_leg_bl(body.species, body.body_type),
1455 ),
1456 Some(
1457 spec.lateral
1458 .read()
1459 .0
1460 .mesh_leg_br(body.species, body.body_type),
1461 ),
1462 Some(
1463 spec.lateral
1464 .read()
1465 .0
1466 .mesh_foot_fl(body.species, body.body_type),
1467 ),
1468 Some(
1469 spec.lateral
1470 .read()
1471 .0
1472 .mesh_foot_fr(body.species, body.body_type),
1473 ),
1474 Some(
1475 spec.lateral
1476 .read()
1477 .0
1478 .mesh_foot_bl(body.species, body.body_type),
1479 ),
1480 Some(
1481 spec.lateral
1482 .read()
1483 .0
1484 .mesh_foot_br(body.species, body.body_type),
1485 ),
1486 None,
1487 ]
1488 }
1489);
1490
1491impl QuadrupedMediumCentralSpec {
1492 fn mesh_head(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1493 let spec = match self.0.get(&(species, body_type)) {
1494 Some(spec) => spec,
1495 None => {
1496 error!(
1497 "No head specification exists for the combination of {:?} and {:?}",
1498 species, body_type
1499 );
1500 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1501 },
1502 };
1503 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
1504
1505 (central, Vec3::from(spec.head.offset))
1506 }
1507
1508 fn mesh_neck(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1509 let spec = match self.0.get(&(species, body_type)) {
1510 Some(spec) => spec,
1511 None => {
1512 error!(
1513 "No neck specification exists for the combination of {:?} and {:?}",
1514 species, body_type
1515 );
1516 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1517 },
1518 };
1519 let central = graceful_load_segment(&spec.neck.central.0, spec.neck.model_index);
1520
1521 (central, Vec3::from(spec.neck.offset))
1522 }
1523
1524 fn mesh_jaw(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1525 let spec = match self.0.get(&(species, body_type)) {
1526 Some(spec) => spec,
1527 None => {
1528 error!(
1529 "No jaw specification exists for the combination of {:?} and {:?}",
1530 species, body_type
1531 );
1532 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1533 },
1534 };
1535 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
1536
1537 (central, Vec3::from(spec.jaw.offset))
1538 }
1539
1540 fn mesh_ears(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1541 let spec = match self.0.get(&(species, body_type)) {
1542 Some(spec) => spec,
1543 None => {
1544 error!(
1545 "No ears specification exists for the combination of {:?} and {:?}",
1546 species, body_type
1547 );
1548 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1549 },
1550 };
1551 let central = graceful_load_segment(&spec.ears.central.0, spec.ears.model_index);
1552
1553 (central, Vec3::from(spec.ears.offset))
1554 }
1555
1556 fn mesh_torso_front(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1557 let spec = match self.0.get(&(species, body_type)) {
1558 Some(spec) => spec,
1559 None => {
1560 error!(
1561 "No torso specification exists for the combination of {:?} and {:?}",
1562 species, body_type
1563 );
1564 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1565 },
1566 };
1567 let central =
1568 graceful_load_segment(&spec.torso_front.central.0, spec.torso_front.model_index);
1569
1570 (central, Vec3::from(spec.torso_front.offset))
1571 }
1572
1573 fn mesh_torso_back(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1574 let spec = match self.0.get(&(species, body_type)) {
1575 Some(spec) => spec,
1576 None => {
1577 error!(
1578 "No torso specification exists for the combination of {:?} and {:?}",
1579 species, body_type
1580 );
1581 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1582 },
1583 };
1584 let central =
1585 graceful_load_segment(&spec.torso_back.central.0, spec.torso_back.model_index);
1586
1587 (central, Vec3::from(spec.torso_back.offset))
1588 }
1589
1590 fn mesh_tail(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1591 let spec = match self.0.get(&(species, body_type)) {
1592 Some(spec) => spec,
1593 None => {
1594 error!(
1595 "No tail specification exists for the combination of {:?} and {:?}",
1596 species, body_type
1597 );
1598 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1599 },
1600 };
1601 let central = graceful_load_segment(&spec.tail.central.0, spec.tail.model_index);
1602
1603 (central, Vec3::from(spec.tail.offset))
1604 }
1605}
1606
1607impl QuadrupedMediumLateralSpec {
1608 fn mesh_leg_fl(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1609 let spec = match self.0.get(&(species, body_type)) {
1610 Some(spec) => spec,
1611 None => {
1612 error!(
1613 "No leg specification exists for the combination of {:?} and {:?}",
1614 species, body_type
1615 );
1616 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1617 },
1618 };
1619 let lateral =
1620 graceful_load_segment_flipped(&spec.leg_fl.lateral.0, true, spec.leg_fl.model_index);
1621
1622 (lateral, Vec3::from(spec.leg_fl.offset))
1623 }
1624
1625 fn mesh_leg_fr(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1626 let spec = match self.0.get(&(species, body_type)) {
1627 Some(spec) => spec,
1628 None => {
1629 error!(
1630 "No leg specification exists for the combination of {:?} and {:?}",
1631 species, body_type
1632 );
1633 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1634 },
1635 };
1636 let lateral = graceful_load_segment(&spec.leg_fr.lateral.0, spec.leg_fr.model_index);
1637
1638 (lateral, Vec3::from(spec.leg_fr.offset))
1639 }
1640
1641 fn mesh_leg_bl(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1642 let spec = match self.0.get(&(species, body_type)) {
1643 Some(spec) => spec,
1644 None => {
1645 error!(
1646 "No leg specification exists for the combination of {:?} and {:?}",
1647 species, body_type
1648 );
1649 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1650 },
1651 };
1652 let lateral =
1653 graceful_load_segment_flipped(&spec.leg_bl.lateral.0, true, spec.leg_bl.model_index);
1654
1655 (lateral, Vec3::from(spec.leg_bl.offset))
1656 }
1657
1658 fn mesh_leg_br(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1659 let spec = match self.0.get(&(species, body_type)) {
1660 Some(spec) => spec,
1661 None => {
1662 error!(
1663 "No leg specification exists for the combination of {:?} and {:?}",
1664 species, body_type
1665 );
1666 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1667 },
1668 };
1669 let lateral = graceful_load_segment(&spec.leg_br.lateral.0, spec.leg_br.model_index);
1670
1671 (lateral, Vec3::from(spec.leg_br.offset))
1672 }
1673
1674 fn mesh_foot_fl(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1675 let spec = match self.0.get(&(species, body_type)) {
1676 Some(spec) => spec,
1677 None => {
1678 error!(
1679 "No foot specification exists for the combination of {:?} and {:?}",
1680 species, body_type
1681 );
1682 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1683 },
1684 };
1685 let lateral =
1686 graceful_load_segment_flipped(&spec.foot_fl.lateral.0, true, spec.foot_fl.model_index);
1687
1688 (lateral, Vec3::from(spec.foot_fl.offset))
1689 }
1690
1691 fn mesh_foot_fr(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1692 let spec = match self.0.get(&(species, body_type)) {
1693 Some(spec) => spec,
1694 None => {
1695 error!(
1696 "No foot specification exists for the combination of {:?} and {:?}",
1697 species, body_type
1698 );
1699 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1700 },
1701 };
1702 let lateral = graceful_load_segment(&spec.foot_fr.lateral.0, spec.foot_fr.model_index);
1703
1704 (lateral, Vec3::from(spec.foot_fr.offset))
1705 }
1706
1707 fn mesh_foot_bl(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1708 let spec = match self.0.get(&(species, body_type)) {
1709 Some(spec) => spec,
1710 None => {
1711 error!(
1712 "No foot specification exists for the combination of {:?} and {:?}",
1713 species, body_type
1714 );
1715 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1716 },
1717 };
1718 let lateral =
1719 graceful_load_segment_flipped(&spec.foot_bl.lateral.0, true, spec.foot_bl.model_index);
1720
1721 (lateral, Vec3::from(spec.foot_bl.offset))
1722 }
1723
1724 fn mesh_foot_br(&self, species: QMSpecies, body_type: QMBodyType) -> BoneMeshes {
1725 let spec = match self.0.get(&(species, body_type)) {
1726 Some(spec) => spec,
1727 None => {
1728 error!(
1729 "No foot specification exists for the combination of {:?} and {:?}",
1730 species, body_type
1731 );
1732 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1733 },
1734 };
1735 let lateral = graceful_load_segment(&spec.foot_br.lateral.0, spec.foot_br.model_index);
1736
1737 (lateral, Vec3::from(spec.foot_br.offset))
1738 }
1739}
1740
1741#[derive(Deserialize)]
1743struct BirdMediumCentralSpec(HashMap<(BMSpecies, BMBodyType), SidedBMCentralVoxSpec>);
1744impl_concatenate_for_wrapper!(BirdMediumCentralSpec);
1745
1746#[derive(Deserialize, Default)]
1747#[serde(default)]
1748struct SidedBMCentralVoxSpec {
1749 head: BirdMediumCentralSubSpec,
1750 chest: BirdMediumCentralSubSpec,
1751 tail: BirdMediumCentralSubSpec,
1752}
1753#[derive(Deserialize, Default)]
1754struct BirdMediumCentralSubSpec {
1755 offset: [f32; 3], central: VoxSimple,
1757 #[serde(default)]
1758 model_index: u32,
1759}
1760
1761#[derive(Deserialize)]
1762struct BirdMediumLateralSpec(HashMap<(BMSpecies, BMBodyType), SidedBMLateralVoxSpec>);
1763impl_concatenate_for_wrapper!(BirdMediumLateralSpec);
1764
1765#[derive(Deserialize, Default)]
1766#[serde(default)]
1767struct SidedBMLateralVoxSpec {
1768 wing_in_l: BirdMediumLateralSubSpec,
1769 wing_in_r: BirdMediumLateralSubSpec,
1770 wing_out_l: BirdMediumLateralSubSpec,
1771 wing_out_r: BirdMediumLateralSubSpec,
1772 leg_l: BirdMediumLateralSubSpec,
1773 leg_r: BirdMediumLateralSubSpec,
1774}
1775#[derive(Deserialize, Default)]
1776struct BirdMediumLateralSubSpec {
1777 offset: [f32; 3], lateral: VoxSimple,
1779 #[serde(default)]
1780 model_index: u32,
1781}
1782
1783make_vox_spec!(
1784 bird_medium::Body,
1785 struct BirdMediumSpec {
1786 central: BirdMediumCentralSpec = "voxygen.voxel.bird_medium_central_manifest",
1787 lateral: BirdMediumLateralSpec = "voxygen.voxel.bird_medium_lateral_manifest",
1788 },
1789 |FigureKey { body, extra, .. }, spec| {
1790 let third_person = extra
1791 .as_ref()
1792 .and_then(|loadout| loadout.third_person.as_ref());
1793
1794 [
1795 third_person.map(|_| {
1796 spec.central
1797 .read()
1798 .0
1799 .mesh_head(body.species, body.body_type)
1800 }),
1801 Some(
1802 spec.central
1803 .read()
1804 .0
1805 .mesh_chest(body.species, body.body_type),
1806 ),
1807 Some(
1808 spec.central
1809 .read()
1810 .0
1811 .mesh_tail(body.species, body.body_type),
1812 ),
1813 Some(
1814 spec.lateral
1815 .read()
1816 .0
1817 .mesh_wing_in_l(body.species, body.body_type),
1818 ),
1819 Some(
1820 spec.lateral
1821 .read()
1822 .0
1823 .mesh_wing_in_r(body.species, body.body_type),
1824 ),
1825 Some(
1826 spec.lateral
1827 .read()
1828 .0
1829 .mesh_wing_out_l(body.species, body.body_type),
1830 ),
1831 Some(
1832 spec.lateral
1833 .read()
1834 .0
1835 .mesh_wing_out_r(body.species, body.body_type),
1836 ),
1837 Some(
1838 spec.lateral
1839 .read()
1840 .0
1841 .mesh_leg_l(body.species, body.body_type),
1842 ),
1843 Some(
1844 spec.lateral
1845 .read()
1846 .0
1847 .mesh_leg_r(body.species, body.body_type),
1848 ),
1849 None,
1850 None,
1851 None,
1852 None,
1853 None,
1854 None,
1855 None,
1856 ]
1857 },
1858);
1859
1860impl BirdMediumCentralSpec {
1861 fn mesh_head(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1862 let spec = match self.0.get(&(species, body_type)) {
1863 Some(spec) => spec,
1864 None => {
1865 error!(
1866 "No head specification exists for the combination of {:?} and {:?}",
1867 species, body_type
1868 );
1869 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1870 },
1871 };
1872 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
1873
1874 (central, Vec3::from(spec.head.offset))
1875 }
1876
1877 fn mesh_chest(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1878 let spec = match self.0.get(&(species, body_type)) {
1879 Some(spec) => spec,
1880 None => {
1881 error!(
1882 "No chest specification exists for the combination of {:?} and {:?}",
1883 species, body_type
1884 );
1885 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1886 },
1887 };
1888 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
1889
1890 (central, Vec3::from(spec.chest.offset))
1891 }
1892
1893 fn mesh_tail(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1894 let spec = match self.0.get(&(species, body_type)) {
1895 Some(spec) => spec,
1896 None => {
1897 error!(
1898 "No tail specification exists for the combination of {:?} and {:?}",
1899 species, body_type
1900 );
1901 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1902 },
1903 };
1904 let central = graceful_load_segment(&spec.tail.central.0, spec.tail.model_index);
1905
1906 (central, Vec3::from(spec.tail.offset))
1907 }
1908}
1909impl BirdMediumLateralSpec {
1910 fn mesh_wing_in_l(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1911 let spec = match self.0.get(&(species, body_type)) {
1912 Some(spec) => spec,
1913 None => {
1914 error!(
1915 "No wing in in left specification exists for the combination of {:?} and {:?}",
1916 species, body_type
1917 );
1918 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1919 },
1920 };
1921 let lateral = graceful_load_segment_flipped(
1922 &spec.wing_in_l.lateral.0,
1923 true,
1924 spec.wing_in_l.model_index,
1925 );
1926
1927 (lateral, Vec3::from(spec.wing_in_l.offset))
1928 }
1929
1930 fn mesh_wing_in_r(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1931 let spec = match self.0.get(&(species, body_type)) {
1932 Some(spec) => spec,
1933 None => {
1934 error!(
1935 "No wing in right specification exists for the combination of {:?} and {:?}",
1936 species, body_type
1937 );
1938 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1939 },
1940 };
1941 let lateral = graceful_load_segment(&spec.wing_in_r.lateral.0, spec.wing_in_r.model_index);
1942
1943 (lateral, Vec3::from(spec.wing_in_r.offset))
1944 }
1945
1946 fn mesh_wing_out_l(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1947 let spec = match self.0.get(&(species, body_type)) {
1948 Some(spec) => spec,
1949 None => {
1950 error!(
1951 "No wing out specification exists for the combination of {:?} and {:?}",
1952 species, body_type
1953 );
1954 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1955 },
1956 };
1957 let lateral = graceful_load_segment_flipped(
1958 &spec.wing_out_l.lateral.0,
1959 true,
1960 spec.wing_out_l.model_index,
1961 );
1962
1963 (lateral, Vec3::from(spec.wing_out_l.offset))
1964 }
1965
1966 fn mesh_wing_out_r(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1967 let spec = match self.0.get(&(species, body_type)) {
1968 Some(spec) => spec,
1969 None => {
1970 error!(
1971 "No wing out specification exists for the combination of {:?} and {:?}",
1972 species, body_type
1973 );
1974 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1975 },
1976 };
1977 let lateral =
1978 graceful_load_segment(&spec.wing_out_r.lateral.0, spec.wing_out_r.model_index);
1979
1980 (lateral, Vec3::from(spec.wing_out_r.offset))
1981 }
1982
1983 fn mesh_leg_l(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
1984 let spec = match self.0.get(&(species, body_type)) {
1985 Some(spec) => spec,
1986 None => {
1987 error!(
1988 "No leg specification exists for the combination of {:?} and {:?}",
1989 species, body_type
1990 );
1991 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
1992 },
1993 };
1994 let lateral =
1995 graceful_load_segment_flipped(&spec.leg_l.lateral.0, true, spec.leg_l.model_index);
1996
1997 (lateral, Vec3::from(spec.leg_l.offset))
1998 }
1999
2000 fn mesh_leg_r(&self, species: BMSpecies, body_type: BMBodyType) -> BoneMeshes {
2001 let spec = match self.0.get(&(species, body_type)) {
2002 Some(spec) => spec,
2003 None => {
2004 error!(
2005 "No leg specification exists for the combination of {:?} and {:?}",
2006 species, body_type
2007 );
2008 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2009 },
2010 };
2011 let lateral = graceful_load_segment(&spec.leg_r.lateral.0, spec.leg_r.model_index);
2012
2013 (lateral, Vec3::from(spec.leg_r.offset))
2014 }
2015}
2016
2017#[derive(Deserialize)]
2019struct TheropodCentralSpec(HashMap<(TSpecies, TBodyType), SidedTCentralVoxSpec>);
2020impl_concatenate_for_wrapper!(TheropodCentralSpec);
2021
2022#[derive(Deserialize, Default)]
2023#[serde(default)]
2024struct SidedTCentralVoxSpec {
2025 head: TheropodCentralSubSpec,
2026 jaw: TheropodCentralSubSpec,
2027 neck: TheropodCentralSubSpec,
2028 chest_front: TheropodCentralSubSpec,
2029 chest_back: TheropodCentralSubSpec,
2030 tail_front: TheropodCentralSubSpec,
2031 tail_back: TheropodCentralSubSpec,
2032}
2033#[derive(Deserialize, Default)]
2034struct TheropodCentralSubSpec {
2035 offset: [f32; 3], central: VoxSimple,
2037 #[serde(default)]
2038 model_index: u32,
2039}
2040#[derive(Deserialize)]
2041struct TheropodLateralSpec(HashMap<(TSpecies, TBodyType), SidedTLateralVoxSpec>);
2042impl_concatenate_for_wrapper!(TheropodLateralSpec);
2043
2044#[derive(Deserialize, Default)]
2045#[serde(default)]
2046struct SidedTLateralVoxSpec {
2047 hand_l: TheropodLateralSubSpec,
2048 hand_r: TheropodLateralSubSpec,
2049 leg_l: TheropodLateralSubSpec,
2050 leg_r: TheropodLateralSubSpec,
2051 foot_l: TheropodLateralSubSpec,
2052 foot_r: TheropodLateralSubSpec,
2053}
2054#[derive(Deserialize, Default)]
2055struct TheropodLateralSubSpec {
2056 offset: [f32; 3], lateral: VoxSimple,
2058 #[serde(default)]
2059 model_index: u32,
2060}
2061make_vox_spec!(
2062 theropod::Body,
2063 struct TheropodSpec {
2064 central: TheropodCentralSpec = "voxygen.voxel.theropod_central_manifest",
2065 lateral: TheropodLateralSpec = "voxygen.voxel.theropod_lateral_manifest",
2066 },
2067 |FigureKey { body, extra, .. }, spec| {
2068 let third_person = extra
2069 .as_ref()
2070 .and_then(|loadout| loadout.third_person.as_ref());
2071
2072 [
2073 third_person.map(|_| {
2074 spec.central
2075 .read()
2076 .0
2077 .mesh_head(body.species, body.body_type)
2078 }),
2079 third_person.map(|_| spec.central.read().0.mesh_jaw(body.species, body.body_type)),
2080 Some(
2081 spec.central
2082 .read()
2083 .0
2084 .mesh_neck(body.species, body.body_type),
2085 ),
2086 Some(
2087 spec.central
2088 .read()
2089 .0
2090 .mesh_chest_front(body.species, body.body_type),
2091 ),
2092 Some(
2093 spec.central
2094 .read()
2095 .0
2096 .mesh_chest_back(body.species, body.body_type),
2097 ),
2098 Some(
2099 spec.central
2100 .read()
2101 .0
2102 .mesh_tail_front(body.species, body.body_type),
2103 ),
2104 Some(
2105 spec.central
2106 .read()
2107 .0
2108 .mesh_tail_back(body.species, body.body_type),
2109 ),
2110 Some(
2111 spec.lateral
2112 .read()
2113 .0
2114 .mesh_hand_l(body.species, body.body_type),
2115 ),
2116 Some(
2117 spec.lateral
2118 .read()
2119 .0
2120 .mesh_hand_r(body.species, body.body_type),
2121 ),
2122 Some(
2123 spec.lateral
2124 .read()
2125 .0
2126 .mesh_leg_l(body.species, body.body_type),
2127 ),
2128 Some(
2129 spec.lateral
2130 .read()
2131 .0
2132 .mesh_leg_r(body.species, body.body_type),
2133 ),
2134 Some(
2135 spec.lateral
2136 .read()
2137 .0
2138 .mesh_foot_l(body.species, body.body_type),
2139 ),
2140 Some(
2141 spec.lateral
2142 .read()
2143 .0
2144 .mesh_foot_r(body.species, body.body_type),
2145 ),
2146 None,
2147 None,
2148 None,
2149 ]
2150 },
2151);
2152
2153impl TheropodCentralSpec {
2154 fn mesh_head(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2155 let spec = match self.0.get(&(species, body_type)) {
2156 Some(spec) => spec,
2157 None => {
2158 error!(
2159 "No head specification exists for the combination of {:?} and {:?}",
2160 species, body_type
2161 );
2162 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2163 },
2164 };
2165 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
2166
2167 (central, Vec3::from(spec.head.offset))
2168 }
2169
2170 fn mesh_jaw(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2171 let spec = match self.0.get(&(species, body_type)) {
2172 Some(spec) => spec,
2173 None => {
2174 error!(
2175 "No jaw specification exists for the combination of {:?} and {:?}",
2176 species, body_type
2177 );
2178 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2179 },
2180 };
2181 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
2182
2183 (central, Vec3::from(spec.jaw.offset))
2184 }
2185
2186 fn mesh_neck(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2187 let spec = match self.0.get(&(species, body_type)) {
2188 Some(spec) => spec,
2189 None => {
2190 error!(
2191 "No jaw specification exists for the combination of {:?} and {:?}",
2192 species, body_type
2193 );
2194 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2195 },
2196 };
2197 let central = graceful_load_segment(&spec.neck.central.0, spec.neck.model_index);
2198
2199 (central, Vec3::from(spec.neck.offset))
2200 }
2201
2202 fn mesh_chest_front(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2203 let spec = match self.0.get(&(species, body_type)) {
2204 Some(spec) => spec,
2205 None => {
2206 error!(
2207 "No front chest specification exists for the combination of {:?} and {:?}",
2208 species, body_type
2209 );
2210 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2211 },
2212 };
2213 let central =
2214 graceful_load_segment(&spec.chest_front.central.0, spec.chest_front.model_index);
2215
2216 (central, Vec3::from(spec.chest_front.offset))
2217 }
2218
2219 fn mesh_chest_back(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2220 let spec = match self.0.get(&(species, body_type)) {
2221 Some(spec) => spec,
2222 None => {
2223 error!(
2224 "No back chest specification exists for the combination of {:?} and {:?}",
2225 species, body_type
2226 );
2227 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2228 },
2229 };
2230 let central =
2231 graceful_load_segment(&spec.chest_back.central.0, spec.chest_back.model_index);
2232
2233 (central, Vec3::from(spec.chest_back.offset))
2234 }
2235
2236 fn mesh_tail_front(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2237 let spec = match self.0.get(&(species, body_type)) {
2238 Some(spec) => spec,
2239 None => {
2240 error!(
2241 "No front tail specification exists for the combination of {:?} and {:?}",
2242 species, body_type
2243 );
2244 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2245 },
2246 };
2247 let central =
2248 graceful_load_segment(&spec.tail_front.central.0, spec.tail_front.model_index);
2249
2250 (central, Vec3::from(spec.tail_front.offset))
2251 }
2252
2253 fn mesh_tail_back(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2254 let spec = match self.0.get(&(species, body_type)) {
2255 Some(spec) => spec,
2256 None => {
2257 error!(
2258 "No back tail specification exists for the combination of {:?} and {:?}",
2259 species, body_type
2260 );
2261 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2262 },
2263 };
2264 let central = graceful_load_segment(&spec.tail_back.central.0, spec.tail_back.model_index);
2265
2266 (central, Vec3::from(spec.tail_back.offset))
2267 }
2268}
2269impl TheropodLateralSpec {
2270 fn mesh_hand_l(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2271 let spec = match self.0.get(&(species, body_type)) {
2272 Some(spec) => spec,
2273 None => {
2274 error!(
2275 "No left hand specification exists for the combination of {:?} and {:?}",
2276 species, body_type
2277 );
2278 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2279 },
2280 };
2281 let lateral =
2282 graceful_load_segment_flipped(&spec.hand_l.lateral.0, true, spec.hand_l.model_index);
2283
2284 (lateral, Vec3::from(spec.hand_l.offset))
2285 }
2286
2287 fn mesh_hand_r(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2288 let spec = match self.0.get(&(species, body_type)) {
2289 Some(spec) => spec,
2290 None => {
2291 error!(
2292 "No right hand specification exists for the combination of {:?} and {:?}",
2293 species, body_type
2294 );
2295 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2296 },
2297 };
2298 let lateral = graceful_load_segment(&spec.hand_r.lateral.0, spec.hand_r.model_index);
2299
2300 (lateral, Vec3::from(spec.hand_r.offset))
2301 }
2302
2303 fn mesh_leg_l(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2304 let spec = match self.0.get(&(species, body_type)) {
2305 Some(spec) => spec,
2306 None => {
2307 error!(
2308 "No left leg specification exists for the combination of {:?} and {:?}",
2309 species, body_type
2310 );
2311 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2312 },
2313 };
2314 let lateral =
2315 graceful_load_segment_flipped(&spec.leg_l.lateral.0, true, spec.leg_l.model_index);
2316
2317 (lateral, Vec3::from(spec.leg_l.offset))
2318 }
2319
2320 fn mesh_leg_r(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2321 let spec = match self.0.get(&(species, body_type)) {
2322 Some(spec) => spec,
2323 None => {
2324 error!(
2325 "No right leg specification exists for the combination of {:?} and {:?}",
2326 species, body_type
2327 );
2328 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2329 },
2330 };
2331 let lateral = graceful_load_segment(&spec.leg_r.lateral.0, spec.leg_r.model_index);
2332
2333 (lateral, Vec3::from(spec.leg_r.offset))
2334 }
2335
2336 fn mesh_foot_l(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2337 let spec = match self.0.get(&(species, body_type)) {
2338 Some(spec) => spec,
2339 None => {
2340 error!(
2341 "No left foot specification exists for the combination of {:?} and {:?}",
2342 species, body_type
2343 );
2344 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2345 },
2346 };
2347 let lateral =
2348 graceful_load_segment_flipped(&spec.foot_l.lateral.0, true, spec.foot_l.model_index);
2349
2350 (lateral, Vec3::from(spec.foot_l.offset))
2351 }
2352
2353 fn mesh_foot_r(&self, species: TSpecies, body_type: TBodyType) -> BoneMeshes {
2354 let spec = match self.0.get(&(species, body_type)) {
2355 Some(spec) => spec,
2356 None => {
2357 error!(
2358 "No right foot specification exists for the combination of {:?} and {:?}",
2359 species, body_type
2360 );
2361 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2362 },
2363 };
2364 let lateral = graceful_load_segment(&spec.foot_r.lateral.0, spec.foot_r.model_index);
2365
2366 (lateral, Vec3::from(spec.foot_r.offset))
2367 }
2368}
2369
2370#[derive(Deserialize)]
2372struct ArthropodCentralSpec(HashMap<(ASpecies, ABodyType), SidedACentralVoxSpec>);
2373impl_concatenate_for_wrapper!(ArthropodCentralSpec);
2374
2375#[derive(Deserialize, Default)]
2376#[serde(default)]
2377struct SidedACentralVoxSpec {
2378 head: ArthropodCentralSubSpec,
2379 chest: ArthropodCentralSubSpec,
2380}
2381#[derive(Deserialize, Default)]
2382struct ArthropodCentralSubSpec {
2383 offset: [f32; 3], central: VoxSimple,
2385 #[serde(default)]
2386 model_index: u32,
2387}
2388#[derive(Deserialize)]
2389struct ArthropodLateralSpec(HashMap<(ASpecies, ABodyType), SidedALateralVoxSpec>);
2390impl_concatenate_for_wrapper!(ArthropodLateralSpec);
2391
2392#[derive(Deserialize, Default)]
2393#[serde(default)]
2394struct SidedALateralVoxSpec {
2395 mandible_l: ArthropodLateralSubSpec,
2396 mandible_r: ArthropodLateralSubSpec,
2397 wing_fl: ArthropodLateralSubSpec,
2398 wing_fr: ArthropodLateralSubSpec,
2399 wing_bl: ArthropodLateralSubSpec,
2400 wing_br: ArthropodLateralSubSpec,
2401 leg_fl: ArthropodLateralSubSpec,
2402 leg_fr: ArthropodLateralSubSpec,
2403 leg_fcl: ArthropodLateralSubSpec,
2404 leg_fcr: ArthropodLateralSubSpec,
2405 leg_bcl: ArthropodLateralSubSpec,
2406 leg_bcr: ArthropodLateralSubSpec,
2407 leg_bl: ArthropodLateralSubSpec,
2408 leg_br: ArthropodLateralSubSpec,
2409}
2410#[derive(Deserialize, Default)]
2411struct ArthropodLateralSubSpec {
2412 offset: [f32; 3], lateral: VoxSimple,
2414 #[serde(default)]
2415 model_index: u32,
2416}
2417make_vox_spec!(
2418 arthropod::Body,
2419 struct ArthropodSpec {
2420 central: ArthropodCentralSpec = "voxygen.voxel.arthropod_central_manifest",
2421 lateral: ArthropodLateralSpec = "voxygen.voxel.arthropod_lateral_manifest",
2422 },
2423 |FigureKey { body, extra, .. }, spec| {
2424 let third_person = extra
2425 .as_ref()
2426 .and_then(|loadout| loadout.third_person.as_ref());
2427
2428 [
2429 third_person.map(|_| {
2430 spec.central
2431 .read()
2432 .0
2433 .mesh_head(body.species, body.body_type)
2434 }),
2435 Some(
2436 spec.central
2437 .read()
2438 .0
2439 .mesh_chest(body.species, body.body_type),
2440 ),
2441 third_person.map(|_| {
2442 spec.lateral
2443 .read()
2444 .0
2445 .mesh_mandible_l(body.species, body.body_type)
2446 }),
2447 third_person.map(|_| {
2448 spec.lateral
2449 .read()
2450 .0
2451 .mesh_mandible_r(body.species, body.body_type)
2452 }),
2453 Some(
2454 spec.lateral
2455 .read()
2456 .0
2457 .mesh_wing_fl(body.species, body.body_type),
2458 ),
2459 Some(
2460 spec.lateral
2461 .read()
2462 .0
2463 .mesh_wing_fr(body.species, body.body_type),
2464 ),
2465 Some(
2466 spec.lateral
2467 .read()
2468 .0
2469 .mesh_wing_bl(body.species, body.body_type),
2470 ),
2471 Some(
2472 spec.lateral
2473 .read()
2474 .0
2475 .mesh_wing_br(body.species, body.body_type),
2476 ),
2477 Some(
2478 spec.lateral
2479 .read()
2480 .0
2481 .mesh_leg_fl(body.species, body.body_type),
2482 ),
2483 Some(
2484 spec.lateral
2485 .read()
2486 .0
2487 .mesh_leg_fr(body.species, body.body_type),
2488 ),
2489 Some(
2490 spec.lateral
2491 .read()
2492 .0
2493 .mesh_leg_fcl(body.species, body.body_type),
2494 ),
2495 Some(
2496 spec.lateral
2497 .read()
2498 .0
2499 .mesh_leg_fcr(body.species, body.body_type),
2500 ),
2501 Some(
2502 spec.lateral
2503 .read()
2504 .0
2505 .mesh_leg_bcl(body.species, body.body_type),
2506 ),
2507 Some(
2508 spec.lateral
2509 .read()
2510 .0
2511 .mesh_leg_bcr(body.species, body.body_type),
2512 ),
2513 Some(
2514 spec.lateral
2515 .read()
2516 .0
2517 .mesh_leg_bl(body.species, body.body_type),
2518 ),
2519 Some(
2520 spec.lateral
2521 .read()
2522 .0
2523 .mesh_leg_br(body.species, body.body_type),
2524 ),
2525 ]
2526 },
2527);
2528
2529impl ArthropodCentralSpec {
2530 fn mesh_head(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2531 let spec = match self.0.get(&(species, body_type)) {
2532 Some(spec) => spec,
2533 None => {
2534 error!(
2535 "No head specification exists for the combination of {:?} and {:?}",
2536 species, body_type
2537 );
2538 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2539 },
2540 };
2541 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
2542
2543 (central, Vec3::from(spec.head.offset))
2544 }
2545
2546 fn mesh_chest(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2547 let spec = match self.0.get(&(species, body_type)) {
2548 Some(spec) => spec,
2549 None => {
2550 error!(
2551 "No chest specification exists for the combination of {:?} and {:?}",
2552 species, body_type
2553 );
2554 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2555 },
2556 };
2557 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
2558
2559 (central, Vec3::from(spec.chest.offset))
2560 }
2561}
2562impl ArthropodLateralSpec {
2563 fn mesh_mandible_l(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2564 let spec = match self.0.get(&(species, body_type)) {
2565 Some(spec) => spec,
2566 None => {
2567 error!(
2568 "No left mandible specification exists for the combination of {:?} and {:?}",
2569 species, body_type
2570 );
2571 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2572 },
2573 };
2574 let lateral = graceful_load_segment_flipped(
2575 &spec.mandible_l.lateral.0,
2576 true,
2577 spec.mandible_l.model_index,
2578 );
2579
2580 (lateral, Vec3::from(spec.mandible_l.offset))
2581 }
2582
2583 fn mesh_mandible_r(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2584 let spec = match self.0.get(&(species, body_type)) {
2585 Some(spec) => spec,
2586 None => {
2587 error!(
2588 "No right mandible specification exists for the combination of {:?} and {:?}",
2589 species, body_type
2590 );
2591 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2592 },
2593 };
2594 let lateral =
2595 graceful_load_segment(&spec.mandible_r.lateral.0, spec.mandible_r.model_index);
2596
2597 (lateral, Vec3::from(spec.mandible_r.offset))
2598 }
2599
2600 fn mesh_wing_fl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2601 let spec = match self.0.get(&(species, body_type)) {
2602 Some(spec) => spec,
2603 None => {
2604 error!(
2605 "No front left wing specification exists for the combination of {:?} and {:?}",
2606 species, body_type
2607 );
2608 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2609 },
2610 };
2611 let lateral =
2612 graceful_load_segment_flipped(&spec.wing_fl.lateral.0, true, spec.wing_fl.model_index);
2613
2614 (lateral, Vec3::from(spec.wing_fl.offset))
2615 }
2616
2617 fn mesh_wing_fr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2618 let spec = match self.0.get(&(species, body_type)) {
2619 Some(spec) => spec,
2620 None => {
2621 error!(
2622 "No front right wing specification exists for the combination of {:?} and {:?}",
2623 species, body_type
2624 );
2625 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2626 },
2627 };
2628 let lateral = graceful_load_segment(&spec.wing_fr.lateral.0, spec.wing_fr.model_index);
2629
2630 (lateral, Vec3::from(spec.wing_fr.offset))
2631 }
2632
2633 fn mesh_wing_bl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2634 let spec = match self.0.get(&(species, body_type)) {
2635 Some(spec) => spec,
2636 None => {
2637 error!(
2638 "No back left wing specification exists for the combination of {:?} and {:?}",
2639 species, body_type
2640 );
2641 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2642 },
2643 };
2644 let lateral =
2645 graceful_load_segment_flipped(&spec.wing_bl.lateral.0, true, spec.wing_bl.model_index);
2646
2647 (lateral, Vec3::from(spec.wing_bl.offset))
2648 }
2649
2650 fn mesh_wing_br(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2651 let spec = match self.0.get(&(species, body_type)) {
2652 Some(spec) => spec,
2653 None => {
2654 error!(
2655 "No back right wing specification exists for the combination of {:?} and {:?}",
2656 species, body_type
2657 );
2658 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2659 },
2660 };
2661 let lateral = graceful_load_segment(&spec.wing_br.lateral.0, spec.wing_br.model_index);
2662
2663 (lateral, Vec3::from(spec.wing_br.offset))
2664 }
2665
2666 fn mesh_leg_fl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2667 let spec = match self.0.get(&(species, body_type)) {
2668 Some(spec) => spec,
2669 None => {
2670 error!(
2671 "No front left leg specification exists for the combination of {:?} and {:?}",
2672 species, body_type
2673 );
2674 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2675 },
2676 };
2677 let lateral =
2678 graceful_load_segment_flipped(&spec.leg_fl.lateral.0, true, spec.leg_fl.model_index);
2679
2680 (lateral, Vec3::from(spec.leg_fl.offset))
2681 }
2682
2683 fn mesh_leg_fr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2684 let spec = match self.0.get(&(species, body_type)) {
2685 Some(spec) => spec,
2686 None => {
2687 error!(
2688 "No front right leg specification exists for the combination of {:?} and {:?}",
2689 species, body_type
2690 );
2691 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2692 },
2693 };
2694 let lateral = graceful_load_segment(&spec.leg_fr.lateral.0, spec.leg_fr.model_index);
2695
2696 (lateral, Vec3::from(spec.leg_fr.offset))
2697 }
2698
2699 fn mesh_leg_fcl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2700 let spec = match self.0.get(&(species, body_type)) {
2701 Some(spec) => spec,
2702 None => {
2703 error!(
2704 "No front center left leg specification exists for the combination of {:?} \
2705 and {:?}",
2706 species, body_type
2707 );
2708 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2709 },
2710 };
2711 let lateral =
2712 graceful_load_segment_flipped(&spec.leg_fcl.lateral.0, true, spec.leg_fcl.model_index);
2713
2714 (lateral, Vec3::from(spec.leg_fcl.offset))
2715 }
2716
2717 fn mesh_leg_fcr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2718 let spec = match self.0.get(&(species, body_type)) {
2719 Some(spec) => spec,
2720 None => {
2721 error!(
2722 "No front center right leg specification exists for the combination of {:?} \
2723 and {:?}",
2724 species, body_type
2725 );
2726 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2727 },
2728 };
2729 let lateral = graceful_load_segment(&spec.leg_fcr.lateral.0, spec.leg_fcr.model_index);
2730
2731 (lateral, Vec3::from(spec.leg_fcr.offset))
2732 }
2733
2734 fn mesh_leg_bcl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2735 let spec = match self.0.get(&(species, body_type)) {
2736 Some(spec) => spec,
2737 None => {
2738 error!(
2739 "No back center left leg specification exists for the combination of {:?} and \
2740 {:?}",
2741 species, body_type
2742 );
2743 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2744 },
2745 };
2746 let lateral =
2747 graceful_load_segment_flipped(&spec.leg_bcl.lateral.0, true, spec.leg_bcl.model_index);
2748
2749 (lateral, Vec3::from(spec.leg_bcl.offset))
2750 }
2751
2752 fn mesh_leg_bcr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2753 let spec = match self.0.get(&(species, body_type)) {
2754 Some(spec) => spec,
2755 None => {
2756 error!(
2757 "No back center right leg specification exists for the combination of {:?} \
2758 and {:?}",
2759 species, body_type
2760 );
2761 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2762 },
2763 };
2764 let lateral = graceful_load_segment(&spec.leg_bcr.lateral.0, spec.leg_bcr.model_index);
2765
2766 (lateral, Vec3::from(spec.leg_bcr.offset))
2767 }
2768
2769 fn mesh_leg_bl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2770 let spec = match self.0.get(&(species, body_type)) {
2771 Some(spec) => spec,
2772 None => {
2773 error!(
2774 "No back left leg specification exists for the combination of {:?} and {:?}",
2775 species, body_type
2776 );
2777 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2778 },
2779 };
2780 let lateral =
2781 graceful_load_segment_flipped(&spec.leg_bl.lateral.0, true, spec.leg_bl.model_index);
2782
2783 (lateral, Vec3::from(spec.leg_bl.offset))
2784 }
2785
2786 fn mesh_leg_br(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
2787 let spec = match self.0.get(&(species, body_type)) {
2788 Some(spec) => spec,
2789 None => {
2790 error!(
2791 "No back right leg specification exists for the combination of {:?} and {:?}",
2792 species, body_type
2793 );
2794 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2795 },
2796 };
2797 let lateral = graceful_load_segment(&spec.leg_br.lateral.0, spec.leg_br.model_index);
2798
2799 (lateral, Vec3::from(spec.leg_br.offset))
2800 }
2801}
2802#[derive(Deserialize)]
2804struct CrustaceanCentralSpec(HashMap<(CSpecies, CBodyType), CrustCentralVoxSpec>);
2805impl_concatenate_for_wrapper!(CrustaceanCentralSpec);
2806
2807#[derive(Deserialize, Default)]
2808#[serde(default)]
2809struct CrustCentralVoxSpec {
2810 chest: CrustaceanCentralSubSpec,
2811 tail_f: CrustaceanCentralSubSpec,
2812 tail_b: CrustaceanCentralSubSpec,
2813}
2814
2815#[derive(Deserialize, Default)]
2816struct CrustaceanCentralSubSpec {
2817 offset: [f32; 3], central: VoxSimple,
2819 #[serde(default)]
2820 model_index: u32,
2821}
2822#[derive(Deserialize)]
2823struct CrustaceanLateralSpec(HashMap<(CSpecies, CBodyType), CrustLateralVoxSpec>);
2824impl_concatenate_for_wrapper!(CrustaceanLateralSpec);
2825
2826#[derive(Deserialize, Default)]
2827#[serde(default)]
2828struct CrustLateralVoxSpec {
2829 arm_l: CrustaceanLateralSubSpec,
2830 pincer_l0: CrustaceanLateralSubSpec,
2831 pincer_l1: CrustaceanLateralSubSpec,
2832 arm_r: CrustaceanLateralSubSpec,
2833 pincer_r0: CrustaceanLateralSubSpec,
2834 pincer_r1: CrustaceanLateralSubSpec,
2835 leg_fl: CrustaceanLateralSubSpec,
2836 leg_cl: CrustaceanLateralSubSpec,
2837 leg_bl: CrustaceanLateralSubSpec,
2838 leg_fr: CrustaceanLateralSubSpec,
2839 leg_cr: CrustaceanLateralSubSpec,
2840 leg_br: CrustaceanLateralSubSpec,
2841}
2842#[derive(Deserialize, Default)]
2843struct CrustaceanLateralSubSpec {
2844 offset: [f32; 3], lateral: VoxMirror,
2846 #[serde(default)]
2847 model_index: u32,
2848}
2849make_vox_spec!(
2850 crustacean::Body,
2851 struct CrustaceanSpec {
2852 central: CrustaceanCentralSpec = "voxygen.voxel.crustacean_central_manifest",
2853 lateral: CrustaceanLateralSpec = "voxygen.voxel.crustacean_lateral_manifest",
2854 },
2855 |FigureKey { body, extra, .. }, spec| {
2856 let third_person = extra
2857 .as_ref()
2858 .and_then(|loadout| loadout.third_person.as_ref());
2859
2860 [
2861 third_person.map(|_| {
2862 spec.central
2863 .read()
2864 .0
2865 .mesh_chest(body.species, body.body_type)
2866 }),
2867 Some(
2868 spec.central
2869 .read()
2870 .0
2871 .mesh_tail_f(body.species, body.body_type),
2872 ),
2873 Some(
2874 spec.central
2875 .read()
2876 .0
2877 .mesh_tail_b(body.species, body.body_type),
2878 ),
2879 Some(
2880 spec.lateral
2881 .read()
2882 .0
2883 .mesh_arm_l(body.species, body.body_type),
2884 ),
2885 Some(
2886 spec.lateral
2887 .read()
2888 .0
2889 .mesh_pincer_l0(body.species, body.body_type),
2890 ),
2891 Some(
2892 spec.lateral
2893 .read()
2894 .0
2895 .mesh_pincer_l1(body.species, body.body_type),
2896 ),
2897 Some(
2898 spec.lateral
2899 .read()
2900 .0
2901 .mesh_arm_r(body.species, body.body_type),
2902 ),
2903 Some(
2904 spec.lateral
2905 .read()
2906 .0
2907 .mesh_pincer_r0(body.species, body.body_type),
2908 ),
2909 Some(
2910 spec.lateral
2911 .read()
2912 .0
2913 .mesh_pincer_r1(body.species, body.body_type),
2914 ),
2915 Some(
2916 spec.lateral
2917 .read()
2918 .0
2919 .mesh_leg_fl(body.species, body.body_type),
2920 ),
2921 Some(
2922 spec.lateral
2923 .read()
2924 .0
2925 .mesh_leg_cl(body.species, body.body_type),
2926 ),
2927 Some(
2928 spec.lateral
2929 .read()
2930 .0
2931 .mesh_leg_bl(body.species, body.body_type),
2932 ),
2933 Some(
2934 spec.lateral
2935 .read()
2936 .0
2937 .mesh_leg_fr(body.species, body.body_type),
2938 ),
2939 Some(
2940 spec.lateral
2941 .read()
2942 .0
2943 .mesh_leg_cr(body.species, body.body_type),
2944 ),
2945 Some(
2946 spec.lateral
2947 .read()
2948 .0
2949 .mesh_leg_br(body.species, body.body_type),
2950 ),
2951 None,
2952 ]
2953 },
2954);
2955
2956impl CrustaceanCentralSpec {
2957 fn mesh_chest(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
2958 let spec = match self.0.get(&(species, body_type)) {
2959 Some(spec) => spec,
2960 None => {
2961 error!(
2962 "No chest specification exists for the combination of {:?} and {:?}",
2963 species, body_type
2964 );
2965 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2966 },
2967 };
2968 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
2969
2970 (central, Vec3::from(spec.chest.offset))
2971 }
2972
2973 fn mesh_tail_f(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
2974 let spec = match self.0.get(&(species, body_type)) {
2975 Some(spec) => spec,
2976 None => {
2977 error!(
2978 "No front tail specification exists for the combination of {:?} and {:?}",
2979 species, body_type
2980 );
2981 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2982 },
2983 };
2984 let central = graceful_load_segment(&spec.tail_f.central.0, spec.tail_f.model_index);
2985
2986 (central, Vec3::from(spec.tail_f.offset))
2987 }
2988
2989 fn mesh_tail_b(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
2990 let spec = match self.0.get(&(species, body_type)) {
2991 Some(spec) => spec,
2992 None => {
2993 error!(
2994 "No back tail specification exists for the combination of {:?} and {:?}",
2995 species, body_type
2996 );
2997 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
2998 },
2999 };
3000 let central = graceful_load_segment(&spec.tail_b.central.0, spec.tail_b.model_index);
3001
3002 (central, Vec3::from(spec.tail_b.offset))
3003 }
3004}
3005impl CrustaceanLateralSpec {
3006 fn mesh_arm_l(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3007 let spec = match self.0.get(&(species, body_type)) {
3008 Some(spec) => spec,
3009 None => {
3010 error!(
3011 "No left arm specification exists for the combination of {:?} and {:?}",
3012 species, body_type
3013 );
3014 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3015 },
3016 };
3017 let lateral = graceful_load_segment_flipped(
3018 &spec.arm_l.lateral.0,
3019 spec.arm_l.lateral.1,
3020 spec.arm_l.model_index,
3021 );
3022
3023 (lateral, Vec3::from(spec.arm_l.offset))
3024 }
3025
3026 fn mesh_pincer_l0(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3027 let spec = match self.0.get(&(species, body_type)) {
3028 Some(spec) => spec,
3029 None => {
3030 error!(
3031 "No left major pincer specification exists for the combination of {:?} and \
3032 {:?}",
3033 species, body_type
3034 );
3035 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3036 },
3037 };
3038 let lateral = graceful_load_segment_flipped(
3039 &spec.pincer_l0.lateral.0,
3040 spec.pincer_l0.lateral.1,
3041 spec.pincer_l0.model_index,
3042 );
3043
3044 (lateral, Vec3::from(spec.pincer_l0.offset))
3045 }
3046
3047 fn mesh_pincer_l1(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3048 let spec = match self.0.get(&(species, body_type)) {
3049 Some(spec) => spec,
3050 None => {
3051 error!(
3052 "No left minor pincer specification exists for the combination of {:?} and \
3053 {:?}",
3054 species, body_type
3055 );
3056 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3057 },
3058 };
3059 let lateral = graceful_load_segment_flipped(
3060 &spec.pincer_l1.lateral.0,
3061 spec.pincer_l0.lateral.1,
3062 spec.pincer_l1.model_index,
3063 );
3064
3065 (lateral, Vec3::from(spec.pincer_l1.offset))
3066 }
3067
3068 fn mesh_arm_r(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3069 let spec = match self.0.get(&(species, body_type)) {
3070 Some(spec) => spec,
3071 None => {
3072 error!(
3073 "No right arm specification exists for the combination of {:?} and {:?}",
3074 species, body_type
3075 );
3076 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3077 },
3078 };
3079 let lateral = graceful_load_segment_flipped(
3080 &spec.arm_r.lateral.0,
3081 spec.arm_r.lateral.1,
3082 spec.arm_r.model_index,
3083 );
3084
3085 (lateral, Vec3::from(spec.arm_r.offset))
3086 }
3087
3088 fn mesh_pincer_r0(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3089 let spec = match self.0.get(&(species, body_type)) {
3090 Some(spec) => spec,
3091 None => {
3092 error!(
3093 "No right major pincer specification exists for the combination of {:?} and \
3094 {:?}",
3095 species, body_type
3096 );
3097 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3098 },
3099 };
3100 let lateral = graceful_load_segment_flipped(
3101 &spec.pincer_r0.lateral.0,
3102 spec.pincer_r0.lateral.1,
3103 spec.pincer_r0.model_index,
3104 );
3105
3106 (lateral, Vec3::from(spec.pincer_r0.offset))
3107 }
3108
3109 fn mesh_pincer_r1(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3110 let spec = match self.0.get(&(species, body_type)) {
3111 Some(spec) => spec,
3112 None => {
3113 error!(
3114 "No right minor pincer specification exists for the combination of {:?} and \
3115 {:?}",
3116 species, body_type
3117 );
3118 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3119 },
3120 };
3121 let lateral = graceful_load_segment_flipped(
3122 &spec.pincer_r1.lateral.0,
3123 spec.pincer_r1.lateral.1,
3124 spec.pincer_r1.model_index,
3125 );
3126
3127 (lateral, Vec3::from(spec.pincer_r1.offset))
3128 }
3129
3130 fn mesh_leg_fl(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3131 let spec = match self.0.get(&(species, body_type)) {
3132 Some(spec) => spec,
3133 None => {
3134 error!(
3135 "No front left leg specification exists for the combination of {:?} and {:?}",
3136 species, body_type
3137 );
3138 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3139 },
3140 };
3141 let lateral = graceful_load_segment_flipped(
3142 &spec.leg_fl.lateral.0,
3143 spec.leg_fl.lateral.1,
3144 spec.leg_fl.model_index,
3145 );
3146
3147 (lateral, Vec3::from(spec.leg_fl.offset))
3148 }
3149
3150 fn mesh_leg_cl(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3151 let spec = match self.0.get(&(species, body_type)) {
3152 Some(spec) => spec,
3153 None => {
3154 error!(
3155 "No center left leg specification exists for the combination of {:?} and {:?}",
3156 species, body_type
3157 );
3158 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3159 },
3160 };
3161 let lateral = graceful_load_segment_flipped(
3162 &spec.leg_cl.lateral.0,
3163 spec.leg_cl.lateral.1,
3164 spec.leg_cl.model_index,
3165 );
3166
3167 (lateral, Vec3::from(spec.leg_cl.offset))
3168 }
3169
3170 fn mesh_leg_bl(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3171 let spec = match self.0.get(&(species, body_type)) {
3172 Some(spec) => spec,
3173 None => {
3174 error!(
3175 "No back left leg specification exists for the combination of {:?} and {:?}",
3176 species, body_type
3177 );
3178 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3179 },
3180 };
3181 let lateral = graceful_load_segment_flipped(
3182 &spec.leg_bl.lateral.0,
3183 spec.leg_bl.lateral.1,
3184 spec.leg_bl.model_index,
3185 );
3186
3187 (lateral, Vec3::from(spec.leg_bl.offset))
3188 }
3189
3190 fn mesh_leg_fr(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3191 let spec = match self.0.get(&(species, body_type)) {
3192 Some(spec) => spec,
3193 None => {
3194 error!(
3195 "No front right leg specification exists for the combination of {:?} and {:?}",
3196 species, body_type
3197 );
3198 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3199 },
3200 };
3201 let lateral = graceful_load_segment_flipped(
3202 &spec.leg_fr.lateral.0,
3203 spec.leg_fr.lateral.1,
3204 spec.leg_fr.model_index,
3205 );
3206
3207 (lateral, Vec3::from(spec.leg_fr.offset))
3208 }
3209
3210 fn mesh_leg_cr(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3211 let spec = match self.0.get(&(species, body_type)) {
3212 Some(spec) => spec,
3213 None => {
3214 error!(
3215 "No center right leg specification exists for the combination of {:?} and {:?}",
3216 species, body_type
3217 );
3218 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3219 },
3220 };
3221 let lateral = graceful_load_segment_flipped(
3222 &spec.leg_cr.lateral.0,
3223 spec.leg_cr.lateral.1,
3224 spec.leg_cr.model_index,
3225 );
3226
3227 (lateral, Vec3::from(spec.leg_cr.offset))
3228 }
3229
3230 fn mesh_leg_br(&self, species: CSpecies, body_type: CBodyType) -> BoneMeshes {
3231 let spec = match self.0.get(&(species, body_type)) {
3232 Some(spec) => spec,
3233 None => {
3234 error!(
3235 "No back right leg specification exists for the combination of {:?} and {:?}",
3236 species, body_type
3237 );
3238 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3239 },
3240 };
3241 let lateral = graceful_load_segment_flipped(
3242 &spec.leg_br.lateral.0,
3243 spec.leg_br.lateral.1,
3244 spec.leg_br.model_index,
3245 );
3246
3247 (lateral, Vec3::from(spec.leg_br.offset))
3248 }
3249}
3250
3251#[derive(Deserialize)]
3252struct FishMediumCentralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMCentralVoxSpec>);
3253impl_concatenate_for_wrapper!(FishMediumCentralSpec);
3254
3255#[derive(Deserialize, Default)]
3256#[serde(default)]
3257struct SidedFMCentralVoxSpec {
3258 head: FishMediumCentralSubSpec,
3259 jaw: FishMediumCentralSubSpec,
3260 chest_front: FishMediumCentralSubSpec,
3261 chest_back: FishMediumCentralSubSpec,
3262 tail: FishMediumCentralSubSpec,
3263}
3264
3265#[derive(Deserialize, Default)]
3266struct FishMediumCentralSubSpec {
3267 offset: [f32; 3], central: VoxSimple,
3269 #[serde(default)]
3270 model_index: u32,
3271}
3272
3273#[derive(Deserialize)]
3274struct FishMediumLateralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMLateralVoxSpec>);
3275impl_concatenate_for_wrapper!(FishMediumLateralSpec);
3276
3277#[derive(Deserialize, Default)]
3278#[serde(default)]
3279struct SidedFMLateralVoxSpec {
3280 fin_l: FishMediumLateralSubSpec,
3281 fin_r: FishMediumLateralSubSpec,
3282}
3283#[derive(Deserialize, Default)]
3284struct FishMediumLateralSubSpec {
3285 offset: [f32; 3], lateral: VoxSimple,
3287 #[serde(default)]
3288 model_index: u32,
3289}
3290
3291make_vox_spec!(
3292 fish_medium::Body,
3293 struct FishMediumSpec {
3294 central: FishMediumCentralSpec = "voxygen.voxel.fish_medium_central_manifest",
3295 lateral: FishMediumLateralSpec = "voxygen.voxel.fish_medium_lateral_manifest",
3296 },
3297 |FigureKey { body, extra, .. }, spec| {
3298 let third_person = extra
3299 .as_ref()
3300 .and_then(|loadout| loadout.third_person.as_ref());
3301
3302 [
3303 third_person.map(|_| {
3304 spec.central
3305 .read()
3306 .0
3307 .mesh_head(body.species, body.body_type)
3308 }),
3309 Some(spec.central.read().0.mesh_jaw(body.species, body.body_type)),
3310 Some(
3311 spec.central
3312 .read()
3313 .0
3314 .mesh_chest_front(body.species, body.body_type),
3315 ),
3316 Some(
3317 spec.central
3318 .read()
3319 .0
3320 .mesh_chest_back(body.species, body.body_type),
3321 ),
3322 Some(
3323 spec.central
3324 .read()
3325 .0
3326 .mesh_tail(body.species, body.body_type),
3327 ),
3328 Some(
3329 spec.lateral
3330 .read()
3331 .0
3332 .mesh_fin_l(body.species, body.body_type),
3333 ),
3334 Some(
3335 spec.lateral
3336 .read()
3337 .0
3338 .mesh_fin_r(body.species, body.body_type),
3339 ),
3340 None,
3341 None,
3342 None,
3343 None,
3344 None,
3345 None,
3346 None,
3347 None,
3348 None,
3349 ]
3350 },
3351);
3352
3353impl FishMediumCentralSpec {
3354 fn mesh_head(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3355 let spec = match self.0.get(&(species, body_type)) {
3356 Some(spec) => spec,
3357 None => {
3358 error!(
3359 "No head specification exists for the combination of {:?} and {:?}",
3360 species, body_type
3361 );
3362 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3363 },
3364 };
3365 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
3366
3367 (central, Vec3::from(spec.head.offset))
3368 }
3369
3370 fn mesh_jaw(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3371 let spec = match self.0.get(&(species, body_type)) {
3372 Some(spec) => spec,
3373 None => {
3374 error!(
3375 "No jaw specification exists for the combination of {:?} and {:?}",
3376 species, body_type
3377 );
3378 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3379 },
3380 };
3381 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
3382
3383 (central, Vec3::from(spec.jaw.offset))
3384 }
3385
3386 fn mesh_chest_front(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3387 let spec = match self.0.get(&(species, body_type)) {
3388 Some(spec) => spec,
3389 None => {
3390 error!(
3391 "No front chest specification exists for the combination of {:?} and {:?}",
3392 species, body_type
3393 );
3394 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3395 },
3396 };
3397 let central =
3398 graceful_load_segment(&spec.chest_front.central.0, spec.chest_front.model_index);
3399
3400 (central, Vec3::from(spec.chest_front.offset))
3401 }
3402
3403 fn mesh_chest_back(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3404 let spec = match self.0.get(&(species, body_type)) {
3405 Some(spec) => spec,
3406 None => {
3407 error!(
3408 "No back chest specification exists for the combination of {:?} and {:?}",
3409 species, body_type
3410 );
3411 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3412 },
3413 };
3414 let central =
3415 graceful_load_segment(&spec.chest_back.central.0, spec.chest_back.model_index);
3416
3417 (central, Vec3::from(spec.chest_back.offset))
3418 }
3419
3420 fn mesh_tail(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3421 let spec = match self.0.get(&(species, body_type)) {
3422 Some(spec) => spec,
3423 None => {
3424 error!(
3425 "No tail specification exists for the combination of {:?} and {:?}",
3426 species, body_type
3427 );
3428 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3429 },
3430 };
3431 let central = graceful_load_segment(&spec.tail.central.0, spec.tail.model_index);
3432
3433 (central, Vec3::from(spec.tail.offset))
3434 }
3435}
3436
3437impl FishMediumLateralSpec {
3438 fn mesh_fin_l(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3439 let spec = match self.0.get(&(species, body_type)) {
3440 Some(spec) => spec,
3441 None => {
3442 error!(
3443 "No fin specification exists for the combination of {:?} and {:?}",
3444 species, body_type
3445 );
3446 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3447 },
3448 };
3449 let lateral =
3450 graceful_load_segment_flipped(&spec.fin_l.lateral.0, true, spec.fin_l.model_index);
3451
3452 (lateral, Vec3::from(spec.fin_l.offset))
3453 }
3454
3455 fn mesh_fin_r(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
3456 let spec = match self.0.get(&(species, body_type)) {
3457 Some(spec) => spec,
3458 None => {
3459 error!(
3460 "No fin specification exists for the combination of {:?} and {:?}",
3461 species, body_type
3462 );
3463 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3464 },
3465 };
3466 let lateral = graceful_load_segment(&spec.fin_r.lateral.0, spec.fin_r.model_index);
3467
3468 (lateral, Vec3::from(spec.fin_r.offset))
3469 }
3470}
3471
3472#[derive(Deserialize)]
3474struct FishSmallCentralSpec(HashMap<(FSSpecies, FSBodyType), SidedFSCentralVoxSpec>);
3475impl_concatenate_for_wrapper!(FishSmallCentralSpec);
3476
3477#[derive(Deserialize, Default)]
3478#[serde(default)]
3479struct SidedFSCentralVoxSpec {
3480 chest: FishSmallCentralSubSpec,
3481 tail: FishSmallCentralSubSpec,
3482}
3483
3484#[derive(Deserialize, Default)]
3485struct FishSmallCentralSubSpec {
3486 offset: [f32; 3], central: VoxSimple,
3488 #[serde(default)]
3489 model_index: u32,
3490}
3491
3492#[derive(Deserialize)]
3493struct FishSmallLateralSpec(HashMap<(FSSpecies, FSBodyType), SidedFSLateralVoxSpec>);
3494impl_concatenate_for_wrapper!(FishSmallLateralSpec);
3495
3496#[derive(Deserialize, Default)]
3497#[serde(default)]
3498struct SidedFSLateralVoxSpec {
3499 fin_l: FishSmallLateralSubSpec,
3500 fin_r: FishSmallLateralSubSpec,
3501}
3502
3503#[derive(Deserialize, Default)]
3504struct FishSmallLateralSubSpec {
3505 offset: [f32; 3], lateral: VoxSimple,
3507 #[serde(default)]
3508 model_index: u32,
3509}
3510
3511make_vox_spec!(
3512 fish_small::Body,
3513 struct FishSmallSpec {
3514 central: FishSmallCentralSpec = "voxygen.voxel.fish_small_central_manifest",
3515 lateral: FishSmallLateralSpec = "voxygen.voxel.fish_small_lateral_manifest",
3516 },
3517 |FigureKey { body, extra, .. }, spec| {
3518 let third_person = extra
3519 .as_ref()
3520 .and_then(|loadout| loadout.third_person.as_ref());
3521
3522 [
3523 third_person.map(|_| {
3524 spec.central
3525 .read()
3526 .0
3527 .mesh_chest(body.species, body.body_type)
3528 }),
3529 Some(
3530 spec.central
3531 .read()
3532 .0
3533 .mesh_tail(body.species, body.body_type),
3534 ),
3535 Some(
3536 spec.lateral
3537 .read()
3538 .0
3539 .mesh_fin_l(body.species, body.body_type),
3540 ),
3541 Some(
3542 spec.lateral
3543 .read()
3544 .0
3545 .mesh_fin_r(body.species, body.body_type),
3546 ),
3547 None,
3548 None,
3549 None,
3550 None,
3551 None,
3552 None,
3553 None,
3554 None,
3555 None,
3556 None,
3557 None,
3558 None,
3559 ]
3560 },
3561);
3562
3563impl FishSmallCentralSpec {
3564 fn mesh_chest(&self, species: FSSpecies, body_type: FSBodyType) -> BoneMeshes {
3565 let spec = match self.0.get(&(species, body_type)) {
3566 Some(spec) => spec,
3567 None => {
3568 error!(
3569 "No chest specification exists for the combination of {:?} and {:?}",
3570 species, body_type
3571 );
3572 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3573 },
3574 };
3575 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
3576
3577 (central, Vec3::from(spec.chest.offset))
3578 }
3579
3580 fn mesh_tail(&self, species: FSSpecies, body_type: FSBodyType) -> BoneMeshes {
3581 let spec = match self.0.get(&(species, body_type)) {
3582 Some(spec) => spec,
3583 None => {
3584 error!(
3585 "No tail specification exists for the combination of {:?} and {:?}",
3586 species, body_type
3587 );
3588 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3589 },
3590 };
3591 let central = graceful_load_segment(&spec.tail.central.0, spec.tail.model_index);
3592
3593 (central, Vec3::from(spec.tail.offset))
3594 }
3595}
3596
3597impl FishSmallLateralSpec {
3598 fn mesh_fin_l(&self, species: FSSpecies, body_type: FSBodyType) -> BoneMeshes {
3599 let spec = match self.0.get(&(species, body_type)) {
3600 Some(spec) => spec,
3601 None => {
3602 error!(
3603 "No fin specification exists for the combination of {:?} and {:?}",
3604 species, body_type
3605 );
3606 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3607 },
3608 };
3609 let lateral =
3610 graceful_load_segment_flipped(&spec.fin_l.lateral.0, true, spec.fin_l.model_index);
3611
3612 (lateral, Vec3::from(spec.fin_l.offset))
3613 }
3614
3615 fn mesh_fin_r(&self, species: FSSpecies, body_type: FSBodyType) -> BoneMeshes {
3616 let spec = match self.0.get(&(species, body_type)) {
3617 Some(spec) => spec,
3618 None => {
3619 error!(
3620 "No fin specification exists for the combination of {:?} and {:?}",
3621 species, body_type
3622 );
3623 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
3624 },
3625 };
3626 let lateral = graceful_load_segment(&spec.fin_r.lateral.0, spec.fin_r.model_index);
3627
3628 (lateral, Vec3::from(spec.fin_r.offset))
3629 }
3630}
3631
3632#[derive(Deserialize)]
3635struct BipedSmallWeaponSpec(HashMap<ToolKey, ArmorVoxSpec>);
3636impl_concatenate_for_wrapper!(BipedSmallWeaponSpec);
3637#[derive(Deserialize)]
3638struct BipedSmallArmorHeadSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
3639impl_concatenate_for_wrapper!(BipedSmallArmorHeadSpec);
3640#[derive(Deserialize)]
3641struct BipedSmallArmorHandSpec(ArmorVoxSpecMap<String, SidedArmorVoxSpec>);
3642impl_concatenate_for_wrapper!(BipedSmallArmorHandSpec);
3643#[derive(Deserialize)]
3644struct BipedSmallArmorFootSpec(ArmorVoxSpecMap<String, SidedArmorVoxSpec>);
3645impl_concatenate_for_wrapper!(BipedSmallArmorFootSpec);
3646#[derive(Deserialize)]
3647struct BipedSmallArmorChestSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
3648impl_concatenate_for_wrapper!(BipedSmallArmorChestSpec);
3649#[derive(Deserialize)]
3650struct BipedSmallArmorPantsSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
3651impl_concatenate_for_wrapper!(BipedSmallArmorPantsSpec);
3652#[derive(Deserialize)]
3653struct BipedSmallArmorTailSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
3654impl_concatenate_for_wrapper!(BipedSmallArmorTailSpec);
3655make_vox_spec!(
3656 biped_small::Body,
3657 struct BipedSmallSpec {
3658 armor_foot: BipedSmallArmorFootSpec = "voxygen.voxel.biped_small_armor_foot_manifest",
3659 weapon: BipedSmallWeaponSpec = "voxygen.voxel.biped_weapon_manifest",
3660 armor_hand: BipedSmallArmorHandSpec = "voxygen.voxel.biped_small_armor_hand_manifest",
3661 armor_chest: BipedSmallArmorChestSpec = "voxygen.voxel.biped_small_armor_chest_manifest",
3662 armor_pants: BipedSmallArmorPantsSpec = "voxygen.voxel.biped_small_armor_pants_manifest",
3663 armor_head: BipedSmallArmorHeadSpec = "voxygen.voxel.biped_small_armor_head_manifest",
3664 armor_tail: BipedSmallArmorTailSpec = "voxygen.voxel.biped_small_armor_tail_manifest",
3665
3666 },
3667 |FigureKey {
3668 body: _,
3669 item_key: _,
3670 extra,
3671 },
3672 spec| {
3673 const DEFAULT_LOADOUT: super::cache::CharacterCacheKey = super::cache::CharacterCacheKey {
3674 third_person: None,
3675 tool: None,
3676 lantern: None,
3677 glider: None,
3678 hand: None,
3679 foot: None,
3680 head: None,
3681 };
3682
3683 let loadout = extra.as_deref().unwrap_or(&DEFAULT_LOADOUT);
3685 let third_person = loadout.third_person.as_ref();
3686 let tool = loadout.tool.as_ref();
3687 let hand = loadout.hand.clone().flatten();
3688 let foot = loadout.foot.as_deref();
3689
3690 [
3691 third_person.map(|loadout| spec.armor_head.read().0.mesh_head(loadout.head.as_deref())),
3692 third_person.map(|loadout| {
3693 spec.armor_chest
3694 .read()
3695 .0
3696 .mesh_chest(loadout.chest.as_deref())
3697 }),
3698 third_person.map(|loadout| {
3699 spec.armor_pants
3700 .read()
3701 .0
3702 .mesh_pants(loadout.pants.as_deref())
3703 }),
3704 third_person.map(|loadout| spec.armor_tail.read().0.mesh_tail(loadout.belt.as_deref())),
3705 tool.and_then(|tool| tool.active.as_ref())
3706 .map(|tool| spec.weapon.read().0.mesh_main(tool, false)),
3707 tool.and_then(|tool| tool.second.as_ref())
3708 .map(|tool| spec.weapon.read().0.mesh_main(tool, true)),
3709 Some(spec.armor_hand.read().0.mesh_left_hand(hand.as_deref())),
3710 Some(spec.armor_hand.read().0.mesh_right_hand(hand.as_deref())),
3711 Some(spec.armor_foot.read().0.mesh_left_foot(foot)),
3712 Some(spec.armor_foot.read().0.mesh_right_foot(foot)),
3713 None,
3714 None,
3715 None,
3716 None,
3717 None,
3718 None,
3719 ]
3720 },
3721);
3722
3723impl BipedSmallArmorHeadSpec {
3724 fn mesh_head(&self, head: Option<&str>) -> BoneMeshes {
3725 let spec = if let Some(head) = head {
3726 match self.0.map.get(head) {
3727 Some(spec) => spec,
3728 None => {
3729 error!(?head, "No head specification exists");
3730 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3731 },
3732 }
3733 } else {
3734 &self.0.default
3735 };
3736
3737 let head_segment = graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2);
3738
3739 let offset = Vec3::new(spec.vox_spec.1[0], spec.vox_spec.1[1], spec.vox_spec.1[2]);
3740
3741 (head_segment, offset)
3742 }
3743}
3744impl BipedSmallArmorChestSpec {
3745 fn mesh_chest(&self, chest: Option<&str>) -> BoneMeshes {
3746 let spec = if let Some(chest) = chest {
3747 match self.0.map.get(chest) {
3748 Some(spec) => spec,
3749 None => {
3750 error!(?chest, "No chest specification exists");
3751 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3752 },
3753 }
3754 } else {
3755 &self.0.default
3756 };
3757
3758 let chest_segment = graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2);
3759
3760 let offset = Vec3::new(spec.vox_spec.1[0], spec.vox_spec.1[1], spec.vox_spec.1[2]);
3761
3762 (chest_segment, offset)
3763 }
3764}
3765impl BipedSmallArmorTailSpec {
3766 fn mesh_tail(&self, tail: Option<&str>) -> BoneMeshes {
3767 let spec = if let Some(tail) = tail {
3768 match self.0.map.get(tail) {
3769 Some(spec) => spec,
3770 None => {
3771 error!(?tail, "No tail specification exists");
3772 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3773 },
3774 }
3775 } else {
3776 &self.0.default
3777 };
3778
3779 let tail_segment = graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2);
3780
3781 let offset = Vec3::new(spec.vox_spec.1[0], spec.vox_spec.1[1], spec.vox_spec.1[2]);
3782
3783 (tail_segment, offset)
3784 }
3785}
3786impl BipedSmallArmorPantsSpec {
3787 fn mesh_pants(&self, pants: Option<&str>) -> BoneMeshes {
3788 let spec = if let Some(pants) = pants {
3789 match self.0.map.get(pants) {
3790 Some(spec) => spec,
3791 None => {
3792 error!(?pants, "No pants specification exists");
3793 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3794 },
3795 }
3796 } else {
3797 &self.0.default
3798 };
3799
3800 let pants_segment = graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2);
3801
3802 let offset = Vec3::new(spec.vox_spec.1[0], spec.vox_spec.1[1], spec.vox_spec.1[2]);
3803
3804 (pants_segment, offset)
3805 }
3806}
3807impl BipedSmallArmorHandSpec {
3808 fn mesh_hand(&self, hand: Option<&str>, flipped: bool) -> BoneMeshes {
3809 let spec = if let Some(hand) = hand {
3810 match self.0.map.get(hand) {
3811 Some(spec) => spec,
3812 None => {
3813 error!(?hand, "No hand specification exists");
3814 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3815 },
3816 }
3817 } else {
3818 &self.0.default
3819 };
3820
3821 let hand_segment = if flipped {
3822 graceful_load_segment_flipped(&spec.left.vox_spec.0, true, spec.left.vox_spec.2)
3823 } else {
3824 graceful_load_segment(&spec.right.vox_spec.0, spec.right.vox_spec.2)
3825 };
3826 let offset = if flipped {
3827 spec.left.vox_spec.1
3828 } else {
3829 spec.right.vox_spec.1
3830 };
3831
3832 (hand_segment, Vec3::from(offset))
3833 }
3834
3835 fn mesh_left_hand(&self, hand: Option<&str>) -> BoneMeshes { self.mesh_hand(hand, true) }
3836
3837 fn mesh_right_hand(&self, hand: Option<&str>) -> BoneMeshes { self.mesh_hand(hand, false) }
3838}
3839impl BipedSmallArmorFootSpec {
3840 fn mesh_foot(&self, foot: Option<&str>, flipped: bool) -> BoneMeshes {
3841 let spec = if let Some(foot) = foot {
3842 match self.0.map.get(foot) {
3843 Some(spec) => spec,
3844 None => {
3845 error!(?foot, "No foot specification exists");
3846 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3847 },
3848 }
3849 } else {
3850 &self.0.default
3851 };
3852
3853 let foot_segment = if flipped {
3854 graceful_load_segment_flipped(&spec.left.vox_spec.0, true, spec.left.vox_spec.2)
3855 } else {
3856 graceful_load_segment(&spec.right.vox_spec.0, spec.right.vox_spec.2)
3857 };
3858 let offset = if flipped {
3859 spec.left.vox_spec.1
3860 } else {
3861 spec.right.vox_spec.1
3862 };
3863
3864 (foot_segment, Vec3::from(offset))
3865 }
3866
3867 fn mesh_left_foot(&self, foot: Option<&str>) -> BoneMeshes { self.mesh_foot(foot, true) }
3868
3869 fn mesh_right_foot(&self, foot: Option<&str>) -> BoneMeshes { self.mesh_foot(foot, false) }
3870}
3871
3872impl BipedSmallWeaponSpec {
3873 fn mesh_main(&self, tool: &ToolKey, flipped: bool) -> BoneMeshes {
3874 let spec = match self.0.get(tool) {
3875 Some(spec) => spec,
3876 None => {
3877 error!(?tool, "No tool/weapon specification exists");
3878 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
3879 },
3880 };
3881
3882 let tool_kind_segment = if flipped {
3883 graceful_load_segment_flipped(&spec.vox_spec.0, true, spec.vox_spec.2)
3884 } else {
3885 graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2)
3886 };
3887
3888 let offset = Vec3::new(
3889 if flipped {
3890 0.0 - spec.vox_spec.1[0] - (tool_kind_segment.sz.x as f32)
3891 } else {
3892 spec.vox_spec.1[0]
3893 },
3894 spec.vox_spec.1[1],
3895 spec.vox_spec.1[2],
3896 );
3897
3898 (tool_kind_segment, offset)
3899 }
3900}
3901
3902#[derive(Deserialize)]
3904struct DragonCentralSpec(HashMap<(DSpecies, DBodyType), SidedDCentralVoxSpec>);
3905impl_concatenate_for_wrapper!(DragonCentralSpec);
3906
3907#[derive(Deserialize, Default)]
3908#[serde(default)]
3909struct SidedDCentralVoxSpec {
3910 upper: DragonCentralSubSpec,
3911 lower: DragonCentralSubSpec,
3912 jaw: DragonCentralSubSpec,
3913 chest_front: DragonCentralSubSpec,
3914 chest_rear: DragonCentralSubSpec,
3915 tail_front: DragonCentralSubSpec,
3916 tail_rear: DragonCentralSubSpec,
3917}
3918#[derive(Deserialize, Default)]
3919struct DragonCentralSubSpec {
3920 offset: [f32; 3], central: VoxSimple,
3922 #[serde(default)]
3923 model_index: u32,
3924}
3925
3926#[derive(Deserialize)]
3927struct DragonLateralSpec(HashMap<(DSpecies, DBodyType), SidedDLateralVoxSpec>);
3928impl_concatenate_for_wrapper!(DragonLateralSpec);
3929
3930#[derive(Deserialize, Default)]
3931#[serde(default)]
3932struct SidedDLateralVoxSpec {
3933 wing_in_l: DragonLateralSubSpec,
3934 wing_in_r: DragonLateralSubSpec,
3935 wing_out_l: DragonLateralSubSpec,
3936 wing_out_r: DragonLateralSubSpec,
3937 foot_fl: DragonLateralSubSpec,
3938 foot_fr: DragonLateralSubSpec,
3939 foot_bl: DragonLateralSubSpec,
3940 foot_br: DragonLateralSubSpec,
3941}
3942#[derive(Deserialize, Default)]
3943struct DragonLateralSubSpec {
3944 offset: [f32; 3], lateral: VoxSimple,
3946 #[serde(default)]
3947 model_index: u32,
3948}
3949
3950make_vox_spec!(
3951 dragon::Body,
3952 struct DragonSpec {
3953 central: DragonCentralSpec = "voxygen.voxel.dragon_central_manifest",
3954 lateral: DragonLateralSpec = "voxygen.voxel.dragon_lateral_manifest",
3955 },
3956 |FigureKey { body, extra, .. }, spec| {
3957 let third_person = extra
3958 .as_ref()
3959 .and_then(|loadout| loadout.third_person.as_ref());
3960
3961 [
3962 third_person.map(|_| {
3963 spec.central
3964 .read()
3965 .0
3966 .mesh_head_upper(body.species, body.body_type)
3967 }),
3968 Some(
3969 spec.central
3970 .read()
3971 .0
3972 .mesh_head_lower(body.species, body.body_type),
3973 ),
3974 third_person.map(|_| spec.central.read().0.mesh_jaw(body.species, body.body_type)),
3975 Some(
3976 spec.central
3977 .read()
3978 .0
3979 .mesh_chest_front(body.species, body.body_type),
3980 ),
3981 Some(
3982 spec.central
3983 .read()
3984 .0
3985 .mesh_chest_rear(body.species, body.body_type),
3986 ),
3987 Some(
3988 spec.central
3989 .read()
3990 .0
3991 .mesh_tail_front(body.species, body.body_type),
3992 ),
3993 Some(
3994 spec.central
3995 .read()
3996 .0
3997 .mesh_tail_rear(body.species, body.body_type),
3998 ),
3999 Some(
4000 spec.lateral
4001 .read()
4002 .0
4003 .mesh_wing_in_l(body.species, body.body_type),
4004 ),
4005 Some(
4006 spec.lateral
4007 .read()
4008 .0
4009 .mesh_wing_in_r(body.species, body.body_type),
4010 ),
4011 Some(
4012 spec.lateral
4013 .read()
4014 .0
4015 .mesh_wing_out_l(body.species, body.body_type),
4016 ),
4017 Some(
4018 spec.lateral
4019 .read()
4020 .0
4021 .mesh_wing_out_r(body.species, body.body_type),
4022 ),
4023 Some(
4024 spec.lateral
4025 .read()
4026 .0
4027 .mesh_foot_fl(body.species, body.body_type),
4028 ),
4029 Some(
4030 spec.lateral
4031 .read()
4032 .0
4033 .mesh_foot_fr(body.species, body.body_type),
4034 ),
4035 Some(
4036 spec.lateral
4037 .read()
4038 .0
4039 .mesh_foot_bl(body.species, body.body_type),
4040 ),
4041 Some(
4042 spec.lateral
4043 .read()
4044 .0
4045 .mesh_foot_br(body.species, body.body_type),
4046 ),
4047 None,
4048 ]
4049 },
4050);
4051
4052impl DragonCentralSpec {
4053 fn mesh_head_upper(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4054 let spec = match self.0.get(&(species, body_type)) {
4055 Some(spec) => spec,
4056 None => {
4057 error!(
4058 "No upper head specification exists for the combination of {:?} and {:?}",
4059 species, body_type
4060 );
4061 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4062 },
4063 };
4064 let central = graceful_load_segment(&spec.upper.central.0, spec.upper.model_index);
4065
4066 (central, Vec3::from(spec.upper.offset))
4067 }
4068
4069 fn mesh_head_lower(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4070 let spec = match self.0.get(&(species, body_type)) {
4071 Some(spec) => spec,
4072 None => {
4073 error!(
4074 "No lower head specification exists for the combination of {:?} and {:?}",
4075 species, body_type
4076 );
4077 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4078 },
4079 };
4080 let central = graceful_load_segment(&spec.lower.central.0, spec.lower.model_index);
4081
4082 (central, Vec3::from(spec.lower.offset))
4083 }
4084
4085 fn mesh_jaw(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4086 let spec = match self.0.get(&(species, body_type)) {
4087 Some(spec) => spec,
4088 None => {
4089 error!(
4090 "No jaw specification exists for the combination of {:?} and {:?}",
4091 species, body_type
4092 );
4093 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4094 },
4095 };
4096 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
4097
4098 (central, Vec3::from(spec.jaw.offset))
4099 }
4100
4101 fn mesh_chest_front(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4102 let spec = match self.0.get(&(species, body_type)) {
4103 Some(spec) => spec,
4104 None => {
4105 error!(
4106 "No chest front specification exists for the combination of {:?} and {:?}",
4107 species, body_type
4108 );
4109 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4110 },
4111 };
4112 let central =
4113 graceful_load_segment(&spec.chest_front.central.0, spec.chest_front.model_index);
4114
4115 (central, Vec3::from(spec.chest_front.offset))
4116 }
4117
4118 fn mesh_chest_rear(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4119 let spec = match self.0.get(&(species, body_type)) {
4120 Some(spec) => spec,
4121 None => {
4122 error!(
4123 "No chest rear specification exists for the combination of {:?} and {:?}",
4124 species, body_type
4125 );
4126 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4127 },
4128 };
4129 let central =
4130 graceful_load_segment(&spec.chest_rear.central.0, spec.chest_rear.model_index);
4131
4132 (central, Vec3::from(spec.chest_rear.offset))
4133 }
4134
4135 fn mesh_tail_front(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4136 let spec = match self.0.get(&(species, body_type)) {
4137 Some(spec) => spec,
4138 None => {
4139 error!(
4140 "No tail front specification exists for the combination of {:?} and {:?}",
4141 species, body_type
4142 );
4143 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4144 },
4145 };
4146 let central =
4147 graceful_load_segment(&spec.tail_front.central.0, spec.tail_front.model_index);
4148
4149 (central, Vec3::from(spec.tail_front.offset))
4150 }
4151
4152 fn mesh_tail_rear(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4153 let spec = match self.0.get(&(species, body_type)) {
4154 Some(spec) => spec,
4155 None => {
4156 error!(
4157 "No tail rear specification exists for the combination of {:?} and {:?}",
4158 species, body_type
4159 );
4160 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4161 },
4162 };
4163 let central = graceful_load_segment(&spec.tail_rear.central.0, spec.tail_rear.model_index);
4164
4165 (central, Vec3::from(spec.tail_rear.offset))
4166 }
4167}
4168impl DragonLateralSpec {
4169 fn mesh_wing_in_l(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4170 let spec = match self.0.get(&(species, body_type)) {
4171 Some(spec) => spec,
4172 None => {
4173 error!(
4174 "No wing specification exists for the combination of {:?} and {:?}",
4175 species, body_type
4176 );
4177 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4178 },
4179 };
4180 let lateral = graceful_load_segment(&spec.wing_in_l.lateral.0, spec.wing_in_l.model_index);
4181
4182 (lateral, Vec3::from(spec.wing_in_l.offset))
4183 }
4184
4185 fn mesh_wing_in_r(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4186 let spec = match self.0.get(&(species, body_type)) {
4187 Some(spec) => spec,
4188 None => {
4189 error!(
4190 "No wing specification exists for the combination of {:?} and {:?}",
4191 species, body_type
4192 );
4193 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4194 },
4195 };
4196 let lateral = graceful_load_segment(&spec.wing_in_r.lateral.0, spec.wing_in_r.model_index);
4197
4198 (lateral, Vec3::from(spec.wing_in_r.offset))
4199 }
4200
4201 fn mesh_wing_out_l(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4202 let spec = match self.0.get(&(species, body_type)) {
4203 Some(spec) => spec,
4204 None => {
4205 error!(
4206 "No wing specification exists for the combination of {:?} and {:?}",
4207 species, body_type
4208 );
4209 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4210 },
4211 };
4212 let lateral =
4213 graceful_load_segment(&spec.wing_out_l.lateral.0, spec.wing_out_l.model_index);
4214
4215 (lateral, Vec3::from(spec.wing_out_l.offset))
4216 }
4217
4218 fn mesh_wing_out_r(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4219 let spec = match self.0.get(&(species, body_type)) {
4220 Some(spec) => spec,
4221 None => {
4222 error!(
4223 "No wing specification exists for the combination of {:?} and {:?}",
4224 species, body_type
4225 );
4226 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4227 },
4228 };
4229 let lateral =
4230 graceful_load_segment(&spec.wing_out_r.lateral.0, spec.wing_out_r.model_index);
4231
4232 (lateral, Vec3::from(spec.wing_out_r.offset))
4233 }
4234
4235 fn mesh_foot_fl(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4236 let spec = match self.0.get(&(species, body_type)) {
4237 Some(spec) => spec,
4238 None => {
4239 error!(
4240 "No foot specification exists for the combination of {:?} and {:?}",
4241 species, body_type
4242 );
4243 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4244 },
4245 };
4246 let lateral = graceful_load_segment(&spec.foot_fl.lateral.0, spec.foot_fl.model_index);
4247
4248 (lateral, Vec3::from(spec.foot_fl.offset))
4249 }
4250
4251 fn mesh_foot_fr(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4252 let spec = match self.0.get(&(species, body_type)) {
4253 Some(spec) => spec,
4254 None => {
4255 error!(
4256 "No foot specification exists for the combination of {:?} and {:?}",
4257 species, body_type
4258 );
4259 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4260 },
4261 };
4262 let lateral = graceful_load_segment(&spec.foot_fr.lateral.0, spec.foot_fr.model_index);
4263
4264 (lateral, Vec3::from(spec.foot_fr.offset))
4265 }
4266
4267 fn mesh_foot_bl(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4268 let spec = match self.0.get(&(species, body_type)) {
4269 Some(spec) => spec,
4270 None => {
4271 error!(
4272 "No foot specification exists for the combination of {:?} and {:?}",
4273 species, body_type
4274 );
4275 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4276 },
4277 };
4278 let lateral = graceful_load_segment(&spec.foot_bl.lateral.0, spec.foot_bl.model_index);
4279
4280 (lateral, Vec3::from(spec.foot_bl.offset))
4281 }
4282
4283 fn mesh_foot_br(&self, species: DSpecies, body_type: DBodyType) -> BoneMeshes {
4284 let spec = match self.0.get(&(species, body_type)) {
4285 Some(spec) => spec,
4286 None => {
4287 error!(
4288 "No foot specification exists for the combination of {:?} and {:?}",
4289 species, body_type
4290 );
4291 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4292 },
4293 };
4294 let lateral = graceful_load_segment(&spec.foot_br.lateral.0, spec.foot_br.model_index);
4295
4296 (lateral, Vec3::from(spec.foot_br.offset))
4297 }
4298}
4299
4300#[derive(Deserialize)]
4302struct BirdLargeCentralSpec(HashMap<(BLASpecies, BLABodyType), SidedBLACentralVoxSpec>);
4303impl_concatenate_for_wrapper!(BirdLargeCentralSpec);
4304
4305#[derive(Deserialize, Default)]
4306#[serde(default)]
4307struct SidedBLACentralVoxSpec {
4308 head: BirdLargeCentralSubSpec,
4309 beak: BirdLargeCentralSubSpec,
4310 neck: BirdLargeCentralSubSpec,
4311 chest: BirdLargeCentralSubSpec,
4312 tail_front: BirdLargeCentralSubSpec,
4313 tail_rear: BirdLargeCentralSubSpec,
4314}
4315
4316#[derive(Deserialize, Default)]
4317struct BirdLargeCentralSubSpec {
4318 offset: [f32; 3], central: VoxSimple,
4320 #[serde(default)]
4321 model_index: u32,
4322}
4323
4324#[derive(Deserialize)]
4325struct BirdLargeLateralSpec(HashMap<(BLASpecies, BLABodyType), SidedBLALateralVoxSpec>);
4326impl_concatenate_for_wrapper!(BirdLargeLateralSpec);
4327
4328#[derive(Deserialize, Default)]
4329#[serde(default)]
4330struct SidedBLALateralVoxSpec {
4331 wing_in_l: BirdLargeLateralSubSpec,
4332 wing_in_r: BirdLargeLateralSubSpec,
4333 wing_mid_l: BirdLargeLateralSubSpec,
4334 wing_mid_r: BirdLargeLateralSubSpec,
4335 wing_out_l: BirdLargeLateralSubSpec,
4336 wing_out_r: BirdLargeLateralSubSpec,
4337 leg_l: BirdLargeLateralSubSpec,
4338 leg_r: BirdLargeLateralSubSpec,
4339 foot_l: BirdLargeLateralSubSpec,
4340 foot_r: BirdLargeLateralSubSpec,
4341}
4342
4343#[derive(Deserialize, Default)]
4344struct BirdLargeLateralSubSpec {
4345 offset: [f32; 3], lateral: VoxSimple,
4347 #[serde(default)]
4348 model_index: u32,
4349}
4350
4351make_vox_spec!(
4352 bird_large::Body,
4353 struct BirdLargeSpec {
4354 central: BirdLargeCentralSpec = "voxygen.voxel.bird_large_central_manifest",
4355 lateral: BirdLargeLateralSpec = "voxygen.voxel.bird_large_lateral_manifest",
4356 },
4357 |FigureKey { body, extra, .. }, spec| {
4358 let third_person = extra
4359 .as_ref()
4360 .and_then(|loadout| loadout.third_person.as_ref());
4361
4362 [
4363 third_person.map(|_| {
4364 spec.central
4365 .read()
4366 .0
4367 .mesh_head(body.species, body.body_type)
4368 }),
4369 third_person.map(|_| {
4370 spec.central
4371 .read()
4372 .0
4373 .mesh_beak(body.species, body.body_type)
4374 }),
4375 Some(
4376 spec.central
4377 .read()
4378 .0
4379 .mesh_neck(body.species, body.body_type),
4380 ),
4381 Some(
4382 spec.central
4383 .read()
4384 .0
4385 .mesh_chest(body.species, body.body_type),
4386 ),
4387 Some(
4388 spec.central
4389 .read()
4390 .0
4391 .mesh_tail_front(body.species, body.body_type),
4392 ),
4393 Some(
4394 spec.central
4395 .read()
4396 .0
4397 .mesh_tail_rear(body.species, body.body_type),
4398 ),
4399 Some(
4400 spec.lateral
4401 .read()
4402 .0
4403 .mesh_wing_in_l(body.species, body.body_type),
4404 ),
4405 Some(
4406 spec.lateral
4407 .read()
4408 .0
4409 .mesh_wing_in_r(body.species, body.body_type),
4410 ),
4411 Some(
4412 spec.lateral
4413 .read()
4414 .0
4415 .mesh_wing_mid_l(body.species, body.body_type),
4416 ),
4417 Some(
4418 spec.lateral
4419 .read()
4420 .0
4421 .mesh_wing_mid_r(body.species, body.body_type),
4422 ),
4423 Some(
4424 spec.lateral
4425 .read()
4426 .0
4427 .mesh_wing_out_l(body.species, body.body_type),
4428 ),
4429 Some(
4430 spec.lateral
4431 .read()
4432 .0
4433 .mesh_wing_out_r(body.species, body.body_type),
4434 ),
4435 Some(
4436 spec.lateral
4437 .read()
4438 .0
4439 .mesh_leg_l(body.species, body.body_type),
4440 ),
4441 Some(
4442 spec.lateral
4443 .read()
4444 .0
4445 .mesh_leg_r(body.species, body.body_type),
4446 ),
4447 Some(
4448 spec.lateral
4449 .read()
4450 .0
4451 .mesh_foot_l(body.species, body.body_type),
4452 ),
4453 Some(
4454 spec.lateral
4455 .read()
4456 .0
4457 .mesh_foot_r(body.species, body.body_type),
4458 ),
4459 ]
4460 },
4461);
4462
4463impl BirdLargeCentralSpec {
4464 fn mesh_head(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4465 let spec = match self.0.get(&(species, body_type)) {
4466 Some(spec) => spec,
4467 None => {
4468 error!(
4469 "No head specification exists for the combination of {:?} and {:?}",
4470 species, body_type
4471 );
4472 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4473 },
4474 };
4475 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
4476
4477 (central, Vec3::from(spec.head.offset))
4478 }
4479
4480 fn mesh_beak(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4481 let spec = match self.0.get(&(species, body_type)) {
4482 Some(spec) => spec,
4483 None => {
4484 error!(
4485 "No beak specification exists for the combination of {:?} and {:?}",
4486 species, body_type
4487 );
4488 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4489 },
4490 };
4491 let central = graceful_load_segment(&spec.beak.central.0, spec.beak.model_index);
4492
4493 (central, Vec3::from(spec.beak.offset))
4494 }
4495
4496 fn mesh_neck(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4497 let spec = match self.0.get(&(species, body_type)) {
4498 Some(spec) => spec,
4499 None => {
4500 error!(
4501 "No neck specification exists for the combination of {:?} and {:?}",
4502 species, body_type
4503 );
4504 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4505 },
4506 };
4507 let central = graceful_load_segment(&spec.neck.central.0, spec.neck.model_index);
4508
4509 (central, Vec3::from(spec.neck.offset))
4510 }
4511
4512 fn mesh_chest(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4513 let spec = match self.0.get(&(species, body_type)) {
4514 Some(spec) => spec,
4515 None => {
4516 error!(
4517 "No chest specification exists for the combination of {:?} and {:?}",
4518 species, body_type
4519 );
4520 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4521 },
4522 };
4523 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
4524
4525 (central, Vec3::from(spec.chest.offset))
4526 }
4527
4528 fn mesh_tail_front(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4529 let spec = match self.0.get(&(species, body_type)) {
4530 Some(spec) => spec,
4531 None => {
4532 error!(
4533 "No tail front specification exists for the combination of {:?} and {:?}",
4534 species, body_type
4535 );
4536 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4537 },
4538 };
4539 let central =
4540 graceful_load_segment(&spec.tail_front.central.0, spec.tail_front.model_index);
4541
4542 (central, Vec3::from(spec.tail_front.offset))
4543 }
4544
4545 fn mesh_tail_rear(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4546 let spec = match self.0.get(&(species, body_type)) {
4547 Some(spec) => spec,
4548 None => {
4549 error!(
4550 "No tail rear specification exists for the combination of {:?} and {:?}",
4551 species, body_type
4552 );
4553 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4554 },
4555 };
4556 let central = graceful_load_segment(&spec.tail_rear.central.0, spec.tail_rear.model_index);
4557
4558 (central, Vec3::from(spec.tail_rear.offset))
4559 }
4560}
4561impl BirdLargeLateralSpec {
4562 fn mesh_wing_in_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4563 let spec = match self.0.get(&(species, body_type)) {
4564 Some(spec) => spec,
4565 None => {
4566 error!(
4567 "No wing in in left specification exists for the combination of {:?} and {:?}",
4568 species, body_type
4569 );
4570 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4571 },
4572 };
4573 let lateral = graceful_load_segment_flipped(
4574 &spec.wing_in_l.lateral.0,
4575 true,
4576 spec.wing_in_l.model_index,
4577 );
4578
4579 (lateral, Vec3::from(spec.wing_in_l.offset))
4580 }
4581
4582 fn mesh_wing_in_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4583 let spec = match self.0.get(&(species, body_type)) {
4584 Some(spec) => spec,
4585 None => {
4586 error!(
4587 "No wing in right specification exists for the combination of {:?} and {:?}",
4588 species, body_type
4589 );
4590 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4591 },
4592 };
4593 let lateral = graceful_load_segment(&spec.wing_in_r.lateral.0, spec.wing_in_r.model_index);
4594
4595 (lateral, Vec3::from(spec.wing_in_r.offset))
4596 }
4597
4598 fn mesh_wing_mid_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4599 let spec = match self.0.get(&(species, body_type)) {
4600 Some(spec) => spec,
4601 None => {
4602 error!(
4603 "No wing mid specification exists for the combination of {:?} and {:?}",
4604 species, body_type
4605 );
4606 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4607 },
4608 };
4609 let lateral = graceful_load_segment_flipped(
4610 &spec.wing_mid_l.lateral.0,
4611 true,
4612 spec.wing_mid_l.model_index,
4613 );
4614
4615 (lateral, Vec3::from(spec.wing_mid_l.offset))
4616 }
4617
4618 fn mesh_wing_mid_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4619 let spec = match self.0.get(&(species, body_type)) {
4620 Some(spec) => spec,
4621 None => {
4622 error!(
4623 "No wing mid specification exists for the combination of {:?} and {:?}",
4624 species, body_type
4625 );
4626 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4627 },
4628 };
4629 let lateral =
4630 graceful_load_segment(&spec.wing_mid_r.lateral.0, spec.wing_mid_r.model_index);
4631
4632 (lateral, Vec3::from(spec.wing_mid_r.offset))
4633 }
4634
4635 fn mesh_wing_out_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4636 let spec = match self.0.get(&(species, body_type)) {
4637 Some(spec) => spec,
4638 None => {
4639 error!(
4640 "No wing out specification exists for the combination of {:?} and {:?}",
4641 species, body_type
4642 );
4643 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4644 },
4645 };
4646 let lateral = graceful_load_segment_flipped(
4647 &spec.wing_out_l.lateral.0,
4648 true,
4649 spec.wing_out_l.model_index,
4650 );
4651
4652 (lateral, Vec3::from(spec.wing_out_l.offset))
4653 }
4654
4655 fn mesh_wing_out_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4656 let spec = match self.0.get(&(species, body_type)) {
4657 Some(spec) => spec,
4658 None => {
4659 error!(
4660 "No wing out specification exists for the combination of {:?} and {:?}",
4661 species, body_type
4662 );
4663 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4664 },
4665 };
4666 let lateral =
4667 graceful_load_segment(&spec.wing_out_r.lateral.0, spec.wing_out_r.model_index);
4668
4669 (lateral, Vec3::from(spec.wing_out_r.offset))
4670 }
4671
4672 fn mesh_leg_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4673 let spec = match self.0.get(&(species, body_type)) {
4674 Some(spec) => spec,
4675 None => {
4676 error!(
4677 "No leg specification exists for the combination of {:?} and {:?}",
4678 species, body_type
4679 );
4680 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4681 },
4682 };
4683 let lateral =
4684 graceful_load_segment_flipped(&spec.leg_l.lateral.0, true, spec.leg_l.model_index);
4685
4686 (lateral, Vec3::from(spec.leg_l.offset))
4687 }
4688
4689 fn mesh_leg_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4690 let spec = match self.0.get(&(species, body_type)) {
4691 Some(spec) => spec,
4692 None => {
4693 error!(
4694 "No leg specification exists for the combination of {:?} and {:?}",
4695 species, body_type
4696 );
4697 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4698 },
4699 };
4700 let lateral = graceful_load_segment(&spec.leg_r.lateral.0, spec.leg_r.model_index);
4701
4702 (lateral, Vec3::from(spec.leg_r.offset))
4703 }
4704
4705 fn mesh_foot_l(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4706 let spec = match self.0.get(&(species, body_type)) {
4707 Some(spec) => spec,
4708 None => {
4709 error!(
4710 "No foot specification exists for the combination of {:?} and {:?}",
4711 species, body_type
4712 );
4713 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4714 },
4715 };
4716 let lateral =
4717 graceful_load_segment_flipped(&spec.foot_l.lateral.0, true, spec.foot_l.model_index);
4718
4719 (lateral, Vec3::from(spec.foot_l.offset))
4720 }
4721
4722 fn mesh_foot_r(&self, species: BLASpecies, body_type: BLABodyType) -> BoneMeshes {
4723 let spec = match self.0.get(&(species, body_type)) {
4724 Some(spec) => spec,
4725 None => {
4726 error!(
4727 "No foot specification exists for the combination of {:?} and {:?}",
4728 species, body_type
4729 );
4730 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4731 },
4732 };
4733 let lateral = graceful_load_segment(&spec.foot_r.lateral.0, spec.foot_r.model_index);
4734
4735 (lateral, Vec3::from(spec.foot_r.offset))
4736 }
4737}
4738
4739#[derive(Deserialize)]
4741struct BipedLargeCentralSpec(HashMap<(BLSpecies, BLBodyType), SidedBLCentralVoxSpec>);
4742impl_concatenate_for_wrapper!(BipedLargeCentralSpec);
4743
4744#[derive(Deserialize, Default)]
4745#[serde(default)]
4746struct SidedBLCentralVoxSpec {
4747 head: BipedLargeCentralSubSpec,
4748 jaw: BipedLargeCentralSubSpec,
4749 torso_upper: BipedLargeCentralSubSpec,
4750 torso_lower: BipedLargeCentralSubSpec,
4751 tail: BipedLargeCentralSubSpec,
4752}
4753#[derive(Deserialize, Default)]
4754struct BipedLargeCentralSubSpec {
4755 offset: [f32; 3], central: VoxSimple,
4757 #[serde(default)]
4758 model_index: u32,
4759}
4760
4761#[derive(Deserialize)]
4762struct BipedLargeLateralSpec(HashMap<(BLSpecies, BLBodyType), SidedBLLateralVoxSpec>);
4763impl_concatenate_for_wrapper!(BipedLargeLateralSpec);
4764
4765#[derive(Deserialize, Default)]
4766#[serde(default)]
4767struct SidedBLLateralVoxSpec {
4768 shoulder_l: BipedLargeLateralSubSpec,
4769 shoulder_r: BipedLargeLateralSubSpec,
4770 hand_l: BipedLargeLateralSubSpec,
4771 hand_r: BipedLargeLateralSubSpec,
4772 leg_l: BipedLargeLateralSubSpec,
4773 leg_r: BipedLargeLateralSubSpec,
4774 foot_l: BipedLargeLateralSubSpec,
4775 foot_r: BipedLargeLateralSubSpec,
4776}
4777
4778#[derive(Deserialize, Default)]
4779struct BipedLargeLateralSubSpec {
4780 offset: [f32; 3], lateral: VoxSimple,
4782 #[serde(default)]
4783 model_index: u32,
4784}
4785
4786#[derive(Deserialize)]
4787struct BipedLargeMainSpec(HashMap<ToolKey, ArmorVoxSpec>);
4788impl_concatenate_for_wrapper!(BipedLargeMainSpec);
4789
4790#[derive(Deserialize)]
4791struct BipedLargeSecondSpec(HashMap<ToolKey, ArmorVoxSpec>);
4792impl_concatenate_for_wrapper!(BipedLargeSecondSpec);
4793
4794make_vox_spec!(
4795 biped_large::Body,
4796 struct BipedLargeSpec {
4797 central: BipedLargeCentralSpec = "voxygen.voxel.biped_large_central_manifest",
4798 lateral: BipedLargeLateralSpec = "voxygen.voxel.biped_large_lateral_manifest",
4799 main: BipedLargeMainSpec = "voxygen.voxel.biped_weapon_manifest",
4800 second: BipedLargeSecondSpec = "voxygen.voxel.biped_weapon_manifest",
4801 },
4802 |FigureKey {
4803 body,
4804 item_key: _,
4805 extra,
4806 },
4807 spec| {
4808 const DEFAULT_LOADOUT: super::cache::CharacterCacheKey = super::cache::CharacterCacheKey {
4809 third_person: None,
4810 tool: None,
4811 lantern: None,
4812 glider: None,
4813 hand: None,
4814 foot: None,
4815 head: None,
4816 };
4817
4818 let loadout = extra.as_deref().unwrap_or(&DEFAULT_LOADOUT);
4820 let third_person = loadout.third_person.as_ref();
4821
4822 let tool = loadout.tool.as_ref();
4824 [
4825 third_person.map(|_| {
4826 spec.central
4827 .read()
4828 .0
4829 .mesh_head(body.species, body.body_type)
4830 }),
4831 third_person.map(|_| spec.central.read().0.mesh_jaw(body.species, body.body_type)),
4832 third_person.map(|_| {
4833 spec.central
4834 .read()
4835 .0
4836 .mesh_torso_upper(body.species, body.body_type)
4837 }),
4838 Some(
4839 spec.central
4840 .read()
4841 .0
4842 .mesh_torso_lower(body.species, body.body_type),
4843 ),
4844 Some(
4845 spec.central
4846 .read()
4847 .0
4848 .mesh_tail(body.species, body.body_type),
4849 ),
4850 tool.and_then(|tool| tool.active.as_ref())
4851 .map(|tool| spec.main.read().0.mesh_main(tool, false)),
4852 tool.and_then(|tool| tool.active.as_ref())
4853 .map(|tool| spec.second.read().0.mesh_second(tool, false)),
4854 Some(
4855 spec.lateral
4856 .read()
4857 .0
4858 .mesh_shoulder_l(body.species, body.body_type),
4859 ),
4860 Some(
4861 spec.lateral
4862 .read()
4863 .0
4864 .mesh_shoulder_r(body.species, body.body_type),
4865 ),
4866 Some(
4867 spec.lateral
4868 .read()
4869 .0
4870 .mesh_hand_l(body.species, body.body_type),
4871 ),
4872 Some(
4873 spec.lateral
4874 .read()
4875 .0
4876 .mesh_hand_r(body.species, body.body_type),
4877 ),
4878 Some(
4879 spec.lateral
4880 .read()
4881 .0
4882 .mesh_leg_l(body.species, body.body_type),
4883 ),
4884 Some(
4885 spec.lateral
4886 .read()
4887 .0
4888 .mesh_leg_r(body.species, body.body_type),
4889 ),
4890 Some(
4891 spec.lateral
4892 .read()
4893 .0
4894 .mesh_foot_l(body.species, body.body_type),
4895 ),
4896 Some(
4897 spec.lateral
4898 .read()
4899 .0
4900 .mesh_foot_r(body.species, body.body_type),
4901 ),
4902 Some(mesh_hold()),
4903 ]
4904 },
4905);
4906
4907impl BipedLargeCentralSpec {
4908 fn mesh_head(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
4909 let spec = match self.0.get(&(species, body_type)) {
4910 Some(spec) => spec,
4911 None => {
4912 error!(
4913 "No head specification exists for the combination of {:?} and {:?}",
4914 species, body_type
4915 );
4916 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4917 },
4918 };
4919 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
4920
4921 (central, Vec3::from(spec.head.offset))
4922 }
4923
4924 fn mesh_jaw(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
4925 let spec = match self.0.get(&(species, body_type)) {
4926 Some(spec) => spec,
4927 None => {
4928 error!(
4929 "No jaw specification exists for the combination of {:?} and {:?}",
4930 species, body_type
4931 );
4932 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4933 },
4934 };
4935 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
4936
4937 (central, Vec3::from(spec.jaw.offset))
4938 }
4939
4940 fn mesh_torso_upper(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
4941 let spec = match self.0.get(&(species, body_type)) {
4942 Some(spec) => spec,
4943 None => {
4944 error!(
4945 "No torso upper specification exists for the combination of {:?} and {:?}",
4946 species, body_type
4947 );
4948 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4949 },
4950 };
4951 let central =
4952 graceful_load_segment(&spec.torso_upper.central.0, spec.torso_upper.model_index);
4953
4954 (central, Vec3::from(spec.torso_upper.offset))
4955 }
4956
4957 fn mesh_torso_lower(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
4958 let spec = match self.0.get(&(species, body_type)) {
4959 Some(spec) => spec,
4960 None => {
4961 error!(
4962 "No torso lower specification exists for the combination of {:?} and {:?}",
4963 species, body_type
4964 );
4965 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4966 },
4967 };
4968 let central =
4969 graceful_load_segment(&spec.torso_lower.central.0, spec.torso_lower.model_index);
4970
4971 (central, Vec3::from(spec.torso_lower.offset))
4972 }
4973
4974 fn mesh_tail(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
4975 let spec = match self.0.get(&(species, body_type)) {
4976 Some(spec) => spec,
4977 None => {
4978 error!(
4979 "No tail specification exists for the combination of {:?} and {:?}",
4980 species, body_type
4981 );
4982 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
4983 },
4984 };
4985 let central = graceful_load_segment(&spec.tail.central.0, spec.tail.model_index);
4986
4987 (central, Vec3::from(spec.tail.offset))
4988 }
4989}
4990impl BipedLargeLateralSpec {
4991 fn mesh_shoulder_l(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
4992 let spec = match self.0.get(&(species, body_type)) {
4993 Some(spec) => spec,
4994 None => {
4995 error!(
4996 "No shoulder specification exists for the combination of {:?} and {:?}",
4997 species, body_type
4998 );
4999 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5000 },
5001 };
5002 let lateral =
5003 graceful_load_segment(&spec.shoulder_l.lateral.0, spec.shoulder_l.model_index);
5004
5005 (lateral, Vec3::from(spec.shoulder_l.offset))
5006 }
5007
5008 fn mesh_shoulder_r(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5009 let spec = match self.0.get(&(species, body_type)) {
5010 Some(spec) => spec,
5011 None => {
5012 error!(
5013 "No shoulder specification exists for the combination of {:?} and {:?}",
5014 species, body_type
5015 );
5016 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5017 },
5018 };
5019 let lateral =
5020 graceful_load_segment(&spec.shoulder_r.lateral.0, spec.shoulder_r.model_index);
5021
5022 (lateral, Vec3::from(spec.shoulder_r.offset))
5023 }
5024
5025 fn mesh_hand_l(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5026 let spec = match self.0.get(&(species, body_type)) {
5027 Some(spec) => spec,
5028 None => {
5029 error!(
5030 "No hand specification exists for the combination of {:?} and {:?}",
5031 species, body_type
5032 );
5033 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5034 },
5035 };
5036 let lateral = graceful_load_segment(&spec.hand_l.lateral.0, spec.hand_l.model_index);
5037
5038 (lateral, Vec3::from(spec.hand_l.offset))
5039 }
5040
5041 fn mesh_hand_r(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5042 let spec = match self.0.get(&(species, body_type)) {
5043 Some(spec) => spec,
5044 None => {
5045 error!(
5046 "No hand specification exists for the combination of {:?} and {:?}",
5047 species, body_type
5048 );
5049 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5050 },
5051 };
5052 let lateral = graceful_load_segment(&spec.hand_r.lateral.0, spec.hand_r.model_index);
5053
5054 (lateral, Vec3::from(spec.hand_r.offset))
5055 }
5056
5057 fn mesh_leg_l(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5058 let spec = match self.0.get(&(species, body_type)) {
5059 Some(spec) => spec,
5060 None => {
5061 error!(
5062 "No leg specification exists for the combination of {:?} and {:?}",
5063 species, body_type
5064 );
5065 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5066 },
5067 };
5068 let lateral = graceful_load_segment(&spec.leg_l.lateral.0, spec.leg_l.model_index);
5069
5070 (lateral, Vec3::from(spec.leg_l.offset))
5071 }
5072
5073 fn mesh_leg_r(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5074 let spec = match self.0.get(&(species, body_type)) {
5075 Some(spec) => spec,
5076 None => {
5077 error!(
5078 "No leg specification exists for the combination of {:?} and {:?}",
5079 species, body_type
5080 );
5081 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5082 },
5083 };
5084 let lateral = graceful_load_segment(&spec.leg_r.lateral.0, spec.leg_r.model_index);
5085
5086 (lateral, Vec3::from(spec.leg_r.offset))
5087 }
5088
5089 fn mesh_foot_l(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5090 let spec = match self.0.get(&(species, body_type)) {
5091 Some(spec) => spec,
5092 None => {
5093 error!(
5094 "No foot specification exists for the combination of {:?} and {:?}",
5095 species, body_type
5096 );
5097 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5098 },
5099 };
5100 let lateral = graceful_load_segment(&spec.foot_l.lateral.0, spec.foot_l.model_index);
5101
5102 (lateral, Vec3::from(spec.foot_l.offset))
5103 }
5104
5105 fn mesh_foot_r(&self, species: BLSpecies, body_type: BLBodyType) -> BoneMeshes {
5106 let spec = match self.0.get(&(species, body_type)) {
5107 Some(spec) => spec,
5108 None => {
5109 error!(
5110 "No foot specification exists for the combination of {:?} and {:?}",
5111 species, body_type
5112 );
5113 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5114 },
5115 };
5116 let lateral = graceful_load_segment(&spec.foot_r.lateral.0, spec.foot_r.model_index);
5117
5118 (lateral, Vec3::from(spec.foot_r.offset))
5119 }
5120}
5121impl BipedLargeMainSpec {
5122 fn mesh_main(&self, tool: &ToolKey, flipped: bool) -> BoneMeshes {
5123 let spec = match self.0.get(tool) {
5124 Some(spec) => spec,
5125 None => {
5126 error!(?tool, "No tool/weapon specification exists");
5127 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
5128 },
5129 };
5130
5131 let tool_kind_segment = if flipped {
5132 graceful_load_segment_flipped(&spec.vox_spec.0, true, spec.vox_spec.2)
5133 } else {
5134 graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2)
5135 };
5136
5137 let offset = Vec3::new(
5138 if flipped {
5139 0.0 - spec.vox_spec.1[0] - (tool_kind_segment.sz.x as f32)
5140 } else {
5141 spec.vox_spec.1[0]
5142 },
5143 spec.vox_spec.1[1],
5144 spec.vox_spec.1[2],
5145 );
5146
5147 (tool_kind_segment, offset)
5148 }
5149}
5150impl BipedLargeSecondSpec {
5151 fn mesh_second(&self, tool: &ToolKey, flipped: bool) -> BoneMeshes {
5152 let spec = match self.0.get(tool) {
5153 Some(spec) => spec,
5154 None => {
5155 error!(?tool, "No tool/weapon specification exists");
5156 return load_mesh("not_found", Vec3::new(-1.5, -1.5, -7.0));
5157 },
5158 };
5159
5160 let tool_kind_segment = if flipped {
5161 graceful_load_segment_flipped(&spec.vox_spec.0, true, spec.vox_spec.2)
5162 } else {
5163 graceful_load_segment(&spec.vox_spec.0, spec.vox_spec.2)
5164 };
5165
5166 let offset = Vec3::new(
5167 if flipped {
5168 0.0 - spec.vox_spec.1[0] - (tool_kind_segment.sz.x as f32)
5169 } else {
5170 spec.vox_spec.1[0]
5171 },
5172 spec.vox_spec.1[1],
5173 spec.vox_spec.1[2],
5174 );
5175
5176 (tool_kind_segment, offset)
5177 }
5178}
5179
5180#[derive(Deserialize)]
5182struct GolemCentralSpec(HashMap<(GSpecies, GBodyType), SidedGCentralVoxSpec>);
5183impl_concatenate_for_wrapper!(GolemCentralSpec);
5184
5185#[derive(Deserialize, Default)]
5186#[serde(default)]
5187struct SidedGCentralVoxSpec {
5188 head: GolemCentralSubSpec,
5189 jaw: GolemCentralSubSpec,
5190 torso_upper: GolemCentralSubSpec,
5191 torso_lower: GolemCentralSubSpec,
5192}
5193
5194#[derive(Deserialize, Default)]
5195struct GolemCentralSubSpec {
5196 offset: [f32; 3], central: VoxSimple,
5198 #[serde(default)]
5199 model_index: u32,
5200}
5201
5202#[derive(Deserialize)]
5203struct GolemLateralSpec(HashMap<(GSpecies, GBodyType), SidedGLateralVoxSpec>);
5204impl_concatenate_for_wrapper!(GolemLateralSpec);
5205
5206#[derive(Deserialize, Default)]
5207#[serde(default)]
5208struct SidedGLateralVoxSpec {
5209 shoulder_l: GolemLateralSubSpec,
5210 shoulder_r: GolemLateralSubSpec,
5211 hand_l: GolemLateralSubSpec,
5212 hand_r: GolemLateralSubSpec,
5213 leg_l: GolemLateralSubSpec,
5214 leg_r: GolemLateralSubSpec,
5215 foot_l: GolemLateralSubSpec,
5216 foot_r: GolemLateralSubSpec,
5217}
5218
5219#[derive(Deserialize, Default)]
5220struct GolemLateralSubSpec {
5221 offset: [f32; 3], lateral: VoxSimple,
5223 #[serde(default)]
5224 model_index: u32,
5225}
5226
5227make_vox_spec!(
5228 golem::Body,
5229 struct GolemSpec {
5230 central: GolemCentralSpec = "voxygen.voxel.golem_central_manifest",
5231 lateral: GolemLateralSpec = "voxygen.voxel.golem_lateral_manifest",
5232 },
5233 |FigureKey { body, extra, .. }, spec| {
5234 let third_person = extra
5235 .as_ref()
5236 .and_then(|loadout| loadout.third_person.as_ref());
5237
5238 [
5239 third_person.map(|_| {
5240 spec.central
5241 .read()
5242 .0
5243 .mesh_head(body.species, body.body_type)
5244 }),
5245 third_person.map(|_| spec.central.read().0.mesh_jaw(body.species, body.body_type)),
5246 Some(
5247 spec.central
5248 .read()
5249 .0
5250 .mesh_torso_upper(body.species, body.body_type),
5251 ),
5252 Some(
5253 spec.central
5254 .read()
5255 .0
5256 .mesh_torso_lower(body.species, body.body_type),
5257 ),
5258 Some(
5259 spec.lateral
5260 .read()
5261 .0
5262 .mesh_shoulder_l(body.species, body.body_type),
5263 ),
5264 Some(
5265 spec.lateral
5266 .read()
5267 .0
5268 .mesh_shoulder_r(body.species, body.body_type),
5269 ),
5270 Some(
5271 spec.lateral
5272 .read()
5273 .0
5274 .mesh_hand_l(body.species, body.body_type),
5275 ),
5276 Some(
5277 spec.lateral
5278 .read()
5279 .0
5280 .mesh_hand_r(body.species, body.body_type),
5281 ),
5282 Some(
5283 spec.lateral
5284 .read()
5285 .0
5286 .mesh_leg_l(body.species, body.body_type),
5287 ),
5288 Some(
5289 spec.lateral
5290 .read()
5291 .0
5292 .mesh_leg_r(body.species, body.body_type),
5293 ),
5294 Some(
5295 spec.lateral
5296 .read()
5297 .0
5298 .mesh_foot_l(body.species, body.body_type),
5299 ),
5300 Some(
5301 spec.lateral
5302 .read()
5303 .0
5304 .mesh_foot_r(body.species, body.body_type),
5305 ),
5306 None,
5307 None,
5308 None,
5309 None,
5310 ]
5311 },
5312);
5313
5314impl GolemCentralSpec {
5315 fn mesh_head(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5316 let spec = match self.0.get(&(species, body_type)) {
5317 Some(spec) => spec,
5318 None => {
5319 error!(
5320 "No head specification exists for the combination of {:?} and {:?}",
5321 species, body_type
5322 );
5323 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5324 },
5325 };
5326 let central = graceful_load_segment(&spec.head.central.0, spec.head.model_index);
5327
5328 (central, Vec3::from(spec.head.offset))
5329 }
5330
5331 fn mesh_jaw(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5332 let spec = match self.0.get(&(species, body_type)) {
5333 Some(spec) => spec,
5334 None => {
5335 error!(
5336 "No jaw specification exists for the combination of {:?} and {:?}",
5337 species, body_type
5338 );
5339 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5340 },
5341 };
5342 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
5343
5344 (central, Vec3::from(spec.jaw.offset))
5345 }
5346
5347 fn mesh_torso_upper(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5348 let spec = match self.0.get(&(species, body_type)) {
5349 Some(spec) => spec,
5350 None => {
5351 error!(
5352 "No torso upper specification exists for the combination of {:?} and {:?}",
5353 species, body_type
5354 );
5355 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5356 },
5357 };
5358 let central =
5359 graceful_load_segment(&spec.torso_upper.central.0, spec.torso_upper.model_index);
5360
5361 (central, Vec3::from(spec.torso_upper.offset))
5362 }
5363
5364 pub fn mesh_torso_lower(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5365 let spec = match self.0.get(&(species, body_type)) {
5366 Some(spec) => spec,
5367 None => {
5368 error!(
5369 "No torso lower specification exists for the combination of {:?} and {:?}",
5370 species, body_type
5371 );
5372 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5373 },
5374 };
5375 let central =
5376 graceful_load_segment(&spec.torso_lower.central.0, spec.torso_lower.model_index);
5377
5378 (central, Vec3::from(spec.torso_lower.offset))
5379 }
5380}
5381impl GolemLateralSpec {
5382 fn mesh_shoulder_l(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5383 let spec = match self.0.get(&(species, body_type)) {
5384 Some(spec) => spec,
5385 None => {
5386 error!(
5387 "No shoulder specification exists for the combination of {:?} and {:?}",
5388 species, body_type
5389 );
5390 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5391 },
5392 };
5393 let lateral =
5394 graceful_load_segment(&spec.shoulder_l.lateral.0, spec.shoulder_l.model_index);
5395
5396 (lateral, Vec3::from(spec.shoulder_l.offset))
5397 }
5398
5399 fn mesh_shoulder_r(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5400 let spec = match self.0.get(&(species, body_type)) {
5401 Some(spec) => spec,
5402 None => {
5403 error!(
5404 "No shoulder specification exists for the combination of {:?} and {:?}",
5405 species, body_type
5406 );
5407 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5408 },
5409 };
5410 let lateral =
5411 graceful_load_segment(&spec.shoulder_r.lateral.0, spec.shoulder_r.model_index);
5412
5413 (lateral, Vec3::from(spec.shoulder_r.offset))
5414 }
5415
5416 fn mesh_hand_l(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5417 let spec = match self.0.get(&(species, body_type)) {
5418 Some(spec) => spec,
5419 None => {
5420 error!(
5421 "No hand specification exists for the combination of {:?} and {:?}",
5422 species, body_type
5423 );
5424 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5425 },
5426 };
5427 let lateral = graceful_load_segment(&spec.hand_l.lateral.0, spec.hand_l.model_index);
5428
5429 (lateral, Vec3::from(spec.hand_l.offset))
5430 }
5431
5432 fn mesh_hand_r(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5433 let spec = match self.0.get(&(species, body_type)) {
5434 Some(spec) => spec,
5435 None => {
5436 error!(
5437 "No hand specification exists for the combination of {:?} and {:?}",
5438 species, body_type
5439 );
5440 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5441 },
5442 };
5443 let lateral = graceful_load_segment(&spec.hand_r.lateral.0, spec.hand_r.model_index);
5444
5445 (lateral, Vec3::from(spec.hand_r.offset))
5446 }
5447
5448 fn mesh_leg_l(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5449 let spec = match self.0.get(&(species, body_type)) {
5450 Some(spec) => spec,
5451 None => {
5452 error!(
5453 "No leg specification exists for the combination of {:?} and {:?}",
5454 species, body_type
5455 );
5456 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5457 },
5458 };
5459 let lateral = graceful_load_segment(&spec.leg_l.lateral.0, spec.leg_l.model_index);
5460
5461 (lateral, Vec3::from(spec.leg_l.offset))
5462 }
5463
5464 fn mesh_leg_r(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5465 let spec = match self.0.get(&(species, body_type)) {
5466 Some(spec) => spec,
5467 None => {
5468 error!(
5469 "No leg specification exists for the combination of {:?} and {:?}",
5470 species, body_type
5471 );
5472 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5473 },
5474 };
5475 let lateral = graceful_load_segment(&spec.leg_r.lateral.0, spec.leg_r.model_index);
5476
5477 (lateral, Vec3::from(spec.leg_r.offset))
5478 }
5479
5480 fn mesh_foot_l(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5481 let spec = match self.0.get(&(species, body_type)) {
5482 Some(spec) => spec,
5483 None => {
5484 error!(
5485 "No foot specification exists for the combination of {:?} and {:?}",
5486 species, body_type
5487 );
5488 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5489 },
5490 };
5491 let lateral = graceful_load_segment(&spec.foot_l.lateral.0, spec.foot_l.model_index);
5492
5493 (lateral, Vec3::from(spec.foot_l.offset))
5494 }
5495
5496 fn mesh_foot_r(&self, species: GSpecies, body_type: GBodyType) -> BoneMeshes {
5497 let spec = match self.0.get(&(species, body_type)) {
5498 Some(spec) => spec,
5499 None => {
5500 error!(
5501 "No foot specification exists for the combination of {:?} and {:?}",
5502 species, body_type
5503 );
5504 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5505 },
5506 };
5507 let lateral = graceful_load_segment(&spec.foot_r.lateral.0, spec.foot_r.model_index);
5508
5509 (lateral, Vec3::from(spec.foot_r.offset))
5510 }
5511}
5512
5513#[derive(Deserialize)]
5515struct QuadrupedLowCentralSpec(HashMap<(QLSpecies, QLBodyType), SidedQLCentralVoxSpec>);
5516impl_concatenate_for_wrapper!(QuadrupedLowCentralSpec);
5517
5518#[derive(Deserialize, Default)]
5519#[serde(default)]
5520struct SidedQLCentralVoxSpec {
5521 upper: QuadrupedLowCentralSubSpec,
5522 lower: QuadrupedLowCentralSubSpec,
5523 jaw: QuadrupedLowCentralSubSpec,
5524 chest: QuadrupedLowCentralSubSpec,
5525 tail_front: QuadrupedLowCentralSubSpec,
5526 tail_rear: QuadrupedLowCentralSubSpec,
5527}
5528
5529#[derive(Deserialize, Default)]
5530struct QuadrupedLowCentralSubSpec {
5531 offset: [f32; 3], central: VoxSimple,
5533 #[serde(default)]
5534 model_index: u32,
5535}
5536
5537#[derive(Deserialize)]
5538struct QuadrupedLowLateralSpec(HashMap<(QLSpecies, QLBodyType), SidedQLLateralVoxSpec>);
5539impl_concatenate_for_wrapper!(QuadrupedLowLateralSpec);
5540
5541#[derive(Deserialize, Default)]
5542#[serde(default)]
5543struct SidedQLLateralVoxSpec {
5544 left_upper: QuadrupedLowLateralSubSpec,
5545 left_lower: QuadrupedLowLateralSubSpec,
5546 left_jaw: QuadrupedLowLateralSubSpec,
5547 right_upper: QuadrupedLowLateralSubSpec,
5548 right_lower: QuadrupedLowLateralSubSpec,
5549 right_jaw: QuadrupedLowLateralSubSpec,
5550 front_left: QuadrupedLowLateralSubSpec,
5551 front_right: QuadrupedLowLateralSubSpec,
5552 back_left: QuadrupedLowLateralSubSpec,
5553 back_right: QuadrupedLowLateralSubSpec,
5554}
5555#[derive(Deserialize, Default)]
5556struct QuadrupedLowLateralSubSpec {
5557 offset: [f32; 3], lateral: VoxMirror,
5559 #[serde(default)]
5560 model_index: u32,
5561}
5562
5563make_vox_spec!(
5564 quadruped_low::Body,
5565 struct QuadrupedLowSpec {
5566 central: QuadrupedLowCentralSpec = "voxygen.voxel.quadruped_low_central_manifest",
5567 lateral: QuadrupedLowLateralSpec = "voxygen.voxel.quadruped_low_lateral_manifest",
5568 },
5569 |FigureKey { body, extra, .. }, spec| {
5570 let third_person = extra
5571 .as_ref()
5572 .and_then(|loadout| loadout.third_person.as_ref());
5573
5574 [
5575 third_person.map(|_| {
5576 spec.central
5577 .read()
5578 .0
5579 .mesh_head_upper(body.species, body.body_type)
5580 }),
5581 third_person.map(|_| {
5582 spec.central
5583 .read()
5584 .0
5585 .mesh_head_lower(body.species, body.body_type)
5586 }),
5587 third_person.map(|_| spec.central.read().0.mesh_jaw(body.species, body.body_type)),
5588 Some(
5589 spec.lateral
5590 .read()
5591 .0
5592 .mesh_left_head_upper(body.species, body.body_type),
5593 ),
5594 Some(
5595 spec.lateral
5596 .read()
5597 .0
5598 .mesh_left_head_lower(body.species, body.body_type),
5599 ),
5600 Some(
5601 spec.lateral
5602 .read()
5603 .0
5604 .mesh_left_jaw(body.species, body.body_type),
5605 ),
5606 Some(
5607 spec.lateral
5608 .read()
5609 .0
5610 .mesh_right_head_upper(body.species, body.body_type),
5611 ),
5612 Some(
5613 spec.lateral
5614 .read()
5615 .0
5616 .mesh_right_head_lower(body.species, body.body_type),
5617 ),
5618 Some(
5619 spec.lateral
5620 .read()
5621 .0
5622 .mesh_right_jaw(body.species, body.body_type),
5623 ),
5624 Some(
5625 spec.central
5626 .read()
5627 .0
5628 .mesh_chest(body.species, body.body_type),
5629 ),
5630 Some(
5631 spec.central
5632 .read()
5633 .0
5634 .mesh_tail_front(body.species, body.body_type),
5635 ),
5636 Some(
5637 spec.central
5638 .read()
5639 .0
5640 .mesh_tail_rear(body.species, body.body_type),
5641 ),
5642 Some(
5643 spec.lateral
5644 .read()
5645 .0
5646 .mesh_foot_fl(body.species, body.body_type),
5647 ),
5648 Some(
5649 spec.lateral
5650 .read()
5651 .0
5652 .mesh_foot_fr(body.species, body.body_type),
5653 ),
5654 Some(
5655 spec.lateral
5656 .read()
5657 .0
5658 .mesh_foot_bl(body.species, body.body_type),
5659 ),
5660 Some(
5661 spec.lateral
5662 .read()
5663 .0
5664 .mesh_foot_br(body.species, body.body_type),
5665 ),
5666 ]
5667 },
5668);
5669
5670impl QuadrupedLowCentralSpec {
5671 fn mesh_head_upper(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5672 let spec = match self.0.get(&(species, body_type)) {
5673 Some(spec) => spec,
5674 None => {
5675 error!(
5676 "No upper head specification exists for the combination of {:?} and {:?}",
5677 species, body_type
5678 );
5679 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5680 },
5681 };
5682 let central = graceful_load_segment(&spec.upper.central.0, spec.upper.model_index);
5683
5684 (central, Vec3::from(spec.upper.offset))
5685 }
5686
5687 fn mesh_head_lower(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5688 let spec = match self.0.get(&(species, body_type)) {
5689 Some(spec) => spec,
5690 None => {
5691 error!(
5692 "No lower head specification exists for the combination of {:?} and {:?}",
5693 species, body_type
5694 );
5695 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5696 },
5697 };
5698 let central = graceful_load_segment(&spec.lower.central.0, spec.lower.model_index);
5699
5700 (central, Vec3::from(spec.lower.offset))
5701 }
5702
5703 fn mesh_jaw(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5704 let spec = match self.0.get(&(species, body_type)) {
5705 Some(spec) => spec,
5706 None => {
5707 error!(
5708 "No jaw specification exists for the combination of {:?} and {:?}",
5709 species, body_type
5710 );
5711 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5712 },
5713 };
5714 let central = graceful_load_segment(&spec.jaw.central.0, spec.jaw.model_index);
5715
5716 (central, Vec3::from(spec.jaw.offset))
5717 }
5718
5719 fn mesh_chest(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5720 let spec = match self.0.get(&(species, body_type)) {
5721 Some(spec) => spec,
5722 None => {
5723 error!(
5724 "No chest specification exists for the combination of {:?} and {:?}",
5725 species, body_type
5726 );
5727 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5728 },
5729 };
5730 let central = graceful_load_segment(&spec.chest.central.0, spec.chest.model_index);
5731
5732 (central, Vec3::from(spec.chest.offset))
5733 }
5734
5735 fn mesh_tail_rear(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5736 let spec = match self.0.get(&(species, body_type)) {
5737 Some(spec) => spec,
5738 None => {
5739 error!(
5740 "No tail_rear specification exists for the combination of {:?} and {:?}",
5741 species, body_type
5742 );
5743 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5744 },
5745 };
5746 let central = graceful_load_segment(&spec.tail_rear.central.0, spec.tail_rear.model_index);
5747
5748 (central, Vec3::from(spec.tail_rear.offset))
5749 }
5750
5751 fn mesh_tail_front(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5752 let spec = match self.0.get(&(species, body_type)) {
5753 Some(spec) => spec,
5754 None => {
5755 error!(
5756 "No tail_front specification exists for the combination of {:?} and {:?}",
5757 species, body_type
5758 );
5759 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5760 },
5761 };
5762 let central =
5763 graceful_load_segment(&spec.tail_front.central.0, spec.tail_front.model_index);
5764
5765 (central, Vec3::from(spec.tail_front.offset))
5766 }
5767}
5768
5769impl QuadrupedLowLateralSpec {
5770 fn mesh_left_head_upper(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5771 let spec = match self.0.get(&(species, body_type)) {
5772 Some(spec) => spec,
5773 None => {
5774 error!(
5775 "No left upper head specification exists for the combination of {:?} and {:?}",
5776 species, body_type
5777 );
5778 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5779 },
5780 };
5781
5782 let latspec = &spec.left_upper.lateral;
5783 let lateral =
5784 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.left_upper.model_index);
5785
5786 (lateral, Vec3::from(spec.left_upper.offset))
5787 }
5788
5789 fn mesh_left_head_lower(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5790 let spec = match self.0.get(&(species, body_type)) {
5791 Some(spec) => spec,
5792 None => {
5793 error!(
5794 "No left lower head specification exists for the combination of {:?} and {:?}",
5795 species, body_type
5796 );
5797 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5798 },
5799 };
5800
5801 let latspec = &spec.left_lower.lateral;
5802 let lateral =
5803 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.left_lower.model_index);
5804
5805 (lateral, Vec3::from(spec.left_lower.offset))
5806 }
5807
5808 fn mesh_left_jaw(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5809 let spec = match self.0.get(&(species, body_type)) {
5810 Some(spec) => spec,
5811 None => {
5812 error!(
5813 "No left jaw specification exists for the combination of {:?} and {:?}",
5814 species, body_type
5815 );
5816 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5817 },
5818 };
5819
5820 let latspec = &spec.left_jaw.lateral;
5821 let lateral =
5822 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.left_jaw.model_index);
5823
5824 (lateral, Vec3::from(spec.left_jaw.offset))
5825 }
5826
5827 fn mesh_right_head_upper(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5828 let spec = match self.0.get(&(species, body_type)) {
5829 Some(spec) => spec,
5830 None => {
5831 error!(
5832 "No right upper head specification exists for the combination of {:?} and {:?}",
5833 species, body_type
5834 );
5835 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5836 },
5837 };
5838
5839 let latspec = &spec.right_upper.lateral;
5840 let lateral =
5841 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.right_upper.model_index);
5842
5843 (lateral, Vec3::from(spec.right_upper.offset))
5844 }
5845
5846 fn mesh_right_head_lower(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5847 let spec = match self.0.get(&(species, body_type)) {
5848 Some(spec) => spec,
5849 None => {
5850 error!(
5851 "No right lower head specification exists for the combination of {:?} and {:?}",
5852 species, body_type
5853 );
5854 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5855 },
5856 };
5857
5858 let latspec = &spec.right_lower.lateral;
5859 let lateral =
5860 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.right_lower.model_index);
5861
5862 (lateral, Vec3::from(spec.right_lower.offset))
5863 }
5864
5865 fn mesh_right_jaw(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5866 let spec = match self.0.get(&(species, body_type)) {
5867 Some(spec) => spec,
5868 None => {
5869 error!(
5870 "No right jaw specification exists for the combination of {:?} and {:?}",
5871 species, body_type
5872 );
5873 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5874 },
5875 };
5876
5877 let latspec = &spec.right_jaw.lateral;
5878 let lateral =
5879 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.right_jaw.model_index);
5880
5881 (lateral, Vec3::from(spec.right_jaw.offset))
5882 }
5883
5884 fn mesh_foot_fl(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5885 let spec = match self.0.get(&(species, body_type)) {
5886 Some(spec) => spec,
5887 None => {
5888 error!(
5889 "No foot specification exists for the combination of {:?} and {:?}",
5890 species, body_type
5891 );
5892 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5893 },
5894 };
5895 let latspec = &spec.front_left.lateral;
5896 let lateral =
5897 graceful_load_segment_flipped(&latspec.0, !latspec.1, spec.front_left.model_index);
5898
5899 (lateral, Vec3::from(spec.front_left.offset))
5900 }
5901
5902 fn mesh_foot_fr(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5903 let spec = match self.0.get(&(species, body_type)) {
5904 Some(spec) => spec,
5905 None => {
5906 error!(
5907 "No foot specification exists for the combination of {:?} and {:?}",
5908 species, body_type
5909 );
5910 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5911 },
5912 };
5913 let latspec = &spec.front_right.lateral;
5914 let lateral =
5915 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.front_right.model_index);
5916
5917 (lateral, Vec3::from(spec.front_right.offset))
5918 }
5919
5920 fn mesh_foot_bl(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5921 let spec = match self.0.get(&(species, body_type)) {
5922 Some(spec) => spec,
5923 None => {
5924 error!(
5925 "No foot specification exists for the combination of {:?} and {:?}",
5926 species, body_type
5927 );
5928 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5929 },
5930 };
5931 let latspec = &spec.back_left.lateral;
5932 let lateral =
5933 graceful_load_segment_flipped(&latspec.0, !latspec.1, spec.back_left.model_index);
5934
5935 (lateral, Vec3::from(spec.back_left.offset))
5936 }
5937
5938 fn mesh_foot_br(&self, species: QLSpecies, body_type: QLBodyType) -> BoneMeshes {
5939 let spec = match self.0.get(&(species, body_type)) {
5940 Some(spec) => spec,
5941 None => {
5942 error!(
5943 "No foot specification exists for the combination of {:?} and {:?}",
5944 species, body_type
5945 );
5946 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
5947 },
5948 };
5949 let latspec = &spec.back_right.lateral;
5950 let lateral =
5951 graceful_load_segment_flipped(&latspec.0, latspec.1, spec.back_right.model_index);
5952
5953 (lateral, Vec3::from(spec.back_right.offset))
5954 }
5955}
5956
5957#[derive(Deserialize)]
5959struct ObjectCentralSpec(HashMap<object::Body, SidedObjectCentralVoxSpec>);
5960
5961#[derive(Deserialize, Default)]
5962#[serde(default)]
5963struct SidedObjectCentralVoxSpec {
5964 bone0: ObjectCentralSubSpec,
5965 bone1: ObjectCentralSubSpec,
5966}
5967
5968#[derive(Deserialize, Default)]
5969struct ObjectCentralSubSpec {
5970 offset: [f32; 3], central: VoxSimple,
5972 #[serde(default)]
5973 model_index: u32,
5974}
5975
5976make_vox_spec!(
5977 object::Body,
5978 struct ObjectSpec {
5979 central: ObjectCentralSpec = "voxygen.voxel.object_manifest",
5980 },
5981 |FigureKey { body, .. }, spec| {
5982 [
5983 Some(spec.central.read().0.mesh_bone0(body)),
5984 Some(spec.central.read().0.mesh_bone1(body)),
5985 None,
5986 None,
5987 None,
5988 None,
5989 None,
5990 None,
5991 None,
5992 None,
5993 None,
5994 None,
5995 None,
5996 None,
5997 None,
5998 None,
5999 ]
6000 },
6001);
6002
6003impl ObjectCentralSpec {
6004 fn mesh_bone0(&self, obj: &object::Body) -> BoneMeshes {
6005 let spec = match self.0.get(obj) {
6006 Some(spec) => spec,
6007 None => {
6008 error!("No specification exists for {:?}", obj);
6009 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
6010 },
6011 };
6012 let central = graceful_load_segment(&spec.bone0.central.0, spec.bone0.model_index);
6013
6014 (central, Vec3::from(spec.bone0.offset))
6015 }
6016
6017 fn mesh_bone1(&self, obj: &object::Body) -> BoneMeshes {
6018 let spec = match self.0.get(obj) {
6019 Some(spec) => spec,
6020 None => {
6021 error!("No specification exists for {:?}", obj);
6022 return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
6023 },
6024 };
6025 let central = graceful_load_segment(&spec.bone1.central.0, spec.bone1.model_index);
6026
6027 (central, Vec3::from(spec.bone1.offset))
6028 }
6029}
6030impl_concatenate_for_wrapper!(ObjectCentralSpec);
6031
6032struct ModelWithOptionalIndex(String, u32);
6033
6034impl<'de> Deserialize<'de> for ModelWithOptionalIndex {
6035 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
6036 struct StringWithOptionalIndex;
6037 use serde::de;
6038
6039 impl<'de> de::Visitor<'de> for StringWithOptionalIndex {
6040 type Value = ModelWithOptionalIndex;
6041
6042 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
6043 formatter.write_str("model_spec or (spec, index)")
6044 }
6045
6046 fn visit_str<E: de::Error>(self, model: &str) -> Result<Self::Value, E> {
6047 Ok(ModelWithOptionalIndex(model.into(), DEFAULT_INDEX))
6048 }
6049
6050 fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
6051 if let Some(spec) = seq.next_element::<String>()? {
6052 if let Some(num) = seq.next_element::<u32>()? {
6053 Ok(ModelWithOptionalIndex(spec, num))
6054 } else {
6055 Err(de::Error::missing_field("index"))
6056 }
6057 } else {
6058 Err(de::Error::missing_field("spec"))
6059 }
6060 }
6061 }
6062 deserializer.deserialize_any(StringWithOptionalIndex {})
6063 }
6064}
6065
6066#[derive(Deserialize)]
6067struct ItemCentralSpec(HashMap<ItemKey, ModelWithOptionalIndex>);
6068impl_concatenate_for_wrapper!(ItemCentralSpec);
6069
6070make_vox_spec!(
6071 body::item::Body,
6072 struct ItemSpec {
6073 central: ItemCentralSpec = "voxygen.voxel.item_drop_manifest",
6074 },
6075 |FigureKey { body, item_key, .. }, spec| {
6076 [
6077 Some(
6078 spec.central
6079 .read()
6080 .0
6081 .mesh_bone0(body, item_key.as_deref().unwrap_or(&ItemKey::Empty)),
6082 ),
6083 None,
6084 None,
6085 None,
6086 None,
6087 None,
6088 None,
6089 None,
6090 None,
6091 None,
6092 None,
6093 None,
6094 None,
6095 None,
6096 None,
6097 None,
6098 ]
6099 },
6100);
6101
6102impl ItemCentralSpec {
6103 fn mesh_bone0(&self, item: &body::item::Body, item_key: &ItemKey) -> BoneMeshes {
6104 let coin_pouch = ModelWithOptionalIndex(
6105 "voxel.sprite.furniture.sack_leather_M".to_string(),
6106 DEFAULT_INDEX,
6107 );
6108
6109 if let Some(spec) = match item {
6110 body::item::Body::CoinPouch => Some(&coin_pouch),
6111 _ => self.0.get(item_key),
6112 } {
6113 let full_spec: String = ["voxygen.", spec.0.as_str()].concat();
6114 let segment = match item {
6115 body::item::Body::Armor(_) => MatSegment::from_vox_model_index(
6116 &graceful_load_vox_fullspec(&full_spec).read().0,
6117 spec.1 as usize,
6118 )
6119 .map(|mat_cell| match mat_cell {
6120 MatCell::None => None,
6121 MatCell::Mat(_) => Some(MatCell::None),
6122 MatCell::Normal(data) => data.attr.is_hollow().then_some(MatCell::None),
6123 })
6124 .to_segment(|_| Default::default()),
6125 _ => graceful_load_segment_fullspec(&full_spec, spec.1),
6126 };
6127 let offset = segment_center(&segment).unwrap_or_default();
6128 (segment, match item {
6129 body::item::Body::Tool(_) | body::item::Body::Thrown(_) => {
6131 Vec3::new(offset.x - 2.0, offset.y, offset.z)
6132 },
6133 body::item::Body::Armor(
6134 body::item::ItemArmorKind::Neck
6135 | body::item::ItemArmorKind::Back
6136 | body::item::ItemArmorKind::Tabard,
6137 ) => Vec3::new(offset.x, offset.y - 2.0, offset.z),
6138 _ => offset * Vec3::new(1.0, 1.0, 0.0),
6139 })
6140 } else {
6141 error!("No specification exists for {:?}, {:?}", item, item_key);
6142 load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5))
6143 }
6144 }
6145}
6146
6147fn segment_center(segment: &Segment) -> Option<Vec3<f32>> {
6148 let (mut x_min, mut x_max, mut y_min, mut y_max, mut z_min, mut z_max) =
6149 (i32::MAX, 0, i32::MAX, 0, i32::MAX, 0);
6150 for pos in segment.full_pos_iter() {
6151 if let Ok(Cell::Filled(data)) = segment.get(pos)
6152 && !data.attr.is_hollow()
6153 {
6154 if pos.x < x_min {
6155 x_min = pos.x;
6156 } else if pos.x > x_max {
6157 x_max = pos.x;
6158 }
6159 if pos.y < y_min {
6160 y_min = pos.y;
6161 } else if pos.y > y_max {
6162 y_max = pos.y;
6163 }
6164 if pos.z < z_min {
6165 z_min = pos.z;
6166 } else if pos.z > z_max {
6167 z_max = pos.z;
6168 }
6169 }
6170 }
6171
6172 if (x_min, x_max, y_min, y_max, z_min, z_max) == (i32::MAX, 0, i32::MAX, 0, i32::MAX, 0) {
6173 None
6174 } else {
6175 Some(Vec3::new(x_min + x_max, y_min + y_max, z_min + z_max).map(|n| n as f32 / -2.0))
6176 }
6177}
6178
6179pub type ShipBoneMeshes = (Dyna<Block, ()>, Vec3<f32>);
6180
6181fn mesh_ship_bone<'a, K: fmt::Debug + Eq + Hash, V, F: Fn(&V) -> Option<&'a VoxelCollider>>(
6182 map: &HashMap<K, V>,
6183 obj: &K,
6184 f: F,
6185) -> Option<ShipBoneMeshes> {
6186 let spec = match map.get(obj) {
6187 Some(spec) => spec,
6188 None => {
6189 error!("No specification exists for {:?}", obj);
6190
6191 return None;
6192 },
6193 };
6194 let bone = f(spec);
6195
6196 bone.map(|bone| (bone.volume().clone(), bone.translation))
6197}
6198
6199impl BodySpec for ship::Body {
6200 type BoneMesh = ShipBoneMeshes;
6201 type Extra = ();
6202 type Manifests = AssetHandle<Self::Spec>;
6203 type ModelEntryFuture<const N: usize> = TerrainModelEntryFuture<N>;
6204 type Spec = ShipSpec;
6205
6206 fn load_spec() -> Result<Self::Manifests, assets::Error> { Self::Spec::load("") }
6207
6208 fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher { manifests.reload_watcher() }
6209
6210 fn bone_meshes(
6211 FigureKey { body, .. }: &FigureKey<Self>,
6212 manifests: &Self::Manifests,
6213 _: Self::Extra,
6214 ) -> [Option<Self::BoneMesh>; anim::MAX_BONE_COUNT] {
6215 let spec = manifests.read();
6216 let spec = &*spec;
6217 let map = &spec.central.read().0.0;
6218 [
6219 mesh_ship_bone(map, body, |ship| spec.colliders.get(&ship.bone0.central.0)),
6220 mesh_ship_bone(map, body, |ship| spec.colliders.get(&ship.bone1.central.0)),
6221 mesh_ship_bone(map, body, |ship| spec.colliders.get(&ship.bone2.central.0)),
6222 mesh_ship_bone(map, body, |ship| spec.colliders.get(&ship.bone3.central.0)),
6223 None,
6224 None,
6225 None,
6226 None,
6227 None,
6228 None,
6229 None,
6230 None,
6231 None,
6232 None,
6233 None,
6234 None,
6235 ]
6236 }
6237}
6238
6239#[cfg(feature = "plugins")]
6240mod plugin {
6241 use super::assets::{
6242 self, AssetCache, AssetExt, AssetHandle, BoxedError, Concatenate, MultiRon, SharedString,
6243 };
6244 use hashbrown::HashMap;
6245 use serde::Deserialize;
6246
6247 #[derive(Debug, Deserialize, Default, Clone, Copy)]
6248 pub enum Orientation {
6249 #[default]
6250 Normal,
6251 Mirror,
6252 }
6253
6254 #[derive(Debug, Deserialize, Clone)]
6255 pub struct BoneMesh {
6256 pub model: String,
6257 pub offset: [f32; 3],
6258 #[serde(default)]
6259 pub model_index: u16,
6260 #[serde(default)]
6261 pub transform: Orientation,
6262 }
6263
6264 #[derive(Deserialize, Clone)]
6265 pub struct PluginBoneSpec(pub(super) HashMap<String, Vec<BoneMesh>>);
6266
6267 impl assets::Asset for PluginBoneSpec {
6268 fn load(_cache: &AssetCache, _: &SharedString) -> Result<Self, BoxedError> {
6269 let data: AssetHandle<MultiRon<PluginBoneSpec>> =
6270 AssetExt::load("voxygen.voxel.plugin_body_manifest")?;
6271 Ok(data.read().0.clone())
6272 }
6273 }
6274
6275 impl_concatenate_for_wrapper!(PluginBoneSpec);
6276}
6277
6278#[cfg(feature = "plugins")]
6279impl BodySpec for common::comp::plugin::Body {
6280 type BoneMesh = BoneMeshes;
6281 type Extra = ();
6282 type Manifests = AssetHandle<Self::Spec>;
6283 type ModelEntryFuture<const N: usize> = FigureModelEntryFuture<N>;
6284 type Spec = plugin::PluginBoneSpec;
6285
6286 fn load_spec() -> Result<Self::Manifests, assets::Error> { Self::Spec::load("") }
6287
6288 fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher { manifests.reload_watcher() }
6289
6290 fn bone_meshes(
6291 key: &FigureKey<Self>,
6292 manifests: &Self::Manifests,
6293 _extra: Self::Extra,
6294 ) -> [Option<BoneMeshes>; anim::MAX_BONE_COUNT] {
6295 let mut result = std::array::from_fn(|_| None);
6296 if let Some(bones) = manifests.read().0.get(&key.body.id()) {
6297 for (mesh, result) in bones.iter().zip(result.iter_mut()) {
6298 *result = Some((
6299 graceful_load_segment_flipped(
6300 &mesh.model,
6301 matches!(mesh.transform, plugin::Orientation::Mirror),
6302 mesh.model_index.into(),
6303 ),
6304 mesh.offset.into(),
6305 ));
6306 }
6307 }
6308 result
6309 }
6310}