feat: 实现喷枪功能
This commit is contained in:
102
src/paint.rs
102
src/paint.rs
@@ -1,6 +1,7 @@
|
||||
use ::image::{ImageBuffer, ImageError, Rgba};
|
||||
use iced::Theme;
|
||||
use iced::padding;
|
||||
use iced::time::{self, Instant, milliseconds};
|
||||
use iced::widget::container;
|
||||
use iced::widget::{Column, button, column, image, pick_list, row, text};
|
||||
use iced::{Border, Color, Element, Length, Point, Renderer, Task};
|
||||
@@ -67,9 +68,11 @@ enum Message {
|
||||
|
||||
/// 全局鼠标释放
|
||||
WindowMouseRelease,
|
||||
|
||||
Tick(Instant),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum Tool {
|
||||
FreeFormSelect,
|
||||
Select,
|
||||
@@ -143,12 +146,16 @@ impl From<Tool> for usize {
|
||||
pub enum ConfigOption {
|
||||
EraserWidth,
|
||||
LineWidth,
|
||||
AirbrushRadius,
|
||||
AirbrushDensity,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Config {
|
||||
eraser_width: i32,
|
||||
line_width: i32,
|
||||
airbrush_radius: i32,
|
||||
airbrush_density: i32,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -161,6 +168,8 @@ impl Config {
|
||||
const DEFAULT: Config = Config {
|
||||
line_width: 1,
|
||||
eraser_width: 4,
|
||||
airbrush_radius: 4,
|
||||
airbrush_density: 16,
|
||||
};
|
||||
fn incr(&mut self, option: ConfigOption, step: i32) {
|
||||
match option {
|
||||
@@ -176,6 +185,18 @@ impl Config {
|
||||
self.line_width = Self::DEFAULT.line_width;
|
||||
}
|
||||
}
|
||||
ConfigOption::AirbrushRadius => {
|
||||
self.airbrush_radius += step;
|
||||
if self.airbrush_radius < Self::DEFAULT.airbrush_radius {
|
||||
self.airbrush_radius = Self::DEFAULT.airbrush_radius;
|
||||
}
|
||||
}
|
||||
ConfigOption::AirbrushDensity => {
|
||||
self.airbrush_density += step;
|
||||
if self.airbrush_density < Self::DEFAULT.airbrush_density {
|
||||
self.airbrush_density = Self::DEFAULT.airbrush_density;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,27 +318,47 @@ impl PaintApp {
|
||||
|
||||
let mut debug_area = row![
|
||||
column![
|
||||
text("Eraser Width "),
|
||||
text("Eraser Width"),
|
||||
row![
|
||||
button("+").on_press(Message::Increment(ConfigOption::EraserWidth)),
|
||||
text(self.config.eraser_width).size(20).center(),
|
||||
button("-").on_press(Message::Decrement(ConfigOption::EraserWidth)),
|
||||
],
|
||||
],
|
||||
]
|
||||
.padding(padding::right(5)),
|
||||
column![
|
||||
text("Line Width "),
|
||||
text("Line Width"),
|
||||
row![
|
||||
button("+").on_press(Message::Increment(ConfigOption::LineWidth)),
|
||||
text(self.config.line_width).size(20).center(),
|
||||
button("-").on_press(Message::Decrement(ConfigOption::LineWidth)),
|
||||
],
|
||||
],
|
||||
]
|
||||
.padding(padding::right(5)),
|
||||
pick_list(
|
||||
&BrushKind::ALL[..],
|
||||
self.brush_selected,
|
||||
Message::BrushSelected,
|
||||
)
|
||||
.placeholder("Brush..."),
|
||||
column![
|
||||
text("Airbrush Radius"),
|
||||
row![
|
||||
button("+").on_press(Message::Increment(ConfigOption::AirbrushRadius)),
|
||||
text(self.config.airbrush_radius).size(20).center(),
|
||||
button("-").on_press(Message::Decrement(ConfigOption::AirbrushRadius)),
|
||||
],
|
||||
]
|
||||
.padding(padding::right(5)),
|
||||
column![
|
||||
text("Airbrush Density"),
|
||||
row![
|
||||
button("+").on_press(Message::Increment(ConfigOption::AirbrushDensity)),
|
||||
text(self.config.airbrush_density).size(20).center(),
|
||||
button("-").on_press(Message::Decrement(ConfigOption::AirbrushDensity)),
|
||||
],
|
||||
]
|
||||
.padding(padding::right(5)),
|
||||
];
|
||||
debug_area = debug_area.padding(padding::top(10).left(5).bottom(10));
|
||||
|
||||
@@ -345,6 +386,9 @@ impl PaintApp {
|
||||
Tool::Brush => {
|
||||
self.update_with_brush(message);
|
||||
}
|
||||
Tool::Airbrush => {
|
||||
self.update_with_airbrush(message);
|
||||
}
|
||||
Tool::Line => {
|
||||
self.update_with_line(message);
|
||||
}
|
||||
@@ -394,6 +438,16 @@ impl PaintApp {
|
||||
// 处理鼠标在 canvas_area 外面释放
|
||||
self.is_drawing = false;
|
||||
}
|
||||
Message::Tick(_) => {
|
||||
if self.is_drawing && self.tool_selected == Tool::Airbrush {
|
||||
self.canvas.spray_paint(
|
||||
self.begin_point,
|
||||
self.config.airbrush_radius,
|
||||
self.config.airbrush_density as u32,
|
||||
);
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -409,13 +463,15 @@ impl PaintApp {
|
||||
}
|
||||
|
||||
pub fn subscription(&self) -> Subscription<Message> {
|
||||
event::listen().filter_map(|event| match event {
|
||||
let ev = event::listen().filter_map(|event| match event {
|
||||
// 只关心鼠标释放事件
|
||||
iced::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => {
|
||||
Some(Message::WindowMouseRelease)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
});
|
||||
let tick = time::every(milliseconds(50)).map(Message::Tick);
|
||||
return Subscription::batch(vec![ev, tick]);
|
||||
}
|
||||
|
||||
// endregion
|
||||
@@ -468,6 +524,7 @@ impl PaintApp {
|
||||
self.is_drawing = true;
|
||||
self.canvas.draw_pixel_at(pos);
|
||||
self.begin_point = pos;
|
||||
self.dirty = true;
|
||||
}
|
||||
Message::MouseReleased(pos) => {
|
||||
self.is_drawing = false;
|
||||
@@ -516,6 +573,37 @@ impl PaintApp {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_with_airbrush(&mut self, message: Message) {
|
||||
match message {
|
||||
Message::MousePressed(pos) => {
|
||||
self.is_drawing = true;
|
||||
self.canvas.spray_paint(
|
||||
pos,
|
||||
self.config.airbrush_radius,
|
||||
self.config.airbrush_density as u32,
|
||||
);
|
||||
self.begin_point = pos;
|
||||
self.dirty = true;
|
||||
}
|
||||
Message::MouseReleased(pos) => {
|
||||
self.is_drawing = false;
|
||||
self.begin_point = pos;
|
||||
}
|
||||
Message::MouseMoved(pos) => {
|
||||
if self.is_drawing {
|
||||
self.canvas.spray_paint(
|
||||
pos,
|
||||
self.config.airbrush_radius,
|
||||
self.config.airbrush_density as u32,
|
||||
);
|
||||
self.begin_point = pos;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_with_line(&mut self, message: Message) {
|
||||
match message {
|
||||
Message::MousePressed(pos) => {
|
||||
|
||||
Reference in New Issue
Block a user