Added TileMap widget

This commit is contained in:
Jonathan Johnson 2023-10-27 15:28:51 -07:00
parent 90593e1938
commit c84ff988f3
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
2 changed files with 135 additions and 0 deletions

View file

@ -4,9 +4,11 @@ mod canvas;
mod input;
mod label;
mod style;
mod tilemap;
pub use button::Button;
pub use canvas::Canvas;
pub use input::Input;
pub use label::Label;
pub use style::Style;
pub use tilemap::TileMap;

133
src/widgets/tilemap.rs Normal file
View file

@ -0,0 +1,133 @@
use std::fmt::Debug;
use std::panic::UnwindSafe;
use kludgine::figures::utils::lossy_f64_to_f32;
use crate::context::{EventContext, GraphicsContext};
use crate::dynamic::Dynamic;
use crate::kludgine::app::winit::event::{DeviceId, KeyEvent, MouseScrollDelta, TouchPhase};
use crate::kludgine::app::winit::keyboard::Key;
use crate::kludgine::figures::units::UPx;
use crate::kludgine::figures::Size;
use crate::kludgine::tilemap;
use crate::kludgine::tilemap::TileMapFocus;
use crate::widget::{Callback, EventHandling, IntoValue, Value, Widget, HANDLED, UNHANDLED};
use crate::ConstraintLimit;
#[derive(Debug)]
#[must_use]
pub struct TileMap<Layers> {
layers: Value<Layers>,
focus: Value<TileMapFocus>,
key: Option<Callback<Key, EventHandling>>,
zoom: f32,
}
impl<Layers> TileMap<Layers> {
fn construct(layers: Value<Layers>) -> Self {
Self {
layers,
focus: Value::Constant(TileMapFocus::default()),
zoom: 1.,
key: None,
}
}
pub fn dynamic(layers: Dynamic<Layers>) -> Self {
Self::construct(Value::Dynamic(layers))
}
pub fn new(layers: Layers) -> Self {
Self::construct(Value::Constant(layers))
}
pub fn focus_on(mut self, focus: impl IntoValue<TileMapFocus>) -> Self {
self.focus = focus.into_value();
self
}
pub fn on_key<F>(mut self, key: F) -> Self
where
F: FnMut(Key) -> EventHandling + Send + UnwindSafe + 'static,
{
self.key = Some(Callback::new(key));
self
}
}
impl<Layers> Widget for TileMap<Layers>
where
Layers: tilemap::Layers,
{
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
self.focus.redraw_when_changed(context);
self.layers.redraw_when_changed(context);
let focus = self.focus.get();
self.layers
.map(|layers| tilemap::draw(layers, focus, self.zoom, &mut context.graphics));
}
fn measure(
&mut self,
available_space: Size<ConstraintLimit>,
_context: &mut GraphicsContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> {
Size::new(available_space.width.max(), available_space.height.max())
}
fn mouse_wheel(
&mut self,
_device_id: DeviceId,
delta: MouseScrollDelta,
_phase: TouchPhase,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
let amount = match delta {
MouseScrollDelta::LineDelta(_, lines) => lines,
MouseScrollDelta::PixelDelta(px) => lossy_f64_to_f32(px.y) / 16.0,
};
self.zoom += self.zoom * 0.1 * amount;
context.set_needs_redraw();
HANDLED
}
fn keyboard_input(
&mut self,
_device_id: DeviceId,
input: KeyEvent,
_is_synthetic: bool,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
if !input.state.is_pressed() {
return UNHANDLED;
}
if let Some(on_key) = &mut self.key {
on_key.invoke(input.logical_key.clone())?;
}
self.focus.map_mut(|focus| {
if let TileMapFocus::Point(focus) = focus {
match input.logical_key {
Key::ArrowLeft => {
focus.x -= 1;
}
Key::ArrowRight => {
focus.x += 1;
}
Key::ArrowUp => {
focus.y -= 1;
}
Key::ArrowDown => {
focus.y += 1;
}
_ => {}
}
}
});
context.set_needs_redraw();
HANDLED
}
}