Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Canvas interactivity and Game of Life example #325

Merged
merged 75 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
0b5028b
Draft `Program` interactivity for `Canvas`
hecrj Apr 19, 2020
8ade09a
Simplify `Canvas` example in documentation
hecrj Apr 19, 2020
a97acd8
Use `Borrow<T>` when binding in `layer::Cache<T>`
hecrj Apr 19, 2020
bb424e5
Add interactivity to `solar_system` example
hecrj Apr 19, 2020
592cc68
Remove `Layer` trait and simplify `Canvas`
hecrj Apr 19, 2020
f59832e
Fix alignment in triangle pipeline of `iced_wgpu`
hecrj Apr 19, 2020
dc97d6f
Remove interaction from `solar_system` example
hecrj Apr 27, 2020
6c2e28d
Implement `std::ops::Sub<Point>` for `Point`
hecrj Apr 27, 2020
20d79a4
Implement `Default` for `Point`
hecrj Apr 28, 2020
56dbd68
Move reusable `mouse` types to `iced_core`
hecrj Apr 28, 2020
b0825ce
Add convenient builder methods to `canvas::Stroke`
hecrj Apr 28, 2020
2381a93
Ask for a `Size` in `Frame::new`
hecrj Apr 28, 2020
59b1e90
Introduce `Translate` primitive in `iced_wgpu`
hecrj Apr 28, 2020
2ca7303
Implement `Drawable` for slices of drawables
hecrj Apr 28, 2020
e4eb055
Allow `canvas::State` to produce messages
hecrj Apr 28, 2020
fd1ceac
Port `bezier_tool` example to use `Canvas`
hecrj Apr 28, 2020
5d5e60a
Implement `Rectangle::new`
hecrj Apr 28, 2020
69c60d3
Implement `std::ops::Add<Vector>` for `Rectangle`
hecrj Apr 28, 2020
e65585a
Clip and cull `Mesh2D` primitives in `iced_wgpu`
hecrj Apr 28, 2020
7f1e7ae
Remove unnecessary `Container` in `bezier_tool`
hecrj Apr 28, 2020
2539042
Remove `Drawable` and rename `State` to `Program`
hecrj Apr 28, 2020
85dc07c
Expose `Rectangle` in `iced_web`
hecrj Apr 28, 2020
59403b6
Remove `OutOfBounds` variant from `MouseCursor`
hecrj Apr 29, 2020
0509710
Add `Crosshair` variant to `MouseCursor`
hecrj Apr 29, 2020
52719c7
Let a `canvas::Program` control the mouse cursor
hecrj Apr 29, 2020
ec712c8
Move `MouseCursor` to `iced_core`
hecrj Apr 29, 2020
475a277
Implement `Rectangle::with_size`
hecrj Apr 29, 2020
5586034
Display crosshair cursor in `bezier_tool` example
hecrj Apr 29, 2020
dc51080
Introduce `Cursor` type in `canvas`
hecrj Apr 29, 2020
61c707f
Merge branch 'master' into feature/canvas-interaction
hecrj Apr 29, 2020
afa0bca
Implement `Rectangle::position`
hecrj Apr 29, 2020
70f86f9
Add `game_of_life` example
hecrj Apr 29, 2020
5d12e19
Rename `Cursor::*_position` methods in `canvas`
hecrj Apr 29, 2020
38c4dd5
Reduce initial size of `triangle` buffers in `iced_wgpu`
hecrj Apr 29, 2020
5e014a7
Use sparse grid representation in `game_of_life`
hecrj Apr 29, 2020
611d9e3
Clarify `tick` logic in `game_of_life`
hecrj Apr 29, 2020
af95d39
Implement camera panning in `game_of_life` example
hecrj Apr 30, 2020
e139aae
Split `Input` keyboard event by `ButtonState`
hecrj Apr 30, 2020
e55cd96
Split `Input` mouse event by `ButtonState`
hecrj Apr 30, 2020
d8b9e03
Remove `ButtonState`
hecrj Apr 30, 2020
137664c
Move `keyboard::Event` to `iced_core`
hecrj Apr 30, 2020
bb9ccc4
Remove inconsistent `input` module in `iced_native`
hecrj Apr 30, 2020
e207661
Implement `time::every` in `iced_futures`
hecrj Apr 30, 2020
1501a93
Disable `time` module on Wasm for now
hecrj Apr 30, 2020
d4c4198
Write documentation for the new `canvas` API
hecrj Apr 30, 2020
98bc8cf
Rename `MouseCursor` to `mouse::Interaction`
hecrj Apr 30, 2020
005ad62
Update `README` of `game_of_life` example
hecrj Apr 30, 2020
ee97887
Introduce `Cell` type in `game_of_life`
hecrj Apr 30, 2020
71323c5
Simplify `Interaction` handling in `game_of_life`
hecrj Apr 30, 2020
a6db1e1
Introduce `Life` type in `game_of_life`
hecrj Apr 30, 2020
377ead9
Improve tick performance in `game_of_life`
hecrj Apr 30, 2020
980ac6c
Add `UNIT` constant to `Size`
hecrj May 1, 2020
345f0e1
Implement scalar multiplication for `Vector`
hecrj May 1, 2020
08b376c
Implement `Frame::fill_rectangle`
hecrj May 1, 2020
404122e
Implement zooming for `game_of_life` example
hecrj May 1, 2020
f922754
Use `fill_rectangle` for cursor in `game_of_life`
hecrj May 1, 2020
c23995e
Increase speed limit to `200` in `game_of_life`
hecrj May 1, 2020
0a5f1bb
Improve zooming logic in `game_of_life`
hecrj May 1, 2020
ffbe59f
Zoom to cursor in `game_of_life` example
hecrj May 1, 2020
1833c77
Improve scrolling smoothness in `game_of_life`
hecrj May 1, 2020
e7e8e76
Change speed limit to `100` in `game_of_life`
hecrj May 1, 2020
4fd8e47
Use `rustc_hash` for hashing in `game_of_life`
hecrj May 2, 2020
8fa9e4c
Rename `visible_in` to `within` in `game_of_life`
hecrj May 2, 2020
916a1bf
Run ticks in a background thread in `game_of_life`
hecrj May 2, 2020
0025b8c
Display some statistics in `game_of_life`
hecrj May 2, 2020
cc8f5b6
Simplify logic and limit ticks in `game_of_life`
hecrj May 2, 2020
a43fb42
Reorganize `view` code in `game_of_life`
hecrj May 2, 2020
c3c5161
Draw grid in `game_of_life`
hecrj May 2, 2020
5aaaea7
Render stats as an overlay in `game_of_life`
hecrj May 2, 2020
4417a34
Fix "1 cells" overlay in `game_of_life`
hecrj May 3, 2020
9171991
Allow erasing cells in `game_of_life`
hecrj May 3, 2020
2f41cce
Update GIF of `game_of_life` example
hecrj May 3, 2020
67b2ccb
Merge branch 'master' into feature/canvas-interaction
hecrj May 4, 2020
80e2d1b
Adapt `color_palette` to new `canvas` API
hecrj May 4, 2020
93c6be5
Update `README` of `game_of_life` example
hecrj May 4, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ members = [
"examples/custom_widget",
"examples/download_progress",
"examples/events",
"examples/game_of_life",
"examples/geometry",
"examples/integration",
"examples/pane_grid",
Expand Down
2 changes: 2 additions & 0 deletions core/src/keyboard.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Reuse basic keyboard types.
mod event;
mod key_code;
mod modifiers_state;

pub use event::Event;
pub use key_code::KeyCode;
pub use modifiers_state::ModifiersState;
15 changes: 10 additions & 5 deletions native/src/input/keyboard/event.rs → core/src/keyboard/event.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::{KeyCode, ModifiersState};
use crate::input::ButtonState;

/// A keyboard event.
///
Expand All @@ -9,11 +8,17 @@ use crate::input::ButtonState;
/// [open an issue]: https://github.com/hecrj/iced/issues
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Event {
/// A keyboard key was pressed or released.
Input {
/// The state of the key
state: ButtonState,
/// A keyboard key was pressed.
KeyPressed {
/// The key identifier
key_code: KeyCode,

/// The state of the modifier keys
modifiers: ModifiersState,
},

/// A keyboard key was released.
KeyReleased {
/// The key identifier
key_code: KeyCode,

Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#![forbid(unsafe_code)]
#![forbid(rust_2018_idioms)]
pub mod keyboard;
pub mod mouse;

mod align;
mod background;
Expand Down
7 changes: 3 additions & 4 deletions native/src/input/mouse.rs → core/src/mouse.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//! Build mouse events.
//! Reuse basic mouse types.
mod button;
mod event;

pub mod click;
mod interaction;

pub use button::Button;
pub use click::Click;
pub use event::{Event, ScrollDelta};
pub use interaction::Interaction;
File renamed without changes.
12 changes: 4 additions & 8 deletions native/src/input/mouse/event.rs → core/src/mouse/event.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::Button;
use crate::input::ButtonState;

/// A mouse event.
///
Expand All @@ -24,14 +23,11 @@ pub enum Event {
y: f32,
},

/// A mouse button was pressed or released.
Input {
/// The state of the button
state: ButtonState,
/// A mouse button was pressed.
ButtonPressed(Button),

/// The button identifier
button: Button,
},
/// A mouse button was released.
ButtonReleased(Button),

/// The mouse wheel was scrolled.
WheelScrolled {
Expand Down
20 changes: 20 additions & 0 deletions core/src/mouse/interaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// The interaction of a mouse cursor.
#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)]
#[allow(missing_docs)]
pub enum Interaction {
Idle,
Pointer,
Grab,
Text,
Crosshair,
Working,
Grabbing,
ResizingHorizontally,
ResizingVertically,
}

impl Default for Interaction {
fn default() -> Interaction {
Interaction::Idle
}
}
10 changes: 9 additions & 1 deletion core/src/point.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Vector;

/// A 2D point.
#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Point {
/// The X coordinate.
pub x: f32,
Expand Down Expand Up @@ -67,3 +67,11 @@ impl std::ops::Sub<Vector> for Point {
}
}
}

impl std::ops::Sub<Point> for Point {
type Output = Vector;

fn sub(self, point: Point) -> Vector {
Vector::new(self.x - point.x, self.y - point.y)
}
}
65 changes: 62 additions & 3 deletions core/src/rectangle.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Point;
use crate::{Point, Size, Vector};

/// A rectangle.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
Expand All @@ -17,6 +17,35 @@ pub struct Rectangle<T = f32> {
}

impl Rectangle<f32> {
/// Creates a new [`Rectangle`] with its top-left corner in the given
/// [`Point`] and with the provided [`Size`].
///
/// [`Rectangle`]: struct.Rectangle.html
/// [`Point`]: struct.Point.html
/// [`Size`]: struct.Size.html
pub fn new(top_left: Point, size: Size) -> Self {
Self {
x: top_left.x,
y: top_left.y,
width: size.width,
height: size.height,
}
}

/// Creates a new [`Rectangle`] with its top-left corner at the origin
/// and with the provided [`Size`].
///
/// [`Rectangle`]: struct.Rectangle.html
/// [`Size`]: struct.Size.html
pub fn with_size(size: Size) -> Self {
Self {
x: 0.0,
y: 0.0,
width: size.width,
height: size.height,
}
}

/// Returns the [`Point`] at the center of the [`Rectangle`].
///
/// [`Point`]: struct.Point.html
Expand All @@ -43,6 +72,21 @@ impl Rectangle<f32> {
self.y + self.height / 2.0
}

/// Returns the position of the top left corner of the [`Rectangle`].
///
/// [`Rectangle`]: struct.Rectangle.html
pub fn position(&self) -> Point {
Point::new(self.x, self.y)
}

/// Returns the [`Size`] of the [`Rectangle`].
///
/// [`Size`]: struct.Size.html
/// [`Rectangle`]: struct.Rectangle.html
pub fn size(&self) -> Size {
Size::new(self.width, self.height)
}

/// Returns true if the given [`Point`] is contained in the [`Rectangle`].
///
/// [`Point`]: struct.Point.html
Expand Down Expand Up @@ -112,8 +156,23 @@ impl From<Rectangle<f32>> for Rectangle<u32> {
Rectangle {
x: rectangle.x as u32,
y: rectangle.y as u32,
width: rectangle.width.ceil() as u32,
height: rectangle.height.ceil() as u32,
width: (rectangle.width + 0.5).round() as u32,
height: (rectangle.height + 0.5).round() as u32,
}
}
}

impl<T> std::ops::Add<Vector<T>> for Rectangle<T>
where
T: std::ops::Add<Output = T>,
{
type Output = Rectangle<T>;

fn add(self, translation: Vector<T>) -> Self {
Rectangle {
x: self.x + translation.x,
y: self.y + translation.y,
..self
}
}
}
5 changes: 5 additions & 0 deletions core/src/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ impl Size {
/// [`Size`]: struct.Size.html
pub const ZERO: Size = Size::new(0., 0.);

/// A [`Size`] with a width and height of 1 unit.
///
/// [`Size`]: struct.Size.html
pub const UNIT: Size = Size::new(1., 1.);

/// A [`Size`] with infinite width and height.
///
/// [`Size`]: struct.Size.html
Expand Down
11 changes: 11 additions & 0 deletions core/src/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ where
}
}

impl<T> std::ops::Mul<T> for Vector<T>
where
T: std::ops::Mul<Output = T> + Copy,
{
type Output = Self;

fn mul(self, scale: T) -> Self {
Self::new(self.x * scale, self.y * scale)
}
}

impl<T> Default for Vector<T>
where
T: Default,
Expand Down
23 changes: 22 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ We have not yet implemented a `LocalStorage` version of the auto-save feature. T

[TodoMVC]: http://todomvc.com/

## [Game of Life](game_of_life)
An interactive version of the [Game of Life], invented by [John Horton Conway].

It runs a simulation in a background thread while allowing interaction with a `Canvas` that displays an infinite grid with zooming, panning, and drawing support.

The relevant code is located in the __[`main`](game_of_life/src/main.rs)__ file.

<div align="center">
<a href="https://gfycat.com/briefaccurateaardvark">
<img src="https://thumbs.gfycat.com/BriefAccurateAardvark-size_restricted.gif">
</a>
</div>

You can run it with `cargo run`:
```
cargo run --package game_of_life
```

[Game of Life]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
[John Horton Conway]: https://en.wikipedia.org/wiki/John_Horton_Conway

## [Styling](styling)
An example showcasing custom styling with a light and dark theme.

Expand All @@ -69,7 +90,7 @@ cargo run --package styling
## Extras
A bunch of simpler examples exist:

- [`bezier_tool`](bezier_tool), a Paint-like tool for drawing Bézier curves using [`lyon`].
- [`bezier_tool`](bezier_tool), a Paint-like tool for drawing Bézier curves using the `Canvas` widget.
- [`clock`](clock), an application that uses the `Canvas` widget to draw a clock and its hands to display the current time.
- [`color_palette`](color_palette), a color palette generator based on a user-defined root color.
- [`counter`](counter), the classic counter example explained in the [`README`](../README.md).
Expand Down
5 changes: 1 addition & 4 deletions examples/bezier_tool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,4 @@ edition = "2018"
publish = false

[dependencies]
iced = { path = "../.." }
iced_native = { path = "../../native" }
iced_wgpu = { path = "../../wgpu" }
lyon = "0.15"
iced = { path = "../..", features = ["canvas"] }
3 changes: 1 addition & 2 deletions examples/bezier_tool/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Bézier tool

A Paint-like tool for drawing Bézier curves using [`lyon`].
A Paint-like tool for drawing Bézier curves using the `Canvas` widget.

The __[`main`]__ file contains all the code of the example.

Expand All @@ -16,4 +16,3 @@ cargo run --package bezier_tool
```

[`main`]: src/main.rs
[`lyon`]: https://github.com/nical/lyon
Loading