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