mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add ron file for head offsets, segment unionizer
This commit is contained in:
parent
6289ce8c7f
commit
7bebffb2af
BIN
assets/voxygen/voxel/figure/accessory/danari/horns.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/accessory/danari/horns.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/accessory/orc/earring.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/accessory/orc/earring.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/beard/dwarf/1.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/beard/dwarf/1.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/beard/orc/1.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/beard/orc/1.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/danari/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/danari/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/dwarf/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/dwarf/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/dwarf/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/dwarf/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/elf/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/elf/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/elf/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/elf/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/human/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/human/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/human/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/human/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/orc/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/orc/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/eyes/orc/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/eyes/orc/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/danari/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/danari/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/danari/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/danari/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/dwarf/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/dwarf/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/elf/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/elf/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/elf/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/elf/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/human/female_2.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/human/female_2.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/human/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/human/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/orc/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/orc/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/hair/orc/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/hair/orc/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/danari/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/danari/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/danari/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/danari/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/dwarf/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/dwarf/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/dwarf/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/dwarf/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/elf/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/elf/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/elf/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/elf/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_danari_female.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_danari_female.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_danari_male.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_danari_male.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_dwarf_male.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_dwarf_male.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_elf_female.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_elf_female.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_elf_male.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_elf_male.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_human_female.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_human_female.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_human_male.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_human_male.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_orc_female.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_orc_female.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/head_orc_male.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/head/head_orc_male.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/human/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/human/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/human/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/human/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/orc/female.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/orc/female.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/figure/head/orc/male.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/figure/head/orc/male.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
39
assets/voxygen/voxel/humanoid_head_manifest.ron
Normal file
39
assets/voxygen/voxel/humanoid_head_manifest.ron
Normal file
@ -0,0 +1,39 @@
|
||||
({
|
||||
(Human, Male): (
|
||||
offset: (-7.0, -5.0, -2.25),
|
||||
head: ("figure.head.human.male", (0, 0, 0)),
|
||||
eyes: ("figure.eyes.human.male", (10, 10, 3)),
|
||||
hair: {
|
||||
None: None,
|
||||
Temp1: Some(("figure.hair.human.male", (1, 2, 3))),
|
||||
Temp2: Some(("figure.hair.human.male", (1, 2, 3))),
|
||||
},
|
||||
beard: {
|
||||
None: None,
|
||||
Some: Some(("figure.beard.human.1", (0, 0, -5))),
|
||||
},
|
||||
accessory: {
|
||||
Nothing: None,
|
||||
Something: None,
|
||||
},
|
||||
),
|
||||
(Human, Female): (
|
||||
offset: (-7.0, -7.5, -3.25),
|
||||
head: ("figure.head.human.female", (0, 0, 0)),
|
||||
eyes: ("figure.eyes.human.female", (1, 2, 3)),
|
||||
hair: {
|
||||
None: None,
|
||||
Temp1: Some(("figure.hair.human.female_1", (1, 2, 3))),
|
||||
Temp2: Some(("figure.hair.human.female_2", (1, 2, 3))),
|
||||
},
|
||||
beard: {
|
||||
None: None,
|
||||
Some: None,
|
||||
},
|
||||
accessory: {
|
||||
Nothing: None,
|
||||
Something: None,
|
||||
},
|
||||
),
|
||||
// More here
|
||||
})
|
BIN
assets/voxygen/voxel/not_found.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/not_found.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -10,6 +10,13 @@ pub struct Body {
|
||||
pub hand: Hand,
|
||||
pub foot: Foot,
|
||||
pub shoulder: Shoulder,
|
||||
pub hair_color: HairColor,
|
||||
pub hair_style: HairStyle,
|
||||
pub beard: Beard,
|
||||
pub skin: Skin,
|
||||
pub eyebrows: Eyebrows,
|
||||
pub eye_color: EyeColor,
|
||||
pub accessory: Accessory,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
@ -24,6 +31,13 @@ impl Body {
|
||||
hand: *(&ALL_HANDS).choose(&mut rng).unwrap(),
|
||||
foot: *(&ALL_FEET).choose(&mut rng).unwrap(),
|
||||
shoulder: *(&ALL_SHOULDERS).choose(&mut rng).unwrap(),
|
||||
hair_color: *(&ALL_HAIR_COLORS).choose(&mut rng).unwrap(),
|
||||
hair_style: *(&ALL_HAIR_STYLES).choose(&mut rng).unwrap(),
|
||||
beard: *(&ALL_BEARDS).choose(&mut rng).unwrap(),
|
||||
skin: *(&ALL_SKINS).choose(&mut rng).unwrap(),
|
||||
eyebrows: *(&ALL_EYEBROWS).choose(&mut rng).unwrap(),
|
||||
eye_color: *(&ALL_EYE_COLORS).choose(&mut rng).unwrap(),
|
||||
accessory: *(&ALL_ACCESSORIES).choose(&mut rng).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,3 +126,74 @@ pub enum Shoulder {
|
||||
Brown1,
|
||||
}
|
||||
pub const ALL_SHOULDERS: [Shoulder; 2] = [Shoulder::None, Shoulder::Brown1];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum HairStyle {
|
||||
None,
|
||||
Temp1,
|
||||
Temp2,
|
||||
}
|
||||
pub const ALL_HAIR_STYLES: [HairStyle; 3] = [HairStyle::None, HairStyle::Temp1, HairStyle::Temp2];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum HairColor {
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Brown,
|
||||
Black,
|
||||
}
|
||||
pub const ALL_HAIR_COLORS: [HairColor; 5] = [
|
||||
HairColor::Red,
|
||||
HairColor::Green,
|
||||
HairColor::Blue,
|
||||
HairColor::Brown,
|
||||
HairColor::Black,
|
||||
];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Skin {
|
||||
Light,
|
||||
Medium,
|
||||
Dark,
|
||||
Rainbow,
|
||||
}
|
||||
pub const ALL_SKINS: [Skin; 4] = [Skin::Light, Skin::Medium, Skin::Dark, Skin::Rainbow];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Eyebrows {
|
||||
Yup,
|
||||
}
|
||||
pub const ALL_EYEBROWS: [Eyebrows; 1] = [Eyebrows::Yup];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum EyeColor {
|
||||
Black,
|
||||
Blue,
|
||||
Green,
|
||||
Brown,
|
||||
Red,
|
||||
White,
|
||||
}
|
||||
pub const ALL_EYE_COLORS: [EyeColor; 6] = [
|
||||
EyeColor::Black,
|
||||
EyeColor::Blue,
|
||||
EyeColor::Green,
|
||||
EyeColor::Brown,
|
||||
EyeColor::Red,
|
||||
EyeColor::White,
|
||||
];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Accessory {
|
||||
Nothing,
|
||||
Something,
|
||||
}
|
||||
pub const ALL_ACCESSORIES: [Accessory; 2] = [Accessory::Nothing, Accessory::Something];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Beard {
|
||||
None,
|
||||
Some,
|
||||
}
|
||||
pub const ALL_BEARDS: [Beard; 2] = [Beard::None, Beard::Some];
|
||||
|
@ -47,10 +47,11 @@ impl From<&DotVoxData> for Segment {
|
||||
}
|
||||
|
||||
impl Segment {
|
||||
// TODO: this is currenlty unused, remove?
|
||||
/// Create a new `Segment` by combining two existing ones
|
||||
pub fn union(&self, other: &Self, other_offset: Vec3<i32>) -> Self {
|
||||
let size = self.get_size();
|
||||
let other_size = self.get_size();
|
||||
let other_size = other.get_size();
|
||||
let new_size = other_offset
|
||||
.map2(other_size, |oo, os| (oo, os))
|
||||
.map2(size, |(oo, os), s| {
|
||||
@ -86,6 +87,7 @@ impl Segment {
|
||||
self
|
||||
}
|
||||
/// Preserve the luminance of all the colors but set the chomaticity to match the provided color
|
||||
// TODO add more advanced recoloring and/or indexed based coloring
|
||||
pub fn chromify(mut self, chroma: Rgb<u8>) -> Self {
|
||||
let chroma = chroma.map(|e| e as f32 * 255.0);
|
||||
for pos in self.iter_positions() {
|
||||
@ -107,3 +109,55 @@ impl Segment {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Segment` builder that combines segments
|
||||
pub struct SegmentUnionizer(Vec<(Segment, Vec3<i32>)>);
|
||||
|
||||
impl SegmentUnionizer {
|
||||
pub fn new() -> Self {
|
||||
SegmentUnionizer(Vec::new())
|
||||
}
|
||||
pub fn add(mut self, segment: Segment, offset: Vec3<i32>) -> Self {
|
||||
self.0.push((segment, offset));
|
||||
self
|
||||
}
|
||||
pub fn maybe_add(self, maybe: Option<(Segment, Vec3<i32>)>) -> Self {
|
||||
match maybe {
|
||||
Some((segment, offset)) => self.add(segment, offset),
|
||||
None => self,
|
||||
}
|
||||
}
|
||||
pub fn unify(self) -> (Segment, Vec3<i32>) {
|
||||
if self.0.is_empty() {
|
||||
return (
|
||||
Segment::filled(Vec3::new(0, 0, 0), Cell::empty(), ()),
|
||||
Vec3::new(0, 0, 0),
|
||||
);
|
||||
}
|
||||
|
||||
// Determine size of the new segment
|
||||
let mut min_point = self.0[0].1;
|
||||
let mut max_point = self.0[0].1 + self.0[0].0.get_size().map(|e| e as i32);
|
||||
for (segment, offset) in self.0.iter().skip(1) {
|
||||
let size = segment.get_size().map(|e| e as i32);
|
||||
min_point = min_point.map2(*offset, std::cmp::min);
|
||||
max_point = max_point.map2(offset + size, std::cmp::max);
|
||||
}
|
||||
let new_size = (max_point - min_point).map(|e| e as u32);
|
||||
// Allocate new segment
|
||||
let mut combined = Segment::filled(new_size, Cell::empty(), ());
|
||||
// Copy segments into combined
|
||||
let origin = min_point.map(|e| e * -1);
|
||||
for (segment, offset) in self.0 {
|
||||
for pos in segment.iter_positions() {
|
||||
if let Cell::Filled(col) = *segment.get(pos).unwrap() {
|
||||
combined
|
||||
.set(origin + offset + pos, Cell::Filled(col))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(combined, origin)
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use conrod_core::{
|
||||
color,
|
||||
color::TRANSPARENT,
|
||||
widget::{text_box::Event as TextBoxEvent, Button, Image, Rectangle, Scrollbar, Text, TextBox},
|
||||
widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
||||
widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget,
|
||||
};
|
||||
|
||||
widget_ids! {
|
||||
@ -838,203 +838,146 @@ impl CharSelectionUi {
|
||||
.set(self.ids.axe_grey, ui_widgets);*/
|
||||
|
||||
// Sliders
|
||||
|
||||
let (metamorph, slider_indicator, slider_range) = (
|
||||
self.fonts.metamorph,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
);
|
||||
let char_slider = move |prev_id,
|
||||
text,
|
||||
text_id,
|
||||
max,
|
||||
selected_val,
|
||||
slider_id,
|
||||
ui_widgets: &mut UiCell| {
|
||||
Text::new(text)
|
||||
.down_from(prev_id, 22.0)
|
||||
.align_middle_x()
|
||||
.font_size(18)
|
||||
.font_id(metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(text_id, ui_widgets);
|
||||
ImageSlider::discrete(selected_val, 0, max, slider_indicator, slider_range)
|
||||
.w_h(208.0, 22.0)
|
||||
.down_from(text_id, 8.0)
|
||||
.align_middle_x()
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(slider_id, ui_widgets)
|
||||
};
|
||||
// Hair Style
|
||||
Text::new("Hair Style")
|
||||
.mid_bottom_with_margin_on(self.ids.creation_buttons_alignment_2, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.hairstyle_text, ui_widgets);
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
let current_hair_style = self.character_body.hair_style;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.creation_buttons_alignment_2,
|
||||
"Hair Style",
|
||||
self.ids.hairstyle_text,
|
||||
humanoid::ALL_HAIR_STYLES.len() - 1,
|
||||
humanoid::ALL_HAIR_STYLES
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_hair_style)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.hairstyle_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.hairstyle_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.hairstyle_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.hair_style = humanoid::ALL_HAIR_STYLES[new_val];
|
||||
}
|
||||
|
||||
// Hair Color
|
||||
|
||||
Text::new("Hair Color")
|
||||
.mid_bottom_with_margin_on(self.ids.hairstyle_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.haircolor_text, ui_widgets);
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
let current_hair_color = self.character_body.hair_color;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.hairstyle_slider,
|
||||
"Hair Color",
|
||||
self.ids.haircolor_text,
|
||||
humanoid::ALL_HAIR_COLORS.len() - 1,
|
||||
humanoid::ALL_HAIR_COLORS
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_hair_color)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.haircolor_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.haircolor_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.haircolor_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.hair_color = humanoid::ALL_HAIR_COLORS[new_val];
|
||||
}
|
||||
|
||||
// Skin
|
||||
|
||||
Text::new("Skin")
|
||||
.mid_bottom_with_margin_on(self.ids.haircolor_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.skin_text, ui_widgets);
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
let current_skin = self.character_body.skin;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.haircolor_slider,
|
||||
"Skin",
|
||||
self.ids.skin_text,
|
||||
humanoid::ALL_SKINS.len() - 1,
|
||||
humanoid::ALL_SKINS
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_skin)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.skin_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.skin_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.skin_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.skin = humanoid::ALL_SKINS[new_val];
|
||||
}
|
||||
|
||||
// EyeBrows
|
||||
Text::new("Eyebrows")
|
||||
.mid_bottom_with_margin_on(self.ids.skin_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.eyebrows_text, ui_widgets);
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
// Eyebrows
|
||||
let current_eyebrows = self.character_body.eyebrows;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.skin_slider,
|
||||
"Eyebrows",
|
||||
self.ids.eyebrows_text,
|
||||
humanoid::ALL_EYEBROWS.len() - 1,
|
||||
humanoid::ALL_EYEBROWS
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_eyebrows)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.eyebrows_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.eyebrows_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.eyebrows_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.eyebrows = humanoid::ALL_EYEBROWS[new_val];
|
||||
}
|
||||
|
||||
// EyeColor
|
||||
Text::new("Eye Color")
|
||||
.mid_bottom_with_margin_on(self.ids.eyebrows_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.eyecolor_text, ui_widgets);
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
let current_eye_color = self.character_body.eye_color;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.eyebrows_slider,
|
||||
"Eye Color",
|
||||
self.ids.eyecolor_text,
|
||||
humanoid::ALL_EYE_COLORS.len() - 1,
|
||||
humanoid::ALL_EYE_COLORS
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_eye_color)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.eyecolor_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.eyecolor_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.eyecolor_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.eye_color = humanoid::ALL_EYE_COLORS[new_val];
|
||||
}
|
||||
// Accessories
|
||||
Text::new("Accessories")
|
||||
.mid_bottom_with_margin_on(self.ids.eyecolor_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.accessories_text, ui_widgets);
|
||||
let current_chest = self.character_body.chest;
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
let current_accessory = self.character_body.accessory;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.eyecolor_slider,
|
||||
"Accessories",
|
||||
self.ids.accessories_text,
|
||||
humanoid::ALL_ACCESSORIES.len() - 1,
|
||||
humanoid::ALL_ACCESSORIES
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_accessory)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.accessories_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.accessories_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.accessories_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.accessory = humanoid::ALL_ACCESSORIES[new_val];
|
||||
}
|
||||
|
||||
// Beard
|
||||
if let humanoid::BodyType::Male = self.character_body.body_type {
|
||||
Text::new("Beard")
|
||||
.mid_bottom_with_margin_on(self.ids.accessories_slider, -40.0)
|
||||
.font_size(18)
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR)
|
||||
.set(self.ids.beard_text, ui_widgets);
|
||||
|
||||
if let Some(new_val) = ImageSlider::discrete(
|
||||
humanoid::ALL_CHESTS
|
||||
let current_beard = self.character_body.beard;
|
||||
if let Some(new_val) = char_slider(
|
||||
self.ids.accessories_slider,
|
||||
"Beard",
|
||||
self.ids.beard_text,
|
||||
humanoid::ALL_BEARDS.len() - 1,
|
||||
humanoid::ALL_BEARDS
|
||||
.iter()
|
||||
.position(|&c| c == current_chest)
|
||||
.position(|&c| c == current_beard)
|
||||
.unwrap_or(0),
|
||||
0,
|
||||
humanoid::ALL_CHESTS.len() - 1,
|
||||
self.imgs.slider_indicator,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.beard_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.beard_slider, ui_widgets)
|
||||
{
|
||||
self.character_body.chest = humanoid::ALL_CHESTS[new_val];
|
||||
self.ids.beard_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.beard = humanoid::ALL_BEARDS[new_val];
|
||||
}
|
||||
} else {
|
||||
Text::new("Beard")
|
||||
@ -1043,22 +986,15 @@ impl CharSelectionUi {
|
||||
.font_id(self.fonts.metamorph)
|
||||
.color(TEXT_COLOR_2)
|
||||
.set(self.ids.beard_text, ui_widgets);
|
||||
if let Some(_val) = ImageSlider::continuous(
|
||||
5.0,
|
||||
0.0,
|
||||
10.0,
|
||||
self.imgs.nothing,
|
||||
self.imgs.slider_range,
|
||||
)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.beard_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.track_color(Color::Rgba(1.0, 1.0, 1.0, 0.2))
|
||||
.slider_color(Color::Rgba(1.0, 1.0, 1.0, 0.2))
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.beard_slider_2, ui_widgets)
|
||||
{}
|
||||
ImageSlider::continuous(5.0, 0.0, 10.0, self.imgs.nothing, self.imgs.slider_range)
|
||||
.w_h(208.0, 22.0)
|
||||
.mid_bottom_with_margin_on(self.ids.beard_text, -30.0)
|
||||
.track_breadth(12.0)
|
||||
.slider_length(10.0)
|
||||
.track_color(Color::Rgba(1.0, 1.0, 1.0, 0.2))
|
||||
.slider_color(Color::Rgba(1.0, 1.0, 1.0, 0.2))
|
||||
.pad_track((5.0, 5.0))
|
||||
.set(self.ids.beard_slider_2, ui_widgets);
|
||||
}
|
||||
} // Char Creation fin
|
||||
|
||||
|
@ -3,7 +3,10 @@ use crate::{
|
||||
anim::SkeletonAttr,
|
||||
render::{FigurePipeline, Mesh, Model, Renderer},
|
||||
};
|
||||
use common::comp::{Body, Equipment};
|
||||
use common::{
|
||||
assets::watch::ReloadIndicator,
|
||||
comp::{Body, Equipment},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
@ -14,12 +17,14 @@ enum FigureKey {
|
||||
|
||||
pub struct FigureModelCache {
|
||||
models: HashMap<FigureKey, ((Model<FigurePipeline>, SkeletonAttr), u64)>,
|
||||
manifest_indicator: ReloadIndicator,
|
||||
}
|
||||
|
||||
impl FigureModelCache {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
models: HashMap::new(),
|
||||
manifest_indicator: ReloadIndicator::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,32 +50,44 @@ impl FigureModelCache {
|
||||
key.clone(),
|
||||
(
|
||||
{
|
||||
let humanoid_head_spec =
|
||||
HumHeadSpec::load_watched(&mut self.manifest_indicator);
|
||||
let bone_meshes = match body {
|
||||
Body::Humanoid(body) => [
|
||||
Some(load_head(body.race, body.body_type)),
|
||||
Some(load_chest(body.chest)),
|
||||
Some(load_belt(body.belt)),
|
||||
Some(load_pants(body.pants)),
|
||||
Some(load_left_hand(body.hand)),
|
||||
Some(load_right_hand(body.hand)),
|
||||
Some(load_left_foot(body.foot)),
|
||||
Some(load_right_foot(body.foot)),
|
||||
Some(load_main(equipment.and_then(|e| e.main.as_ref()))),
|
||||
Some(load_left_shoulder(body.shoulder)),
|
||||
Some(load_right_shoulder(body.shoulder)),
|
||||
Some(load_draw()),
|
||||
Some(humanoid_head_spec.mesh_head(
|
||||
body.race,
|
||||
body.body_type,
|
||||
body.hair_color,
|
||||
body.hair_style,
|
||||
body.beard,
|
||||
body.eye_color,
|
||||
body.skin,
|
||||
body.eyebrows,
|
||||
body.accessory,
|
||||
)),
|
||||
Some(mesh_chest(body.chest)),
|
||||
Some(mesh_belt(body.belt)),
|
||||
Some(mesh_pants(body.pants)),
|
||||
Some(mesh_left_hand(body.hand)),
|
||||
Some(mesh_right_hand(body.hand)),
|
||||
Some(mesh_left_foot(body.foot)),
|
||||
Some(mesh_right_foot(body.foot)),
|
||||
Some(mesh_main(equipment.and_then(|e| e.main.as_ref()))),
|
||||
Some(mesh_left_shoulder(body.shoulder)),
|
||||
Some(mesh_right_shoulder(body.shoulder)),
|
||||
Some(mesh_draw()),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
],
|
||||
Body::Quadruped(body) => [
|
||||
Some(load_pig_head(body.head)),
|
||||
Some(load_pig_chest(body.chest)),
|
||||
Some(load_pig_leg_lf(body.leg_l)),
|
||||
Some(load_pig_leg_rf(body.leg_r)),
|
||||
Some(load_pig_leg_lb(body.leg_l)),
|
||||
Some(load_pig_leg_rb(body.leg_r)),
|
||||
Some(mesh_pig_head(body.head)),
|
||||
Some(mesh_pig_chest(body.chest)),
|
||||
Some(mesh_pig_leg_lf(body.leg_l)),
|
||||
Some(mesh_pig_leg_rf(body.leg_r)),
|
||||
Some(mesh_pig_leg_lb(body.leg_l)),
|
||||
Some(mesh_pig_leg_rb(body.leg_r)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -83,17 +100,17 @@ impl FigureModelCache {
|
||||
None,
|
||||
],
|
||||
Body::QuadrupedMedium(body) => [
|
||||
Some(load_wolf_head_upper(body.head_upper)),
|
||||
Some(load_wolf_jaw(body.jaw)),
|
||||
Some(load_wolf_head_lower(body.head_lower)),
|
||||
Some(load_wolf_tail(body.tail)),
|
||||
Some(load_wolf_torso_back(body.torso_back)),
|
||||
Some(load_wolf_torso_mid(body.torso_mid)),
|
||||
Some(load_wolf_ears(body.ears)),
|
||||
Some(load_wolf_foot_lf(body.foot_lf)),
|
||||
Some(load_wolf_foot_rf(body.foot_rf)),
|
||||
Some(load_wolf_foot_lb(body.foot_lb)),
|
||||
Some(load_wolf_foot_rb(body.foot_rb)),
|
||||
Some(mesh_wolf_head_upper(body.head_upper)),
|
||||
Some(mesh_wolf_jaw(body.jaw)),
|
||||
Some(mesh_wolf_head_lower(body.head_lower)),
|
||||
Some(mesh_wolf_tail(body.tail)),
|
||||
Some(mesh_wolf_torso_back(body.torso_back)),
|
||||
Some(mesh_wolf_torso_mid(body.torso_mid)),
|
||||
Some(mesh_wolf_ears(body.ears)),
|
||||
Some(mesh_wolf_foot_lf(body.foot_lf)),
|
||||
Some(mesh_wolf_foot_rf(body.foot_rf)),
|
||||
Some(mesh_wolf_foot_lb(body.foot_lb)),
|
||||
Some(mesh_wolf_foot_rb(body.foot_rb)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -101,7 +118,7 @@ impl FigureModelCache {
|
||||
None,
|
||||
],
|
||||
Body::Object(object) => [
|
||||
Some(load_object(object)),
|
||||
Some(mesh_object(object)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -148,6 +165,11 @@ impl FigureModelCache {
|
||||
}
|
||||
|
||||
pub fn clean(&mut self, tick: u64) {
|
||||
// Check for reloaded manifests
|
||||
// TODO: maybe do this in a different function, maintain?
|
||||
if self.manifest_indicator.reloaded() {
|
||||
self.models.clear();
|
||||
}
|
||||
// TODO: Don't hard-code this.
|
||||
self.models
|
||||
.retain(|_, (_, last_used)| *last_used + 60 > tick);
|
||||
|
@ -3,69 +3,184 @@ use crate::{
|
||||
render::{FigurePipeline, Mesh},
|
||||
};
|
||||
use common::{
|
||||
assets,
|
||||
assets::{self, watch::ReloadIndicator, Asset},
|
||||
comp::{
|
||||
humanoid::{Belt, BodyType, Chest, Foot, Hand, Pants, Race, Shoulder},
|
||||
humanoid::{
|
||||
Accessory, Beard, Belt, BodyType, Chest, EyeColor, Eyebrows, Foot, HairColor,
|
||||
HairStyle, Hand, Pants, Race, Shoulder, Skin,
|
||||
},
|
||||
item::Tool,
|
||||
object, quadruped, quadruped_medium, Item,
|
||||
},
|
||||
figure::Segment,
|
||||
figure::{Segment, SegmentUnionizer},
|
||||
};
|
||||
use dot_vox::DotVoxData;
|
||||
use hashbrown::HashMap;
|
||||
use log::{error, warn};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs::File, io::BufReader, sync::Arc};
|
||||
use vek::*;
|
||||
|
||||
pub fn load_segment(mesh_name: &str) -> Segment {
|
||||
let full_specifier: String = ["voxygen.voxel.", mesh_name].concat();
|
||||
Segment::from(assets::load_expect::<DotVoxData>(full_specifier.as_str()).as_ref())
|
||||
}
|
||||
pub fn graceful_load_segment(mesh_name: &str) -> Segment {
|
||||
let full_specifier: String = ["voxygen.voxel.", mesh_name].concat();
|
||||
let dot_vox = match assets::load::<DotVoxData>(full_specifier.as_str()) {
|
||||
Ok(dot_vox) => dot_vox,
|
||||
Err(_) => {
|
||||
error!("Could not load vox file for figure: {}", full_specifier);
|
||||
assets::load_expect::<DotVoxData>("voxygen.voxel.not_found")
|
||||
}
|
||||
};
|
||||
Segment::from(dot_vox.as_ref())
|
||||
}
|
||||
pub fn load_mesh(mesh_name: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
|
||||
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(&load_segment(mesh_name), position).0
|
||||
}
|
||||
|
||||
pub fn load_head(race: Race, body_type: BodyType) -> Mesh<FigurePipeline> {
|
||||
let (name, offset) = match (race, body_type) {
|
||||
// z-value should be 0.25 of the total z
|
||||
(Race::Human, BodyType::Male) => {
|
||||
("figure.head.head_human_male", Vec3::new(-7.0, -5.0, -2.25))
|
||||
}
|
||||
(Race::Human, BodyType::Female) => (
|
||||
"figure.head.head_human_female",
|
||||
Vec3::new(-7.0, -7.5, -3.25),
|
||||
),
|
||||
(Race::Elf, BodyType::Male) => ("figure.head.head_elf_male", Vec3::new(-8.0, -5.0, -2.25)),
|
||||
(Race::Elf, BodyType::Female) => {
|
||||
("figure.head.head_elf_female", Vec3::new(-8.0, -5.5, -3.0))
|
||||
}
|
||||
(Race::Dwarf, BodyType::Male) => {
|
||||
("figure.head.head_dwarf_male", Vec3::new(-6.0, -5.0, -12.5))
|
||||
}
|
||||
(Race::Dwarf, BodyType::Female) => (
|
||||
"figure.head.head_dwarf_female",
|
||||
Vec3::new(-6.0, -6.0, -9.25),
|
||||
),
|
||||
(Race::Orc, BodyType::Male) => ("figure.head.head_orc_male", Vec3::new(-8.0, -5.0, -2.50)),
|
||||
(Race::Orc, BodyType::Female) => {
|
||||
("figure.head.head_orc_female", Vec3::new(-8.0, -8.0, -3.5))
|
||||
}
|
||||
(Race::Undead, BodyType::Male) => {
|
||||
("figure.head.head_undead_male", Vec3::new(-5.5, -5.0, -2.5))
|
||||
}
|
||||
(Race::Undead, BodyType::Female) => (
|
||||
"figure.head.head_undead_female",
|
||||
Vec3::new(-6.0, -5.0, -2.5),
|
||||
),
|
||||
(Race::Danari, BodyType::Male) => {
|
||||
("figure.head.head_danari_male", Vec3::new(-9.0, -5.0, -2.75))
|
||||
}
|
||||
(Race::Danari, BodyType::Female) => (
|
||||
"figure.head.head_danari_female",
|
||||
Vec3::new(-9.0, -7.5, -3.0),
|
||||
),
|
||||
};
|
||||
load_mesh(name, offset)
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct VoxSpec(String, [i32; 3]); // All offsets should be relative to an initial origin that doesn't change when combining segments
|
||||
// All reliant on humanoid::Race and humanoid::BodyType
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct HumHeadSubSpec {
|
||||
offset: [f32; 3], // Should be relative to initial origin
|
||||
head: VoxSpec,
|
||||
eyes: VoxSpec,
|
||||
hair: HashMap<HairStyle, Option<VoxSpec>>,
|
||||
beard: HashMap<Beard, Option<VoxSpec>>,
|
||||
accessory: HashMap<Accessory, Option<VoxSpec>>,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct HumHeadSpec(HashMap<(Race, BodyType), HumHeadSubSpec>);
|
||||
|
||||
impl Asset for HumHeadSpec {
|
||||
const ENDINGS: &'static [&'static str] = &["ron"];
|
||||
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
|
||||
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid head spec"))
|
||||
}
|
||||
}
|
||||
|
||||
impl HumHeadSpec {
|
||||
pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc<Self> {
|
||||
assets::load_watched::<Self>("voxygen.voxel.humanoid_head_manifest", indicator).unwrap()
|
||||
}
|
||||
pub fn mesh_head(
|
||||
&self,
|
||||
race: Race,
|
||||
body_type: BodyType,
|
||||
hair_color: HairColor,
|
||||
hair_style: HairStyle,
|
||||
beard: Beard,
|
||||
eye_color: EyeColor,
|
||||
skin: Skin,
|
||||
eyebrows: Eyebrows,
|
||||
accessory: Accessory,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(race, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No head specification exists for the combination of {:?} and {:?}",
|
||||
race, body_type
|
||||
);
|
||||
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -5.0));
|
||||
}
|
||||
};
|
||||
// TODO: color hair(via index or recoloring), color skin(via index)
|
||||
// Load segment pieces
|
||||
let bare_head = graceful_load_segment(&spec.head.0);
|
||||
let eyes = graceful_load_segment(&spec.eyes.0);
|
||||
let hair = match spec.hair.get(&hair_style) {
|
||||
Some(Some(spec)) => Some((graceful_load_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(None) => None,
|
||||
None => {
|
||||
warn!("No specification for this hair style: {:?}", hair_style);
|
||||
None
|
||||
}
|
||||
};
|
||||
let beard = match spec.beard.get(&beard) {
|
||||
Some(Some(spec)) => Some((graceful_load_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(None) => None,
|
||||
None => {
|
||||
warn!("No specification for this beard: {:?}", beard);
|
||||
None
|
||||
}
|
||||
};
|
||||
let accessory = match spec.accessory.get(&accessory) {
|
||||
Some(Some(spec)) => Some((graceful_load_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(None) => None,
|
||||
None => {
|
||||
warn!("No specification for this accessory: {:?}", accessory);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let (head, origin_offset) = SegmentUnionizer::new()
|
||||
.add(bare_head, spec.head.1.into())
|
||||
.add(eyes, spec.eyes.1.into())
|
||||
.maybe_add(hair)
|
||||
.maybe_add(beard)
|
||||
.maybe_add(accessory)
|
||||
.unify();
|
||||
|
||||
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(
|
||||
&head,
|
||||
Vec3::from(spec.offset) + origin_offset.map(|e| e as f32 * -1.0),
|
||||
)
|
||||
.0
|
||||
/*let (name, offset) = match (race, body_type) {
|
||||
// z-value should be 0.25 of the total z
|
||||
(Race::Human, BodyType::Male) => {
|
||||
("figure.head.head_human_male", Vec3::new(-7.0, -5.0, -2.25))
|
||||
}
|
||||
(Race::Human, BodyType::Female) => (
|
||||
"figure.head.head_human_female",
|
||||
Vec3::new(-7.0, -7.5, -3.25),
|
||||
),
|
||||
(Race::Elf, BodyType::Male) => ("figure.head.head_elf_male", Vec3::new(-8.0, -5.0, -2.25)),
|
||||
(Race::Elf, BodyType::Female) => {
|
||||
("figure.head.head_elf_female", Vec3::new(-8.0, -5.5, -3.0))
|
||||
}
|
||||
(Race::Dwarf, BodyType::Male) => {
|
||||
("figure.head.head_dwarf_male", Vec3::new(-6.0, -5.0, -12.5))
|
||||
}
|
||||
(Race::Dwarf, BodyType::Female) => (
|
||||
"figure.head.head_dwarf_female",
|
||||
Vec3::new(-6.0, -6.0, -9.25),
|
||||
),
|
||||
(Race::Orc, BodyType::Male) => ("figure.head.head_orc_male", Vec3::new(-8.0, -5.0, -2.50)),
|
||||
(Race::Orc, BodyType::Female) => {
|
||||
("figure.head.head_orc_female", Vec3::new(-8.0, -8.0, -3.5))
|
||||
}
|
||||
(Race::Undead, BodyType::Male) => {
|
||||
("figure.head.head_undead_male", Vec3::new(-5.5, -5.0, -2.5))
|
||||
}
|
||||
(Race::Undead, BodyType::Female) => (
|
||||
"figure.head.head_undead_female",
|
||||
Vec3::new(-6.0, -5.0, -2.5),
|
||||
),
|
||||
(Race::Danari, BodyType::Male) => {
|
||||
("figure.head.head_danari_male", Vec3::new(-9.0, -5.0, -2.75))
|
||||
}
|
||||
(Race::Danari, BodyType::Female) => {
|
||||
let hair = load_segment("figure.hair.danari.female");
|
||||
let accessory = load_segment("figure.accessory.danari.horns");
|
||||
let bare_head = load_segment("figure.head.danari.female");
|
||||
let head = bare_head
|
||||
.union(&eyes, Vec3::new(0, 0, 0))
|
||||
.union(&hair, Vec3::new(0, 0, 0))
|
||||
.union(&accessory, Vec3::new(0, 0, 0));
|
||||
|
||||
return head.generate_mesh(Vec3::new(-9.0, -7.5, -3.0)).0;
|
||||
}
|
||||
};*/
|
||||
//load_mesh(name, offset)
|
||||
}
|
||||
}
|
||||
// loads models with different offsets
|
||||
// pub fn load_beard(beard: Beard) -> Mesh<FigurePipeline> {
|
||||
// pub fn mesh_beard(beard: Beard) -> Mesh<FigurePipeline> {
|
||||
// let (name, offset) = match beard {
|
||||
// Beard::None => ("figure/body/empty", Vec3::new(0.0, 0.0, 0.0)),
|
||||
// Beard::Human1 => ("figure/empty", Vec3::new(0.0, 0.0, 0.0)),
|
||||
@ -73,7 +188,7 @@ pub fn load_head(race: Race, body_type: BodyType) -> Mesh<FigurePipeline> {
|
||||
// load_mesh(name, offset)
|
||||
// }
|
||||
|
||||
pub fn load_chest(chest: Chest) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_chest(chest: Chest) -> Mesh<FigurePipeline> {
|
||||
let color = match chest {
|
||||
Chest::Brown => (125, 53, 0),
|
||||
Chest::Dark => (0, 38, 43),
|
||||
@ -89,7 +204,7 @@ pub fn load_chest(chest: Chest) -> Mesh<FigurePipeline> {
|
||||
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(&chest, Vec3::new(-6.0, -3.5, 0.0)).0
|
||||
}
|
||||
|
||||
pub fn load_belt(belt: Belt) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_belt(belt: Belt) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match belt {
|
||||
//Belt::Default => "figure/body/belt_male",
|
||||
@ -99,7 +214,7 @@ pub fn load_belt(belt: Belt) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_pants(pants: Pants) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pants(pants: Pants) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match pants {
|
||||
Pants::Blue => "armor.pants.pants_blue",
|
||||
@ -112,7 +227,7 @@ pub fn load_pants(pants: Pants) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_left_hand(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_left_hand(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match hand {
|
||||
Hand::Default => "figure.body.hand",
|
||||
@ -121,7 +236,7 @@ pub fn load_left_hand(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_right_hand(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_right_hand(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match hand {
|
||||
Hand::Default => "figure.body.hand",
|
||||
@ -130,7 +245,7 @@ pub fn load_right_hand(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_left_foot(foot: Foot) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_left_foot(foot: Foot) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match foot {
|
||||
Foot::Dark => "armor.foot.foot_dark",
|
||||
@ -139,7 +254,7 @@ pub fn load_left_foot(foot: Foot) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_right_foot(foot: Foot) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_right_foot(foot: Foot) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match foot {
|
||||
Foot::Dark => "armor.foot.foot_dark",
|
||||
@ -148,7 +263,7 @@ pub fn load_right_foot(foot: Foot) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_main(item: Option<&Item>) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_main(item: Option<&Item>) -> Mesh<FigurePipeline> {
|
||||
if let Some(item) = item {
|
||||
let (name, offset) = match item {
|
||||
Item::Tool { kind, .. } => match kind {
|
||||
@ -169,7 +284,7 @@ pub fn load_main(item: Option<&Item>) -> Mesh<FigurePipeline> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_left_shoulder(shoulder: Shoulder) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_left_shoulder(shoulder: Shoulder) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match shoulder {
|
||||
Shoulder::None => "figure.empty",
|
||||
@ -179,7 +294,7 @@ pub fn load_left_shoulder(shoulder: Shoulder) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_right_shoulder(shoulder: Shoulder) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_right_shoulder(shoulder: Shoulder) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match shoulder {
|
||||
Shoulder::None => "figure.empty",
|
||||
@ -190,11 +305,11 @@ pub fn load_right_shoulder(shoulder: Shoulder) -> Mesh<FigurePipeline> {
|
||||
}
|
||||
|
||||
// TODO: Inventory
|
||||
pub fn load_draw() -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_draw() -> Mesh<FigurePipeline> {
|
||||
load_mesh("object.glider", Vec3::new(-26.0, -26.0, -5.0))
|
||||
}
|
||||
|
||||
//pub fn load_right_equip(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
//pub fn mesh_right_equip(hand: Hand) -> Mesh<FigurePipeline> {
|
||||
// load_mesh(
|
||||
// match hand {
|
||||
// Hand::Default => "figure/body/hand",
|
||||
@ -204,7 +319,7 @@ pub fn load_draw() -> Mesh<FigurePipeline> {
|
||||
//}
|
||||
|
||||
/////////
|
||||
pub fn load_pig_head(head: quadruped::Head) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pig_head(head: quadruped::Head) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match head {
|
||||
quadruped::Head::Default => "npc.pig_purple.pig_head",
|
||||
@ -213,7 +328,7 @@ pub fn load_pig_head(head: quadruped::Head) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_pig_chest(chest: quadruped::Chest) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pig_chest(chest: quadruped::Chest) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match chest {
|
||||
quadruped::Chest::Default => "npc.pig_purple.pig_chest",
|
||||
@ -222,7 +337,7 @@ pub fn load_pig_chest(chest: quadruped::Chest) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_pig_leg_lf(leg_l: quadruped::LegL) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pig_leg_lf(leg_l: quadruped::LegL) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match leg_l {
|
||||
quadruped::LegL::Default => "npc.pig_purple.pig_leg_l",
|
||||
@ -231,7 +346,7 @@ pub fn load_pig_leg_lf(leg_l: quadruped::LegL) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_pig_leg_rf(leg_r: quadruped::LegR) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pig_leg_rf(leg_r: quadruped::LegR) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match leg_r {
|
||||
quadruped::LegR::Default => "npc.pig_purple.pig_leg_r",
|
||||
@ -240,7 +355,7 @@ pub fn load_pig_leg_rf(leg_r: quadruped::LegR) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_pig_leg_lb(leg_l: quadruped::LegL) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pig_leg_lb(leg_l: quadruped::LegL) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match leg_l {
|
||||
quadruped::LegL::Default => "npc.pig_purple.pig_leg_l",
|
||||
@ -249,7 +364,7 @@ pub fn load_pig_leg_lb(leg_l: quadruped::LegL) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_pig_leg_rb(leg_r: quadruped::LegR) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_pig_leg_rb(leg_r: quadruped::LegR) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match leg_r {
|
||||
quadruped::LegR::Default => "npc.pig_purple.pig_leg_r",
|
||||
@ -258,7 +373,7 @@ pub fn load_pig_leg_rb(leg_r: quadruped::LegR) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
//////
|
||||
pub fn load_wolf_head_upper(upper_head: quadruped_medium::HeadUpper) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_head_upper(upper_head: quadruped_medium::HeadUpper) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match upper_head {
|
||||
quadruped_medium::HeadUpper::Default => "npc.wolf.wolf_head_upper",
|
||||
@ -267,7 +382,7 @@ pub fn load_wolf_head_upper(upper_head: quadruped_medium::HeadUpper) -> Mesh<Fig
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_jaw(jaw: quadruped_medium::Jaw) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_jaw(jaw: quadruped_medium::Jaw) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match jaw {
|
||||
quadruped_medium::Jaw::Default => "npc.wolf.wolf_jaw",
|
||||
@ -276,7 +391,7 @@ pub fn load_wolf_jaw(jaw: quadruped_medium::Jaw) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_head_lower(head_lower: quadruped_medium::HeadLower) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_head_lower(head_lower: quadruped_medium::HeadLower) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match head_lower {
|
||||
quadruped_medium::HeadLower::Default => "npc.wolf.wolf_head_lower",
|
||||
@ -285,7 +400,7 @@ pub fn load_wolf_head_lower(head_lower: quadruped_medium::HeadLower) -> Mesh<Fig
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_tail(tail: quadruped_medium::Tail) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_tail(tail: quadruped_medium::Tail) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match tail {
|
||||
quadruped_medium::Tail::Default => "npc.wolf.wolf_tail",
|
||||
@ -294,7 +409,7 @@ pub fn load_wolf_tail(tail: quadruped_medium::Tail) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_torso_back(torso_back: quadruped_medium::TorsoBack) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_torso_back(torso_back: quadruped_medium::TorsoBack) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match torso_back {
|
||||
quadruped_medium::TorsoBack::Default => "npc.wolf.wolf_torso_back",
|
||||
@ -303,7 +418,7 @@ pub fn load_wolf_torso_back(torso_back: quadruped_medium::TorsoBack) -> Mesh<Fig
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_torso_mid(torso_mid: quadruped_medium::TorsoMid) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_torso_mid(torso_mid: quadruped_medium::TorsoMid) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match torso_mid {
|
||||
quadruped_medium::TorsoMid::Default => "npc.wolf.wolf_torso_mid",
|
||||
@ -312,7 +427,7 @@ pub fn load_wolf_torso_mid(torso_mid: quadruped_medium::TorsoMid) -> Mesh<Figure
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_ears(ears: quadruped_medium::Ears) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_ears(ears: quadruped_medium::Ears) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match ears {
|
||||
quadruped_medium::Ears::Default => "npc.wolf.wolf_ears",
|
||||
@ -321,7 +436,7 @@ pub fn load_wolf_ears(ears: quadruped_medium::Ears) -> Mesh<FigurePipeline> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_foot_lf(foot_lf: quadruped_medium::FootLF) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_foot_lf(foot_lf: quadruped_medium::FootLF) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match foot_lf {
|
||||
quadruped_medium::FootLF::Default => "npc.wolf.wolf_foot_lf",
|
||||
@ -330,7 +445,7 @@ pub fn load_wolf_foot_lf(foot_lf: quadruped_medium::FootLF) -> Mesh<FigurePipeli
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_foot_rf(foot_rf: quadruped_medium::FootRF) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_foot_rf(foot_rf: quadruped_medium::FootRF) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match foot_rf {
|
||||
quadruped_medium::FootRF::Default => "npc.wolf.wolf_foot_rf",
|
||||
@ -339,7 +454,7 @@ pub fn load_wolf_foot_rf(foot_rf: quadruped_medium::FootRF) -> Mesh<FigurePipeli
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_foot_lb(foot_lb: quadruped_medium::FootLB) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_foot_lb(foot_lb: quadruped_medium::FootLB) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match foot_lb {
|
||||
quadruped_medium::FootLB::Default => "npc.wolf.wolf_foot_lb",
|
||||
@ -348,7 +463,7 @@ pub fn load_wolf_foot_lb(foot_lb: quadruped_medium::FootLB) -> Mesh<FigurePipeli
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_wolf_foot_rb(foot_rb: quadruped_medium::FootRB) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_wolf_foot_rb(foot_rb: quadruped_medium::FootRB) -> Mesh<FigurePipeline> {
|
||||
load_mesh(
|
||||
match foot_rb {
|
||||
quadruped_medium::FootRB::Default => "npc.wolf.wolf_foot_rb",
|
||||
@ -357,7 +472,7 @@ pub fn load_wolf_foot_rb(foot_rb: quadruped_medium::FootRB) -> Mesh<FigurePipeli
|
||||
)
|
||||
}
|
||||
|
||||
pub fn load_object(obj: object::Body) -> Mesh<FigurePipeline> {
|
||||
pub fn mesh_object(obj: object::Body) -> Mesh<FigurePipeline> {
|
||||
use object::Body;
|
||||
|
||||
let (name, offset) = match obj {
|
||||
|
Loading…
Reference in New Issue
Block a user