Compare commits
3 commits
cabacd32e2
...
76986010ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76986010ba | ||
|
|
c0042d7680 | ||
|
|
b2b8a6e0d2 |
5 changed files with 262 additions and 2 deletions
BIN
res/font.ttf
Normal file
BIN
res/font.ttf
Normal file
Binary file not shown.
48
src/button.rs
Normal file
48
src/button.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use sfml::{graphics::{CircleShape, Drawable, Font, Shape, Text, Transformable}, system::Vector2f};
|
||||
|
||||
use crate::constants::button::{DEFAULT_BG_COLOR, DEFAULT_TXT_COLOR, PRECISION};
|
||||
|
||||
pub struct Button<'a> {
|
||||
background: CircleShape<'a>,
|
||||
text: Text<'a>
|
||||
}
|
||||
|
||||
impl<'a> Button<'a> {
|
||||
pub fn new(text: String, font: &'a Font, font_size: u32, pos: impl Into<Vector2f>, radius: f32) -> Self {
|
||||
let mut background = CircleShape::new(radius, PRECISION);
|
||||
background.set_origin((radius, radius));
|
||||
background.set_position(pos);
|
||||
background.set_fill_color(DEFAULT_BG_COLOR);
|
||||
|
||||
let mut text = Text::new(&text, font, font_size);
|
||||
text.set_position(background.position());
|
||||
text.set_fill_color(DEFAULT_TXT_COLOR);
|
||||
|
||||
let bounds = text.local_bounds();
|
||||
text.set_origin((
|
||||
bounds.left + bounds.width / 2.,
|
||||
bounds.top + bounds.height / 2.,
|
||||
));
|
||||
|
||||
Button {
|
||||
background,
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, m_pos: Vector2f) -> bool {
|
||||
self.background.global_bounds().contains(m_pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Drawable for Button<'d> {
|
||||
fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>(
|
||||
&'a self,
|
||||
target: &mut dyn sfml::graphics::RenderTarget,
|
||||
states: &sfml::graphics::RenderStates<'texture, 'shader, 'shader_texture>,
|
||||
) {
|
||||
|
||||
self.background.draw(target, states);
|
||||
self.text.draw(target, states);
|
||||
}
|
||||
}
|
||||
35
src/constants.rs
Normal file
35
src/constants.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
pub mod common {
|
||||
pub const WINDOW_SIZE: (u32, u32) = (800, 600);
|
||||
pub const WINDOW_SIZE_F: (f32, f32) = (WINDOW_SIZE.0 as f32, WINDOW_SIZE.1 as f32);
|
||||
|
||||
pub const FPS: u32 = 60;
|
||||
}
|
||||
|
||||
pub mod counter {
|
||||
use sfml::{graphics::Color, system::Vector2f};
|
||||
|
||||
pub const SIZE: Vector2f = Vector2f::new(200., 70.);
|
||||
|
||||
pub const DEFAULT_BG_COLOR: Color = Color::YELLOW;
|
||||
pub const DEFAULT_OUTLINE_COLOR: Color = Color::BLUE;
|
||||
pub const DEFAULT_OUTLINE_THICKNESS: f32 = 10.;
|
||||
|
||||
pub const HOFFSET_PERC: f32 = 0.35;
|
||||
pub const VOFFSET_PERC: f32 = 0.30;
|
||||
|
||||
pub const FONT_SIZE: u32 = 32;
|
||||
}
|
||||
|
||||
pub mod button {
|
||||
use sfml::graphics::Color;
|
||||
|
||||
pub const RADIUS_BIG: f32 = 20.;
|
||||
pub const RADIUS_SMALL: f32 = 8.;
|
||||
pub const PRECISION: usize = 20;
|
||||
|
||||
pub const DEFAULT_BG_COLOR: Color = Color::GREEN;
|
||||
pub const DEFAULT_TXT_COLOR: Color = Color::BLACK;
|
||||
|
||||
pub const FONT_SIZE_BIG: u32 = 32;
|
||||
pub const FONT_SIZE_SMALL: u32 = 16;
|
||||
}
|
||||
139
src/counter.rs
Normal file
139
src/counter.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use sfml::{
|
||||
graphics::{Color, Drawable, Font, RectangleShape, Shape, Text, Transformable},
|
||||
system::Vector2f,
|
||||
};
|
||||
|
||||
use crate::{button::Button, constants::{button::{FONT_SIZE_BIG, FONT_SIZE_SMALL, RADIUS_BIG, RADIUS_SMALL}, common::WINDOW_SIZE_F, counter::{DEFAULT_BG_COLOR, DEFAULT_OUTLINE_COLOR, DEFAULT_OUTLINE_THICKNESS, FONT_SIZE, HOFFSET_PERC, SIZE, VOFFSET_PERC}}};
|
||||
|
||||
pub struct Counter<'a> {
|
||||
count: u32,
|
||||
count_str: Text<'a>,
|
||||
background: RectangleShape<'a>,
|
||||
dec_button: Button<'a>,
|
||||
inc_button: Button<'a>,
|
||||
reset_button: Button<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Counter<'a> {
|
||||
pub fn new(count: u32, font: &'a Font) -> Self {
|
||||
let mut background = RectangleShape::with_size(SIZE);
|
||||
background.set_fill_color(DEFAULT_BG_COLOR);
|
||||
background.set_outline_color(DEFAULT_OUTLINE_COLOR);
|
||||
background.set_outline_thickness(DEFAULT_OUTLINE_THICKNESS);
|
||||
background.set_position((WINDOW_SIZE_F.0/2., WINDOW_SIZE_F.1/2.));
|
||||
let bounds = background.local_bounds();
|
||||
background.set_origin((
|
||||
bounds.left + bounds.width / 2.,
|
||||
bounds.top + bounds.height / 2.,
|
||||
));
|
||||
|
||||
let mut count_str = Text::new(&count.to_string(), font, FONT_SIZE);
|
||||
count_str.set_fill_color(Color::BLACK);
|
||||
count_str.set_position((WINDOW_SIZE_F.0/2., WINDOW_SIZE_F.1/2.));
|
||||
let bounds = count_str.local_bounds();
|
||||
count_str.set_origin((
|
||||
bounds.left + bounds.width / 2.,
|
||||
bounds.top + bounds.height / 2.,
|
||||
));
|
||||
|
||||
let dec_button = Button::new(
|
||||
"-".to_string(),
|
||||
font,
|
||||
FONT_SIZE_BIG,
|
||||
Vector2f::new(
|
||||
background.position().x - HOFFSET_PERC*background.size().x,
|
||||
background.position().y,
|
||||
),
|
||||
RADIUS_BIG
|
||||
);
|
||||
|
||||
let inc_button = Button::new(
|
||||
"+".to_string(),
|
||||
font,
|
||||
FONT_SIZE_BIG,
|
||||
Vector2f::new(
|
||||
background.position().x + HOFFSET_PERC*background.size().x,
|
||||
background.position().y,
|
||||
),
|
||||
RADIUS_BIG
|
||||
);
|
||||
|
||||
let reset_button = Button::new(
|
||||
"R".to_string(),
|
||||
font,
|
||||
FONT_SIZE_SMALL,
|
||||
Vector2f::new(
|
||||
background.position().x,
|
||||
background.position().y + (1. - VOFFSET_PERC)*background.size().y/2.
|
||||
),
|
||||
RADIUS_SMALL
|
||||
);
|
||||
|
||||
Counter {
|
||||
count,
|
||||
count_str,
|
||||
background,
|
||||
dec_button,
|
||||
inc_button,
|
||||
reset_button,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inc(&mut self) {
|
||||
if self.count < u32::MAX {
|
||||
self.count += 1;
|
||||
}
|
||||
self.update();
|
||||
}
|
||||
|
||||
pub fn dec(&mut self) {
|
||||
if self.count > 0 {
|
||||
self.count -= 1;
|
||||
}
|
||||
self.update();
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.count = 0;
|
||||
self.update();
|
||||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
self.count_str.set_string(&self.count.to_string());
|
||||
let digits = self.count.checked_ilog10().unwrap_or(0);
|
||||
if self.count % (10 * if digits == 0 { 1 } else { digits }) == 0 {
|
||||
let bounds = self.count_str.local_bounds();
|
||||
self.count_str.set_origin((
|
||||
bounds.left + bounds.width / 2.,
|
||||
bounds.top + bounds.height / 2.,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mouse(&mut self, m_pos: impl Into<Vector2f>) {
|
||||
let m_pos = m_pos.into();
|
||||
if self.dec_button.contains(m_pos) {
|
||||
self.dec();
|
||||
}
|
||||
if self.inc_button.contains(m_pos) {
|
||||
self.inc();
|
||||
}
|
||||
if self.reset_button.contains(m_pos) {
|
||||
self.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Drawable for Counter<'d> {
|
||||
fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>(
|
||||
&'a self,
|
||||
target: &mut dyn sfml::graphics::RenderTarget,
|
||||
states: &sfml::graphics::RenderStates<'texture, 'shader, 'shader_texture>,
|
||||
) {
|
||||
self.background.draw(target, states);
|
||||
self.count_str.draw(target, states);
|
||||
self.dec_button.draw(target, states);
|
||||
self.inc_button.draw(target, states);
|
||||
self.reset_button.draw(target, states);
|
||||
}
|
||||
}
|
||||
42
src/main.rs
42
src/main.rs
|
|
@ -1,3 +1,41 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use sfml::{graphics::{Color, Font, RenderTarget, RenderWindow}, window::{mouse, Event, Key, Style}, SfResult};
|
||||
|
||||
mod counter;
|
||||
mod button;
|
||||
mod constants;
|
||||
|
||||
use counter::Counter;
|
||||
use crate::constants::common::{FPS, WINDOW_SIZE};
|
||||
|
||||
|
||||
fn main() -> SfResult<()>{
|
||||
let font = Font::from_file("res/font.ttf").unwrap();
|
||||
let mut c1 = Counter::new(0, &font);
|
||||
|
||||
let mut window = RenderWindow::new(WINDOW_SIZE, "Multi Counter", Style::CLOSE, &Default::default())?;
|
||||
window.set_framerate_limit(FPS);
|
||||
|
||||
while window.is_open() {
|
||||
while let Some(event) = window.poll_event() {
|
||||
match event {
|
||||
Event::Closed => window.close(),
|
||||
Event::KeyPressed { code, .. } => match code {
|
||||
Key::Left => c1.dec(),
|
||||
Key::Right => c1.inc(),
|
||||
Key::Space => c1.reset(),
|
||||
_ => {}
|
||||
},
|
||||
Event::MouseButtonPressed { button, x, y } => if button == mouse::Button::Left {
|
||||
c1.handle_mouse((x as f32, y as f32));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
window.clear(Color::BLACK);
|
||||
window.draw(&c1);
|
||||
window.display();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue