11from __future__ import annotations
22
3+ import math
34from typing import Union
45
56from 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