Skip to content

Commit cfeaa4d

Browse files
bors[bot]jacobsky
andauthored
Merge #729
729: Implemented some additional API functions related to crate::core_type… r=toasteater a=jacobsky …s::Color I needed some additional functionality from the Color class in godot and noticed that there were a lot of APIs that weren't accessible from rust. This PR plumbs in the functions from godot and adds some tests that can be used to sanity check them. This commit adds the API functionality and some basic sanity tests that I verified are passing in the engine. If additional tests are required, please let me know. Signed-off-by: Jacobsky <[email protected]> Co-authored-by: Jacobsky <[email protected]>
2 parents 6a1af86 + 45f1279 commit cfeaa4d

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

gdnative-core/src/core_types/color.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::private::get_api;
22
use crate::sys;
33
use std::mem::transmute;
44

5+
use crate::core_types::GodotString;
56
/// RGBA color with 32 bits floating point components.
67
#[repr(C)]
78
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -47,6 +48,68 @@ impl Color {
4748
a: self.a + (weight * (other.a - self.a)),
4849
}
4950
}
51+
#[inline]
52+
pub fn blend(&self, other: &Color) -> Color {
53+
Color::from_sys(unsafe { (get_api().godot_color_blend)(self.sys(), other.sys()) })
54+
}
55+
56+
#[inline]
57+
pub fn contrasted(&self) -> Color {
58+
Color::from_sys(unsafe { (get_api().godot_color_contrasted)(self.sys()) })
59+
}
60+
#[inline]
61+
pub fn darkened(&self, amount: f32) -> Color {
62+
Color::from_sys(unsafe { (get_api().godot_color_darkened)(self.sys(), amount) })
63+
}
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+
}
69+
#[inline]
70+
pub fn gray(&self) -> f32 {
71+
// Implemented as described in godot docs
72+
(self.r + self.b + self.g) / 3.0
73+
}
74+
75+
#[inline]
76+
pub fn inverted(&self) -> Color {
77+
// Implementation as described in godot docs.
78+
Color {
79+
r: 1.0f32 - self.r,
80+
g: 1.0f32 - self.g,
81+
b: 1.0f32 - self.b,
82+
a: self.a,
83+
}
84+
}
85+
86+
pub fn to_abgr32(&self) -> i32 {
87+
unsafe { (get_api().godot_color_to_abgr32)(self.sys()) }
88+
}
89+
90+
pub fn to_abgr64(&self) -> i32 {
91+
unsafe { (get_api().godot_color_to_abgr64)(self.sys()) }
92+
}
93+
94+
pub fn to_argb32(&self) -> i32 {
95+
unsafe { (get_api().godot_color_to_argb32)(self.sys()) }
96+
}
97+
98+
pub fn to_argb64(&self) -> i32 {
99+
unsafe { (get_api().godot_color_to_argb64)(self.sys()) }
100+
}
101+
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) })
104+
}
105+
106+
pub fn to_rgba32(&self) -> i32 {
107+
unsafe { (get_api().godot_color_to_rgba32)(self.sys()) }
108+
}
109+
110+
pub fn to_rgba64(&self) -> i32 {
111+
unsafe { (get_api().godot_color_to_rgba64)(self.sys()) }
112+
}
50113

51114
#[doc(hidden)]
52115
#[inline]
@@ -72,3 +135,49 @@ fn color_repr() {
72135
use std::mem::size_of;
73136
assert_eq!(size_of::<Color>(), size_of::<sys::godot_color>());
74137
}
138+
139+
godot_test!(test_color {
140+
// 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());
147+
// Test Gray
148+
// String comparison due to non-trivial way to truncate floats
149+
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()));
154+
// Test invert
155+
let inverted = Color::rgb(1.0, 1.0,1.0).inverted();
156+
assert!(0f32.is_equal_approx(inverted.r));
157+
assert!(0f32.is_equal_approx(inverted.g));
158+
assert!(0f32.is_equal_approx(inverted.b));
159+
160+
let inverted = Color::rgb(0.95, 0.95,0.95).inverted();
161+
assert!(0.05f32.is_equal_approx(inverted.r));
162+
assert!(0.05f32.is_equal_approx(inverted.g));
163+
assert!(0.05f32.is_equal_approx(inverted.b));
164+
165+
let inverted = Color::rgb(0.05, 0.95,0.55).inverted();
166+
assert!(0.95f32.is_equal_approx(inverted.r));
167+
assert!(0.05f32.is_equal_approx(inverted.g));
168+
assert!(0.45f32.is_equal_approx(inverted.b));
169+
170+
// 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);
183+
});

test/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub extern "C" fn run_tests(
2222

2323
status &= gdnative::core_types::dictionary::test_dictionary();
2424
// status &= gdnative::test_dictionary_clone_clear();
25-
25+
status &= gdnative::core_types::test_color();
2626
status &= gdnative::core_types::test_array();
2727
status &= gdnative::core_types::test_array_debug();
2828
// status &= gdnative::test_array_clone_clear();

0 commit comments

Comments
 (0)