From 046cd7e5c10c77dfd3015911fe7f1b47a843ec21 Mon Sep 17 00:00:00 2001 From: wyhaya Date: Thu, 27 Aug 2020 12:09:09 +0800 Subject: [PATCH 1/4] Add Color::hex fn --- crates/bevy_render/Cargo.toml | 1 + crates/bevy_render/src/color.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 5d7c1324ef8bd..c98902a7e5b1e 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -38,6 +38,7 @@ once_cell = "1.4.0" downcast-rs = "1.1.1" thiserror = "1.0" anyhow = "1.0" +hex = "0.4.2" hexasphere = "0.1.5" parking_lot = "0.10" diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index c747a5838fd5b..28f185bc43865 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -37,6 +37,19 @@ impl Color { pub const fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color { Color { r, g, b, a } } + + pub fn hex>(hex: T) -> Color { + let mut buf = [0; 3]; + if hex::decode_to_slice(hex, &mut buf).is_ok() { + let r = buf[0] as f32 / 255.0; + let g = buf[1] as f32 / 255.0; + let b = buf[2] as f32 / 255.0; + Color::rgb(r, g, b) + }else { + // Invalid value, use default color + Color::default() + } + } } impl Default for Color { From 11e7f3bba1d14efe586f292f5912f33d5d03ccf7 Mon Sep 17 00:00:00 2001 From: wyhaya Date: Thu, 27 Aug 2020 12:24:20 +0800 Subject: [PATCH 2/4] Fix cargo fmt --- crates/bevy_render/src/color.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 28f185bc43865..81ea26cf3e3a1 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -45,7 +45,7 @@ impl Color { let g = buf[1] as f32 / 255.0; let b = buf[2] as f32 / 255.0; Color::rgb(r, g, b) - }else { + } else { // Invalid value, use default color Color::default() } From 0c0c51731e6ceb8a9c97515db75e8e5c76c8956e Mon Sep 17 00:00:00 2001 From: wyhaya Date: Fri, 28 Aug 2020 11:08:08 +0800 Subject: [PATCH 3/4] Allow to add alpha value in Color::hex --- crates/bevy_render/src/color.rs | 90 +++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 81ea26cf3e3a1..607c87d88ffca 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -38,17 +38,41 @@ impl Color { Color { r, g, b, a } } - pub fn hex>(hex: T) -> Color { - let mut buf = [0; 3]; - if hex::decode_to_slice(hex, &mut buf).is_ok() { - let r = buf[0] as f32 / 255.0; - let g = buf[1] as f32 / 255.0; - let b = buf[2] as f32 / 255.0; - Color::rgb(r, g, b) - } else { - // Invalid value, use default color - Color::default() + pub fn hex>(hex: T) -> Color { + let hex = hex.as_ref(); + + // RGB + if hex.len() == 3 { + let mut data = [0; 6]; + for (i, ch) in hex.chars().enumerate() { + data[i * 2] = ch as u8; + data[i * 2 + 1] = ch as u8; + } + return decode_rgb(&data); + } + + // RGBA + if hex.len() == 4 { + let mut data = [0; 8]; + for (i, ch) in hex.chars().enumerate() { + data[i * 2] = ch as u8; + data[i * 2 + 1] = ch as u8; + } + return decode_rgba(&data); + } + + // RRGGBB + if hex.len() == 6 { + return decode_rgb(hex.as_bytes()); } + + // RRGGBBAA + if hex.len() == 8 { + return decode_rgba(hex.as_bytes()); + } + + // Invalid value, use default color + Color::default() } } @@ -217,3 +241,49 @@ impl From> for ColorSource { } impl_render_resource_bytes!(Color); + +fn decode_rgb(data: &[u8]) -> Color { + let mut buf = [0; 3]; + if hex::decode_to_slice(data, &mut buf).is_ok() { + let r = buf[0] as f32 / 255.0; + let g = buf[1] as f32 / 255.0; + let b = buf[2] as f32 / 255.0; + Color::rgb(r, g, b) + } else { + Color::default() + } +} + +fn decode_rgba(data: &[u8]) -> Color { + let mut buf = [0; 4]; + if hex::decode_to_slice(data, &mut buf).is_ok() { + let r = buf[0] as f32 / 255.0; + let g = buf[1] as f32 / 255.0; + let b = buf[2] as f32 / 255.0; + let a = buf[3] as f32 / 255.0; + Color::rgba(r, g, b, a) + } else { + Color::default() + } +} + +#[test] +fn test_hex_color() { + assert_eq!(Color::hex("FFF"), Color::rgb(1.0, 1.0, 1.0)); + assert_eq!(Color::hex("000"), Color::rgb(0.0, 0.0, 0.0)); + assert_eq!(Color::hex("---"), Color::default()); + + assert_eq!(Color::hex("FFFF"), Color::rgba(1.0, 1.0, 1.0, 1.0)); + assert_eq!(Color::hex("0000"), Color::rgba(0.0, 0.0, 0.0, 0.0)); + assert_eq!(Color::hex("----"), Color::default()); + + assert_eq!(Color::hex("FFFFFF"), Color::rgb(1.0, 1.0, 1.0)); + assert_eq!(Color::hex("000000"), Color::rgb(0.0, 0.0, 0.0)); + assert_eq!(Color::hex("------"), Color::default()); + + assert_eq!(Color::hex("FFFFFFFF"), Color::rgba(1.0, 1.0, 1.0, 1.0)); + assert_eq!(Color::hex("00000000"), Color::rgba(0.0, 0.0, 0.0, 0.0)); + assert_eq!(Color::hex("--------"), Color::default()); + + assert_eq!(Color::hex("1234567890"), Color::default()); +} From 2f61cba2fdad73e7c7cd9129d8ca4b99e0b2207e Mon Sep 17 00:00:00 2001 From: wyhaya Date: Sat, 29 Aug 2020 12:28:39 +0800 Subject: [PATCH 4/4] Remove the default color of hex color --- crates/bevy_render/src/color.rs | 87 +++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/crates/bevy_render/src/color.rs b/crates/bevy_render/src/color.rs index 1e6336c40ec53..6c626231d953a 100644 --- a/crates/bevy_render/src/color.rs +++ b/crates/bevy_render/src/color.rs @@ -38,7 +38,7 @@ impl Color { Color { r, g, b, a } } - pub fn hex>(hex: T) -> Color { + pub fn hex>(hex: T) -> Result { let hex = hex.as_ref(); // RGB @@ -71,8 +71,7 @@ impl Color { return decode_rgba(hex.as_bytes()); } - // Invalid value, use default color - Color::default() + Err(HexColorError::Length) } pub fn rgb_u8(r: u8, g: u8, b: u8) -> Color { @@ -257,48 +256,62 @@ impl From> for ColorSource { impl_render_resource_bytes!(Color); -fn decode_rgb(data: &[u8]) -> Color { +#[derive(Debug)] +pub enum HexColorError { + Length, + Hex(hex::FromHexError), +} + +fn decode_rgb(data: &[u8]) -> Result { let mut buf = [0; 3]; - if hex::decode_to_slice(data, &mut buf).is_ok() { - let r = buf[0] as f32 / 255.0; - let g = buf[1] as f32 / 255.0; - let b = buf[2] as f32 / 255.0; - Color::rgb(r, g, b) - } else { - Color::default() + match hex::decode_to_slice(data, &mut buf) { + Ok(_) => { + let r = buf[0] as f32 / 255.0; + let g = buf[1] as f32 / 255.0; + let b = buf[2] as f32 / 255.0; + Ok(Color::rgb(r, g, b)) + } + Err(err) => Err(HexColorError::Hex(err)), } } -fn decode_rgba(data: &[u8]) -> Color { +fn decode_rgba(data: &[u8]) -> Result { let mut buf = [0; 4]; - if hex::decode_to_slice(data, &mut buf).is_ok() { - let r = buf[0] as f32 / 255.0; - let g = buf[1] as f32 / 255.0; - let b = buf[2] as f32 / 255.0; - let a = buf[3] as f32 / 255.0; - Color::rgba(r, g, b, a) - } else { - Color::default() + match hex::decode_to_slice(data, &mut buf) { + Ok(_) => { + let r = buf[0] as f32 / 255.0; + let g = buf[1] as f32 / 255.0; + let b = buf[2] as f32 / 255.0; + let a = buf[3] as f32 / 255.0; + Ok(Color::rgba(r, g, b, a)) + } + Err(err) => Err(HexColorError::Hex(err)), } } #[test] fn test_hex_color() { - assert_eq!(Color::hex("FFF"), Color::rgb(1.0, 1.0, 1.0)); - assert_eq!(Color::hex("000"), Color::rgb(0.0, 0.0, 0.0)); - assert_eq!(Color::hex("---"), Color::default()); - - assert_eq!(Color::hex("FFFF"), Color::rgba(1.0, 1.0, 1.0, 1.0)); - assert_eq!(Color::hex("0000"), Color::rgba(0.0, 0.0, 0.0, 0.0)); - assert_eq!(Color::hex("----"), Color::default()); - - assert_eq!(Color::hex("FFFFFF"), Color::rgb(1.0, 1.0, 1.0)); - assert_eq!(Color::hex("000000"), Color::rgb(0.0, 0.0, 0.0)); - assert_eq!(Color::hex("------"), Color::default()); - - assert_eq!(Color::hex("FFFFFFFF"), Color::rgba(1.0, 1.0, 1.0, 1.0)); - assert_eq!(Color::hex("00000000"), Color::rgba(0.0, 0.0, 0.0, 0.0)); - assert_eq!(Color::hex("--------"), Color::default()); - - assert_eq!(Color::hex("1234567890"), Color::default()); + assert_eq!(Color::hex("FFF").unwrap(), Color::rgb(1.0, 1.0, 1.0)); + assert_eq!(Color::hex("000").unwrap(), Color::rgb(0.0, 0.0, 0.0)); + assert!(Color::hex("---").is_err()); + + assert_eq!(Color::hex("FFFF").unwrap(), Color::rgba(1.0, 1.0, 1.0, 1.0)); + assert_eq!(Color::hex("0000").unwrap(), Color::rgba(0.0, 0.0, 0.0, 0.0)); + assert!(Color::hex("----").is_err()); + + assert_eq!(Color::hex("FFFFFF").unwrap(), Color::rgb(1.0, 1.0, 1.0)); + assert_eq!(Color::hex("000000").unwrap(), Color::rgb(0.0, 0.0, 0.0)); + assert!(Color::hex("------").is_err()); + + assert_eq!( + Color::hex("FFFFFFFF").unwrap(), + Color::rgba(1.0, 1.0, 1.0, 1.0) + ); + assert_eq!( + Color::hex("00000000").unwrap(), + Color::rgba(0.0, 0.0, 0.0, 0.0) + ); + assert!(Color::hex("--------").is_err()); + + assert!(Color::hex("1234567890").is_err()); }