use std::ffi::CString;
use crate::core::math::Rectangle;
use crate::ffi::*;
pub enum DrawResult {
Empty,
Bool(bool),
Rectangle(Rectangle),
Scroll(Vector2, Rectangle),
Selected(i32),
Dropdown(bool, bool),
Value(i32, bool),
Text(CString, bool),
Percentage(f32),
ScrollBar(i32),
ListView(i32, bool, bool),
ListViewEx(CString, bool, bool, bool, i32),
Color(Color),
Grid(Vector2),
}
fn u322bool(u: u32) -> bool {
return match u {
0 => false,
1 => true,
_ => panic!("none zero or one boolean result"),
};
}
impl From<u32> for DrawResult {
fn from(b: u32) -> DrawResult {
DrawResult::Bool(u322bool(b))
}
}
impl From<i32> for DrawResult {
fn from(selected: i32) -> DrawResult {
DrawResult::Selected(selected)
}
}
impl From<f32> for DrawResult {
fn from(percentage: f32) -> DrawResult {
DrawResult::Percentage(percentage)
}
}
impl From<bool> for DrawResult {
fn from(b: bool) -> DrawResult {
DrawResult::Bool(b)
}
}
impl From<()> for DrawResult {
fn from(_empty: ()) -> DrawResult {
DrawResult::Empty
}
}
impl From<Rectangle> for DrawResult {
fn from(rect: Rectangle) -> DrawResult {
DrawResult::Rectangle(rect)
}
}
pub trait GuiDraw {
fn draw(&self) -> DrawResult;
}
macro_rules! gui_draw {
(struct $name:ident {
$($field_name:ident: $field_type:ty,)*
}, $draw:expr) => {
#[derive(Clone, Debug)]
pub struct $name {
$(pub $field_name: $field_type,)*
}
impl GuiDraw for $name{
fn draw(&self) -> crate::rgui::DrawResult {
$(let $field_name = &self.$field_name;)*
unsafe {
$draw
}
}
}
impl GuiDraw for &$name{
fn draw(&self) -> crate::rgui::DrawResult {
$(let $field_name = &self.$field_name;)*
unsafe {
$draw
}
}
}
};
}
gui_draw! {
struct WindowBox {
bounds: Rectangle,
text: CString,
},
GuiWindowBox(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct GroupBox {
bounds: Rectangle,
text: CString,
},
GuiGroupBox(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct Line {
bounds: Rectangle,
text: CString,
},
GuiLine(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct Panel {
bounds: Rectangle,
},
GuiPanel(bounds.into()).into()
}
gui_draw! {
struct ScrollPanel {
bounds: Rectangle,
content: Rectangle,
scroll: Vector2,
},
{
let mut scroll = scroll.clone();
let rect = GuiScrollPanel(bounds.into(), content.into(), &mut scroll);
DrawResult::Scroll(scroll, rect.into())
}
}
gui_draw! {
struct Label {
bounds: Rectangle,
text: CString,
},
GuiLabel(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct Button {
bounds: Rectangle,
text: CString,
},
GuiButton(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct LabelButton {
bounds: Rectangle,
text: CString,
},
GuiLabelButton(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct ImageButton {
bounds: Rectangle,
texture: Texture2D,
},
GuiImageButton(bounds.into(), *texture).into()
}
gui_draw! {
struct ImageButtonEx {
bounds: Rectangle,
texture: Texture2D,
tex_source: Rectangle,
text: CString,
},
GuiImageButtonEx(
bounds.into(),
*texture,
tex_source.into(),
text.as_ptr(),
)
.into()
}
gui_draw! {
struct Toggle {
bounds: Rectangle,
text: CString,
active: bool,
},
GuiToggle(
bounds.into(),
text.as_ptr(),
if *active { true } else { false },
)
.into()
}
gui_draw! {
struct ToggleGroup {
bounds: Rectangle,
text: CString,
active: bool,
},
GuiToggleGroup(
bounds.into(),
text.as_ptr(),
if *active { 1 } else { 0 },
)
.into()
}
gui_draw! {
struct CheckBox {
bounds: Rectangle,
text: CString,
checked: bool,
},
GuiCheckBox(bounds.into(), text.as_ptr(), if *checked {true} else {false}).into()
}
gui_draw! {
struct DropDownBox {
bounds: Rectangle,
text: CString,
active: bool,
edit_mode: bool,
},
{
let mut active = if *active { 1 } else { 0 };
let b = GuiDropdownBox(
bounds.into(),
text.as_ptr(),
&mut active,
if *edit_mode { true } else { false },
);
DrawResult::Dropdown(u322bool(active as u32), b)
}
}
gui_draw! {
struct Spinner {
bounds: Rectangle,
value: i32,
min_value: i32,
max_value: i32,
edit_mode: bool,
},
{
let mut value = *value;
let b = GuiSpinner(
bounds.into(),
&mut value,
*min_value,
*max_value,
if *edit_mode { true } else { false },
);
DrawResult::Value(value, b)
}
}
gui_draw! {
struct TextBox {
bounds: Rectangle,
text: CString,
text_size: i32,
edit_mode: bool,
},
{
let update = text.clone();
let b = GuiTextBox(
bounds.into(),
update.as_ptr() as *mut i8,
*text_size,
if *edit_mode { true } else { false },
);
DrawResult::Text(update, b)
}
}
gui_draw! {
struct TextBoxMulti {
bounds: Rectangle,
text: CString,
text_size: i32,
edit_mode: bool,
},
{
let update = text.clone();
let b = GuiTextBoxMulti(
bounds.into(),
update.as_ptr() as *mut i8,
*text_size,
if *edit_mode { true } else { false },
);
DrawResult::Text(update, b)
}
}
gui_draw! {
struct ValueBox {
bounds: Rectangle,
value: i32,
min_value: i32,
max_value: i32,
edit_mode: bool,
},
{
let mut value = *value;
let b = GuiValueBox(bounds.into(), &mut value, *min_value, *max_value, if *edit_mode {true} else {false});
DrawResult::Value(value, b)
}
}
gui_draw! {
struct Slider {
bounds: Rectangle,
text: CString,
valuef: f32,
min_valuef: f32,
max_valuef: f32,
show_value: bool,
},
GuiSlider(
bounds.into(),
text.as_ptr(),
*valuef,
*min_valuef,
*max_valuef,
if *show_value { true } else { false },
)
.into()
}
gui_draw! {
struct SliderBar {
bounds: Rectangle,
text: CString,
valuef: f32,
min_valuef: f32,
max_valuef: f32,
show_value: bool,
},
GuiSliderBar(
bounds.into(),
text.as_ptr(),
*valuef,
*min_valuef,
*max_valuef,
if *show_value { true } else { false },
)
.into()
}
gui_draw! {
struct ProgressBar {
bounds: Rectangle,
text: CString,
valuef: f32,
min_valuef: f32,
max_valuef: f32,
show_value: bool,
},
GuiProgressBar(
bounds.into(),
text.as_ptr(),
*valuef,
*min_valuef,
*max_valuef,
if *show_value { true } else { false },
)
.into()
}
gui_draw! {
struct StatusBar {
bounds: Rectangle,
text: CString,
},
GuiStatusBar(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct DummyRec {
bounds: Rectangle,
text: CString,
},
GuiDummyRec(bounds.into(), text.as_ptr()).into()
}
gui_draw! {
struct ScrollBar {
bounds: Rectangle,
value: i32,
min_value: i32,
max_value: i32,
},
DrawResult::ScrollBar(GuiScrollBar(
bounds.into(),
*value,
*min_value,
*max_value,
))
}
gui_draw! {
struct ListView {
bounds: Rectangle,
text: CString,
active: bool,
scroll_index: i32,
edit_mode: bool,
},
{
let mut scroll_index = *scroll_index;
let mut active = if *active { 1 } else { 0 };
let b = GuiListView(
bounds.into(),
text.as_ptr(),
&mut active,
&mut scroll_index,
if *edit_mode { true } else { false },
);
DrawResult::ListView(scroll_index, u322bool(active as u32), b)
}
}
gui_draw! {
struct ListViewEx {
bounds: Rectangle,
text: CString,
count: i32,
enabled: bool,
active: bool,
focus: bool,
scroll_index: i32,
edit_mode: bool,
},
{
let mut current_text = text.clone();
let current_text_ptr = current_text.as_ptr() as *mut i8;
let next_text = current_text_ptr;
let mut enabled = if *enabled { 1 } else { 0 };
let mut active = if *active { 1 } else { 0 };
let mut focus = if *focus { 1 } else { 0 };
let mut scroll_index = *scroll_index;
let _b = GuiListViewEx(
bounds.into(),
&mut (next_text as *const i8),
*count,
&mut enabled,
&mut active,
&mut focus,
&mut scroll_index,
if *edit_mode { true } else { false },
);
current_text = CString::from_raw(next_text);
DrawResult::ListViewEx(
current_text,
u322bool(enabled as u32),
u322bool(active as u32),
u322bool(focus as u32),
scroll_index,
)
}
}
gui_draw! {
struct MessageBox {
bounds: Rectangle,
window_title: CString,
message: CString,
buttons: CString,
},
DrawResult::Selected(GuiMessageBox(
bounds.into(),
window_title.as_ptr(),
message.as_ptr(),
buttons.as_ptr(),
))
}
gui_draw! {
struct ColorPicker {
bounds: Rectangle,
color: Color,
},
DrawResult::Color(GuiColorPicker(bounds.into(), *color))
}
gui_draw! {
struct Grid {
bounds: Rectangle,
spacing: f32,
subdivs: i32,
},
DrawResult::Grid(GuiGrid(bounds.into(), *spacing, *subdivs))
}