Add DrawListMut::add_image and friends

This commit is contained in:
dbr 2021-02-10 14:56:26 +11:00
parent 56d95395e7
commit 00d8180671
2 changed files with 407 additions and 1 deletions

View File

@ -79,7 +79,7 @@ impl CustomTexturesApp {
fn show_textures(&self, ui: &Ui) {
Window::new(im_str!("Hello textures"))
.size([400.0, 600.0], Condition::FirstUseEver)
.size([400.0, 400.0], Condition::FirstUseEver)
.build(ui, || {
ui.text(im_str!("Hello textures!"));
if let Some(my_texture_id) = self.my_texture_id {
@ -91,6 +91,89 @@ impl CustomTexturesApp {
ui.text("Say hello to Lenna.jpg");
lenna.show(ui);
}
// Example of using custom textures on a button
if let Some(lenna) = &self.lenna {
ui.text("The Lenna buttons");
{
let _is_clicked =
ui.invisible_button(im_str!("Boring Button"), [100.0, 100.0]);
// See also `imgui::Ui::style_color`
let tint_none = [1.0, 1.0, 1.0, 1.0];
let tint_green = [0.5, 1.0, 0.5, 1.0];
let tint_red = [1.0, 0.5, 0.5, 1.0];
let tint = match (
ui.is_item_hovered(),
ui.is_mouse_down(imgui::MouseButton::Left),
) {
(false, false) => tint_none,
(false, true) => tint_none,
(true, false) => tint_green,
(true, true) => tint_red,
};
let draw_list = ui.get_window_draw_list();
draw_list
.add_image(lenna.texture_id, ui.item_rect_min(), ui.item_rect_max())
.col(tint)
.build();
}
{
ui.same_line(0.0);
// Button using quad positioned image
let is_clicked =
ui.invisible_button(im_str!("Exciting Button"), [100.0, 100.0]);
// Button bounds
let min = ui.item_rect_min();
let max = ui.item_rect_max();
// get corner coordinates
let tl = [
min[0],
min[1] + (ui.frame_count() as f32 / 10.0).cos() * 10.0,
];
let tr = [
max[0],
min[1] + (ui.frame_count() as f32 / 10.0).sin() * 10.0,
];
let bl = [min[0], max[1]];
let br = max;
let draw_list = ui.get_window_draw_list();
draw_list
.add_image_quad(lenna.texture_id, tl, tr, br, bl)
.build();
}
// Rounded image
{
ui.same_line(0.0);
let is_clicked =
ui.invisible_button(im_str!("Smooth Button"), [100.0, 100.0]);
let draw_list = ui.get_window_draw_list();
draw_list
.add_image_rounded(
lenna.texture_id,
ui.item_rect_min(),
ui.item_rect_max(),
16.0,
)
// Tint brighter for visiblity of corners
.col([2.0, 0.5, 0.5, 1.0])
// Rounding on each corner can be changed separately
.round_top_left((ui.frame_count()+0) / 60 % 4 == 0)
.round_top_right((ui.frame_count()+1) / 60 % 4 == 1)
.round_bot_right((ui.frame_count()+3) / 60 % 4 == 2)
.round_bot_left((ui.frame_count()+2) / 60 % 4 == 3)
.build();
}
}
});
}
}

View File

@ -3,6 +3,7 @@ use sys::ImDrawList;
use super::Ui;
use crate::legacy::ImDrawCornerFlags;
use crate::render::renderer::TextureId;
use std::marker::PhantomData;
@ -251,6 +252,66 @@ impl<'ui> DrawListMut<'ui> {
}
}
/// # Images
impl<'ui> DrawListMut<'ui> {
/// Draw the specified image in the rect specified by `p_min` to
/// `p_max`.
///
/// # Examples
///
/// ```
/// # use imgui::*;
/// fn custom_button(ui: &Ui, img_id: TextureId) {
/// // Tint image red
///
/// // Invisible button is good widget to customise with custom image
/// ui.invisible_button(im_str!("custom_button"), [100.0, 20.0]);
///
/// // Red tint when button is hovered, no tint otherwise
/// let overlay_color = if ui.is_item_hovered() {
/// [1.0, 0.6, 0.6, 1.0]
/// } else {
/// [1.0, 1.0, 1.0, 1.0]
/// };
///
/// // Get draw list and draw image over invisible button
/// let draw_list = ui.get_window_draw_list();
/// draw_list
/// .add_image(img_id, ui.item_rect_min(), ui.item_rect_max())
/// .col(overlay_color)
/// .build();
/// }
/// ```
pub fn add_image(&'ui self, texture_id: TextureId, p_min: [f32; 2], p_max: [f32; 2]) -> Image {
Image::new(self, texture_id, p_min, p_max)
}
/// Draw the specified image to a quad with the specified
/// coordinates. Similar to [`DrawListMut::add_image`] but this
/// method is able to draw non-rectangle images.
pub fn add_image_quad(
&'ui self,
texture_id: TextureId,
p1: [f32; 2],
p2: [f32; 2],
p3: [f32; 2],
p4: [f32; 2],
) -> ImageQuad {
ImageQuad::new(self, texture_id, p1, p2, p3, p4)
}
/// Draw the speciied image, with rounded corners
pub fn add_image_rounded(
&'ui self,
texture_id: TextureId,
p_min: [f32; 2],
p_max: [f32; 2],
rounding: f32,
) -> ImageRounded {
ImageRounded::new(self, texture_id, p_min, p_max, rounding)
}
}
/// Represents a line about to be drawn
#[must_use = "should call .build() to draw the object"]
pub struct Line<'ui> {
@ -605,3 +666,265 @@ impl<'ui> BezierCurve<'ui> {
}
}
}
/// Represents a image about to be drawn
#[must_use = "should call .build() to draw the object"]
pub struct Image<'ui> {
texture_id: TextureId,
p_min: [f32; 2],
p_max: [f32; 2],
uv_min: [f32; 2],
uv_max: [f32; 2],
col: ImColor32,
draw_list: &'ui DrawListMut<'ui>,
}
impl<'ui> Image<'ui> {
fn new(
draw_list: &'ui DrawListMut,
texture_id: TextureId,
p_min: [f32; 2],
p_max: [f32; 2],
) -> Self {
Self {
texture_id,
p_min,
p_max,
uv_min: [0.0, 0.0],
uv_max: [1.0, 1.0],
col: [1.0, 1.0, 1.0, 1.0].into(),
draw_list,
}
}
/// Set uv_min (default `[0.0, 0.0]`)
pub fn uv_min(mut self, uv_min: [f32; 2]) -> Self {
self.uv_min = uv_min;
self
}
/// Set uv_max (default `[1.0, 1.0]`)
pub fn uv_max(mut self, uv_max: [f32; 2]) -> Self {
self.uv_max = uv_max;
self
}
/// Set color tint (default: no tint/white `[1.0, 1.0, 1.0, 1.0]`)
pub fn col<C>(mut self, col: C) -> Self
where
C: Into<ImColor32>,
{
self.col = col.into();
self
}
/// Draw the image on the window.
pub fn build(self) {
use std::os::raw::c_void;
unsafe {
sys::ImDrawList_AddImage(
self.draw_list.draw_list,
self.texture_id.id() as *mut c_void,
self.p_min.into(),
self.p_max.into(),
self.uv_min.into(),
self.uv_max.into(),
self.col.into(),
);
}
}
}
/// Represents a image about to be drawn
#[must_use = "should call .build() to draw the object"]
pub struct ImageQuad<'ui> {
texture_id: TextureId,
p1: [f32; 2],
p2: [f32; 2],
p3: [f32; 2],
p4: [f32; 2],
uv1: [f32; 2],
uv2: [f32; 2],
uv3: [f32; 2],
uv4: [f32; 2],
col: ImColor32,
draw_list: &'ui DrawListMut<'ui>,
}
impl<'ui> ImageQuad<'ui> {
fn new(
draw_list: &'ui DrawListMut,
texture_id: TextureId,
p1: [f32; 2],
p2: [f32; 2],
p3: [f32; 2],
p4: [f32; 2],
) -> Self {
Self {
texture_id,
p1,
p2,
p3,
p4,
uv1: [0.0, 0.0],
uv2: [1.0, 0.0],
uv3: [1.0, 1.0],
uv4: [0.0, 1.0],
col: [1.0, 1.0, 1.0, 1.0].into(),
draw_list,
}
}
/// Set uv coordinates of each point of the quad. If not called, defaults are:
///
/// ```
/// uv1: [0, 0],
/// uv2: [1, 0],
/// uv3: [1, 1],
/// uv4: [0, 1],
/// ```
pub fn uv(mut self, uv1: [f32; 2], uv2: [f32; 2], uv3: [f32; 2], uv4: [f32; 2]) -> Self {
self.uv1 = uv1;
self.uv2 = uv2;
self.uv3 = uv3;
self.uv4 = uv4;
self
}
/// Set color tint (default: no tint/white `[1.0, 1.0, 1.0, 1.0]`)
pub fn col<C>(mut self, col: C) -> Self
where
C: Into<ImColor32>,
{
self.col = col.into();
self
}
/// Draw the image on the window.
pub fn build(self) {
use std::os::raw::c_void;
unsafe {
sys::ImDrawList_AddImageQuad(
self.draw_list.draw_list,
self.texture_id.id() as *mut c_void,
self.p1.into(),
self.p2.into(),
self.p3.into(),
self.p4.into(),
self.uv1.into(),
self.uv2.into(),
self.uv3.into(),
self.uv4.into(),
self.col.into(),
);
}
}
}
/// Represents a image about to be drawn
#[must_use = "should call .build() to draw the object"]
pub struct ImageRounded<'ui> {
texture_id: TextureId,
p_min: [f32; 2],
p_max: [f32; 2],
uv_min: [f32; 2],
uv_max: [f32; 2],
col: ImColor32,
rounding: f32,
rounding_corners: ImDrawCornerFlags,
draw_list: &'ui DrawListMut<'ui>,
}
impl<'ui> ImageRounded<'ui> {
fn new(
draw_list: &'ui DrawListMut,
texture_id: TextureId,
p_min: [f32; 2],
p_max: [f32; 2],
rounding: f32,
) -> Self {
Self {
texture_id,
p_min,
p_max,
uv_min: [0.0, 0.0],
uv_max: [1.0, 1.0],
col: [1.0, 1.0, 1.0, 1.0].into(),
rounding,
rounding_corners: ImDrawCornerFlags::All,
draw_list,
}
}
/// Set uv_min (default `[0.0, 0.0]`)
pub fn uv_min(mut self, uv_min: [f32; 2]) -> Self {
self.uv_min = uv_min;
self
}
/// Set uv_max (default `[1.0, 1.0]`)
pub fn uv_max(mut self, uv_max: [f32; 2]) -> Self {
self.uv_max = uv_max;
self
}
/// Set color tint (default: no tint/white `[1.0, 1.0, 1.0, 1.0]`)
pub fn col<C>(mut self, col: C) -> Self
where
C: Into<ImColor32>,
{
self.col = col.into();
self
}
/// Set flag to indicate rounding on all all corners.
pub fn round_all(mut self, value: bool) -> Self {
self.rounding_corners.set(ImDrawCornerFlags::All, value);
self
}
/// Set flag to indicate if image's top-left corner will be rounded.
pub fn round_top_left(mut self, value: bool) -> Self {
self.rounding_corners.set(ImDrawCornerFlags::TopLeft, value);
self
}
/// Set flag to indicate if image's top-right corner will be rounded.
pub fn round_top_right(mut self, value: bool) -> Self {
self.rounding_corners
.set(ImDrawCornerFlags::TopRight, value);
self
}
/// Set flag to indicate if image's bottom-left corner will be rounded.
pub fn round_bot_left(mut self, value: bool) -> Self {
self.rounding_corners.set(ImDrawCornerFlags::BotLeft, value);
self
}
/// Set flag to indicate if image's bottom-right corner will be rounded.
pub fn round_bot_right(mut self, value: bool) -> Self {
self.rounding_corners
.set(ImDrawCornerFlags::BotRight, value);
self
}
/// Draw the image on the window.
pub fn build(self) {
use std::os::raw::c_void;
unsafe {
sys::ImDrawList_AddImageRounded(
self.draw_list.draw_list,
self.texture_id.id() as *mut c_void,
self.p_min.into(),
self.p_max.into(),
self.uv_min.into(),
self.uv_max.into(),
self.col.into(),
self.rounding.into(),
self.rounding_corners.bits(),
);
}
}
}