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