mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-16 07:58:33 +00:00
Merge branch 'main' of https://github.com/imgui-rs/imgui-rs
This commit is contained in:
commit
69528d7942
34
.github/workflows/ci.yml
vendored
34
.github/workflows/ci.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
rust: ["1.54"]
|
||||
rust: ["1.57"]
|
||||
|
||||
env:
|
||||
RUSTFLAGS: -D warnings
|
||||
@ -67,15 +67,8 @@ jobs:
|
||||
- name: freetype and docking
|
||||
run: cargo clippy --workspace --all-targets --features freetype,docking
|
||||
|
||||
# supported winit versions (with otherwise default features)
|
||||
- run: cargo doc
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-19 --all-targets
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-20 --all-targets
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-22 --all-targets
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-23/default --all-targets
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-24/default --all-targets
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-25/default --all-targets
|
||||
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-26/default --all-targets
|
||||
- name: all features
|
||||
run: cargo clippy --workspace --all-targets --features docking,freetype
|
||||
|
||||
test:
|
||||
name: Run tests
|
||||
@ -89,7 +82,7 @@ jobs:
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
- "1.54"
|
||||
- "1.57"
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macos-latest
|
||||
@ -147,20 +140,17 @@ jobs:
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: cargo test --workspace --all-targets --features freetype
|
||||
|
||||
- name: freetype and docking
|
||||
- name: all features
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: cargo test --workspace --all-targets --features freetype,docking
|
||||
run: cargo test --workspace --all-targets --features docking,freetype
|
||||
|
||||
- name: doc tests
|
||||
run: cargo test --workspace --doc
|
||||
|
||||
- run: cargo test --workspace --doc
|
||||
# run to check for lint problems
|
||||
- run: cargo doc
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-19
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-20
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-22
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-23/default
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-24/default
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-25/default
|
||||
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-26/default
|
||||
- name: build documentation
|
||||
run: cargo doc
|
||||
|
||||
# Run unreasonably slow tests under release, but only the crates that have
|
||||
# them, and don't bother doing this on most platforms.
|
||||
- run: cargo test -p imgui --release -- --ignored
|
||||
|
||||
@ -1,11 +1,20 @@
|
||||
# Change Log
|
||||
|
||||
## Unreleased
|
||||
## [unreleased]
|
||||
- Removed `im_str!` macro - deprecated since v0.8.
|
||||
|
||||
- MSRV is now **1.54**. We soft-updated to this in 0.8.0 with a feature `min-const-generics`, which has now been removed (and as such, we resume having no default features).
|
||||
`ui.button(im_str!("Example"))` just becomes `ui.button("Example")` and `ui.button(&im_str!("My age is {}", 100))` becomes `ui.button!(format!("My age is {}", 100))`
|
||||
|
||||
## [0.9.0] - 2022-11-30
|
||||
|
||||
- MSRV is now **1.57**. We soft-updated to this to Rust 1.54 in the v0.8.0 release (with a feature `min-const-generics`), which has now been removed (and as such, we resume having no default features). Rust 1.56 is required for the Rust 2021 edition, and 1.57 is required by some dependencies
|
||||
|
||||
- Upgraded from Dear ImGui 1.84.2 to 1.86. See [the 1.85](https://github.com/ocornut/imgui/releases/tag/v1.85) and [the 1.86](https://github.com/ocornut/imgui/releases/tag/v1.86) release notes
|
||||
|
||||
- Upgraded winit version to `v0.27` for `imgu-winit-support`
|
||||
|
||||
- The `imgui-winit-support` and `imgui-glow-renderer` re-export `winit` and `glow` respectively to make setup easier for simple projects. [PR #676](https://github.com/imgui-rs/imgui-rs/pull/676)
|
||||
|
||||
- BREAKING: Removed `push_style_colors` and `push_style_vars`. Instead, use `push_style_color` in a loop. This was deprecated in `0.7.0` and should have been removed in `0.8.0`. This also removes their associated tokens.
|
||||
|
||||
- BREAKING: Ui now does not have a lifetime associated with it, but is only ever given to users in the form of `&mut Ui`. Additionally, the `render` function has been moved to the `Context` instead of `Ui`.
|
||||
@ -36,6 +45,10 @@
|
||||
|
||||
- Fixed dpi related issues when not in `HiDpiMode::Default` mode. The wrong scale factor was used when converting winit physical size to logical size, causing the imgui display size to be incorrect.
|
||||
|
||||
- Fixed creation of `.crate` (published to crates.io) so required files for freetype feature are included
|
||||
|
||||
- Added binding to TextFilter API. [PR #658](https://github.com/imgui-rs/imgui-rs/pull/658)
|
||||
|
||||
## [0.8.0] - 2021-09-17
|
||||
|
||||
Welcome to the `0.8.0` update. This is one of the largest updates imgui-rs has ever seen; it will generate errors in a `0.7` project, but hopefully it should be both quick to fix, and enjoyable to update. See our [release page](https://github.com/imgui-rs/imgui-rs/releases/tag/v0.8.0) for more information and a list of contributors to this cycle. Thank you to everyone who uses `imgui-rs`, files issues, and spend their time and effort to PR new changes into the codebase. Because of all that effort, this is by far the best `imgui-rs` has looked!
|
||||
@ -771,7 +784,8 @@ As mentioned, the 0.6.1 release of `imgui-winit-support` has been yanked.
|
||||
|
||||
- Initial release with cimgui/imgui 1.44, glium 0.9
|
||||
|
||||
[unreleased]: https://github.com/Gekkio/imgui-rs/compare/v0.8.0...HEAD
|
||||
[unreleased]: https://github.com/Gekkio/imgui-rs/compare/v0.9.0...HEAD
|
||||
[0.9.0]: https://github.com/Gekkio/imgui-rs/compare/v0.8.0...v0.9.0
|
||||
[0.8.0]: https://github.com/Gekkio/imgui-rs/compare/v0.7.0...v0.8.0
|
||||
[0.7.0]: https://github.com/Gekkio/imgui-rs/compare/v0.6.1...v0.7.0
|
||||
[0.6.1]: https://github.com/Gekkio/imgui-rs/compare/v0.6.0...v0.6.1
|
||||
|
||||
@ -3,9 +3,7 @@
|
||||
[](https://github.com/imgui-rs/imgui-rs/actions)
|
||||
[](https://crates.io/crates/imgui)
|
||||
[](https://docs.rs/imgui)
|
||||
[](https://github.com/ocornut/imgui)
|
||||
|
||||
(Recently under new maintenance, things subject to change)
|
||||
[](https://github.com/ocornut/imgui)
|
||||
|
||||

|
||||
|
||||
@ -34,11 +32,6 @@ ui.window("Hello world")
|
||||
- imgui-glium-renderer: Renderer implementation that uses the `glium` crate
|
||||
- imgui-sys: Low-level unsafe API (automatically generated)
|
||||
|
||||
Additionally, the following are no longer maintained, but might work still:
|
||||
|
||||
- imgui-gfx-renderer: Renderer implementation that uses the `gfx` crate (_not
|
||||
the new gfx-hal crate_). This can be found at [imgui-rs/imgui-gfx-renderer](https://github.com/imgui-rs/imgui-gfx-renderer)
|
||||
|
||||
## Features
|
||||
|
||||
- Bindings for Dear ImGui that can be used with safe Rust. Note: API coverage
|
||||
@ -51,7 +44,7 @@ Additionally, the following are no longer maintained, but might work still:
|
||||
|
||||
## Minimum Support Rust Version (MSRV)
|
||||
|
||||
The MSRV for `imgui-rs` and all of the backend crates is **1.54**. We update our MSRV periodically, and issue a minor bump for it.
|
||||
The MSRV for `imgui-rs` and all of the backend crates is **1.57**. We update our MSRV periodically, and issue a minor bump for it.
|
||||
|
||||
## Choosing a backend platform and a renderer
|
||||
|
||||
@ -90,6 +83,8 @@ Additionally, there are other libraries which provide other kinds of renderers,
|
||||
1. [`imgui-wgpu`](https://github.com/Yatekii/imgui-wgpu-rs)
|
||||
2. [`imgui-d3d12-renderer`](https://github.com/curldivergence/imgui-d3d12-renderer)
|
||||
3. [`imgui-dx11-renderer`](https://github.com/veykril/imgui-dx11-renderer)
|
||||
4. [`imgui-gfx-renderer`](https://github.com/imgui-rs/imgui-gfx-renderer): Deprecated (no longer maintained beyond imgui-rs v0.8). Renderer implementation that uses the `gfx` crate (_not the new gfx-hal crate_)
|
||||
|
||||
|
||||
You can also write your own support code if you have a more advanced use case, because **imgui-rs is not tied to any specific graphics / OS API**.
|
||||
|
||||
|
||||
37
docs/development-process.md
Normal file
37
docs/development-process.md
Normal file
@ -0,0 +1,37 @@
|
||||
# imgui-rs development process
|
||||
|
||||
As summarised in [issue #665](https://github.com/imgui-rs/imgui-rs/issues/665)
|
||||
|
||||
In summary:
|
||||
|
||||
1. There is a `main` branch
|
||||
2. For each semver compatible release there is a stable branch (e.g `0.9-stable`)
|
||||
3. Each patch release becomes a tagged commit on this stable branch (e.g `v0.9.5` would come from a tagged commit on the `0.9-stable` branch)
|
||||
|
||||
## General process
|
||||
|
||||
Day to day development
|
||||
|
||||
1. Work on `main` branch
|
||||
2. General PR's are submitted against the `main` branch
|
||||
|
||||
When it is time to make a new release, we create a `x.y-stable` branch (e.g `0.9-stable`) from `main`
|
||||
|
||||
1. Ensure `CHANGELOG` is up to date
|
||||
2. Ensure README is up-to-date (including the Dear ImGui Version in badge URL, MSRV)
|
||||
3. Bump `version` in the various `Cargo.toml`
|
||||
4. A stable branch is created, e.g `git switch -c 0.9-stable` and pushed to Github
|
||||
5. Publish various crates (noting it has to be done starting with `imgui-sys`, then `imgui`, then the others)
|
||||
6. Create annotated tag `v0.9.0` and push to github
|
||||
7. Create Release for this version on Github
|
||||
8. Update and close any relevant tickets
|
||||
|
||||
All further PR's are still done to `main`
|
||||
|
||||
1. If they are applicable to previous release (e.g bugfixes or non-breaking changes), they are cherry-picked back to the applicable `stable` branch(es)
|
||||
|
||||
## When to bump versions in Cargo.toml
|
||||
|
||||
Only before publishing to crates.io.
|
||||
|
||||
This makes users able use `[patch.crates-io]` without hand-editing versions throughout their dependency tree (typically impossible without forking/editing transitive dependencies, even if there are no breaking code changes otherwise).
|
||||
@ -2,7 +2,6 @@
|
||||
name = "imgui-examples"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
authors = ["The imgui-rs Developers"]
|
||||
description = "imgui crate examples using Glium backend"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
@ -11,11 +10,16 @@ publish = false
|
||||
|
||||
[dev-dependencies]
|
||||
clipboard = "0.5"
|
||||
glium = { version = "0.31", default-features = true }
|
||||
glium = { version = "0.32.1", default-features = true }
|
||||
image = "0.23"
|
||||
imgui = { path = "../imgui", features = ["tables-api"] }
|
||||
imgui-glium-renderer = { path = "../imgui-glium-renderer" }
|
||||
imgui-winit-support = { path = "../imgui-winit-support", features=["viewports"] }
|
||||
|
||||
glow = "0.11.2"
|
||||
glutin = "0.28.0"
|
||||
# Pin indirect dependency scoped-tls to 1.0.0
|
||||
# as 1.0.1 bumped MSRV to 1.59
|
||||
# Used only in
|
||||
# imgui-examples -> glium -> glutin -> wayland-client -> scoped-tls
|
||||
# so not worth bumping MSRV for this basically to keep CI happy
|
||||
# FIXME: Remove this for imgui-rs v0.10 and bump MSRV
|
||||
scoped-tls = "=1.0.0"
|
||||
|
||||
@ -15,8 +15,10 @@ fn main() {
|
||||
|
||||
let system = support::init(file!());
|
||||
system.main_loop(move |_, ui| {
|
||||
// Show the C++ style API
|
||||
ui.window("Hello long world")
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
.size([100.0, 500.0], Condition::FirstUseEver)
|
||||
.position([10.0, 10.0], crate::Condition::Always)
|
||||
.build(|| {
|
||||
let mut clipper = imgui::ListClipper::new(lots_of_words.len() as i32)
|
||||
.items_height(ui.current_font_size())
|
||||
@ -27,5 +29,18 @@ fn main() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Show the more Rust'y iterator
|
||||
ui.window("Hello long world (iterator API)")
|
||||
.size([100.0, 500.0], Condition::FirstUseEver)
|
||||
.position([150.0, 10.0], crate::Condition::Always)
|
||||
.build(|| {
|
||||
let clipper = imgui::ListClipper::new(lots_of_words.len() as i32)
|
||||
.items_height(ui.current_font_size())
|
||||
.begin(ui);
|
||||
for row_num in clipper.iter() {
|
||||
ui.text(&lots_of_words[row_num as usize]);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
52
imgui-examples/examples/long_table.rs
Normal file
52
imgui-examples/examples/long_table.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use imgui::*;
|
||||
|
||||
mod support;
|
||||
|
||||
fn main() {
|
||||
let system = support::init(file!());
|
||||
|
||||
system.main_loop(move |_, ui| {
|
||||
ui.show_demo_window(&mut true);
|
||||
|
||||
ui.window("Table with list clipper")
|
||||
.size([800.0, 700.0], Condition::FirstUseEver)
|
||||
.build(|| {
|
||||
let num_cols = 3;
|
||||
let num_rows = 1000;
|
||||
|
||||
let flags = imgui::TableFlags::ROW_BG
|
||||
| imgui::TableFlags::RESIZABLE
|
||||
| imgui::TableFlags::BORDERS_H
|
||||
| imgui::TableFlags::BORDERS_V; //| imgui::TableFlags::SCROLL_Y;
|
||||
|
||||
if let Some(_t) = ui.begin_table_with_sizing(
|
||||
"longtable",
|
||||
num_cols,
|
||||
flags,
|
||||
[300.0, 100.0],
|
||||
/*inner width=*/ 0.0,
|
||||
) {
|
||||
ui.table_setup_column("A");
|
||||
ui.table_setup_column("B");
|
||||
ui.table_setup_column("C");
|
||||
|
||||
// Freeze first row so headers are visible even
|
||||
// when scrolling
|
||||
ui.table_setup_scroll_freeze(num_cols, 1);
|
||||
|
||||
// Done with headers row
|
||||
ui.table_headers_row();
|
||||
|
||||
// Create clipper with st
|
||||
let clip = imgui::ListClipper::new(num_rows).begin(ui);
|
||||
for row_num in clip.iter() {
|
||||
ui.table_next_row();
|
||||
for col_num in 0..num_cols {
|
||||
ui.table_set_column_index(col_num);
|
||||
ui.text(format!("Hello {},{}", col_num, row_num));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -53,6 +53,7 @@ struct State {
|
||||
stacked_modals_item: usize,
|
||||
stacked_modals_color: [f32; 4],
|
||||
app_log: Vec<String>,
|
||||
filter: imgui::TextFilter,
|
||||
|
||||
tabs: TabState,
|
||||
}
|
||||
@ -117,6 +118,7 @@ impl Default for State {
|
||||
stacked_modals_item: 0,
|
||||
stacked_modals_color: [0.4, 0.7, 0.0, 0.5],
|
||||
app_log: Vec::new(),
|
||||
filter: TextFilter::new(String::from("Test")),
|
||||
tabs: TabState::default(),
|
||||
}
|
||||
}
|
||||
@ -389,7 +391,8 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
|
||||
}
|
||||
if CollapsingHeader::new("Widgets").build(ui) {
|
||||
if let Some(_t) = ui.tree_node("Tree") {
|
||||
for i in 0..5 {
|
||||
let num_child = 4;
|
||||
for i in 0..num_child {
|
||||
if let Some(_t) = ui.tree_node(format!("Child {}", i)) {
|
||||
ui.text("blah blah");
|
||||
ui.same_line();
|
||||
@ -398,6 +401,20 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let tree_node_stack = ui.tree_node_config("##HideTreeNodeLabel")
|
||||
.allow_item_overlap(true)
|
||||
.push();
|
||||
ui.same_line();
|
||||
if ui.small_button(format!("Child {} is a button", num_child)) {
|
||||
println!("TreeNode Button pressed.");
|
||||
}
|
||||
|
||||
if tree_node_stack.is_some() {
|
||||
ui.text("blah blah")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(_t) = ui.tree_node("Bullets") {
|
||||
@ -732,6 +749,30 @@ CTRL+click on individual component to input value.\n",
|
||||
}
|
||||
}
|
||||
|
||||
if CollapsingHeader::new("Filtering").build(ui) {
|
||||
ui.text_wrapped(
|
||||
"Filter usage:\n\
|
||||
\"\" display all lines\n\
|
||||
\"xxx\" display lines containing \"xxx\"\n\
|
||||
\"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n\
|
||||
\"-xxx\" hide lines containing \"xxx\""
|
||||
);
|
||||
|
||||
state.filter.draw();
|
||||
let lines = vec!["aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world!"];
|
||||
|
||||
ui.same_line();
|
||||
if ui.button("Clear##clear_filter") {
|
||||
state.filter.clear();
|
||||
}
|
||||
|
||||
for i in lines.iter() {
|
||||
if state.filter.pass_filter(i) {
|
||||
ui.bullet_text(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if CollapsingHeader::new("Popups & Modal windows").build(ui) {
|
||||
if let Some(_t) = ui.tree_node("Popups") {
|
||||
ui.text_wrapped(
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
[package]
|
||||
name = "imgui-glium-renderer"
|
||||
version = "0.8.1-alpha.0"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
authors = ["The imgui-rs Developers"]
|
||||
description = "Glium renderer for the imgui crate"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
documentation = "https://docs.rs/imgui-glium-renderer"
|
||||
license = "MIT/Apache-2.0"
|
||||
categories = ["gui", "rendering"]
|
||||
|
||||
[dependencies]
|
||||
glium = { version = "0.31", default-features = false }
|
||||
imgui = { version = "0.8.1-alpha.0", path = "../imgui" }
|
||||
glium = { version = "0.32.1", default-features = false }
|
||||
imgui = { version = "0.9.0", path = "../imgui" }
|
||||
|
||||
@ -117,18 +117,21 @@ impl glium::vertex::Vertex for GliumDrawVert {
|
||||
(
|
||||
Borrowed("pos"),
|
||||
0,
|
||||
-1,
|
||||
glium::vertex::AttributeType::F32F32,
|
||||
false,
|
||||
),
|
||||
(
|
||||
Borrowed("uv"),
|
||||
8,
|
||||
-1,
|
||||
glium::vertex::AttributeType::F32F32,
|
||||
false,
|
||||
),
|
||||
(
|
||||
Borrowed("col"),
|
||||
16,
|
||||
-1,
|
||||
glium::vertex::AttributeType::U8U8U8U8,
|
||||
false,
|
||||
),
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
[package]
|
||||
name = "imgui-glow-renderer"
|
||||
version = "0.8.1-alpha.0"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
authors = ["jmaargh and the imgui-rs Developers"]
|
||||
description = "glow renderer for the imgui crate"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
@ -10,13 +9,13 @@ license = "MIT/Apache-2.0"
|
||||
categories = ["gui", "rendering"]
|
||||
|
||||
[dependencies]
|
||||
imgui = { version = "0.8.1-alpha.0", path = "../imgui" }
|
||||
imgui = { version = "0.9.0", path = "../imgui" }
|
||||
glow = "0.10.0"
|
||||
memoffset = "0.6.4"
|
||||
|
||||
[dev-dependencies]
|
||||
glutin = "0.28.0"
|
||||
imgui-winit-support = { version = "0.8.1-alpha.0", path = "../imgui-winit-support" }
|
||||
glutin = "0.29.1"
|
||||
imgui-winit-support = { version = "0.9.0", path = "../imgui-winit-support" }
|
||||
image = "0.23"
|
||||
|
||||
[features]
|
||||
|
||||
@ -26,7 +26,10 @@
|
||||
//! Consider this an example renderer. It is intended to be sufficent for simple
|
||||
//! applications running imgui-rs as the final rendering step. If your application
|
||||
//! has more specific needs, it's probably best to write your own renderer, in
|
||||
//! which case this can be a useful starting point.
|
||||
//! which case this can be a useful starting point. This renderer is also not
|
||||
//! foolproof (largely due to the global nature of the OpenGL state). For example,
|
||||
//! a few "internal" functions are marked `pub` to allow the user more
|
||||
//! fine-grained control at the cost of allowing potential rendering errors.
|
||||
//!
|
||||
//! # sRGB
|
||||
//!
|
||||
@ -47,6 +50,9 @@ use std::{borrow::Cow, error::Error, fmt::Display, mem::size_of};
|
||||
use imgui::{internal::RawWrapper, DrawCmd, DrawData, DrawVert};
|
||||
|
||||
use crate::versions::{GlVersion, GlslVersion};
|
||||
|
||||
// Re-export glow to make it easier for users to use the correct version.
|
||||
pub use glow;
|
||||
use glow::{Context, HasContext};
|
||||
|
||||
pub mod versions;
|
||||
@ -276,6 +282,16 @@ impl Renderer {
|
||||
gl_debug_message(gl, "imgui-rs-glow: start render");
|
||||
self.state_backup.pre_render(gl, self.gl_version);
|
||||
|
||||
#[cfg(feature = "bind_vertex_array_support")]
|
||||
if self.gl_version.bind_vertex_array_support() {
|
||||
unsafe {
|
||||
self.vertex_array_object = gl
|
||||
.create_vertex_array()
|
||||
.map_err(|err| format!("Error creating vertex array object: {}", err))?;
|
||||
gl.bind_vertex_array(Some(self.vertex_array_object));
|
||||
}
|
||||
}
|
||||
|
||||
self.set_up_render_state(gl, draw_data, fb_width, fb_height)?;
|
||||
|
||||
gl_debug_message(gl, "start loop over draw lists");
|
||||
@ -396,16 +412,6 @@ impl Renderer {
|
||||
unsafe { gl.bind_sampler(0, None) };
|
||||
}
|
||||
|
||||
#[cfg(feature = "bind_vertex_array_support")]
|
||||
if self.gl_version.bind_vertex_array_support() {
|
||||
unsafe {
|
||||
self.vertex_array_object = gl
|
||||
.create_vertex_array()
|
||||
.map_err(|err| format!("Error creating vertex array object: {}", err))?;
|
||||
gl.bind_vertex_array(Some(self.vertex_array_object));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: soon it should be possible for these to be `const` functions
|
||||
let position_field_offset = memoffset::offset_of!(DrawVert, pos) as _;
|
||||
let uv_field_offset = memoffset::offset_of!(DrawVert, uv) as _;
|
||||
|
||||
@ -1,19 +1,20 @@
|
||||
[package]
|
||||
name = "imgui-sdl2-support"
|
||||
version = "0.8.1-alpha.0"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
authors = ["The imgui-rs Developers"]
|
||||
description = "sdl2 support code for the imgui crate"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
documentation = "https://docs.rs/imgui-sdl2-support"
|
||||
license = "MIT/Apache-2.0"
|
||||
categories = ["gui"]
|
||||
|
||||
[dependencies]
|
||||
imgui = { version = "0.8.1-alpha.0", path = "../imgui" }
|
||||
imgui = { version = "0.9.0", path = "../imgui" }
|
||||
sdl2 = "0.34.5"
|
||||
|
||||
[dev-dependencies]
|
||||
glow = "0.10.0"
|
||||
imgui-glow-renderer = { version = "0.8.1-alpha.0", path = "../imgui-glow-renderer" }
|
||||
imgui-glow-renderer = { version = "0.9.0", path = "../imgui-glow-renderer" }
|
||||
sdl2 = { version = "0.34.5", features = ["bundled", "static-link"] }
|
||||
|
||||
@ -167,25 +167,29 @@ impl SdlPlatform {
|
||||
///
|
||||
/// * keyboard state is updated
|
||||
/// * mouse state is updated
|
||||
pub fn handle_event(&mut self, context: &mut Context, event: &Event) {
|
||||
pub fn handle_event(&mut self, context: &mut Context, event: &Event) -> bool {
|
||||
let io = context.io_mut();
|
||||
|
||||
match *event {
|
||||
Event::MouseWheel { x, y, .. } => {
|
||||
io.mouse_wheel = y as f32;
|
||||
io.mouse_wheel_h = x as f32;
|
||||
true
|
||||
}
|
||||
|
||||
Event::MouseButtonDown { mouse_btn, .. } => {
|
||||
self.handle_mouse_button(&mouse_btn, true);
|
||||
true
|
||||
}
|
||||
|
||||
Event::MouseButtonUp { mouse_btn, .. } => {
|
||||
self.handle_mouse_button(&mouse_btn, false);
|
||||
true
|
||||
}
|
||||
|
||||
Event::TextInput { ref text, .. } => {
|
||||
text.chars().for_each(|c| io.add_input_character(c));
|
||||
true
|
||||
}
|
||||
|
||||
Event::KeyDown {
|
||||
@ -195,6 +199,7 @@ impl SdlPlatform {
|
||||
} => {
|
||||
io.keys_down[key as usize] = true;
|
||||
handle_key_modifier(io, &keymod);
|
||||
true
|
||||
}
|
||||
|
||||
Event::KeyUp {
|
||||
@ -204,9 +209,10 @@ impl SdlPlatform {
|
||||
} => {
|
||||
io.keys_down[key as usize] = false;
|
||||
handle_key_modifier(io, &keymod);
|
||||
true
|
||||
}
|
||||
|
||||
_ => {}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,17 +1,29 @@
|
||||
[package]
|
||||
name = "imgui-sys"
|
||||
version = "0.8.1-alpha.0"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
authors = ["The imgui-rs Developers"]
|
||||
description = "Raw FFI bindings to dear imgui"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
documentation = "https://docs.rs/imgui-sys"
|
||||
license = "MIT/Apache-2.0"
|
||||
categories = ["gui", "external-ffi-bindings"]
|
||||
build = "build.rs"
|
||||
links = "imgui"
|
||||
# exclude .json, .lua from imgui dirs - they are intermediate artifacts from cimgui generator
|
||||
exclude = ["third-party/imgui-*/*.json", "third-party/imgui-*/*.lua"]
|
||||
|
||||
# exclude json, lua, and the imgui subdirs (imgui/examples, imgui/docs, etc)
|
||||
# ..but we need imgui/misc/freetype/ for the freetype feature
|
||||
exclude = [
|
||||
"third-party/*.json",
|
||||
"third-party/*.lua",
|
||||
"third-party/imgui/backends/",
|
||||
"third-party/imgui/docs/",
|
||||
"third-party/imgui/examples/",
|
||||
"third-party/imgui/misc/cpp/",
|
||||
"third-party/imgui/misc/debuggers/",
|
||||
"third-party/imgui/misc/fonts/",
|
||||
"third-party/imgui/misc/single_file/",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
chlorine = "1.0.7"
|
||||
|
||||
@ -1,32 +1,17 @@
|
||||
[package]
|
||||
name = "imgui-winit-support"
|
||||
version = "0.8.1-alpha.0"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
authors = ["The imgui-rs Developers"]
|
||||
description = "winit support code for the imgui crate"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
documentation = "https://docs.rs/imgui-winit-support"
|
||||
license = "MIT/Apache-2.0"
|
||||
categories = ["gui"]
|
||||
|
||||
[dependencies]
|
||||
imgui = { version = "0.8.1-alpha.0", path = "../imgui" }
|
||||
winit-19 = { version = ">= 0.16, < 0.20", package = "winit", optional = true }
|
||||
winit-20 = { version = ">= 0.20, < 0.22", package = "winit", optional = true }
|
||||
winit-22 = { version = "0.22", package = "winit", optional = true }
|
||||
winit-23 = { version = "0.23", package = "winit", default-features = false, optional = true }
|
||||
winit-24 = { version = "0.24", package = "winit", default-features = false, optional = true }
|
||||
winit-25 = { version = "0.25", package = "winit", default-features = false, optional = true }
|
||||
winit-26 = { version = "0.26", package = "winit", default-features = false, optional = true }
|
||||
imgui = { version = "0.9.0", path = "../imgui" }
|
||||
winit = { version = "0.27.2", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["winit-26/default"]
|
||||
test = ["winit-23/default", "winit-24/default", "winit-25/default", "winit-26/default"]
|
||||
|
||||
viewports = [ "imgui/docking" ]
|
||||
|
||||
# This is phrased as a negative (unlike most features) so that it needs to be
|
||||
# explicitly disabled (and `default-features = false` won't do it). To avoid
|
||||
# problems from this we don't expose this in the public API in any way, keeping
|
||||
# things additive.
|
||||
no-warn-on-multiple = []
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
# Updating Winit
|
||||
|
||||
Updating the default version of Winit is very annoying and error prone. We should make some automated way to do it so we don't have any issues in the future, but here is what needs to be done:
|
||||
|
||||
1. Make sure that glutin is on the new version of Winit that you want to use. It's easier if our default winit version is on that new default.
|
||||
2. Update the default in the Cargo.toml by simply changing the default guard.
|
||||
3. At the top of lib.rs, edit the CFG guards which handle `use winit_x as winit;` such that the new default only relies on a positive feature guard (just copy the form used for the old default). If you don't do this, you'll get some particularly strange errors about two crates being used, since somehow the dependency resolver will pick a winit that the user didn't choose (and presumably won't use if it actually made it to compilation).
|
||||
4. Profit??
|
||||
@ -13,16 +13,15 @@
|
||||
//! 4. Call frame preparation callback (every frame)
|
||||
//! 5. Call render preparation callback (every frame)
|
||||
//!
|
||||
//! ## Complete example for winit 0.20+ (without a renderer)
|
||||
//! ## Complete example (without a renderer)
|
||||
//!
|
||||
//! ```rust,no_run,ignore
|
||||
//! # // TODO: Remove ignore when only one winit version is used
|
||||
//! ```no_run
|
||||
//! use imgui::Context;
|
||||
//! use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
||||
//! use std::time::Instant;
|
||||
//! use winit::event::{Event, WindowEvent};
|
||||
//! use winit::event_loop::{ControlFlow, EventLoop};
|
||||
//! use winit::window::{Window};
|
||||
//! use winit::window::Window;
|
||||
//!
|
||||
//! let mut event_loop = EventLoop::new();
|
||||
//! let mut window = Window::new(&event_loop).unwrap();
|
||||
@ -39,7 +38,9 @@
|
||||
//! match event {
|
||||
//! Event::NewEvents(_) => {
|
||||
//! // other application-specific logic
|
||||
//! last_frame = imgui.io_mut().update_delta_time(last_frame);
|
||||
//! let now = Instant::now();
|
||||
//! imgui.io_mut().update_delta_time(now - last_frame);
|
||||
//! last_frame = now;
|
||||
//! },
|
||||
//! Event::MainEventsCleared => {
|
||||
//! // other application-specific logic
|
||||
@ -55,7 +56,7 @@
|
||||
//!
|
||||
//! platform.prepare_render(&ui, &window); // step 5
|
||||
//! // render the UI with a renderer
|
||||
//! let draw_data = ui.render();
|
||||
//! let draw_data = imgui.render();
|
||||
//! // renderer.render(..., draw_data).expect("UI rendering failed");
|
||||
//!
|
||||
//! // application-specific rendering *over the UI*
|
||||
@ -71,152 +72,15 @@
|
||||
//! }
|
||||
//! })
|
||||
//! ```
|
||||
//!
|
||||
//! ## `winit` versions and features.
|
||||
//!
|
||||
//! This crate has several features which control the version of winit which is
|
||||
//! used.
|
||||
//!
|
||||
//! The following versions are supported, controlled by the listed feature.
|
||||
//!
|
||||
//! - The `winit-26` feature uses winit versions compatible with `0.26`. This is
|
||||
//! on by default, so to use any other version you need to disable this crates
|
||||
//! default features.
|
||||
//! - The `winit-25` feature supports winit versions `0.25`.
|
||||
//! - The `winit-24` feature supports winit versions `0.24`.
|
||||
//! - The `winit-23` feature uses winit versions compatible with `0.23`.
|
||||
//! - The `winit-22` feature uses winit versions compatible with `0.22`.
|
||||
//! - The `winit-20` feature should support winit either `0.20` or winit `0.21`.
|
||||
//! - The `winit-19` feature should support winits older than `0.19` (possibly
|
||||
//! back to winit 0.16.*, but this isn't regularly tested and may not work).
|
||||
//!
|
||||
//! If multiple `winit-*` features are enabled, and it is a debug build (as
|
||||
//! determined by `debug_assertions`), we will log a warning to stderr during
|
||||
//! init. This can be disabled by either turning on the `no-warn-on-multiple`
|
||||
//! feature, fixing the configuration, or disabling `debug_assertions`.
|
||||
//!
|
||||
//! Conversely, if no `winit-*` features are enabled, we will fail to compile.
|
||||
//! This is not an issue generally, as by default we turn on `winit-26`.
|
||||
//!
|
||||
//! All of this is in attempt to preserve the additive nature of features (while
|
||||
//! still helping users notice project configuration issues), however it's done
|
||||
//! fairly weakly as our this crate's API isn't 100% identical across winit
|
||||
//! versions.
|
||||
//!
|
||||
//! ### Using an older `winit` version
|
||||
//!
|
||||
//! To use an older version, you must configure `default-features = false` in
|
||||
//! your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.imgui-winit-support]
|
||||
//! version = "0.6"
|
||||
//! features = ["winit-$YOUR_VERSION_HERE"]
|
||||
//! default-features = false
|
||||
//! ```
|
||||
//!
|
||||
//! ### Old `winit` compatibility
|
||||
//!
|
||||
//! No guarantee is made on how long this crate will support legacy versions of
|
||||
//! `winit`, but we'll try to follow these rules:
|
||||
//!
|
||||
//! - Versions which are still in widespread use in the ecosystem will be
|
||||
//! supported while that is true (for example, 0.19 at the time of writing is
|
||||
//! quite old, but used by the most recent version of several popular crates).
|
||||
//!
|
||||
//! - Versions which are not a significant maintenance burden will be supported
|
||||
//! (for example, supporting versions older than winit 0.19 given that we
|
||||
//! support 0.19).
|
||||
//!
|
||||
//! - Explicitly removing support for a feature-indicated version will be
|
||||
//! considered a breaking change.
|
||||
//!
|
||||
//! - Changing the default feature to the new latest `winit` version is *not* a
|
||||
//! breaking change.
|
||||
|
||||
#[cfg(feature = "winit-26")]
|
||||
use winit_26 as winit;
|
||||
|
||||
#[cfg(all(not(any(feature = "winit-26")), feature = "winit-25"))]
|
||||
use winit_25 as winit;
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "winit-26", feature = "winit-25")),
|
||||
feature = "winit-24"
|
||||
))]
|
||||
use winit_24 as winit;
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "winit-26", feature = "winit-25", feature = "winit-24")),
|
||||
feature = "winit-23"
|
||||
))]
|
||||
use winit_23 as winit;
|
||||
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23"
|
||||
)),
|
||||
feature = "winit-22",
|
||||
))]
|
||||
use winit_22 as winit;
|
||||
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22"
|
||||
)),
|
||||
feature = "winit-20",
|
||||
))]
|
||||
use winit_20 as winit;
|
||||
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
use winit_19 as winit;
|
||||
|
||||
use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui};
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
// Re-export winit to make it easier for users to use the correct version.
|
||||
pub use winit;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
use winit::{
|
||||
DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseCursor, MouseScrollDelta,
|
||||
TouchPhase, VirtualKeyCode, Window, WindowEvent,
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
))]
|
||||
use winit::{
|
||||
error::ExternalError,
|
||||
event::{
|
||||
@ -226,83 +90,6 @@ use winit::{
|
||||
window::{CursorIcon as MouseCursor, Window},
|
||||
};
|
||||
|
||||
// Ensure at least one is enabled
|
||||
#[cfg(not(any(
|
||||
feature = "winit-19",
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26",
|
||||
)))]
|
||||
compile_error!("Please enable at least one version of `winit` (see documentation for details).");
|
||||
|
||||
// FIXME(thom): make updading winit and adding a new feature less of a hassle here.
|
||||
fn check_multiple_winits() {
|
||||
use std::io::Write as _;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
// bail out for release builds or if we've been explicitly disabled.
|
||||
if cfg!(any(not(debug_assertions), feature = "no-warn-on-multiple")) {
|
||||
return;
|
||||
}
|
||||
let winits_enabled = cfg!(feature = "winit-26") as usize
|
||||
+ cfg!(feature = "winit-25") as usize
|
||||
+ cfg!(feature = "winit-24") as usize
|
||||
+ cfg!(feature = "winit-23") as usize
|
||||
+ cfg!(feature = "winit-22") as usize
|
||||
+ cfg!(feature = "winit-20") as usize
|
||||
+ cfg!(feature = "winit-19") as usize;
|
||||
|
||||
// Only complain once even if we're called multiple times.
|
||||
static COMPLAINED: AtomicBool = AtomicBool::new(false);
|
||||
// Note that the `Ordering` basically doesn't matter here, but even if it
|
||||
// did, `Relaxed` is still correct because we're only interested in the
|
||||
// effects on a single atomic variable.
|
||||
if winits_enabled <= 1
|
||||
|| COMPLAINED
|
||||
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let mut err = Vec::with_capacity(512);
|
||||
|
||||
// Log the complaint into a buffer first — in practice this is enough to
|
||||
// ensure atomicity.
|
||||
let _ = writeln!(
|
||||
err,
|
||||
"Warning (imgui-winit-support): More than one `winit-*` version feature is enabled \
|
||||
(this likely indicates misconfiguration, see documentation for details)."
|
||||
);
|
||||
let feats = [
|
||||
("winit-26", cfg!(feature = "winit-26"), " (default)"),
|
||||
("winit-25", cfg!(feature = "winit-25"), ""),
|
||||
("winit-24", cfg!(feature = "winit-24"), ""),
|
||||
("winit-23", cfg!(feature = "winit-23"), ""),
|
||||
("winit-22", cfg!(feature = "winit-22"), ""),
|
||||
("winit-20", cfg!(feature = "winit-20"), ""),
|
||||
("winit-19", cfg!(feature = "winit-19"), ""),
|
||||
];
|
||||
for &(name, enabled, extra) in &feats {
|
||||
if enabled {
|
||||
let _ = writeln!(err, " `feature = {:?}` is enabled{}", name, extra);
|
||||
}
|
||||
}
|
||||
if cfg!(feature = "winit-25") && winits_enabled == 2 {
|
||||
let _ = writeln!(
|
||||
err,
|
||||
" Perhaps you are missing a `default-features = false`?",
|
||||
);
|
||||
}
|
||||
let _ = writeln!(
|
||||
err,
|
||||
" (Note: This warning is only present in debug builds, and \
|
||||
can be disabled using the \"no-warn-on-multiple\" feature)"
|
||||
);
|
||||
let _ = std::io::stderr().write_all(&err);
|
||||
}
|
||||
|
||||
/// State of a single mouse button. Used so that we can detect cases where mouse
|
||||
/// press and release occur on the same frame (seems surprisingly frequent on
|
||||
/// macOS now...)
|
||||
@ -365,34 +152,6 @@ fn to_winit_cursor(cursor: imgui::MouseCursor) -> MouseCursor {
|
||||
}
|
||||
|
||||
impl CursorSettings {
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
fn apply(&self, window: &Window) {
|
||||
match self.cursor {
|
||||
Some(mouse_cursor) if !self.draw_cursor => {
|
||||
window.hide_cursor(false);
|
||||
window.set_cursor(to_winit_cursor(mouse_cursor));
|
||||
}
|
||||
_ => window.hide_cursor(true),
|
||||
}
|
||||
}
|
||||
#[cfg(any(
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26"
|
||||
))]
|
||||
fn apply(&self, window: &Window) {
|
||||
match self.cursor {
|
||||
Some(mouse_cursor) if !self.draw_cursor => {
|
||||
@ -571,8 +330,6 @@ impl WinitPlatform {
|
||||
/// * keys are configured
|
||||
/// * platform name is set
|
||||
pub fn init(imgui: &mut Context) -> WinitPlatform {
|
||||
// noop in non-debug builds, if disabled, or if called a second time.
|
||||
check_multiple_winits();
|
||||
let io = imgui.io_mut();
|
||||
io.backend_flags.insert(BackendFlags::HAS_MOUSE_CURSORS);
|
||||
io.backend_flags.insert(BackendFlags::HAS_SET_MOUSE_POS);
|
||||
@ -718,41 +475,6 @@ impl WinitPlatform {
|
||||
///
|
||||
/// * framebuffer scale (= DPI factor) is set
|
||||
/// * display size is set
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
pub fn attach_window(&mut self, io: &mut Io, window: &Window, hidpi_mode: HiDpiMode) {
|
||||
let (hidpi_mode, hidpi_factor) = hidpi_mode.apply(window.get_hidpi_factor());
|
||||
self.hidpi_mode = hidpi_mode;
|
||||
self.hidpi_factor = hidpi_factor;
|
||||
io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
|
||||
if let Some(logical_size) = window.get_inner_size() {
|
||||
let logical_size = self.scale_size_from_winit(window, logical_size);
|
||||
io.display_size = [logical_size.width as f32, logical_size.height as f32];
|
||||
}
|
||||
}
|
||||
/// Attaches the platform instance to a winit window.
|
||||
///
|
||||
/// This function configures imgui-rs in the following ways:
|
||||
///
|
||||
/// * framebuffer scale (= DPI factor) is set
|
||||
/// * display size is set
|
||||
#[cfg(any(
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26",
|
||||
))]
|
||||
pub fn attach_window(&mut self, io: &mut Io, window: &Window, hidpi_mode: HiDpiMode) {
|
||||
let (hidpi_mode, hidpi_factor) = hidpi_mode.apply(window.scale_factor());
|
||||
self.hidpi_mode = hidpi_mode;
|
||||
@ -772,37 +494,6 @@ impl WinitPlatform {
|
||||
///
|
||||
/// This utility function is useful if you are using a DPI mode other than default, and want
|
||||
/// your application to use the same logical coordinates as imgui-rs.
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
pub fn scale_size_from_winit(&self, window: &Window, logical_size: LogicalSize) -> LogicalSize {
|
||||
match self.hidpi_mode {
|
||||
ActiveHiDpiMode::Default => logical_size,
|
||||
_ => logical_size
|
||||
.to_physical(window.get_hidpi_factor())
|
||||
.to_logical(self.hidpi_factor),
|
||||
}
|
||||
}
|
||||
/// Scales a logical size coming from winit using the current DPI mode.
|
||||
///
|
||||
/// This utility function is useful if you are using a DPI mode other than default, and want
|
||||
/// your application to use the same logical coordinates as imgui-rs.
|
||||
#[cfg(any(
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26"
|
||||
))]
|
||||
pub fn scale_size_from_winit(
|
||||
&self,
|
||||
window: &Window,
|
||||
@ -819,41 +510,6 @@ impl WinitPlatform {
|
||||
///
|
||||
/// This utility function is useful if you are using a DPI mode other than default, and want
|
||||
/// your application to use the same logical coordinates as imgui-rs.
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
pub fn scale_pos_from_winit(
|
||||
&self,
|
||||
window: &Window,
|
||||
logical_pos: LogicalPosition,
|
||||
) -> LogicalPosition {
|
||||
match self.hidpi_mode {
|
||||
ActiveHiDpiMode::Default => logical_pos,
|
||||
_ => logical_pos
|
||||
.to_physical(window.get_hidpi_factor())
|
||||
.to_logical(self.hidpi_factor),
|
||||
}
|
||||
}
|
||||
/// Scales a logical position coming from winit using the current DPI mode.
|
||||
///
|
||||
/// This utility function is useful if you are using a DPI mode other than default, and want
|
||||
/// your application to use the same logical coordinates as imgui-rs.
|
||||
#[cfg(any(
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26"
|
||||
))]
|
||||
pub fn scale_pos_from_winit(
|
||||
&self,
|
||||
window: &Window,
|
||||
@ -870,41 +526,6 @@ impl WinitPlatform {
|
||||
///
|
||||
/// This utility function is useful if you are using a DPI mode other than default, and want
|
||||
/// your application to use the same logical coordinates as imgui-rs.
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
pub fn scale_pos_for_winit(
|
||||
&self,
|
||||
window: &Window,
|
||||
logical_pos: LogicalPosition,
|
||||
) -> LogicalPosition {
|
||||
match self.hidpi_mode {
|
||||
ActiveHiDpiMode::Default => logical_pos,
|
||||
_ => logical_pos
|
||||
.to_physical(self.hidpi_factor)
|
||||
.to_logical(window.get_hidpi_factor()),
|
||||
}
|
||||
}
|
||||
/// Scales a logical position for winit using the current DPI mode.
|
||||
///
|
||||
/// This utility function is useful if you are using a DPI mode other than default, and want
|
||||
/// your application to use the same logical coordinates as imgui-rs.
|
||||
#[cfg(any(
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26"
|
||||
))]
|
||||
pub fn scale_pos_for_winit(
|
||||
&self,
|
||||
window: &Window,
|
||||
@ -924,116 +545,6 @@ impl WinitPlatform {
|
||||
/// * window size / dpi factor changes are applied
|
||||
/// * keyboard state is updated
|
||||
/// * mouse state is updated
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
pub fn handle_event(&mut self, io: &mut Io, window: &Window, event: &Event) {
|
||||
match *event {
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
ref event,
|
||||
} if window_id == window.id() => {
|
||||
self.handle_window_event(io, window, event);
|
||||
}
|
||||
// Track key release events outside our window. If we don't do this,
|
||||
// we might never see the release event if some other window gets focus.
|
||||
Event::DeviceEvent {
|
||||
event:
|
||||
DeviceEvent::Key(KeyboardInput {
|
||||
state: ElementState::Released,
|
||||
virtual_keycode: Some(key),
|
||||
..
|
||||
}),
|
||||
..
|
||||
} => {
|
||||
io.keys_down[key as usize] = false;
|
||||
match key {
|
||||
VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = false,
|
||||
VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = false,
|
||||
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = false,
|
||||
VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = false,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
/// Handles a winit event.
|
||||
///
|
||||
/// This function performs the following actions (depends on the event):
|
||||
///
|
||||
/// * window size / dpi factor changes are applied
|
||||
/// * keyboard state is updated
|
||||
/// * mouse state is updated
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22"
|
||||
)),
|
||||
feature = "winit-20",
|
||||
))]
|
||||
pub fn handle_event<T>(&mut self, io: &mut Io, window: &Window, event: &Event<T>) {
|
||||
match *event {
|
||||
Event::WindowEvent {
|
||||
window_id,
|
||||
ref event,
|
||||
} if window_id == window.id() => {
|
||||
self.handle_window_event(io, window, event);
|
||||
}
|
||||
// Track key release events outside our window. If we don't do this,
|
||||
// we might never see the release event if some other window gets focus.
|
||||
Event::DeviceEvent {
|
||||
event:
|
||||
DeviceEvent::Key(KeyboardInput {
|
||||
state: ElementState::Released,
|
||||
virtual_keycode: Some(key),
|
||||
..
|
||||
}),
|
||||
..
|
||||
} => {
|
||||
io.keys_down[key as usize] = false;
|
||||
}
|
||||
|
||||
// We need to track modifiers separately because some system like macOS, will
|
||||
// not reliably send modifier states during certain events like ScreenCapture.
|
||||
// Gotta let the people show off their pretty imgui widgets!
|
||||
Event::DeviceEvent {
|
||||
event: DeviceEvent::ModifiersChanged(modifiers),
|
||||
..
|
||||
} => {
|
||||
io.key_shift = modifiers.shift();
|
||||
io.key_ctrl = modifiers.ctrl();
|
||||
io.key_alt = modifiers.alt();
|
||||
io.key_super = modifiers.logo();
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
/// Handles a winit event.
|
||||
///
|
||||
/// This function performs the following actions (depends on the event):
|
||||
///
|
||||
/// * window size / dpi factor changes are applied
|
||||
/// * keyboard state is updated
|
||||
/// * mouse state is updated
|
||||
#[cfg(any(
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26",
|
||||
))]
|
||||
pub fn handle_event<T>(&mut self, io: &mut Io, window: &Window, event: &Event<T>) {
|
||||
match *event {
|
||||
Event::WindowEvent {
|
||||
@ -1068,6 +579,7 @@ impl WinitPlatform {
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
pub fn handle_viewport_event<T>(
|
||||
&mut self,
|
||||
@ -1213,221 +725,6 @@ impl WinitPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
|
||||
match *event {
|
||||
WindowEvent::Resized(logical_size) => {
|
||||
let logical_size = self.scale_size_from_winit(window, logical_size);
|
||||
io.display_size = [logical_size.width as f32, logical_size.height as f32];
|
||||
}
|
||||
WindowEvent::HiDpiFactorChanged(scale) => {
|
||||
let hidpi_factor = match self.hidpi_mode {
|
||||
ActiveHiDpiMode::Default => scale,
|
||||
ActiveHiDpiMode::Rounded => scale.round(),
|
||||
_ => return,
|
||||
};
|
||||
// Mouse position needs to be changed while we still have both the old and the new
|
||||
// values
|
||||
if io.mouse_pos[0].is_finite() && io.mouse_pos[1].is_finite() {
|
||||
io.mouse_pos = [
|
||||
io.mouse_pos[0] * (hidpi_factor / self.hidpi_factor) as f32,
|
||||
io.mouse_pos[1] * (hidpi_factor / self.hidpi_factor) as f32,
|
||||
];
|
||||
}
|
||||
self.hidpi_factor = hidpi_factor;
|
||||
io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
|
||||
// Window size might change too if we are using DPI rounding
|
||||
if let Some(logical_size) = window.get_inner_size() {
|
||||
let logical_size = self.scale_size_from_winit(window, logical_size);
|
||||
io.display_size = [logical_size.width as f32, logical_size.height as f32];
|
||||
}
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
virtual_keycode: Some(key),
|
||||
state,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
io.keys_down[key as usize] = state == ElementState::Pressed;
|
||||
}
|
||||
WindowEvent::ReceivedCharacter(ch) => {
|
||||
// Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then
|
||||
// delete it.
|
||||
if ch != '\u{7f}' {
|
||||
io.add_input_character(ch)
|
||||
}
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let position = self.scale_pos_from_winit(window, position);
|
||||
io.mouse_pos = [position.x as f32, position.y as f32];
|
||||
}
|
||||
WindowEvent::MouseWheel {
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
..
|
||||
} => match delta {
|
||||
MouseScrollDelta::LineDelta(h, v) => {
|
||||
io.mouse_wheel_h = h;
|
||||
io.mouse_wheel = v;
|
||||
}
|
||||
MouseScrollDelta::PixelDelta(pos) => {
|
||||
match pos.x.partial_cmp(&0.0) {
|
||||
Some(Ordering::Greater) => io.mouse_wheel_h += 1.0,
|
||||
Some(Ordering::Less) => io.mouse_wheel_h -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
match pos.y.partial_cmp(&0.0) {
|
||||
Some(Ordering::Greater) => io.mouse_wheel += 1.0,
|
||||
Some(Ordering::Less) => io.mouse_wheel -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
},
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
match button {
|
||||
MouseButton::Left => self.mouse_buttons[0].set(pressed),
|
||||
MouseButton::Right => self.mouse_buttons[1].set(pressed),
|
||||
MouseButton::Middle => self.mouse_buttons[2].set(pressed),
|
||||
MouseButton::Other(idx @ 0..=4) => {
|
||||
self.mouse_buttons[idx as usize].set(pressed)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26"
|
||||
)),
|
||||
any(feature = "winit-20", feature = "winit-22")
|
||||
))]
|
||||
fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
|
||||
match *event {
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
let logical_size = physical_size.to_logical(window.scale_factor());
|
||||
let logical_size = self.scale_size_from_winit(window, logical_size);
|
||||
io.display_size = [logical_size.width as f32, logical_size.height as f32];
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
|
||||
let hidpi_factor = match self.hidpi_mode {
|
||||
ActiveHiDpiMode::Default => scale_factor,
|
||||
ActiveHiDpiMode::Rounded => scale_factor.round(),
|
||||
_ => return,
|
||||
};
|
||||
// Mouse position needs to be changed while we still have both the old and the new
|
||||
// values
|
||||
if io.mouse_pos[0].is_finite() && io.mouse_pos[1].is_finite() {
|
||||
io.mouse_pos = [
|
||||
io.mouse_pos[0] * (hidpi_factor / self.hidpi_factor) as f32,
|
||||
io.mouse_pos[1] * (hidpi_factor / self.hidpi_factor) as f32,
|
||||
];
|
||||
}
|
||||
self.hidpi_factor = hidpi_factor;
|
||||
io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
|
||||
// Window size might change too if we are using DPI rounding
|
||||
let logical_size = window.inner_size().to_logical(scale_factor);
|
||||
let logical_size = self.scale_size_from_winit(window, logical_size);
|
||||
io.display_size = [logical_size.width as f32, logical_size.height as f32];
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
virtual_keycode: Some(key),
|
||||
state,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
io.keys_down[key as usize] = pressed;
|
||||
|
||||
// This is a bit redundant here, but we'll leave it in. The OS occasionally
|
||||
// fails to send modifiers keys, but it doesn't seem to send false-positives,
|
||||
// so double checking isn't terrible in case some system *doesn't* send
|
||||
// device events sometimes.
|
||||
match key {
|
||||
VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = pressed,
|
||||
VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = pressed,
|
||||
VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = pressed,
|
||||
VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = pressed,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
WindowEvent::ReceivedCharacter(ch) => {
|
||||
// Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then
|
||||
// delete it.
|
||||
if ch != '\u{7f}' {
|
||||
io.add_input_character(ch)
|
||||
}
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let position = position.to_logical(window.scale_factor());
|
||||
let position = self.scale_pos_from_winit(window, position);
|
||||
io.mouse_pos = [position.x as f32, position.y as f32];
|
||||
}
|
||||
WindowEvent::MouseWheel {
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
..
|
||||
} => match delta {
|
||||
MouseScrollDelta::LineDelta(h, v) => {
|
||||
io.mouse_wheel_h = h;
|
||||
io.mouse_wheel = v;
|
||||
}
|
||||
MouseScrollDelta::PixelDelta(pos) => {
|
||||
match pos.x.partial_cmp(&0.0) {
|
||||
Some(Ordering::Greater) => io.mouse_wheel_h += 1.0,
|
||||
Some(Ordering::Less) => io.mouse_wheel_h -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
match pos.y.partial_cmp(&0.0) {
|
||||
Some(Ordering::Greater) => io.mouse_wheel += 1.0,
|
||||
Some(Ordering::Less) => io.mouse_wheel -= 1.0,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
},
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
match button {
|
||||
MouseButton::Left => self.mouse_buttons[0].set(pressed),
|
||||
MouseButton::Right => self.mouse_buttons[1].set(pressed),
|
||||
MouseButton::Middle => self.mouse_buttons[2].set(pressed),
|
||||
MouseButton::Other(idx @ 0..=4) => {
|
||||
self.mouse_buttons[idx as usize].set(pressed)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26"
|
||||
))]
|
||||
fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
|
||||
match *event {
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
@ -1527,6 +824,13 @@ impl WinitPlatform {
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
WindowEvent::Focused(newly_focused) => {
|
||||
if !newly_focused {
|
||||
// Set focus-lost to avoid stuck keys (like 'alt'
|
||||
// when alt-tabbing)
|
||||
io.app_focus_lost = true;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -1536,43 +840,6 @@ impl WinitPlatform {
|
||||
/// This function performs the following actions:
|
||||
///
|
||||
/// * mouse cursor is repositioned (if requested by imgui-rs)
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
feature = "winit-25",
|
||||
feature = "winit-24",
|
||||
feature = "winit-23",
|
||||
feature = "winit-22",
|
||||
feature = "winit-20"
|
||||
)),
|
||||
feature = "winit-19",
|
||||
))]
|
||||
pub fn prepare_frame(&self, io: &mut Io, window: &Window) -> Result<(), String> {
|
||||
self.copy_mouse_to_io(&mut io.mouse_down);
|
||||
if io.want_set_mouse_pos {
|
||||
let logical_pos = self.scale_pos_for_winit(
|
||||
window,
|
||||
LogicalPosition::new(f64::from(io.mouse_pos[0]), f64::from(io.mouse_pos[1])),
|
||||
);
|
||||
window.set_cursor_position(logical_pos)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
/// Frame preparation callback.
|
||||
///
|
||||
/// Call this before calling the imgui-rs context `frame` function.
|
||||
/// This function performs the following actions:
|
||||
///
|
||||
/// * mouse cursor is repositioned (if requested by imgui-rs)
|
||||
#[cfg(any(
|
||||
feature = "winit-20",
|
||||
feature = "winit-22",
|
||||
feature = "winit-23",
|
||||
feature = "winit-24",
|
||||
feature = "winit-25",
|
||||
feature = "winit-26",
|
||||
))]
|
||||
pub fn prepare_frame(&self, io: &mut Io, window: &Window) -> Result<(), ExternalError> {
|
||||
self.copy_mouse_to_io(&mut io.mouse_down);
|
||||
if io.want_set_mouse_pos {
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
[package]
|
||||
name = "imgui"
|
||||
version = "0.8.1-alpha.0"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
authors = ["The imgui-rs Developers"]
|
||||
description = "High-level Rust bindings to dear imgui"
|
||||
homepage = "https://github.com/imgui-rs/imgui-rs"
|
||||
repository = "https://github.com/imgui-rs/imgui-rs"
|
||||
documentation = "https://docs.rs/imgui"
|
||||
license = "MIT/Apache-2.0"
|
||||
categories = ["gui", "api-bindings"]
|
||||
readme = "../README.markdown"
|
||||
@ -17,9 +17,9 @@ features = ["freetype", "docking", "tables-api"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1"
|
||||
imgui-sys = { version = "0.8.1-alpha.0", path = "../imgui-sys" }
|
||||
imgui-sys = { version = "0.9.0", path = "../imgui-sys" }
|
||||
mint = "0.5.6"
|
||||
parking_lot = "0.11"
|
||||
parking_lot = "0.12"
|
||||
cfg-if = "1"
|
||||
|
||||
[features]
|
||||
|
||||
@ -426,7 +426,7 @@ impl<'ui> DrawListMut<'ui> {
|
||||
/// # use imgui::*;
|
||||
/// fn custom_button(ui: &Ui, img_id: TextureId) {
|
||||
/// // Invisible button is good widget to customise with image
|
||||
/// ui.invisible_button(im_str!("custom_button"), [100.0, 20.0]);
|
||||
/// ui.invisible_button("custom_button", [100.0, 20.0]);
|
||||
///
|
||||
/// // Get draw list and draw image over invisible button
|
||||
/// let draw_list = ui.get_window_draw_list();
|
||||
|
||||
@ -1051,7 +1051,20 @@ impl TextCallbackData {
|
||||
/// This Range is given in `usize` so that it might be used in indexing
|
||||
/// operations more easily. To quickly grab the selected text, use [selected](Self::selected).
|
||||
pub fn selection(&self) -> Range<usize> {
|
||||
unsafe { (*(self.0)).SelectionStart as usize..(*(self.0)).SelectionEnd as usize }
|
||||
let (start, end) = unsafe {
|
||||
(
|
||||
(*(self.0)).SelectionStart as usize,
|
||||
(*(self.0)).SelectionEnd as usize,
|
||||
)
|
||||
};
|
||||
// Avoid returning a range with start > end, which would be problematic. For example, it
|
||||
// would cause panics when used to index the string buffer and would also cause Self::has_selection
|
||||
// to return a false negative.
|
||||
if start < end {
|
||||
start..end
|
||||
} else {
|
||||
end..start
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the selected text directly. Note that if no text is selected,
|
||||
|
||||
@ -369,7 +369,11 @@ pub struct Io {
|
||||
nav_inputs_down_duration: [f32; NavInput::COUNT + NavInput::INTERNAL_COUNT],
|
||||
nav_inputs_down_duration_prev: [f32; NavInput::COUNT + NavInput::INTERNAL_COUNT],
|
||||
pen_pressure: f32,
|
||||
app_focus_lost: bool,
|
||||
|
||||
/// Clear buttons state when focus is lost (this is useful so
|
||||
/// e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger
|
||||
/// the Alt menu toggle)
|
||||
pub app_focus_lost: bool,
|
||||
input_queue_surrogate: sys::ImWchar16,
|
||||
input_queue_characters: ImVector<sys::ImWchar>,
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ pub use self::style::*;
|
||||
|
||||
#[cfg(feature = "tables-api")]
|
||||
pub use self::tables::*;
|
||||
pub use self::text_filter::*;
|
||||
pub use self::utils::*;
|
||||
pub use self::widget::color_editors::*;
|
||||
pub use self::widget::combo_box::*;
|
||||
@ -89,6 +90,7 @@ mod style;
|
||||
mod tables;
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
pub mod text_filter;
|
||||
mod utils;
|
||||
mod widget;
|
||||
mod window;
|
||||
@ -465,6 +467,7 @@ impl Ui {
|
||||
|
||||
// Widgets: Input
|
||||
impl<'ui> Ui {
|
||||
/// Edits text in a single line input widget
|
||||
#[doc(alias = "InputText", alias = "InputTextWithHint")]
|
||||
pub fn input_text<'p, L: AsRef<str>>(
|
||||
&'ui self,
|
||||
@ -473,6 +476,8 @@ impl<'ui> Ui {
|
||||
) -> InputText<'ui, 'p, L> {
|
||||
InputText::new(self, label, buf)
|
||||
}
|
||||
|
||||
/// Edits text in a multi line widget
|
||||
#[doc(alias = "InputText", alias = "InputTextMultiline")]
|
||||
pub fn input_text_multiline<'p, L: AsRef<str>>(
|
||||
&'ui self,
|
||||
@ -482,6 +487,8 @@ impl<'ui> Ui {
|
||||
) -> InputTextMultiline<'ui, 'p, L> {
|
||||
InputTextMultiline::new(self, label, buf, size)
|
||||
}
|
||||
|
||||
/// Simple floating point number widget
|
||||
#[doc(alias = "InputFloat2")]
|
||||
pub fn input_float<'p, L: AsRef<str>>(
|
||||
&'ui self,
|
||||
@ -618,7 +625,7 @@ impl Ui {
|
||||
/// ui.text("Hover over me");
|
||||
/// if ui.is_item_hovered() {
|
||||
/// ui.tooltip(|| {
|
||||
/// ui.text_colored([1.0, 0.0, 0.0, 1.0], im_str!("I'm red!"));
|
||||
/// ui.text_colored([1.0, 0.0, 0.0, 1.0], "I'm red!");
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
@ -685,7 +692,7 @@ impl Ui {
|
||||
/// fn user_interface(ui: &Ui) {
|
||||
/// let disable_buttons = true;
|
||||
/// let _d = ui.begin_disabled(disable_buttons);
|
||||
/// ui.button(im_str!("Dangerous button"));
|
||||
/// ui.button("Dangerous button");
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@ -712,7 +719,7 @@ impl Ui {
|
||||
/// fn user_interface(ui: &Ui) {
|
||||
/// let safe_mode = true;
|
||||
/// ui.disabled(safe_mode, || {
|
||||
/// ui.button(im_str!("Dangerous button"));
|
||||
/// ui.button("Dangerous button");
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
@ -727,9 +734,7 @@ impl Ui {
|
||||
/// [`Ui::begin_enabled`].
|
||||
#[doc(alias = "BeginDisabled", alias = "EndDisabled")]
|
||||
pub fn enabled<F: FnOnce()>(&self, enabled: bool, f: F) {
|
||||
unsafe { sys::igBeginDisabled(!enabled) };
|
||||
f();
|
||||
unsafe { sys::igEndDisabled() };
|
||||
self.disabled(!enabled, f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -802,6 +807,7 @@ impl Ui {
|
||||
}
|
||||
|
||||
impl<'ui> Ui {
|
||||
/// Plot a list of floats as a "sparkline" style plot
|
||||
#[doc(alias = "PlotLines")]
|
||||
pub fn plot_lines<'p, Label: AsRef<str>>(
|
||||
&'ui self,
|
||||
@ -811,6 +817,7 @@ impl<'ui> Ui {
|
||||
PlotLines::new(self, label, values)
|
||||
}
|
||||
|
||||
/// Plot a list of floats as a histogram
|
||||
#[doc(alias = "PlotHistogram")]
|
||||
pub fn plot_histogram<'p, Label: AsRef<str>>(
|
||||
&'ui self,
|
||||
@ -863,7 +870,11 @@ impl<'ui> Ui {
|
||||
|
||||
/// # Draw list for custom drawing
|
||||
impl Ui {
|
||||
/// Get access to drawing API
|
||||
/// Get access to drawing API.
|
||||
///
|
||||
/// The window draw list draws within the current
|
||||
/// window. Coordinates are within the current window coordinates,
|
||||
/// so `[0.0, 0.0]` would be at beginning of window
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -898,12 +909,24 @@ impl Ui {
|
||||
DrawListMut::window(self)
|
||||
}
|
||||
|
||||
/// Get draw list to draw behind all windows
|
||||
///
|
||||
/// Coordinates are in window coordinates, so `[0.0, 0.0]` is at
|
||||
/// top left of the Dear ImGui window
|
||||
///
|
||||
/// See [`Self::get_window_draw_list`] for more details
|
||||
#[must_use]
|
||||
#[doc(alias = "GetBackgroundDrawList")]
|
||||
pub fn get_background_draw_list(&self) -> DrawListMut<'_> {
|
||||
DrawListMut::background(self)
|
||||
}
|
||||
|
||||
/// Get draw list instance to draw above all window content
|
||||
///
|
||||
/// Coordinates are in window coordinates, so `[0.0, 0.0]` is at
|
||||
/// top left of the Dear ImGui window
|
||||
///
|
||||
/// See [`Self::get_window_draw_list`] for more details
|
||||
#[must_use]
|
||||
#[doc(alias = "GetForegroundDrawList")]
|
||||
pub fn get_foreground_draw_list(&self) -> DrawListMut<'_> {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::thread;
|
||||
|
||||
use crate::sys;
|
||||
use crate::Ui;
|
||||
@ -22,6 +21,7 @@ pub struct ListClipper {
|
||||
}
|
||||
|
||||
impl ListClipper {
|
||||
/// Begins configuring a list clipper.
|
||||
pub const fn new(items_count: i32) -> Self {
|
||||
ListClipper {
|
||||
items_count,
|
||||
@ -45,9 +45,23 @@ impl ListClipper {
|
||||
}
|
||||
}
|
||||
|
||||
/// List clipper is a mechanism to efficiently implement scrolling of
|
||||
/// large lists with random access.
|
||||
///
|
||||
/// For example you have a list of 1 million buttons, and the list
|
||||
/// clipper will help you only draw the ones which are visible.
|
||||
pub struct ListClipperToken<'ui> {
|
||||
list_clipper: *mut sys::ImGuiListClipper,
|
||||
_phantom: PhantomData<&'ui Ui>,
|
||||
|
||||
/// In upstream imgui < 1.87, calling step too many times will
|
||||
/// cause a segfault due to null pointer. So we keep track of this
|
||||
/// and panic instead.
|
||||
///
|
||||
/// Fixed in https://github.com/ocornut/imgui/commit/dca527b which
|
||||
/// will likely be part of imgui 1.88 - at which point this can be
|
||||
/// removed.
|
||||
consumed_workaround: bool,
|
||||
}
|
||||
|
||||
impl<'ui> ListClipperToken<'ui> {
|
||||
@ -55,40 +69,202 @@ impl<'ui> ListClipperToken<'ui> {
|
||||
Self {
|
||||
list_clipper,
|
||||
_phantom: PhantomData,
|
||||
consumed_workaround: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Progress the list clipper.
|
||||
///
|
||||
/// If this returns returns `true` then the you can loop between
|
||||
/// between `clipper.display_start() .. clipper.display_end()`.
|
||||
/// If this returns false, you must stop calling this method.
|
||||
///
|
||||
/// Calling step again after it returns `false` will cause imgui
|
||||
/// to abort. This mirrors the C++ interface.
|
||||
///
|
||||
/// It is recommended to use the iterator interface!
|
||||
pub fn step(&mut self) -> bool {
|
||||
unsafe { sys::ImGuiListClipper_Step(self.list_clipper) }
|
||||
let is_imgui_1_88_or_higher = false;
|
||||
if is_imgui_1_88_or_higher {
|
||||
unsafe { sys::ImGuiListClipper_Step(self.list_clipper) }
|
||||
} else {
|
||||
if self.consumed_workaround {
|
||||
panic!("ListClipperToken::step called after it has previously returned false");
|
||||
}
|
||||
let ret = unsafe { sys::ImGuiListClipper_Step(self.list_clipper) };
|
||||
if !ret {
|
||||
self.consumed_workaround = true;
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// This is automatically called back the final call to
|
||||
/// `step`. You can call it sooner but typically not needed.
|
||||
pub fn end(&mut self) {
|
||||
unsafe {
|
||||
sys::ImGuiListClipper_End(self.list_clipper);
|
||||
}
|
||||
}
|
||||
|
||||
/// First item to call, updated each call to `step`
|
||||
pub fn display_start(&self) -> i32 {
|
||||
unsafe { (*self.list_clipper).DisplayStart }
|
||||
}
|
||||
|
||||
/// End of items to call (exclusive), updated each call to `step`
|
||||
pub fn display_end(&self) -> i32 {
|
||||
unsafe { (*self.list_clipper).DisplayEnd }
|
||||
}
|
||||
|
||||
/// Get an iterator which outputs all visible indexes. This is the
|
||||
/// recommended way of using the clipper.
|
||||
pub fn iter(self) -> ListClipperIterator<'ui> {
|
||||
ListClipperIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ui> Drop for ListClipperToken<'ui> {
|
||||
fn drop(&mut self) {
|
||||
if !self.step() {
|
||||
unsafe {
|
||||
sys::ImGuiListClipper_destroy(self.list_clipper);
|
||||
};
|
||||
} else if !thread::panicking() {
|
||||
panic!(
|
||||
"Forgot to call End(), or to Step() until false? \
|
||||
This is the only token in the repository which users must call `.end()` or `.step()` \
|
||||
with. See https://github.com/imgui-rs/imgui-rs/issues/438"
|
||||
);
|
||||
unsafe {
|
||||
sys::ImGuiListClipper_destroy(self.list_clipper);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ListClipperIterator<'ui> {
|
||||
list_clipper: ListClipperToken<'ui>,
|
||||
exhausted: bool,
|
||||
last_value: Option<i32>,
|
||||
}
|
||||
|
||||
impl<'ui> ListClipperIterator<'ui> {
|
||||
fn new(list_clipper: ListClipperToken<'ui>) -> Self {
|
||||
Self {
|
||||
list_clipper,
|
||||
exhausted: false,
|
||||
last_value: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ListClipperIterator<'_> {
|
||||
type Item = i32;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(lv) = self.last_value {
|
||||
// Currently iterating a chunk (returning all values
|
||||
// between display_start and display_end)
|
||||
let next_value = lv + 1;
|
||||
|
||||
if lv >= self.list_clipper.display_end() - 1 {
|
||||
// If we reach the end of the current chunk, clear
|
||||
// last_value so we call step below
|
||||
self.last_value = None;
|
||||
} else {
|
||||
// Otherwise just increment it
|
||||
self.last_value = Some(next_value);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(lv) = self.last_value {
|
||||
// Next item within current step's chunk
|
||||
Some(lv)
|
||||
} else {
|
||||
// Start iterating a new chunk
|
||||
|
||||
if self.exhausted {
|
||||
// If the clipper is exhausted, don't call step again!
|
||||
None
|
||||
} else {
|
||||
// Advance the clipper
|
||||
let ret = self.list_clipper.step();
|
||||
if !ret {
|
||||
self.exhausted = true;
|
||||
None
|
||||
} else {
|
||||
// Setup iteration for this step's chunk
|
||||
let start = self.list_clipper.display_start();
|
||||
let end = self.list_clipper.display_end();
|
||||
|
||||
if start == end {
|
||||
// Somewhat special case: if a single item, we
|
||||
// don't store the last_value so we call
|
||||
// step() again next iteration
|
||||
self.last_value = None;
|
||||
} else {
|
||||
self.last_value = Some(start);
|
||||
}
|
||||
Some(start)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cpp_style_usage() {
|
||||
// Setup
|
||||
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
||||
let ui = ctx.frame();
|
||||
|
||||
let _window = ui
|
||||
.window("Example")
|
||||
.position([0.0, 0.0], crate::Condition::Always)
|
||||
.size([100.0, 800.0], crate::Condition::Always)
|
||||
.begin();
|
||||
|
||||
// Create clipper
|
||||
let clip = ListClipper::new(1000);
|
||||
let mut tok = clip.begin(ui);
|
||||
|
||||
let mut ticks = 0;
|
||||
|
||||
while dbg!(tok.step()) {
|
||||
for row_num in dbg!(tok.display_start())..dbg!(tok.display_end()) {
|
||||
dbg!(row_num);
|
||||
ui.text("...");
|
||||
ticks += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Check it's called an expected amount of time (only the ones
|
||||
// visible in given sized window)
|
||||
assert_eq!(ticks, 44);
|
||||
|
||||
// Calling end multiple times is fine albeit redundant
|
||||
tok.end();
|
||||
tok.end();
|
||||
tok.end();
|
||||
tok.end();
|
||||
tok.end();
|
||||
tok.end();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_usage() {
|
||||
// Setup
|
||||
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
||||
let ui = ctx.frame();
|
||||
|
||||
let _window = ui
|
||||
.window("Example")
|
||||
.position([0.0, 0.0], crate::Condition::Always)
|
||||
.size([100.0, 800.0], crate::Condition::Always)
|
||||
.begin();
|
||||
|
||||
// Create clipper
|
||||
let clip = ListClipper::new(1000);
|
||||
|
||||
let mut ticks = 0;
|
||||
|
||||
let tok = clip.begin(ui);
|
||||
for row_num in tok.iter() {
|
||||
dbg!(row_num);
|
||||
ui.text("...");
|
||||
ticks += 1;
|
||||
}
|
||||
|
||||
// Should be consistent with size in `cpp_style_usage`
|
||||
assert_eq!(ticks, 44);
|
||||
}
|
||||
|
||||
@ -179,7 +179,8 @@ unsafe fn push_style_var(style_var: StyleVar) {
|
||||
impl Ui {
|
||||
/// Changes the item width by pushing a change to the item width stack.
|
||||
///
|
||||
/// Returns an `ItemWidthStackToken` that may be popped by calling `.pop()`
|
||||
/// Returns an `ItemWidthStackToken`. The pushed width item is popped when either
|
||||
/// `ItemWidthStackToken` goes out of scope, or `.end()` is called.
|
||||
///
|
||||
/// - `> 0.0`: width is `item_width` pixels
|
||||
/// - `= 0.0`: default to ~2/3 of window width
|
||||
@ -208,13 +209,14 @@ impl Ui {
|
||||
unsafe { sys::igCalcItemWidth() }
|
||||
}
|
||||
|
||||
/// Changes the text wrapping position to the end of window (or column), which
|
||||
/// is generally the default.
|
||||
/// Makes the text wrap at the end of window/column (which is generally the default), by
|
||||
/// pushing a change to the text wrapping position stack.
|
||||
///
|
||||
/// This is the same as calling [push_text_wrap_pos_with_pos](Self::push_text_wrap_pos_with_pos)
|
||||
/// with `wrap_pos_x` set to 0.0.
|
||||
///
|
||||
/// Returns a `TextWrapPosStackToken` that may be popped by calling `.pop()`
|
||||
/// Returns a `TextWrapPosStackToken`. The pushed position item is popped when either
|
||||
/// `TextWrapPosStackToken` goes out of scope, or `.end()` is called.
|
||||
#[doc(alias = "PushTextWrapPos")]
|
||||
pub fn push_text_wrap_pos(&self) -> TextWrapPosStackToken<'_> {
|
||||
self.push_text_wrap_pos_with_pos(0.0)
|
||||
@ -222,7 +224,8 @@ impl Ui {
|
||||
|
||||
/// Changes the text wrapping position by pushing a change to the text wrapping position stack.
|
||||
///
|
||||
/// Returns a `TextWrapPosStackToken` that may be popped by calling `.pop()`
|
||||
/// Returns a `TextWrapPosStackToken`. The pushed position item is popped when either
|
||||
/// `TextWrapPosStackToken` goes out of scope, or `.end()` is called.
|
||||
///
|
||||
/// - `> 0.0`: wrap at `wrap_pos_x` position in window local space
|
||||
/// - `= 0.0`: wrap to end of window (or column)
|
||||
|
||||
@ -74,36 +74,6 @@ impl UiBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[deprecated = "all functions take AsRef<str> now -- use inline strings or `format` instead"]
|
||||
macro_rules! im_str {
|
||||
($e:literal $(,)?) => {{
|
||||
const __INPUT: &str = concat!($e, "\0");
|
||||
{
|
||||
// Trigger a compile error if there's an interior NUL character.
|
||||
const _CHECK_NUL: [(); 0] = [(); {
|
||||
let bytes = __INPUT.as_bytes();
|
||||
let mut i = 0;
|
||||
let mut found_nul = 0;
|
||||
while i < bytes.len() - 1 && found_nul == 0 {
|
||||
if bytes[i] == 0 {
|
||||
found_nul = 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
found_nul
|
||||
}];
|
||||
const RESULT: &'static $crate::ImStr = unsafe {
|
||||
$crate::__core::mem::transmute::<&'static [u8], &'static $crate::ImStr>(__INPUT.as_bytes())
|
||||
};
|
||||
RESULT
|
||||
}
|
||||
}};
|
||||
($e:literal, $($arg:tt)+) => ({
|
||||
$crate::ImString::new(format!($e, $($arg)*))
|
||||
});
|
||||
}
|
||||
|
||||
/// A UTF-8 encoded, growable, implicitly nul-terminated string.
|
||||
#[derive(Clone, Hash, Ord, Eq, PartialOrd, PartialEq)]
|
||||
pub struct ImString(pub(crate) Vec<u8>);
|
||||
|
||||
106
imgui/src/text_filter.rs
Normal file
106
imgui/src/text_filter.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use crate::sys;
|
||||
use crate::Ui;
|
||||
use std::ptr;
|
||||
|
||||
/// Helper to parse and apply text filters
|
||||
pub struct TextFilter {
|
||||
id: String,
|
||||
raw: *mut sys::ImGuiTextFilter,
|
||||
}
|
||||
|
||||
impl TextFilter {
|
||||
/// Creates a new TextFilter with an empty filter.
|
||||
///
|
||||
/// This is equivalent of [new_with_filter](Self::new_with_filter) with `filter` set to `""`.
|
||||
pub fn new(label: String) -> Self {
|
||||
Self::new_with_filter(label, String::new())
|
||||
}
|
||||
|
||||
/// Creates a new TextFilter with a custom filter.
|
||||
pub fn new_with_filter(label: String, mut filter: String) -> Self {
|
||||
filter.push('\0');
|
||||
let ptr = filter.as_mut_ptr();
|
||||
Self {
|
||||
id: label,
|
||||
raw: unsafe { sys::ImGuiTextFilter_ImGuiTextFilter(ptr as *mut sys::cty::c_char) },
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds the TextFilter with its filter attribute. You can use
|
||||
/// [`pass_filter()`](Self::pass_filter) after it.
|
||||
///
|
||||
/// If you want control the filter with an InputText, check [`draw()`](Self::draw).
|
||||
pub fn build(&self) {
|
||||
unsafe {
|
||||
sys::ImGuiTextFilter_Build(self.raw);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws an [InputText](crate::input_widget::InputText) to control the filter of the TextFilter.
|
||||
///
|
||||
/// This is equivalent of [draw_with_size](Self::draw_with_size) with `size` set to `0.0`.
|
||||
pub fn draw(&self) {
|
||||
self.draw_with_size(0.0);
|
||||
}
|
||||
|
||||
/// Draws an [InputText](crate::input_widget::InputText) to control the filter of the TextFilter.
|
||||
///
|
||||
/// The InputText has the size passed in parameters.
|
||||
pub fn draw_with_size(&self, size: f32) {
|
||||
unsafe {
|
||||
let mut id = self.id.clone();
|
||||
id.push('\0');
|
||||
let ptr = id.as_mut_ptr();
|
||||
sys::ImGuiTextFilter_Draw(self.raw, ptr as *mut sys::cty::c_char, size);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the filter is not empty (`""`).
|
||||
pub fn is_active(&self) -> bool {
|
||||
unsafe { sys::ImGuiTextFilter_IsActive(self.raw) }
|
||||
}
|
||||
|
||||
/// Returns true if the buffer matches the filter.
|
||||
///
|
||||
/// [`draw()`](Self::draw) or [`build()`](Self::build) mut be called **before** this function.
|
||||
pub fn pass_filter(&self, buf: &str) -> bool {
|
||||
let mut buf = String::from(buf);
|
||||
buf.push('\0');
|
||||
let ptr = buf.as_mut_ptr();
|
||||
unsafe {
|
||||
sys::ImGuiTextFilter_PassFilter(self.raw, ptr as *mut sys::cty::c_char, ptr::null())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pass_filter_with_end(&self, start: &str, end: &str) -> bool {
|
||||
let (mut start, mut end) = (String::from(start), String::from(end));
|
||||
start.push('\0');
|
||||
end.push('\0');
|
||||
let b_ptr = start.as_mut_ptr();
|
||||
let e_ptr = end.as_mut_ptr();
|
||||
unsafe {
|
||||
sys::ImGuiTextFilter_PassFilter(
|
||||
self.raw,
|
||||
b_ptr as *mut sys::cty::c_char,
|
||||
e_ptr as *mut sys::cty::c_char,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the filter.
|
||||
pub fn clear(&self) {
|
||||
unsafe {
|
||||
sys::ImGuiTextFilter_Clear(self.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ui {
|
||||
pub fn text_filter(label: String) -> TextFilter {
|
||||
TextFilter::new(label)
|
||||
}
|
||||
|
||||
pub fn text_filter_with_filter(label: String, filter: String) -> TextFilter {
|
||||
TextFilter::new_with_filter(label, filter)
|
||||
}
|
||||
}
|
||||
@ -253,7 +253,6 @@ where
|
||||
#[doc(alias = "DragIntRange2")]
|
||||
pub fn build(self, ui: &Ui, min: &mut i32, max: &mut i32) -> bool {
|
||||
unsafe {
|
||||
let label;
|
||||
let mut display_format = std::ptr::null();
|
||||
let mut max_display_format = std::ptr::null();
|
||||
|
||||
@ -261,7 +260,7 @@ where
|
||||
let buffer = &mut *ui.scratch_buffer().get();
|
||||
buffer.refresh_buffer();
|
||||
|
||||
label = buffer.push(self.label);
|
||||
let label = buffer.push(self.label);
|
||||
if let Some(v) = self.display_format {
|
||||
display_format = buffer.push(v);
|
||||
}
|
||||
|
||||
@ -196,8 +196,7 @@ where
|
||||
/// Constructs a new vertical slider builder with the given size and range.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use imgui::im_str;
|
||||
/// imgui::VerticalSlider::new(im_str!("Example"), [20.0, 20.0], i8::MIN, i8::MAX)
|
||||
/// imgui::VerticalSlider::new("Example", [20.0, 20.0], i8::MIN, i8::MAX)
|
||||
/// .range(4, 8)
|
||||
/// // Remember to call .build(&ui)
|
||||
/// ;
|
||||
@ -227,8 +226,7 @@ where
|
||||
/// Sets the range for the vertical slider.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use imgui::im_str;
|
||||
/// imgui::VerticalSlider::new(im_str!("Example"), [20.0, 20.0], i8::MIN, i8::MAX)
|
||||
/// imgui::VerticalSlider::new("Example", [20.0, 20.0], i8::MIN, i8::MAX)
|
||||
/// .range(4, 8)
|
||||
/// // Remember to call .build(&ui)
|
||||
/// ;
|
||||
@ -320,8 +318,7 @@ where
|
||||
{
|
||||
/// Sets the range in degrees (inclusive)
|
||||
/// ```rust
|
||||
/// # use imgui::im_str;
|
||||
/// imgui::AngleSlider::new(im_str!("Example"))
|
||||
/// imgui::AngleSlider::new("Example")
|
||||
/// .range_degrees(-20.0, 20.0)
|
||||
/// // Remember to call .build(&ui)
|
||||
/// ;
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
//! # let ui = ctx.frame();
|
||||
//!
|
||||
//! // During UI construction
|
||||
//! TabBar::new(im_str!("tabbar")).build(&ui, || {
|
||||
//! TabItem::new(im_str!("a tab")).build(&ui, || {
|
||||
//! ui.text(im_str!("tab content 1"));
|
||||
//! TabBar::new("tabbar").build(&ui, || {
|
||||
//! TabItem::new("a tab").build(&ui, || {
|
||||
//! ui.text("tab content 1");
|
||||
//! });
|
||||
//! TabItem::new(im_str!("2tab")).build(&ui, || {
|
||||
//! ui.text(im_str!("tab content 2"));
|
||||
//! TabItem::new("2tab").build(&ui, || {
|
||||
//! ui.text("tab content 2");
|
||||
//! });
|
||||
//! });
|
||||
//! ```
|
||||
|
||||
@ -287,17 +287,16 @@ impl<'a, T: AsRef<str>, L: AsRef<str>> TreeNode<'a, T, L> {
|
||||
sys::igSetNextItemOpen(self.opened, self.opened_cond as i32);
|
||||
}
|
||||
match self.id {
|
||||
TreeNodeId::Str(id) => {
|
||||
let (id, label) = match self.label {
|
||||
Some(label) => self.ui.scratch_txt_two(id, label),
|
||||
None => {
|
||||
let v = self.ui.scratch_txt(id);
|
||||
(v, v)
|
||||
}
|
||||
};
|
||||
|
||||
sys::igTreeNodeExStrStr(id, self.flags.bits() as i32, fmt_ptr(), label)
|
||||
}
|
||||
TreeNodeId::Str(id) => match self.label {
|
||||
Some(label) => {
|
||||
let (id, label) = self.ui.scratch_txt_two(id, label);
|
||||
sys::igTreeNodeExStrStr(id, self.flags.bits() as i32, fmt_ptr(), label)
|
||||
}
|
||||
None => {
|
||||
let id = self.ui.scratch_txt(id);
|
||||
sys::igTreeNodeExStr(id, self.flags.bits() as i32)
|
||||
}
|
||||
},
|
||||
TreeNodeId::Ptr(id) => sys::igTreeNodeExPtr(
|
||||
id,
|
||||
self.flags.bits() as i32,
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
[package]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
authors = ["Thom Chiovoloni <chiovolonit@gmail.com>"]
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::flags::Bindgen;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
impl Bindgen {
|
||||
@ -140,7 +140,7 @@ fn generate_binding_file(
|
||||
eprintln!("Executing bindgen [output = {}]", output.display());
|
||||
let status = cmd.status().context("Failed to execute bindgen")?;
|
||||
if !status.success() {
|
||||
anyhow!(
|
||||
bail!(
|
||||
"Failed to execute bindgen: {}, see output for details",
|
||||
status
|
||||
);
|
||||
|
||||
@ -32,30 +32,11 @@ fn try_main() -> Result<()> {
|
||||
}
|
||||
|
||||
fn lint_all() -> Result<()> {
|
||||
// Lint with only default, only docking, and only freetype
|
||||
// Lint with only default, only docking, and only freetype, and everything
|
||||
xshell::cmd!("cargo clippy --workspace --all-targets").run()?;
|
||||
xshell::cmd!("cargo clippy --workspace --all-targets --features docking").run()?;
|
||||
xshell::cmd!("cargo clippy --workspace --all-targets --features freetype").run()?;
|
||||
|
||||
// Lint winit with all features
|
||||
xshell::cmd!(
|
||||
"cargo clippy --manifest-path imgui-winit-support/Cargo.toml --all-features --all-targets"
|
||||
)
|
||||
.run()?;
|
||||
|
||||
// Lint with various winit versions
|
||||
let winits = &[
|
||||
"winit-19",
|
||||
"winit-20",
|
||||
"winit-22",
|
||||
"winit-23/default",
|
||||
"winit-24/default",
|
||||
"winit-25/default",
|
||||
"winit-26/default",
|
||||
];
|
||||
for &winit in winits {
|
||||
xshell::cmd!("cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features {winit} --all-targets").run()?;
|
||||
}
|
||||
xshell::cmd!("cargo clippy --workspace --all-targets --all-features").run()?;
|
||||
|
||||
// Check formatting
|
||||
xshell::cmd!("cargo fmt --all -- --check").run()?;
|
||||
@ -71,18 +52,6 @@ fn test_all() -> Result<()> {
|
||||
// Test doc examples
|
||||
xshell::cmd!("cargo test --workspace --doc").run()?;
|
||||
|
||||
// Test with various winit versions
|
||||
let winits = &[
|
||||
"winit-19",
|
||||
"winit-20",
|
||||
"winit-22",
|
||||
"winit-23/default",
|
||||
"winit-24/default",
|
||||
"winit-25/default",
|
||||
];
|
||||
for &winit in winits {
|
||||
xshell::cmd!("cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features {winit} --all-targets").run()?;
|
||||
}
|
||||
// Run heavy tests in release mode
|
||||
xshell::cmd!("cargo test -p imgui --release -- --ignored").run()?;
|
||||
Ok(())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user