mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
adjust how figure head coloring is done
This commit is contained in:
parent
9654262938
commit
c4999f5e9d
BIN
assets/voxygen/voxel/figure/hair/danari/female.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/figure/hair/danari/female.vox
(Stored with Git LFS)
Binary file not shown.
@ -1,4 +1,5 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use rand::{seq::SliceRandom, thread_rng, Rng};
|
||||
use vek::Rgb;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
@ -10,20 +11,21 @@ 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,
|
||||
pub hair_color: u8,
|
||||
pub skin: u8,
|
||||
pub eye_color: u8,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
pub fn random() -> Self {
|
||||
let mut rng = thread_rng();
|
||||
let race = *(&ALL_RACES).choose(&mut rng).unwrap();
|
||||
Self {
|
||||
race: *(&ALL_RACES).choose(&mut rng).unwrap(),
|
||||
race,
|
||||
body_type: *(&ALL_BODY_TYPES).choose(&mut rng).unwrap(),
|
||||
chest: *(&ALL_CHESTS).choose(&mut rng).unwrap(),
|
||||
belt: *(&ALL_BELTS).choose(&mut rng).unwrap(),
|
||||
@ -31,13 +33,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(),
|
||||
hair_color: rng.gen_range(0, race.num_hair_colors()) as u8,
|
||||
skin: rng.gen_range(0, race.num_skin_colors()) as u8,
|
||||
eye_color: rng.gen_range(0, race.num_eye_colors()) as u8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,6 +61,92 @@ pub const ALL_RACES: [Race; 6] = [
|
||||
Race::Orc,
|
||||
Race::Undead,
|
||||
];
|
||||
// Hair Colors
|
||||
pub const DANARI_HAIR_COLORS: [(u8, u8, u8); 4] = [
|
||||
(198, 169, 113),
|
||||
(200, 100, 100),
|
||||
(100, 100, 200),
|
||||
(100, 200, 100),
|
||||
];
|
||||
pub const DWARF_HAIR_COLORS: [(u8, u8, u8); 3] =
|
||||
[(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const ELF_HAIR_COLORS: [(u8, u8, u8); 3] = [(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const HUMAN_HAIR_COLORS: [(u8, u8, u8); 3] =
|
||||
[(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const ORC_HAIR_COLORS: [(u8, u8, u8); 3] = [(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const UNDEAD_HAIR_COLORS: [(u8, u8, u8); 3] =
|
||||
[(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
// Skin colors
|
||||
pub const DANARI_SKIN_COLORS: [(u8, u8, u8); 4] = [
|
||||
(198, 169, 113),
|
||||
(200, 100, 100),
|
||||
(100, 100, 200),
|
||||
(100, 200, 100),
|
||||
];
|
||||
pub const DWARF_SKIN_COLORS: [(u8, u8, u8); 3] =
|
||||
[(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const ELF_SKIN_COLORS: [(u8, u8, u8); 3] = [(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const HUMAN_SKIN_COLORS: [(u8, u8, u8); 3] =
|
||||
[(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const ORC_SKIN_COLORS: [(u8, u8, u8); 3] = [(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
pub const UNDEAD_SKIN_COLORS: [(u8, u8, u8); 3] =
|
||||
[(200, 100, 100), (100, 100, 200), (100, 200, 100)];
|
||||
impl Race {
|
||||
fn hair_colors(self) -> &'static [(u8, u8, u8)] {
|
||||
match self {
|
||||
Race::Danari => &DANARI_HAIR_COLORS,
|
||||
Race::Dwarf => &DWARF_HAIR_COLORS,
|
||||
Race::Elf => &ELF_HAIR_COLORS,
|
||||
Race::Human => &HUMAN_HAIR_COLORS,
|
||||
Race::Orc => &ORC_HAIR_COLORS,
|
||||
Race::Undead => &UNDEAD_HAIR_COLORS,
|
||||
}
|
||||
}
|
||||
fn skin_colors(self) -> &'static [(u8, u8, u8)] {
|
||||
match self {
|
||||
Race::Danari => &DANARI_SKIN_COLORS,
|
||||
Race::Dwarf => &DWARF_SKIN_COLORS,
|
||||
Race::Elf => &ELF_SKIN_COLORS,
|
||||
Race::Human => &HUMAN_SKIN_COLORS,
|
||||
Race::Orc => &ORC_SKIN_COLORS,
|
||||
Race::Undead => &UNDEAD_SKIN_COLORS,
|
||||
}
|
||||
}
|
||||
fn eye_colors(self) -> &'static [EyeColor] {
|
||||
match self {
|
||||
_ => &ALL_EYE_COLORS,
|
||||
}
|
||||
}
|
||||
pub fn hair_color(self, val: u8) -> Rgb<u8> {
|
||||
self.hair_colors()
|
||||
.get(val as usize)
|
||||
.copied()
|
||||
.unwrap_or((0, 0, 0))
|
||||
.into()
|
||||
}
|
||||
pub fn num_hair_colors(self) -> usize {
|
||||
self.hair_colors().len()
|
||||
}
|
||||
pub fn skin_color(self, val: u8) -> Rgb<u8> {
|
||||
self.skin_colors()
|
||||
.get(val as usize)
|
||||
.copied()
|
||||
.unwrap_or((0, 0, 0))
|
||||
.into()
|
||||
}
|
||||
pub fn num_skin_colors(self) -> usize {
|
||||
self.skin_colors().len()
|
||||
}
|
||||
pub fn eye_color(self, val: u8) -> EyeColor {
|
||||
self.eye_colors()
|
||||
.get(val as usize)
|
||||
.copied()
|
||||
.unwrap_or(EyeColor::Black)
|
||||
}
|
||||
pub fn num_eye_colors(self) -> usize {
|
||||
self.eye_colors().len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum BodyType {
|
||||
@ -135,31 +223,6 @@ pub enum HairStyle {
|
||||
}
|
||||
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,
|
||||
@ -183,6 +246,34 @@ pub const ALL_EYE_COLORS: [EyeColor; 6] = [
|
||||
EyeColor::Red,
|
||||
EyeColor::White,
|
||||
];
|
||||
impl EyeColor {
|
||||
pub fn light_rgb(self) -> Rgb<u8> {
|
||||
match self {
|
||||
EyeColor::Black => Rgb::new(0, 0, 0),
|
||||
EyeColor::Blue => Rgb::new(0, 0, 200),
|
||||
EyeColor::Green => Rgb::new(0, 200, 0),
|
||||
EyeColor::Brown => Rgb::new(150, 150, 0),
|
||||
EyeColor::Red => Rgb::new(255, 0, 0),
|
||||
EyeColor::White => Rgb::new(255, 255, 255),
|
||||
}
|
||||
}
|
||||
pub fn dark_rgb(self) -> Rgb<u8> {
|
||||
match self {
|
||||
EyeColor::Black => Rgb::new(0, 0, 0),
|
||||
EyeColor::Blue => Rgb::new(0, 0, 100),
|
||||
EyeColor::Green => Rgb::new(0, 100, 0),
|
||||
EyeColor::Brown => Rgb::new(50, 50, 0),
|
||||
EyeColor::Red => Rgb::new(200, 0, 0),
|
||||
EyeColor::White => Rgb::new(255, 255, 255),
|
||||
}
|
||||
}
|
||||
pub fn white_rgb(self) -> Rgb<u8> {
|
||||
match self {
|
||||
EyeColor::White => Rgb::new(0, 0, 0),
|
||||
_ => Rgb::new(255, 255, 255),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Accessory {
|
||||
|
@ -51,34 +51,52 @@ impl From<&DotVoxData> for Segment {
|
||||
}
|
||||
|
||||
impl Segment {
|
||||
/// Replaces one cell with another
|
||||
pub fn replace(mut self, old: Cell, new: Cell) -> Self {
|
||||
/// Transform cells
|
||||
pub fn map(mut self, transform: impl Fn(Cell) -> Option<Cell>) -> Self {
|
||||
for pos in self.iter_positions() {
|
||||
if old == *self.get(pos).unwrap() {
|
||||
if let Some(new) = transform(*self.get(pos).unwrap()) {
|
||||
self.set(pos, new).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
let cell = match self.get(pos).unwrap() {
|
||||
Cell::Filled(rgb) => Cell::Filled(
|
||||
chromify_srgb(Rgb::from_slice(rgb).map(|e| e as f32 / 255.0), chroma)
|
||||
.map(|e| (e * 255.0) as u8)
|
||||
.into_array(),
|
||||
),
|
||||
Cell::Empty => continue,
|
||||
};
|
||||
self.set(pos, cell).unwrap();
|
||||
}
|
||||
|
||||
self
|
||||
/// Transform cell colors
|
||||
pub fn map_rgb(self, transform: impl Fn(Rgb<u8>) -> Rgb<u8>) -> Self {
|
||||
self.map(|cell| cell.get_color().map(|rgb| Cell::new(transform(rgb))))
|
||||
}
|
||||
/// Replaces one cell with another
|
||||
// TODO unused -> remove?
|
||||
pub fn replace(self, old: Cell, new: Cell) -> Self {
|
||||
self.map(|cell| if cell == old { Some(new) } else { None })
|
||||
}
|
||||
/// Preserve the luminance of all the colors but set the chomaticity to match the provided color
|
||||
pub fn chromify(self, chroma: Rgb<u8>) -> Self {
|
||||
let chroma = chroma.map(|e| e as f32 / 255.0);
|
||||
self.map_rgb(|rgb| {
|
||||
chromify_srgb(rgb.map(|e| e as f32 / 255.0), chroma).map(|e| (e * 255.0) as u8)
|
||||
})
|
||||
}
|
||||
// Sets the chromaticity based on the provided color
|
||||
// Multiplies luma with luma of the provided color (might not be what we want)
|
||||
/*pub fn colorify(mut self, color: Rgb<u8>) -> Self {
|
||||
self.map_rgb(|rgb| {
|
||||
let l = rgb_to_xyy(srgb_to_linear(rgb.map(|e| e as f32 / 255.0))).z;
|
||||
let mut xyy = rgb_to_xyy(srgb_to_linear(color.map(|e| e as f32 / 255.0)));
|
||||
xyy.z = l;
|
||||
|
||||
linear_to_srgb(xyy_to_rgb(xyy).map(|e| e.min(1.0).max(0.0))).map(|e| (e * 255.0) as u8)
|
||||
})
|
||||
}
|
||||
// Multiplies the supplied color with all the current colors in linear space
|
||||
pub fn tint(mut self, color: Rgb<u8>) -> Self {
|
||||
self.map_rgb(|rgb| {
|
||||
let c1 = srgb_to_linear(rgb.map(|e| e as f32 / 255.0));
|
||||
let c2 = srgb_to_linear(color.map(|e| e as f32 / 255.0));
|
||||
|
||||
linear_to_srgb(c1*c2).map(|e| (e.min(1.0).max(0.0) * 255.0) as u8)
|
||||
})
|
||||
}*/
|
||||
}
|
||||
|
||||
// TODO: move
|
||||
|
@ -883,36 +883,28 @@ impl CharSelectionUi {
|
||||
self.character_body.hair_style = humanoid::ALL_HAIR_STYLES[new_val];
|
||||
}
|
||||
// Hair Color
|
||||
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_hair_color)
|
||||
.unwrap_or(0),
|
||||
self.character_body.race.num_hair_colors() - 1,
|
||||
self.character_body.hair_color as usize,
|
||||
self.ids.haircolor_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.hair_color = humanoid::ALL_HAIR_COLORS[new_val];
|
||||
self.character_body.hair_color = new_val as u8;
|
||||
}
|
||||
// Skin
|
||||
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_skin)
|
||||
.unwrap_or(0),
|
||||
self.character_body.race.num_skin_colors() - 1,
|
||||
self.character_body.skin as usize,
|
||||
self.ids.skin_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.skin = humanoid::ALL_SKINS[new_val];
|
||||
self.character_body.skin = new_val as u8;
|
||||
}
|
||||
// Eyebrows
|
||||
let current_eyebrows = self.character_body.eyebrows;
|
||||
@ -931,20 +923,16 @@ impl CharSelectionUi {
|
||||
self.character_body.eyebrows = humanoid::ALL_EYEBROWS[new_val];
|
||||
}
|
||||
// EyeColor
|
||||
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_eye_color)
|
||||
.unwrap_or(0),
|
||||
self.character_body.race.num_eye_colors() - 1,
|
||||
self.character_body.eye_color as usize,
|
||||
self.ids.eyecolor_slider,
|
||||
ui_widgets,
|
||||
) {
|
||||
self.character_body.eye_color = humanoid::ALL_EYE_COLORS[new_val];
|
||||
self.character_body.eye_color = new_val as u8;
|
||||
}
|
||||
// Accessories
|
||||
let current_accessory = self.character_body.accessory;
|
||||
|
@ -6,8 +6,8 @@ use common::{
|
||||
assets::{self, watch::ReloadIndicator, Asset},
|
||||
comp::{
|
||||
humanoid::{
|
||||
Accessory, Beard, Belt, BodyType, Chest, EyeColor, Eyebrows, Foot, HairColor,
|
||||
HairStyle, Hand, Pants, Race, Shoulder, Skin,
|
||||
Accessory, Beard, Belt, BodyType, Chest, EyeColor, Eyebrows, Foot, HairStyle, Hand,
|
||||
Pants, Race, Shoulder,
|
||||
},
|
||||
item::Tool,
|
||||
object, quadruped, quadruped_medium, Item,
|
||||
@ -21,25 +21,48 @@ use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs::File, io::BufReader, sync::Arc};
|
||||
use vek::*;
|
||||
|
||||
pub fn load_segment(mesh_name: &str) -> Segment {
|
||||
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_mat_segment(mesh_name: &str) -> MatSegment {
|
||||
fn graceful_load_vox(mesh_name: &str) -> Arc<DotVoxData> {
|
||||
let full_specifier: String = ["voxygen.voxel.", mesh_name].concat();
|
||||
let dot_vox = match assets::load::<DotVoxData>(full_specifier.as_str()) {
|
||||
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")
|
||||
}
|
||||
};
|
||||
MatSegment::from(dot_vox.as_ref())
|
||||
}
|
||||
}
|
||||
fn graceful_load_segment(mesh_name: &str) -> Segment {
|
||||
Segment::from(graceful_load_vox(mesh_name).as_ref())
|
||||
}
|
||||
fn graceful_load_mat_segment(mesh_name: &str) -> MatSegment {
|
||||
MatSegment::from(graceful_load_vox(mesh_name).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
|
||||
}
|
||||
|
||||
fn color_segment(
|
||||
mat_segment: MatSegment,
|
||||
skin: Rgb<u8>,
|
||||
hair_color: Rgb<u8>,
|
||||
eye_color: EyeColor,
|
||||
) -> Segment {
|
||||
// TODO move some of the colors to common
|
||||
mat_segment.to_segment(|mat| match mat {
|
||||
Material::Skin => skin,
|
||||
Material::Hair => hair_color,
|
||||
// TODO add back multiple colors
|
||||
Material::EyeLight => eye_color.light_rgb(),
|
||||
Material::EyeDark => eye_color.dark_rgb(),
|
||||
Material::EyeWhite => eye_color.white_rgb(),
|
||||
})
|
||||
}
|
||||
|
||||
#[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
|
||||
@ -70,11 +93,11 @@ impl HumHeadSpec {
|
||||
&self,
|
||||
race: Race,
|
||||
body_type: BodyType,
|
||||
hair_color: HairColor,
|
||||
hair_color: u8,
|
||||
hair_style: HairStyle,
|
||||
beard: Beard,
|
||||
eye_color: EyeColor,
|
||||
skin: Skin,
|
||||
eye_color: u8,
|
||||
skin: u8,
|
||||
_eyebrows: Eyebrows,
|
||||
accessory: Accessory,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
@ -88,11 +111,35 @@ impl HumHeadSpec {
|
||||
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
|
||||
}
|
||||
};
|
||||
|
||||
let hair_rgb = race.hair_color(hair_color);
|
||||
let skin_rgb = race.skin_color(skin);
|
||||
let eye_color = race.eye_color(eye_color);
|
||||
|
||||
fn recolor_greys(segment: Segment, color: Rgb<u8>) -> Segment {
|
||||
use common::util::{linear_to_srgb, srgb_to_linear};
|
||||
|
||||
segment.map_rgb(|rgb| {
|
||||
const BASE_GREY: f32 = 178.0;
|
||||
if rgb.r == rgb.g && rgb.g == rgb.b {
|
||||
let c1 = srgb_to_linear(rgb.map(|e| e as f32 / BASE_GREY));
|
||||
let c2 = srgb_to_linear(color.map(|e| e as f32 / 255.0));
|
||||
|
||||
linear_to_srgb(c1 * c2).map(|e| (e.min(1.0).max(0.0) * 255.0) as u8)
|
||||
} else {
|
||||
rgb
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Load segment pieces
|
||||
let bare_head = graceful_load_mat_segment(&spec.head.0);
|
||||
let eyes = graceful_load_mat_segment(&spec.eyes.0);
|
||||
let hair = match spec.hair.get(&hair_style) {
|
||||
Some(Some(spec)) => Some((graceful_load_mat_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(Some(spec)) => Some((
|
||||
recolor_greys(graceful_load_segment(&spec.0), hair_rgb),
|
||||
Vec3::from(spec.1),
|
||||
)),
|
||||
Some(None) => None,
|
||||
None => {
|
||||
warn!("No specification for this hair style: {:?}", hair_style);
|
||||
@ -100,7 +147,10 @@ impl HumHeadSpec {
|
||||
}
|
||||
};
|
||||
let beard = match spec.beard.get(&beard) {
|
||||
Some(Some(spec)) => Some((graceful_load_mat_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(Some(spec)) => Some((
|
||||
recolor_greys(graceful_load_segment(&spec.0), hair_rgb),
|
||||
Vec3::from(spec.1),
|
||||
)),
|
||||
Some(None) => None,
|
||||
None => {
|
||||
warn!("No specification for this beard: {:?}", beard);
|
||||
@ -108,7 +158,7 @@ impl HumHeadSpec {
|
||||
}
|
||||
};
|
||||
let accessory = match spec.accessory.get(&accessory) {
|
||||
Some(Some(spec)) => Some((graceful_load_mat_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(Some(spec)) => Some((graceful_load_segment(&spec.0), Vec3::from(spec.1))),
|
||||
Some(None) => None,
|
||||
None => {
|
||||
warn!("No specification for this accessory: {:?}", accessory);
|
||||
@ -117,65 +167,21 @@ impl HumHeadSpec {
|
||||
};
|
||||
|
||||
let (head, origin_offset) = DynaUnionizer::new()
|
||||
.add(bare_head, spec.head.1.into())
|
||||
.add(eyes, spec.eyes.1.into())
|
||||
.add(
|
||||
color_segment(bare_head, skin_rgb, hair_rgb, eye_color),
|
||||
spec.head.1.into(),
|
||||
)
|
||||
.add(
|
||||
color_segment(eyes, skin_rgb, hair_rgb, eye_color),
|
||||
spec.eyes.1.into(),
|
||||
)
|
||||
.maybe_add(hair)
|
||||
.maybe_add(beard)
|
||||
.maybe_add(accessory)
|
||||
.unify();
|
||||
|
||||
// TODO move this code to a fn
|
||||
// TODO move some of the colors to rgb
|
||||
let colored = head.to_segment(|mat| match mat {
|
||||
Material::Skin => match skin {
|
||||
// TODO include Race in match
|
||||
Skin::Light => Rgb::new(243, 198, 165),
|
||||
Skin::Medium => Rgb::new(203, 128, 97),
|
||||
Skin::Dark => Rgb::new(151, 91, 67),
|
||||
Skin::Rainbow => {
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
*[
|
||||
Rgb::new(240, 4, 4),
|
||||
Rgb::new(240, 140, 4),
|
||||
Rgb::new(240, 235, 4),
|
||||
Rgb::new(50, 240, 5),
|
||||
Rgb::new(4, 4, 240),
|
||||
Rgb::new(150, 0, 175),
|
||||
]
|
||||
.choose(&mut thread_rng())
|
||||
.unwrap()
|
||||
}
|
||||
},
|
||||
Material::Hair => match hair_color {
|
||||
HairColor::Red => Rgb::new(255, 20, 20),
|
||||
HairColor::Green => Rgb::new(20, 255, 20),
|
||||
HairColor::Blue => Rgb::new(20, 20, 255),
|
||||
HairColor::Brown => Rgb::new(50, 50, 0),
|
||||
HairColor::Black => Rgb::new(10, 10, 20),
|
||||
},
|
||||
Material::EyeLight => match eye_color {
|
||||
EyeColor::Black => Rgb::new(0, 0, 0),
|
||||
EyeColor::Blue => Rgb::new(0, 0, 200),
|
||||
EyeColor::Green => Rgb::new(0, 200, 0),
|
||||
EyeColor::Brown => Rgb::new(150, 150, 0),
|
||||
EyeColor::Red => Rgb::new(255, 0, 0),
|
||||
EyeColor::White => Rgb::new(255, 255, 255),
|
||||
},
|
||||
Material::EyeDark => match eye_color {
|
||||
EyeColor::Black => Rgb::new(0, 0, 0),
|
||||
EyeColor::Blue => Rgb::new(0, 0, 100),
|
||||
EyeColor::Green => Rgb::new(0, 100, 0),
|
||||
EyeColor::Brown => Rgb::new(50, 50, 0),
|
||||
EyeColor::Red => Rgb::new(200, 0, 0),
|
||||
EyeColor::White => Rgb::new(255, 255, 255),
|
||||
},
|
||||
Material::EyeWhite => match eye_color {
|
||||
EyeColor::White => Rgb::new(0, 0, 0),
|
||||
_ => Rgb::new(255, 255, 255),
|
||||
},
|
||||
});
|
||||
Meshable::<FigurePipeline, FigurePipeline>::generate_mesh(
|
||||
&colored,
|
||||
&head,
|
||||
Vec3::from(spec.offset) + origin_offset.map(|e| e as f32 * -1.0),
|
||||
)
|
||||
.0
|
||||
|
Loading…
Reference in New Issue
Block a user