Skip to content

Commit d0eda54

Browse files
authored
feat(gui):support angle in UIImage (#2381)
1 parent 79a7cc4 commit d0eda54

File tree

1 file changed

+47
-9
lines changed

1 file changed

+47
-9
lines changed

arcade/gui/widgets/image.py

+47-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import math
34
from typing import Union
45

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

3236
def __init__(
3337
self,
@@ -46,17 +50,51 @@ def __init__(
4650
)
4751
bind(self, "texture", self.trigger_render)
4852
bind(self, "alpha", self.trigger_full_render)
53+
bind(self, "angle", self.trigger_full_render)
4954

5055
@override
5156
def do_render(self, surface: Surface):
5257
"""Render the stored texture in the size of the widget."""
53-
self.prepare_render(surface)
5458
if self.texture:
55-
surface.draw_texture(
56-
x=0,
57-
y=0,
58-
width=self.content_width,
59-
height=self.content_height,
60-
tex=self.texture,
61-
alpha=self.alpha,
62-
)
59+
self.prepare_render(surface)
60+
61+
if self.angle == 0:
62+
surface.draw_texture(
63+
x=0,
64+
y=0,
65+
width=self.content_width,
66+
height=self.content_height,
67+
tex=self.texture,
68+
alpha=self.alpha,
69+
)
70+
else:
71+
w = self.content_width
72+
h = self.content_height
73+
angle_radians = math.radians(self.angle)
74+
cos_value = abs(math.cos(angle_radians))
75+
sin_value = abs(math.sin(angle_radians))
76+
77+
# https://stackoverflow.com/a/33867165/2947505
78+
# Calculate the minimum size of the rotated image
79+
# W = w·|cos φ| + h·|sin φ|
80+
w_rotated = w * cos_value + h * sin_value
81+
# H = w·|sin φ| + h·|cos φ|
82+
h_rotated = w * sin_value + h * cos_value
83+
# a = min(wo / W, ho / H)
84+
factor = min(w / w_rotated, h / h_rotated)
85+
# W′ = a·w
86+
w_fitted = factor * w
87+
# H′ = a·h
88+
h_fitted = factor * h
89+
90+
draw_rect = self.content_rect.align_left(0).align_bottom(0)
91+
draw_rect = draw_rect.resize(w_fitted, h_fitted)
92+
surface.draw_texture(
93+
x=draw_rect.left,
94+
y=draw_rect.bottom,
95+
width=draw_rect.width,
96+
height=draw_rect.height,
97+
tex=self.texture,
98+
alpha=self.alpha,
99+
angle=self.angle,
100+
)

0 commit comments

Comments
 (0)