Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wraps the dear ImGui custom drawing API #111

Merged
merged 28 commits into from
Apr 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
db97041
window_draw_list.rs: Basic structure to wrap ImGui's draw API
malikolivier Mar 29, 2018
05b382e
WindowDrawList: Wrap add_rect method
malikolivier Mar 29, 2018
d1879b2
window_draw_list.rs: Add add_rect_filled_multicolor
malikolivier Mar 29, 2018
878de08
window_draw_list.rs: Wrap add_circle
malikolivier Mar 29, 2018
8471bd4
window_draw_list.rs: Wrap add_triangle
malikolivier Mar 29, 2018
35db5fc
window_draw_list.rs: Wrap add_bezier_curve
malikolivier Mar 29, 2018
4358360
window_draw_list.rs: Wrap ImDrawList_PushClipRect
malikolivier Mar 29, 2018
a60465c
ui: Wrap dummy
malikolivier Mar 29, 2018
15048ad
ui: Add mouse helper methods is_mouse_{dragging,down,clicked}
malikolivier Mar 26, 2018
c58a93b
ui: Wrap invisible_button
malikolivier Mar 30, 2018
738a9c9
ui: Wrap get_content_region_avail
malikolivier Mar 29, 2018
ab90810
test_window_impl.rs: Add first part half of show_example_app_custom_r…
malikolivier Mar 28, 2018
c277488
test_window_impl: show_example_app_custom_rendering: Include drawing …
malikolivier Mar 29, 2018
2312f41
test_drawing_channels_split: Add an example for channels_split
malikolivier Mar 30, 2018
664660a
Add missing imports in example code
malikolivier Mar 30, 2018
eab85ea
with_window_draw_list: Fix example test
malikolivier Apr 8, 2018
43a2484
ImMouseButton: Derive Copy, Clone, Eq, PartialEq, Debug
malikolivier Apr 15, 2018
746bdc5
ImColor: Derive Eq, PartialEq, Debug
malikolivier Apr 15, 2018
7be9f15
window_draw_list: Fix typo in doc
malikolivier Apr 15, 2018
3aa807b
DrawAPI: Remove unused lifetime
malikolivier Apr 15, 2018
9a65a64
WindowDrawList: Cannot use WindowDrawList::new outside of crate
malikolivier Apr 15, 2018
95577a0
ui: Rename to with_window_draw_list ot get_window_draw_list
malikolivier Apr 15, 2018
29b0d20
ChannelsSplit: Panic when channel index overflows
malikolivier Apr 15, 2018
734292f
imgui: Make ChannelsSplit struct visible outside the crate
malikolivier Apr 15, 2018
082d5e4
window_draw_list: Fix awkward wording in doc
malikolivier Apr 15, 2018
454e980
Do not allow to create coexisting instances of WindowDrawList
malikolivier Apr 15, 2018
9a9484f
ChannelsSplit: Rename channels_set_current to set_current
malikolivier Apr 24, 2018
892fe55
WindowDrawList: Get rid of DrawApi trait
malikolivier Apr 24, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 47 additions & 0 deletions imgui-examples/examples/test_drawing_channels_split.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
extern crate glium;
extern crate imgui;
extern crate imgui_glium_renderer;

mod support;

const CLEAR_COLOR: [f32; 4] = [0.2, 0.2, 0.2, 1.0];
const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];

fn main() {
support::run(
"test_drawing_channels_split".to_owned(),
CLEAR_COLOR,
|ui| {
let draw_list = ui.get_window_draw_list();
// Will draw channel 0 first, then channel 1, whatever the order of
// the calls in the code.
//
// Here, we draw a red line on channel 1 then a white circle on
// channel 0. As a result, the red line will always appear on top of
// the white circle.
draw_list.channels_split(2, |channels| {
const RADIUS: f32 = 100.0;
let canvas_pos = ui.get_cursor_screen_pos();
channels.set_current(1);
draw_list
.add_line(
canvas_pos,
[canvas_pos.0 + RADIUS, canvas_pos.1 + RADIUS],
RED,
)
.thickness(5.0)
.build();

channels.set_current(0);
let center = (canvas_pos.0 + RADIUS, canvas_pos.1 + RADIUS);
draw_list
.add_circle(center, RADIUS, WHITE)
.thickness(10.0)
.num_segments(50)
.build();
});
true
},
);
}
269 changes: 269 additions & 0 deletions imgui-examples/examples/test_window_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct State {
file_menu: FileMenuState,
radio_button: i32,
color_edit: ColorEditState,
custom_rendering: CustomRenderingState,
}

impl Default for State {
Expand Down Expand Up @@ -95,6 +96,7 @@ impl Default for State {
file_menu: Default::default(),
radio_button: 0,
color_edit: ColorEditState::default(),
custom_rendering: Default::default(),
}
}
}
Expand Down Expand Up @@ -155,6 +157,24 @@ impl Default for AutoResizeState {
fn default() -> Self { AutoResizeState { lines: 10 } }
}

