Skip to content

Instantly share code, notes, and snippets.

@ChristopherBiscardi
Created July 19, 2024 19:29
Show Gist options
  • Save ChristopherBiscardi/0e29ac6853c1ba9013295a0085a837e4 to your computer and use it in GitHub Desktop.
Save ChristopherBiscardi/0e29ac6853c1ba9013295a0085a837e4 to your computer and use it in GitHub Desktop.
A calculator in bevy! (codegolf)
use std::ops::Deref;
use bevy::{color::palettes::tailwind::*, prelude::*};
use calc::*;
use itertools::Itertools;
use rust_decimal::prelude::*;
fn main() {
App::new()
.insert_resource(ClearColor(SLATE_950.into()))
.add_plugins(DefaultPlugins)
.add_systems(Startup, startup)
.add_systems(Update, button_system)
.observe(calculate)
.run();
}
fn calculate(
trigger: Trigger<PressEvent>,
mut display: Local<String>,
mut text_query: Query<&mut Text, With<Output>>,
) {
match trigger.event().0.deref() {
"C" => {
*display = "".to_string();
}
"=" => {
let Ok(result) = Context::<f64>::default()
.evaluate(&display)
else {
*display = "error".to_string();
return;
};
if let Some(result) = Decimal::from_f64(
(result * 100.).round() / 100.,
) {
*display = result.normalize().to_string();
} else {
*display = result.to_string();
}
}
x => {
display.push_str(x);
}
}
for mut text in &mut text_query {
text.sections[0].value =
display.chars().tail(11).collect::<String>();
}
}
#[derive(Component)]
struct Output;
fn startup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
let container = commands
.spawn(NodeBundle {
style: Style {
display: Display::Grid,
grid_template_columns:
RepeatedGridTrack::auto(4),
margin: UiRect::all(Val::Auto),
..default()
},
..default()
})
.id();
let items = vec![
"C", "", "7", "8", "9", "/", "4", "5", "6", "*",
"1", "2", "3", "-", "0", ".", "=", "+",
];
for item in items {
let button = commands
.spawn(ButtonBundle {
style: Style {
grid_column: GridPlacement::span(
if item == "" { 3 } else { 1 },
),
border: UiRect::all(Val::Px(1.)),
padding: UiRect::all(Val::Px(20.)),
margin: UiRect::all(Val::Px(5.)),
..default()
},
border_radius: BorderRadius::all(
if item == "" {
Val::Px(0.)
} else {
Val::Px(5.)
},
),
border_color: BorderColor(if item == "" {
SKY_950.into()
} else {
SLATE_400.into()
}),
..default()
})
.with_children(|builder| {
let mut b = builder.spawn(TextBundle {
text: Text::from_section(
item,
TextStyle::default(),
),
..default()
});
if item == "" {
b.insert(Output);
}
})
.id();
commands.entity(container).add_child(button);
}
}
#[derive(Event)]
struct PressEvent(String);
const NORMAL_BUTTON: Srgba = SLATE_500;
const HOVERED_BUTTON: Srgba = SLATE_400;
const PRESSED_BUTTON: Srgba = GREEN_400;
fn button_system(
mut commands: Commands,
mut interaction_query: Query<
(
&Interaction,
&mut BackgroundColor,
&Children,
),
(Changed<Interaction>, With<Button>),
>,
text_query: Query<&Text>,
) {
for (interaction, mut color, children) in
&mut interaction_query
{
let text = text_query.get(children[0]).unwrap();
match *interaction {
Interaction::Pressed => {
*color = PRESSED_BUTTON.into();
commands.trigger(PressEvent(
text.sections[0].value.to_string(),
));
}
Interaction::Hovered => {
*color = HOVERED_BUTTON.into();
}
Interaction::None => {
*color = NORMAL_BUTTON.into();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment