diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index ddeb9f3fba..135521148f 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -81,6 +81,19 @@ impl FigureModelCache { { let humanoid_head_spec = HumHeadSpec::load_watched(&mut self.manifest_indicator); + let humanoid_armor_shoulder_spec = + HumArmorShoulderSpec::load_watched(&mut self.manifest_indicator); + let humanoid_armor_chest_spec = + HumArmorChestSpec::load_watched(&mut self.manifest_indicator); + let humanoid_armor_hand_spec = + HumArmorHandSpec::load_watched(&mut self.manifest_indicator); + let humanoid_armor_belt_spec = + HumArmorBeltSpec::load_watched(&mut self.manifest_indicator); + let humanoid_armor_pants_spec = + HumArmorPantsSpec::load_watched(&mut self.manifest_indicator); + let humanoid_armor_foot_spec = + HumArmorFootSpec::load_watched(&mut self.manifest_indicator); + let bone_meshes = match body { Body::Humanoid(body) => [ match camera_mode { @@ -100,27 +113,39 @@ impl FigureModelCache { CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_chest( - body.chest, - body.race, - body.skin, - body.hair_color, - body.eye_color, - )), + CameraMode::ThirdPerson => Some( + humanoid_armor_chest_spec.mesh_chest( + body.chest, + body.race, + body.body_type, + body.skin, + body.hair_color, + body.eye_color, + ) + ), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_belt(body.belt)), + CameraMode::ThirdPerson => Some( + humanoid_armor_belt_spec.mesh_belt( + body.belt, + body.race, + body.body_type, + ) + ), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_pants( - body.pants, - body.race, - body.skin, - body.hair_color, - body.eye_color, - )), + CameraMode::ThirdPerson => Some( + humanoid_armor_pants_spec.mesh_pants( + body.pants, + body.race, + body.body_type, + body.skin, + body.hair_color, + body.eye_color, + ) + ), CameraMode::FirstPerson => None, }, if camera_mode == CameraMode::FirstPerson @@ -130,9 +155,10 @@ impl FigureModelCache { { None } else { - Some(mesh_left_hand( + Some(humanoid_armor_hand_spec.mesh_left_hand( body.hand, body.race, + body.body_type, body.skin, body.hair_color, body.eye_color, @@ -144,32 +170,39 @@ impl FigureModelCache { { None } else { - Some(mesh_right_hand( + Some(humanoid_armor_hand_spec.mesh_right_hand( body.hand, body.race, + body.body_type, body.skin, body.hair_color, body.eye_color, )) }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_left_foot( - body.foot, - body.race, - body.skin, - body.hair_color, - body.eye_color, - )), + CameraMode::ThirdPerson => Some( + humanoid_armor_foot_spec.mesh_left_foot( + body.foot, + body.race, + body.body_type, + body.skin, + body.hair_color, + body.eye_color, + ) + ), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_right_foot( - body.foot, - body.race, - body.skin, - body.hair_color, - body.eye_color, - )), + CameraMode::ThirdPerson => Some( + humanoid_armor_foot_spec.mesh_right_foot( + body.foot, + body.race, + body.body_type, + body.skin, + body.hair_color, + body.eye_color, + ) + ), CameraMode::FirstPerson => None, }, if camera_mode != CameraMode::FirstPerson @@ -186,23 +219,29 @@ impl FigureModelCache { None }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_left_shoulder( - body.shoulder, - body.race, - body.skin, - body.hair_color, - body.eye_color, - )), + CameraMode::ThirdPerson => Some( + humanoid_armor_shoulder_spec.mesh_left_shoulder( + body.shoulder, + body.race, + body.body_type, + body.skin, + body.hair_color, + body.eye_color, + ) + ), CameraMode::FirstPerson => None, }, match camera_mode { - CameraMode::ThirdPerson => Some(mesh_right_shoulder( - body.shoulder, - body.race, - body.skin, - body.hair_color, - body.eye_color, - )), + CameraMode::ThirdPerson => Some( + humanoid_armor_shoulder_spec.mesh_right_shoulder( + body.shoulder, + body.race, + body.body_type, + body.skin, + body.hair_color, + body.eye_color, + ) + ), CameraMode::FirstPerson => None, }, Some(mesh_draw()), diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 94ae64f548..0a0a585f56 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -192,160 +192,342 @@ impl HumHeadSpec { ) } } +// All reliant on humanoid::Race and humanoid::BodyType +// Armor spects should be in the same order, top to bottom. +// These seem overly split up, but wanted to keep the armor seperated +// unlike head which is done above. This can also make adding further +// customization easier, such as allowing a 'chest_emblem' to be added. +#[derive(Serialize, Deserialize)] +struct HumArmorShoulderSubSpec { + offset: [f32; 3], + shoulder: Vec>, +} +#[derive(Serialize, Deserialize)] +struct HumArmorChestSubSpec { + offset: [f32; 3], + chest: Vec>, +} +#[derive(Serialize, Deserialize)] +struct HumArmorHandSubSpec { + offset: [f32; 3], + hand: Vec>, +} +#[derive(Serialize, Deserialize)] +struct HumArmorBeltSubSpec { + offset: [f32; 3], + belt: Vec>, +} +#[derive(Serialize, Deserialize)] +struct HumArmorPantsSubSpec { + offset: [f32; 3], + pants: Vec>, +} +#[derive(Serialize, Deserialize)] +struct HumArmorFootSubSpec { + offset: [f32; 3], + foot: Vec>, +} -pub fn mesh_chest( - chest: Chest, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let chest_color = match chest { - Chest::Blue => (44, 74, 109), - Chest::Brown => (90, 49, 43), - Chest::Dark => (73, 63, 59), - Chest::Green => (59, 95, 67), - Chest::Orange => (109, 58, 58), - Chest::Midnight => (29, 26, 33), - }; +#[derive(Serialize, Deserialize)] +pub struct HumArmorShoulderSpec(HashMap<(Race, BodyType), HumArmorShoulderSubSpec>); +#[derive(Serialize, Deserialize)] +pub struct HumArmorChestSpec(HashMap<(Race, BodyType), HumArmorChestSubSpec>); +#[derive(Serialize, Deserialize)] +pub struct HumArmorHandSpec(HashMap<(Race, BodyType), HumArmorHandSubSpec>); +#[derive(Serialize, Deserialize)] +pub struct HumArmorBeltSpec(HashMap<(Race, BodyType), HumArmorBeltSubSpec>); +#[derive(Serialize, Deserialize)] +pub struct HumArmorPantsSpec(HashMap<(Race, BodyType), HumArmorPantsSubSpec>); +#[derive(Serialize, Deserialize)] +pub struct HumArmorFootSpec(HashMap<(Race, BodyType), HumArmorFootSubSpec>); - let color = |mat_segment| { - color_segment( - mat_segment, +impl Asset for HumArmorShoulderSpec { + const ENDINGS: &'static [&'static str] = &["ron"]; + fn parse(buf_reader: BufReader) -> Result { + Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor shoulder spec")) + } +} +impl Asset for HumArmorChestSpec { + const ENDINGS: &'static [&'static str] = &["ron"]; + fn parse(buf_reader: BufReader) -> Result { + Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor chest spec")) + } +} +impl Asset for HumArmorHandSpec { + const ENDINGS: &'static [&'static str] = &["ron"]; + fn parse(buf_reader: BufReader) -> Result { + Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor hand spec")) + } +} +impl Asset for HumArmorBeltSpec { + const ENDINGS: &'static [&'static str] = &["ron"]; + fn parse(buf_reader: BufReader) -> Result { + Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor belt spec")) + } +} +impl Asset for HumArmorPantsSpec { + const ENDINGS: &'static [&'static str] = &["ron"]; + fn parse(buf_reader: BufReader) -> Result { + Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor pants spec")) + } +} +impl Asset for HumArmorFootSpec { + const ENDINGS: &'static [&'static str] = &["ron"]; + fn parse(buf_reader: BufReader) -> Result { + Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor foot spec")) + } +} + +impl HumArmorShoulderSpec { + pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc { + assets::load_watched::("voxygen.voxel.humanoid_armor_shoulder_manifest", indicator).unwrap() + } + + pub fn mesh_left_shoulder( + &self, + shoulder: Shoulder, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let shoulder_segment = color_segment( + graceful_load_mat_segment(match shoulder { + Shoulder::None => return Mesh::new(), + Shoulder::Brown1 => "armor.shoulder.brown_left", + }), race.skin_color(skin), race.hair_color(hair_color), race.eye_color(eye_color), + ); + + generate_mesh(&shoulder_segment, Vec3::new(-3.0, -3.5, 0.1)) + } + + pub fn mesh_right_shoulder( + &self, + shoulder: Shoulder, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let shoulder_segment = color_segment( + graceful_load_mat_segment(match shoulder { + Shoulder::None => return Mesh::new(), + Shoulder::Brown1 => "armor.shoulder.brown_right", + }), + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ); + + generate_mesh(&shoulder_segment, Vec3::new(-2.0, -3.5, 0.1)) + } +} + +impl HumArmorChestSpec { + pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc { + assets::load_watched::("voxygen.voxel.humanoid_armor_chest_manifest", indicator).unwrap() + } + + pub fn mesh_chest( + &self, + chest: Chest, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let chest_color = match chest { + Chest::Blue => (44, 74, 109), + Chest::Brown => (90, 49, 43), + Chest::Dark => (73, 63, 59), + Chest::Green => (59, 95, 67), + Chest::Orange => (109, 58, 58), + Chest::Midnight => (29, 26, 33), + }; + + let color = |mat_segment| { + color_segment( + mat_segment, + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ) + }; + + let bare_chest = graceful_load_mat_segment("armor.chest.grayscale"); + let chest_armor = graceful_load_mat_segment("armor.chest.grayscale"); + let chest = DynaUnionizer::new() + .add(color(bare_chest), Vec3::new(0, 0, 0)) + .add( + color(chest_armor.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(chest_color)))), + Vec3::new(0, 0, 0), + ) + .unify() + .0; + + generate_mesh(&chest, Vec3::new(-7.0, -3.5, 2.0)) + } +} + +impl HumArmorHandSpec { + pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc { + assets::load_watched::("voxygen.voxel.humanoid_armor_hand_manifest", indicator).unwrap() + } + + pub fn mesh_left_hand( + &self, + hand: Hand, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let hand_segment = color_segment( + graceful_load_mat_segment(match hand { + Hand::Bare => "armor.hand.default_left", + Hand::Dark => "armor.hand.default_left", + }), + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ); + + generate_mesh(&hand_segment, Vec3::new(-1.5, -1.5, -7.0)) + } + + pub fn mesh_right_hand( + &self, + hand: Hand, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let hand_segment = color_segment( + graceful_load_mat_segment(match hand { + Hand::Bare => "armor.hand.default_right", + Hand::Dark => "armor.hand.default_right", + }), + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ); + + generate_mesh(&hand_segment, Vec3::new(-1.5, -1.5, -7.0)) + } +} + +impl HumArmorBeltSpec { + pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc { + assets::load_watched::("voxygen.voxel.humanoid_armor_belt_manifest", indicator).unwrap() + } + + pub fn mesh_belt( + &self, + belt: Belt, + race: Race, + body_type: BodyType, + ) -> Mesh { + load_mesh( + match belt { + //Belt::Default => "figure/body/belt_male", + Belt::Dark => "armor.belt.dark", + }, + Vec3::new(-4.0, -3.5, 2.0), ) - }; - - let bare_chest = graceful_load_mat_segment("armor.chest.grayscale"); - let chest_armor = graceful_load_mat_segment("armor.chest.grayscale"); - let chest = DynaUnionizer::new() - .add(color(bare_chest), Vec3::new(0, 0, 0)) - .add( - color(chest_armor.map_rgb(|rgb| recolor_grey(rgb, Rgb::from(chest_color)))), - Vec3::new(0, 0, 0), - ) - .unify() - .0; - - generate_mesh(&chest, Vec3::new(-7.0, -3.5, 2.0)) + } } -pub fn mesh_belt(belt: Belt) -> Mesh { - load_mesh( - match belt { - //Belt::Default => "figure/body/belt_male", - Belt::Dark => "armor.belt.dark", - }, - Vec3::new(-4.0, -3.5, 2.0), - ) +impl HumArmorPantsSpec { + pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc { + assets::load_watched::("voxygen.voxel.humanoid_armor_pants_manifest", indicator).unwrap() + } + + pub fn mesh_pants( + &self, + pants: Pants, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let color = match pants { + Pants::Blue => (28, 66, 109), + Pants::Brown => (54, 30, 26), + Pants::Dark => (24, 19, 17), + Pants::Green => (49, 95, 59), + Pants::Orange => (148, 52, 33), + }; + + let pants_segment = color_segment( + graceful_load_mat_segment("armor.pants.grayscale") + .map_rgb(|rgb| recolor_grey(rgb, Rgb::from(color))), + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ); + + generate_mesh(&pants_segment, Vec3::new(-5.0, -3.5, 1.0)) + } } -pub fn mesh_pants( - pants: Pants, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let color = match pants { - Pants::Blue => (28, 66, 109), - Pants::Brown => (54, 30, 26), - Pants::Dark => (24, 19, 17), - Pants::Green => (49, 95, 59), - Pants::Orange => (148, 52, 33), - }; +impl HumArmorFootSpec { + pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc { + assets::load_watched::("voxygen.voxel.humanoid_armor_foot_manifest", indicator).unwrap() + } - let pants_segment = color_segment( - graceful_load_mat_segment("armor.pants.grayscale") - .map_rgb(|rgb| recolor_grey(rgb, Rgb::from(color))), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); + pub fn mesh_left_foot( + &self, + foot: Foot, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let foot_segment = color_segment( + graceful_load_mat_segment(match foot { + Foot::Bare => "armor.foot.dark-0", + Foot::Dark => "armor.foot.dark-0", + }), + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ); - generate_mesh(&pants_segment, Vec3::new(-5.0, -3.5, 1.0)) -} + generate_mesh(&foot_segment, Vec3::new(-2.5, -3.5, -9.0)) + } -pub fn mesh_left_hand( - hand: Hand, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let hand_segment = color_segment( - graceful_load_mat_segment(match hand { - Hand::Bare => "armor.hand.default_left", - Hand::Dark => "armor.hand.default_left", - }), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); + pub fn mesh_right_foot( + &self, + foot: Foot, + race: Race, + body_type: BodyType, + skin: u8, + hair_color: u8, + eye_color: u8, + ) -> Mesh { + let foot_segment = color_segment( + graceful_load_mat_segment(match foot { + Foot::Bare => "armor.foot.dark-0", + Foot::Dark => "armor.foot.dark-0", + }), + race.skin_color(skin), + race.hair_color(hair_color), + race.eye_color(eye_color), + ); - generate_mesh(&hand_segment, Vec3::new(-1.5, -1.5, -7.0)) -} - -pub fn mesh_right_hand( - hand: Hand, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let hand_segment = color_segment( - graceful_load_mat_segment(match hand { - Hand::Bare => "armor.hand.default_right", - Hand::Dark => "armor.hand.default_right", - }), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); - - generate_mesh(&hand_segment, Vec3::new(-1.5, -1.5, -7.0)) -} - -pub fn mesh_left_foot( - foot: Foot, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let foot_segment = color_segment( - graceful_load_mat_segment(match foot { - Foot::Bare => "armor.foot.dark-0", - Foot::Dark => "armor.foot.dark-0", - }), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); - - generate_mesh(&foot_segment, Vec3::new(-2.5, -3.5, -9.0)) -} - -pub fn mesh_right_foot( - foot: Foot, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let foot_segment = color_segment( - graceful_load_mat_segment(match foot { - Foot::Bare => "armor.foot.dark-0", - Foot::Dark => "armor.foot.dark-0", - }), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); - - generate_mesh(&foot_segment, Vec3::new(-2.5, -3.5, -9.0)) + generate_mesh(&foot_segment, Vec3::new(-2.5, -3.5, -9.0)) + } } pub fn mesh_main(item: Option<&Item>) -> Mesh { @@ -369,46 +551,6 @@ pub fn mesh_main(item: Option<&Item>) -> Mesh { } } -pub fn mesh_left_shoulder( - shoulder: Shoulder, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let shoulder_segment = color_segment( - graceful_load_mat_segment(match shoulder { - Shoulder::None => return Mesh::new(), - Shoulder::Brown1 => "armor.shoulder.brown_left", - }), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); - - generate_mesh(&shoulder_segment, Vec3::new(-3.0, -3.5, 0.1)) -} - -pub fn mesh_right_shoulder( - shoulder: Shoulder, - race: Race, - skin: u8, - hair_color: u8, - eye_color: u8, -) -> Mesh { - let shoulder_segment = color_segment( - graceful_load_mat_segment(match shoulder { - Shoulder::None => return Mesh::new(), - Shoulder::Brown1 => "armor.shoulder.brown_right", - }), - race.skin_color(skin), - race.hair_color(hair_color), - race.eye_color(eye_color), - ); - - generate_mesh(&shoulder_segment, Vec3::new(-2.0, -3.5, 0.1)) -} - // TODO: Inventory pub fn mesh_draw() -> Mesh { load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0))