Skip to content

Commit c608e1a

Browse files
committed
squash! Implemented some additional API functions related to crate::core_types::Color
1 parent 45f1279 commit c608e1a

File tree

3 files changed

+166
-63
lines changed

3 files changed

+166
-63
lines changed

examples/spinning_cube/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl RustTest {
6464
if let Some(mat) = owner.get_surface_material(0) {
6565
let mat = unsafe { mat.assume_safe() };
6666
let mat = mat.cast::<SpatialMaterial>().expect("Incorrect material");
67-
mat.set_albedo(Color::rgba(self.time.cos().abs(), 0.0, 0.0, 1.0));
67+
mat.set_albedo(Color::from_rgba(self.time.cos().abs(), 0.0, 0.0, 1.0));
6868
}
6969
}
7070
}

gdnative-core/src/core_types/color.rs

Lines changed: 150 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,44 @@ pub struct Color {
1414
}
1515

1616
impl Color {
17+
#[deprecated]
1718
#[inline]
1819
pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
1920
Color { r, g, b, a }
2021
}
2122

23+
#[deprecated]
2224
#[inline]
2325
pub fn rgb(r: f32, g: f32, b: f32) -> Color {
2426
Color { r, g, b, a: 1.0 }
2527
}
2628

29+
#[inline]
30+
pub fn from_rgba(r: f32, g: f32, b: f32, a: f32) -> Color {
31+
Color { r, g, b, a }
32+
}
33+
34+
#[inline]
35+
pub fn from_rgb(r: f32, g: f32, b: f32) -> Color {
36+
Color { r, g, b, a: 1.0 }
37+
}
38+
39+
#[inline]
40+
pub fn from_hsv(h: f32, s: f32, v: f32) -> Color {
41+
Color::from_hsva(h, s, v, 1.0)
42+
}
43+
44+
#[inline]
45+
pub fn from_hsva(h: f32, s: f32, v: f32, a: f32) -> Color {
46+
let color = Color {
47+
r: 0.0,
48+
g: 0.0,
49+
b: 0.0,
50+
a: 0.0,
51+
};
52+
Color::from_sys(unsafe { (get_api().godot_color_from_hsv)(color.sys(), h, s, v, a) })
53+
}
54+
2755
#[inline]
2856
pub fn h(&self) -> f32 {
2957
unsafe { (get_api().godot_color_get_h)(self.sys()) }
@@ -48,6 +76,7 @@ impl Color {
4876
a: self.a + (weight * (other.a - self.a)),
4977
}
5078
}
79+
5180
#[inline]
5281
pub fn blend(&self, other: &Color) -> Color {
5382
Color::from_sys(unsafe { (get_api().godot_color_blend)(self.sys(), other.sys()) })
@@ -57,15 +86,12 @@ impl Color {
5786
pub fn contrasted(&self) -> Color {
5887
Color::from_sys(unsafe { (get_api().godot_color_contrasted)(self.sys()) })
5988
}
89+
6090
#[inline]
6191
pub fn darkened(&self, amount: f32) -> Color {
6292
Color::from_sys(unsafe { (get_api().godot_color_darkened)(self.sys(), amount) })
6393
}
64-
#[inline]
65-
pub fn from_hsv(h: f32, s: f32, v: f32, a: f32) -> Color {
66-
let color = Color::rgba(0.0, 0.0, 0.0, 0.0);
67-
Color::from_sys(unsafe { (get_api().godot_color_from_hsv)(color.sys(), h, s, v, a) })
68-
}
94+
6995
#[inline]
7096
pub fn gray(&self) -> f32 {
7197
// Implemented as described in godot docs
@@ -76,39 +102,105 @@ impl Color {
76102
pub fn inverted(&self) -> Color {
77103
// Implementation as described in godot docs.
78104
Color {
79-
r: 1.0f32 - self.r,
80-
g: 1.0f32 - self.g,
81-
b: 1.0f32 - self.b,
105+
r: 1.0 - self.r,
106+
g: 1.0 - self.g,
107+
b: 1.0 - self.b,
82108
a: self.a,
83109
}
84110
}
85111

86-
pub fn to_abgr32(&self) -> i32 {
87-
unsafe { (get_api().godot_color_to_abgr32)(self.sys()) }
112+
#[inline]
113+
pub fn to_html(&self, with_alpha: bool) -> GodotString {
114+
GodotString::from_sys(unsafe { (get_api().godot_color_to_html)(self.sys(), with_alpha) })
88115
}
89116

90-
pub fn to_abgr64(&self) -> i32 {
91-
unsafe { (get_api().godot_color_to_abgr64)(self.sys()) }
117+
/// Returns the reverse of the RGBA32 byte representation for this color where each byte represents a component of the ABGR profile.
118+
/// This is the byte information used when storing this color as a part of a texture.
119+
/// # Endianness
120+
/// On big endian architecture this is stored in ABGR byte order
121+
/// On little endian machines this is stored in RGBA byte order
122+
/// # Example
123+
/// `0x00FF7FFF` would be the equivalent to `Color::from_rgba(1.0, 0.5, 1.0, 0.0)`
124+
#[inline]
125+
pub fn to_abgr32(&self) -> u32 {
126+
((self.a * 255.0) as u32) << 24
127+
| ((self.b * 255.0) as u32) << 16
128+
| ((self.g * 255.0) as u32) << 8
129+
| (self.r * 255.0) as u32
92130
}
93131

94-
pub fn to_argb32(&self) -> i32 {
95-
unsafe { (get_api().godot_color_to_argb32)(self.sys()) }
132+
/// Returns the reverse of the RGBA64 byte representation for this color where each word represents represents a component of the ABGR profile.
133+
/// This is the byte information used when storing this color as a part of a texture.
134+
/// # Endianness
135+
/// On big endian architecture this is stored in ABGR word order
136+
/// On little endian machines this is stored in RGBA word order
137+
/// # Example
138+
/// `0x0000FFFF7FFFFFFF` would be the equivalent to `Color::from_rgba(0.0, 1.0, 0.5, 1.0)`
139+
#[inline]
140+
pub fn to_abgr64(&self) -> u64 {
141+
((self.a * 65535.0) as u64) << 48
142+
| ((self.b * 65535.0) as u64) << 32
143+
| ((self.g * 65535.0) as u64) << 16
144+
| ((self.r * 65535.0) as u64)
96145
}
97146

98-
pub fn to_argb64(&self) -> i32 {
99-
unsafe { (get_api().godot_color_to_argb64)(self.sys()) }
147+
/// Returns the ARGB32 format representation representation for this color where each byte represents a component of the ARGB profile.
148+
/// This is the byte information used when storing this color as a part of a texture.
149+
/// # Endianness
150+
/// On big endian architecture this is stored in the order ARGB byte order
151+
/// On little endian machines this is stored in the order BGRA byte order
152+
/// `0x0000FFFF7FFFFFFF` would be the equivalent to `Color::from_rgba(1.0, 0.5, 1.0, 0.0)`
153+
#[inline]
154+
pub fn to_argb32(&self) -> u32 {
155+
((self.a * 255.0) as u32) << 24
156+
| ((self.r * 255.0) as u32) << 16
157+
| ((self.g * 255.0) as u32) << 8
158+
| (self.b * 255.0) as u32
100159
}
101160

102-
pub fn to_html(&self, with_alpha: bool) -> GodotString {
103-
GodotString::from_sys(unsafe { (get_api().godot_color_to_html)(self.sys(), with_alpha) })
161+
/// Returns the ARGB64 format representation for this color where each word represents a component of the ARGB profile.
162+
/// This is the byte information used when storing this color as a part of a texture.
163+
/// # Endianness
164+
/// On big endian architecture this is stored in the order ARGB word order
165+
/// On little endian machines this is stored in the order BGRA word order
166+
/// # Example
167+
/// `0x0000FFFF7FFFFFFF` would be the equivalent to `Color::from_rgba(1.0, 0.5, 1.0, 0.0)`
168+
#[inline]
169+
pub fn to_argb64(&self) -> u64 {
170+
((self.a * 65535.0) as u64) << 48
171+
| ((self.r * 65535.0) as u64) << 32
172+
| ((self.g * 65535.0) as u64) << 16
173+
| ((self.b * 65535.0) as u64)
104174
}
105175

106-
pub fn to_rgba32(&self) -> i32 {
107-
unsafe { (get_api().godot_color_to_rgba32)(self.sys()) }
176+
/// Returns the OpenGL Texture format byte representation for this color where each byte represents a component of the RGBA profile.
177+
/// This is the byte information used when storing this color as a part of a texture.
178+
/// # Endianness
179+
/// On big endian architecture this is stored in RGBA byte order
180+
/// On little endian machines this is stored in ABGR byte order
181+
/// # Example
182+
/// `0x00FF7FFF` would be the equivalent to `Color::from_rgba(0.0, 1.0, 0.5, 1.0)`
183+
#[inline]
184+
pub fn to_rgba32(&self) -> u32 {
185+
((self.r * 255.0) as u32) << 24
186+
| ((self.g * 255.0) as u32) << 16
187+
| ((self.b * 255.0) as u32) << 8
188+
| (self.a * 255.0) as u32
108189
}
109190

110-
pub fn to_rgba64(&self) -> i32 {
111-
unsafe { (get_api().godot_color_to_rgba64)(self.sys()) }
191+
/// Returns the OpenGL Texture format byte representation for this color where each byte represents a component of the RGBA profile.
192+
/// This is the byte information used when storing this color as a part of a texture.
193+
/// # Endianness
194+
/// On big endian architecture this is stored in RGBA word order
195+
/// On little endian machines this is stored in ABGR word order
196+
/// # Example
197+
/// `0x0000FFFF7FFFFFFF` would be the equivalent to `Color::from_rgba(0.0, 1.0, 0.5, 1.0)`
198+
#[inline]
199+
pub fn to_rgba64(&self) -> u64 {
200+
((self.r * 65535.0) as u64) << 48
201+
| ((self.g * 65535.0) as u64) << 32
202+
| ((self.b * 65535.0) as u64) << 16
203+
| ((self.a * 65535.0) as u64)
112204
}
113205

114206
#[doc(hidden)]
@@ -136,48 +228,59 @@ fn color_repr() {
136228
assert_eq!(size_of::<Color>(), size_of::<sys::godot_color>());
137229
}
138230

231+
#[test]
232+
fn color_to_pixel_color_formats() {
233+
let color = Color::from_rgba(1.0, 0.5, 1.0, 0.0);
234+
assert_eq!(0xFF7FFF00, color.to_rgba32());
235+
assert_eq!(0xFFFF7FFFFFFF0000, color.to_rgba64());
236+
assert_eq!(0x00FF7FFF, color.to_abgr32());
237+
assert_eq!(0x0000FFFF7FFFFFFF, color.to_abgr64());
238+
assert_eq!(0x00FF7FFF, color.to_argb32());
239+
assert_eq!(0x0000FFFF7FFFFFFF, color.to_argb64());
240+
}
241+
139242
godot_test!(test_color {
140243
// Test to_html
141-
assert_eq!("ffffffff", Color::rgba(1.0, 1.0, 1.0, 1.0).to_html(true).to_string());
142-
assert_eq!("ffffff", Color::rgba(1.0, 1.0, 1.0, 1.0).to_html(false).to_string());
143-
assert_eq!("80ffffff", Color::rgba(1.0, 1.0, 1.0, 0.5).to_html(true).to_string());
144-
assert_eq!("ffffff", Color::rgba(1.0, 1.0, 1.0, 0.5).to_html(false).to_string());
145-
assert_eq!("ff8000", Color::rgb(1.0, 0.5, 0.0).to_html(false).to_string());
146-
assert_eq!("ff0080ff", Color::rgb(0.0, 0.5, 1.0).to_html(true).to_string());
244+
assert_eq!("ffffffff", Color::from_rgba(1.0, 1.0, 1.0, 1.0).to_html(true).to_string());
245+
assert_eq!("ffffff", Color::from_rgba(1.0, 1.0, 1.0, 1.0).to_html(false).to_string());
246+
assert_eq!("80ffffff", Color::from_rgba(1.0, 1.0, 1.0, 0.5).to_html(true).to_string());
247+
assert_eq!("ffffff", Color::from_rgba(1.0, 1.0, 1.0, 0.5).to_html(false).to_string());
248+
assert_eq!("ff8000", Color::from_rgb(1.0, 0.5, 0.0).to_html(false).to_string());
249+
assert_eq!("ff0080ff", Color::from_rgb(0.0, 0.5, 1.0).to_html(true).to_string());
147250
// Test Gray
148251
// String comparison due to non-trivial way to truncate floats
149252
use crate::core_types::IsEqualApprox;
150-
assert!(0.4f32.is_equal_approx(Color::rgb(0.2, 0.4, 0.6).gray()));
151-
assert!(0.5f32.is_equal_approx(Color::rgb(0.1, 0.5, 0.9).gray()));
152-
assert!(0.9f32.is_equal_approx(Color::rgb(1.0, 1.0, 0.7).gray()));
153-
assert!(0.42f32.is_equal_approx(Color::rgb(0.6, 0.6, 0.06).gray()));
253+
assert!(0.4f32.is_equal_approx(Color::from_rgb(0.2, 0.4, 0.6).gray()));
254+
assert!(0.5f32.is_equal_approx(Color::from_rgb(0.1, 0.5, 0.9).gray()));
255+
assert!(0.9f32.is_equal_approx(Color::from_rgb(1.0, 1.0, 0.7).gray()));
256+
assert!(0.42f32.is_equal_approx(Color::from_rgb(0.6, 0.6, 0.06).gray()));
154257
// Test invert
155-
let inverted = Color::rgb(1.0, 1.0,1.0).inverted();
258+
let inverted = Color::from_rgb(1.0, 1.0,1.0).inverted();
156259
assert!(0f32.is_equal_approx(inverted.r));
157260
assert!(0f32.is_equal_approx(inverted.g));
158261
assert!(0f32.is_equal_approx(inverted.b));
159262

160-
let inverted = Color::rgb(0.95, 0.95,0.95).inverted();
263+
let inverted = Color::from_rgb(0.95, 0.95,0.95).inverted();
161264
assert!(0.05f32.is_equal_approx(inverted.r));
162265
assert!(0.05f32.is_equal_approx(inverted.g));
163266
assert!(0.05f32.is_equal_approx(inverted.b));
164267

165-
let inverted = Color::rgb(0.05, 0.95,0.55).inverted();
268+
let inverted = Color::from_rgb(0.05, 0.95,0.55).inverted();
166269
assert!(0.95f32.is_equal_approx(inverted.r));
167270
assert!(0.05f32.is_equal_approx(inverted.g));
168271
assert!(0.45f32.is_equal_approx(inverted.b));
169272

170273
// This is a series of sanity checks to test that the API bounds work properly.
171-
let color = Color::from_hsv(1.0, 1.0, 1.0, 1.0);
172-
color.darkened(0.20);
173-
color.contrasted();
174-
color.inverted();
175-
color.to_rgba32();
176-
color.to_rgba64();
177-
color.to_abgr32();
178-
color.to_abgr64();
179-
color.to_argb32();
180-
color.to_argb64();
181-
let other_color = Color::rgba(1.0, 1.0, 1.0, 1.0);
182-
color.blend(&other_color);
274+
let hsv_color = Color::from_hsv(0.75, 0.5, 0.25);
275+
let color = Color::from_hsva(0.75, 0.5, 0.25, 1.0);
276+
assert_eq!(hsv_color, color);
277+
let color = Color::from_rgb(0.75, 0.5, 0.25);
278+
assert_eq!(Color::from_rgb(0.25, 0.5, 0.75), color.inverted());
279+
// Following results were derived from the godot engine code based on the RGB values of 0.75, 0.5, 0.25 respectively.
280+
assert_eq!(Color::from_rgb(0.25, 0.00, 0.75), color.contrasted());
281+
assert_eq!(Color::from_rgba(0.60, 0.40, 0.20, 1.0), color.darkened(0.20));
282+
// Check that the blend values are correct.
283+
let color = Color::from_rgba(0.0, 1.0, 0.5, 1.0);
284+
let other_color = Color::from_rgba(1.0, 0.0, 0.5, 1.0);
285+
assert_eq!(Color::from_rgba(1.0, 0.0, 0.5, 1.0), color.blend(&other_color));
183286
});

gdnative-core/src/core_types/color_array.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ godot_test!(
99
use crate::NewRef as _;
1010

1111
let arr = ColorArray::from_vec(vec![
12-
Color::rgb(1.0, 0.0, 0.0),
13-
Color::rgb(0.0, 1.0, 0.0),
14-
Color::rgb(0.0, 0.0, 1.0),
12+
Color::from_rgb(1.0, 0.0, 0.0),
13+
Color::from_rgb(0.0, 1.0, 0.0),
14+
Color::from_rgb(0.0, 0.0, 1.0),
1515
]);
1616

1717
let original_read = {
1818
let read = arr.read();
1919
assert_eq!(&[
20-
Color::rgb(1.0, 0.0, 0.0),
21-
Color::rgb(0.0, 1.0, 0.0),
22-
Color::rgb(0.0, 0.0, 1.0),
20+
Color::from_rgb(1.0, 0.0, 0.0),
21+
Color::from_rgb(0.0, 1.0, 0.0),
22+
Color::from_rgb(0.0, 0.0, 1.0),
2323
], read.as_slice());
2424
read.clone()
2525
};
@@ -34,25 +34,25 @@ godot_test!(
3434
}
3535
}
3636

37-
assert_eq!(Color::rgb(1.0, 0.0, 1.0), cow_arr.get(0));
38-
assert_eq!(Color::rgb(0.0, 1.0, 1.0), cow_arr.get(1));
39-
assert_eq!(Color::rgb(0.0, 0.0, 1.0), cow_arr.get(2));
37+
assert_eq!(Color::from_rgb(1.0, 0.0, 1.0), cow_arr.get(0));
38+
assert_eq!(Color::from_rgb(0.0, 1.0, 1.0), cow_arr.get(1));
39+
assert_eq!(Color::from_rgb(0.0, 0.0, 1.0), cow_arr.get(2));
4040

4141
// the write shouldn't have affected the original array
4242
assert_eq!(&[
43-
Color::rgb(1.0, 0.0, 0.0),
44-
Color::rgb(0.0, 1.0, 0.0),
45-
Color::rgb(0.0, 0.0, 1.0),
43+
Color::from_rgb(1.0, 0.0, 0.0),
44+
Color::from_rgb(0.0, 1.0, 0.0),
45+
Color::from_rgb(0.0, 0.0, 1.0),
4646
], original_read.as_slice());
4747
}
4848
);
4949

5050
godot_test!(
5151
test_color_array_debug {
5252
let arr = ColorArray::from_vec(vec![
53-
Color::rgb(1.0, 0.0, 0.0),
54-
Color::rgb(0.0, 1.0, 0.0),
55-
Color::rgb(0.0, 0.0, 1.0),
53+
Color::from_rgb(1.0, 0.0, 0.0),
54+
Color::from_rgb(0.0, 1.0, 0.0),
55+
Color::from_rgb(0.0, 0.0, 1.0),
5656
]);
5757

5858
assert_eq!(format!("{:?}", arr), "[Color { r: 1.0, g: 0.0, b: 0.0, a: 1.0 }, Color { r: 0.0, g: 1.0, b: 0.0, a: 1.0 }, Color { r: 0.0, g: 0.0, b: 1.0, a: 1.0 }]");

0 commit comments

Comments
 (0)