Skip to content

Commit

Permalink
feat(gui):support angle in UIImage (#2381)
Browse files Browse the repository at this point in the history
  • Loading branch information
eruvanos authored Sep 29, 2024
1 parent 79a7cc4 commit d0eda54
Showing 1 changed file with 47 additions and 9 deletions.
56 changes: 47 additions & 9 deletions arcade/gui/widgets/image.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import math
from typing import Union

from typing_extensions import override
Expand Down Expand Up @@ -28,6 +29,9 @@ class UIImage(UIWidget):
alpha = Property(255)
"""Alpha value of the texture, value between 0 and 255.
0 is fully transparent, 255 is fully visible."""
angle = Property(0)
"""Angle of the texture in degrees.
The image will be rotated around its center and fitted into the widget size."""

def __init__(
self,
Expand All @@ -46,17 +50,51 @@ def __init__(
)
bind(self, "texture", self.trigger_render)
bind(self, "alpha", self.trigger_full_render)
bind(self, "angle", self.trigger_full_render)

@override
def do_render(self, surface: Surface):
"""Render the stored texture in the size of the widget."""
self.prepare_render(surface)
if self.texture:
surface.draw_texture(
x=0,
y=0,
width=self.content_width,
height=self.content_height,
tex=self.texture,
alpha=self.alpha,
)
self.prepare_render(surface)

if self.angle == 0:
surface.draw_texture(
x=0,
y=0,
width=self.content_width,
height=self.content_height,
tex=self.texture,
alpha=self.alpha,
)
else:
w = self.content_width
h = self.content_height
angle_radians = math.radians(self.angle)
cos_value = abs(math.cos(angle_radians))
sin_value = abs(math.sin(angle_radians))

# https://stackoverflow.com/a/33867165/2947505
# Calculate the minimum size of the rotated image
# W = w·|cos φ| + h·|sin φ|
w_rotated = w * cos_value + h * sin_value
# H = w·|sin φ| + h·|cos φ|
h_rotated = w * sin_value + h * cos_value
# a = min(wo / W, ho / H)
factor = min(w / w_rotated, h / h_rotated)
# W′ = a·w
w_fitted = factor * w
# H′ = a·h
h_fitted = factor * h

draw_rect = self.content_rect.align_left(0).align_bottom(0)
draw_rect = draw_rect.resize(w_fitted, h_fitted)
surface.draw_texture(
x=draw_rect.left,
y=draw_rect.bottom,
width=draw_rect.width,
height=draw_rect.height,
tex=self.texture,
alpha=self.alpha,
angle=self.angle,
)

0 comments on commit d0eda54

Please sign in to comment.