Added sprite perserve_aspect

master
Mark 2024-02-05 14:11:47 -08:00
parent a817ad0d0f
commit cbcb060c66
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
6 changed files with 50 additions and 15 deletions

View File

@ -8,7 +8,6 @@
- Mouse colliders - Mouse colliders
- UI captures input? - UI captures input?
- No UI zoom scroll - No UI zoom scroll
- Preserve aspect for icons
- outfitter - outfitter
## Small jobs ## Small jobs

2
assets

@ -1 +1 @@
Subproject commit dc5962ffb96f6d4c7fc271a1b132865b280b528c Subproject commit fba4f1083b5a07a10445cf28bcae4bb05c2cede6

View File

@ -57,6 +57,7 @@ fn init(state) {
Anchor::NorthWest Anchor::NorthWest
) )
); );
sprite::preserve_aspect("ship_thumb", true);
textbox::add( textbox::add(
"ship_name", 10.0, 10.0, "ship_name", 10.0, 10.0,
@ -119,6 +120,8 @@ fn init(state) {
Anchor::NorthEast Anchor::NorthEast
) )
); );
sprite::preserve_aspect("outfit_thumb", true);
textbox::add( textbox::add(
"outfit_name", 16.0, 16.0, "outfit_name", 16.0, 16.0,

View File

@ -39,6 +39,17 @@ pub fn build_sprite_module(ct_src: Arc<Content>, state_src: Rc<RefCell<UiState>>
}, },
); );
let state = state_src.clone();
let _ = FuncRegistration::new("exists")
.with_namespace(FnNamespace::Internal)
.set_into_module(&mut module, move |name: ImmutableString| {
let mut ui_state = state.borrow_mut();
match ui_state.get_mut_by_name(&name) {
Some(UiElement::Sprite(_)) => true,
_ => false,
}
});
let state = state_src.clone(); let state = state_src.clone();
let _ = FuncRegistration::new("remove") let _ = FuncRegistration::new("remove")
.with_namespace(FnNamespace::Internal) .with_namespace(FnNamespace::Internal)
@ -155,15 +166,16 @@ pub fn build_sprite_module(ct_src: Arc<Content>, state_src: Rc<RefCell<UiState>>
}); });
let state = state_src.clone(); let state = state_src.clone();
let _ = FuncRegistration::new("exists") let _ = FuncRegistration::new("preserve_aspect")
.with_namespace(FnNamespace::Internal) .with_namespace(FnNamespace::Internal)
.set_into_module(&mut module, move |name: ImmutableString| { .set_into_module(&mut module, move |name: ImmutableString, x: bool| {
let mut ui_state = state.borrow_mut(); let mut ui_state = state.borrow_mut();
match ui_state.get_mut_by_name(&name) { match ui_state.get_mut_by_name(&name) {
Some(UiElement::Sprite(_)) => true, Some(UiElement::Sprite(s)) => s.set_preserve_aspect(x),
_ => false, _ => {
error!("called `sprite::set_preserve_aspect` on an invalid name `{name}`")
}
} }
}); });
return module; return module;
} }

View File

@ -85,12 +85,11 @@ impl CustomType for Rect {
/// Represents a rectangular region, in absolute coordinates relative to the screen center. /// Represents a rectangular region, in absolute coordinates relative to the screen center.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) struct CenteredRect { pub(crate) struct CenteredRect {
/// The position of the top-left corner of this rectangle, in fractional units. /// The position of the center of this rectangle, in post-scale logical pixels,
/// (0.0 is left edge of sprite, 1.0 is right edge) /// relative to (0, 0) in the center of the screen.
pub pos: Point2<f32>, pub pos: Point2<f32>,
/// The width and height of this rectangle, in fractional units. /// The width and height of this rectangle, in post-scale logical pixels.
/// 1.0 will be as tall as the sprite, 0.5 will be half as tall
pub dim: Vector2<f32>, pub dim: Vector2<f32>,
} }

View File

@ -16,6 +16,10 @@ pub struct Sprite {
/// Sprite angle, in degrees /// Sprite angle, in degrees
angle: f32, angle: f32,
/// If true, this sprite will be scaled to fit in its box without affecting aspect ratio.
/// If false, this sprite will be stretched to fit in its box
preserve_aspect: bool,
rect: Rect, rect: Rect,
mask: Option<SpriteHandle>, mask: Option<SpriteHandle>,
color: Color, color: Color,
@ -38,6 +42,7 @@ impl Sprite {
has_mouse: false, has_mouse: false,
has_click: false, has_click: false,
waiting_for_release: false, waiting_for_release: false,
preserve_aspect: false,
} }
} }
@ -57,15 +62,32 @@ impl Sprite {
self.color = color; self.color = color;
} }
pub fn set_preserve_aspect(&mut self, preserve_aspect: bool) {
self.preserve_aspect = preserve_aspect;
}
pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) { pub fn push_to_buffer(&self, input: &RenderInput, state: &mut RenderState) {
let rect = self let mut rect = self
.rect .rect
.to_centered(&state.window, input.ct.get_config().ui_scale); .to_centered(&state.window, input.ct.get_config().ui_scale);
// TODO: use both dimensions, if self.preserve_aspect {
// not just height let rect_aspect = rect.dim.x / rect.dim.y;
let anim_state = self.anim.get_texture_idx(); let sprite_aspect = input.ct.get_sprite(self.anim.get_sprite()).aspect;
// "wide rect" case => match height, reduce width
if rect_aspect > sprite_aspect {
let shrink = rect.dim.x - rect.dim.y * sprite_aspect;
rect.dim.x -= shrink;
// "tall rect" case => match width, reduce height
} else if rect_aspect < sprite_aspect {
let shrink = rect.dim.y - rect.dim.x / sprite_aspect;
rect.dim.y -= shrink;
}
}
let anim_state = self.anim.get_texture_idx();
state.push_ui_buffer(UiInstance { state.push_ui_buffer(UiInstance {
position: rect.pos.into(), position: rect.pos.into(),
angle: to_radians(90.0 + self.angle), angle: to_radians(90.0 + self.angle),