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