struct CustomRenderingState {
sz: f32,
col: [f32; 3],
points: Vec<(f32, f32)>,
adding_line: bool,
}

impl Default for CustomRenderingState {
fn default() -> Self {
CustomRenderingState {
sz: 36.0,
col: [1.0, 1.0, 0.4],
points: vec![],
adding_line: false,
}
}
}

const CLEAR_COLOR: [f32; 4] = [114.0 / 255.0, 144.0 / 255.0, 154.0 / 255.0, 1.0];

fn main() {
Expand Down Expand Up @@ -239,6 +259,14 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
});
}

if state.show_app_custom_rendering {
show_example_app_custom_rendering(
ui,
&mut state.custom_rendering,
&mut state.show_app_custom_rendering,
);
}

ui.window(im_str!("ImGui Demo"))
.title_bar(!state.no_titlebar)
.show_borders(!state.no_border)
Expand Down Expand Up @@ -742,3 +770,244 @@ My title is the same as window 1, but my identifier is unique.",
.position((100.0, 300.0), ImGuiCond::FirstUseEver)
.build(|| ui.text("This window has a changing title"));
}

fn show_example_app_custom_rendering(ui: &Ui, state: &mut CustomRenderingState, opened: &mut bool) {
ui.window(im_str!("Example: Custom rendering"))
.size((350.0, 560.0), ImGuiCond::FirstUseEver)
.opened(opened)
.build(|| {
ui.text("Primitives");
// TODO: Add DragFloat to change value of sz
ui.color_edit(im_str!("Color"), &mut state.col).build();
let draw_list = ui.get_window_draw_list();
let p = ui.get_cursor_screen_pos();
let spacing = 8.0;
let mut y = p.1 + 4.0;
for n in 0..2 {
let mut x = p.0 + 4.0;
let thickness = if n == 0 { 1.0 } else { 4.0 };
draw_list
.add_circle(
(x + state.sz * 0.5, y + state.sz * 0.5),
state.sz * 0.5,
state.col,
)
.num_segments(20)
.thickness(thickness)
.build();
x += state.sz + spacing;
draw_list
.add_rect((x, y), (x + state.sz, y + state.sz), state.col)
.thickness(thickness)
.build();
x += state.sz + spacing;
draw_list
.add_rect((x, y), (x + state.sz, y + state.sz), state.col)
.thickness(thickness)
.rounding(10.0)
.build();
x += state.sz + spacing;
draw_list
.add_rect((x, y), (x + state.sz, y + state.sz), state.col)
.thickness(thickness)
.rounding(10.0)
.round_top_right(false)
.round_bot_left(false)
.build();
x += state.sz + spacing;
draw_list
.add_triangle(
(x + state.sz * 0.5, y),
(x + state.sz, y + state.sz - 0.5),
(x, y + state.sz - 0.5),
state.col,
)
.thickness(thickness)
.build();
x += state.sz + spacing;
draw_list
.add_line((x, y), (x + state.sz, y), state.col)
.thickness(thickness)
.build();
x += state.sz + spacing;
draw_list
.add_line((x, y), (x + state.sz, y + state.sz), state.col)
.thickness(thickness)
.build();
x += state.sz + spacing;
draw_list
.add_line((x, y), (x, y + state.sz), state.col)
.thickness(thickness)
.build();
x += spacing;
draw_list
.add_bezier_curve(
(x, y),
(x + state.sz * 1.3, y + state.sz * 0.3),
(x + state.sz - state.sz * 1.3, y + state.sz - state.sz * 0.3),
(x + state.sz, y + state.sz),
state.col,
)
.thickness(thickness)
.build();
y += state.sz + spacing;
}
let mut x = p.0 + 4.0;
draw_list
.add_circle(
(x + state.sz * 0.5, y + state.sz * 0.5),
state.sz * 0.5,
state.col,
)
.num_segments(32)
.filled(true)
.build();
x += state.sz + spacing;
draw_list
.add_rect((x, y), (x + state.sz, y + state.sz), state.col)
.filled(true)
.build();
x += state.sz + spacing;
draw_list
.add_rect((x, y), (x + state.sz, y + state.sz), state.col)
.filled(true)
.rounding(10.0)
.build();
x += state.sz + spacing;
draw_list
.add_rect((x, y), (x + state.sz, y + state.sz), state.col)
.filled(true)
.rounding(10.0)
.round_top_right(false)
.round_bot_left(false)
.build();
x += state.sz + spacing;
draw_list
.add_triangle(
(x + state.sz * 0.5, y),
(x + state.sz, y + state.sz - 0.5),
(x, y + state.sz - 0.5),
state.col,
)
.filled(true)
.build();
x += state.sz + spacing;
const MULTICOLOR_RECT_CORNER_COLOR1: [f32; 3] = [0.0, 0.0, 0.0];
const MULTICOLOR_RECT_CORNER_COLOR2: [f32; 3] = [1.0, 0.0, 0.0];
const MULTICOLOR_RECT_CORNER_COLOR3: [f32; 3] = [1.0, 1.0, 0.0];
const MULTICOLOR_RECT_CORNER_COLOR4: [f32; 3] = [0.0, 1.0, 0.0];
draw_list.add_rect_filled_multicolor(
(x, y),
(x + state.sz, y + state.sz),
MULTICOLOR_RECT_CORNER_COLOR1,
MULTICOLOR_RECT_CORNER_COLOR2,
MULTICOLOR_RECT_CORNER_COLOR3,
MULTICOLOR_RECT_CORNER_COLOR4,
);
ui.dummy(((state.sz + spacing) * 8.0, (state.sz + spacing) * 3.0));
ui.separator();

ui.text(im_str!("Canvas example"));
if ui.button(im_str!("Clear"), (0.0, 0.0)) {
state.points.clear();
}
if state.points.len() >= 2 {
ui.same_line(0.0);
if ui.button(im_str!("Undo"), (0.0, 0.0)) {
state.points.pop();
state.points.pop();
}
}
ui.text(im_str!(
"Left-click and drag to add lines,\nRight-click to undo"
));
// Here we are using InvisibleButton() as a convenience to
// 1) advance the cursor, and
// 2) allows us to use IsItemHovered()
// However you can draw directly and poll mouse/keyboard by
// yourself. You can manipulate the cursor using GetCursorPos() and
// SetCursorPos(). If you only use the ImDrawList API, you can
// notify the owner window of its extends by using
// SetCursorPos(max).

// ImDrawList API uses screen coordinates!
let canvas_pos = ui.get_cursor_screen_pos();
// Resize canvas to what's available
let mut canvas_size = ui.get_content_region_avail();
if canvas_size.0 < 50.0 {
canvas_size.0 = 50.0;
}
if canvas_size.1 < 50.0 {
canvas_size.1 = 50.0;
}
const CANVAS_CORNER_COLOR1: [f32; 3] = [0.2, 0.2, 0.2];
const CANVAS_CORNER_COLOR2: [f32; 3] = [0.2, 0.2, 0.24];
const CANVAS_CORNER_COLOR3: [f32; 3] = [0.24, 0.24, 0.27];
const CANVAS_CORNER_COLOR4: [f32; 3] = [0.2, 0.2, 0.24];
draw_list.add_rect_filled_multicolor(
canvas_pos,
(canvas_pos.0 + canvas_size.0, canvas_pos.1 + canvas_size.1),
CANVAS_CORNER_COLOR1,
CANVAS_CORNER_COLOR2,
CANVAS_CORNER_COLOR3,
CANVAS_CORNER_COLOR4,
);
const CANVAS_BORDER_COLOR: [f32; 3] = [1.0, 1.0, 1.0];
draw_list
.add_rect(
canvas_pos,
(canvas_pos.0 + canvas_size.0, canvas_pos.1 + canvas_size.1),
CANVAS_BORDER_COLOR,
)
.build();

let mut adding_preview = false;
ui.invisible_button(im_str!("canvas"), canvas_size);
let mouse_pos = ui.imgui().mouse_pos();
let mouse_pos_in_canvas = (mouse_pos.0 - canvas_pos.0, mouse_pos.1 - canvas_pos.1);
if state.adding_line {
adding_preview = true;
state.points.push(mouse_pos_in_canvas);
if !ui.imgui().is_mouse_down(ImMouseButton::Left) {
state.adding_line = false;
adding_preview = false;
}
}
if ui.is_item_hovered() {
if !state.adding_line && ui.imgui().is_mouse_clicked(ImMouseButton::Left) {
state.points.push(mouse_pos_in_canvas);
state.adding_line = true;
}
if ui.imgui().is_mouse_clicked(ImMouseButton::Right) && !state.points.is_empty() {
state.adding_line = false;
adding_preview = false;
state.points.pop();
state.points.pop();
}
}
draw_list.with_clip_rect_intersect(
canvas_pos,
(canvas_pos.0 + canvas_size.0, canvas_pos.1 + canvas_size.1),
|| {
const LINE_COLOR: [f32; 3] = [1.0, 1.0, 0.0];
for line in state.points.chunks(2) {
if line.len() < 2 {
break;
}
let (p1, p2) = (line[0], line[1]);
draw_list
.add_line(
(canvas_pos.0 + p1.0, canvas_pos.1 + p1.1),
(canvas_pos.0 + p2.0, canvas_pos.1 + p2.1),
LINE_COLOR,
)
.thickness(2.0)
.build();
}
},
);
if adding_preview {
state.points.pop();
}
});
}