1
1
from __future__ import annotations
2
2
3
+ import math
3
4
from typing import Union
4
5
5
6
from typing_extensions import override
@@ -28,6 +29,9 @@ class UIImage(UIWidget):
28
29
alpha = Property (255 )
29
30
"""Alpha value of the texture, value between 0 and 255.
30
31
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."""
31
35
32
36
def __init__ (
33
37
self ,
@@ -46,17 +50,51 @@ def __init__(
46
50
)
47
51
bind (self , "texture" , self .trigger_render )
48
52
bind (self , "alpha" , self .trigger_full_render )
53
+ bind (self , "angle" , self .trigger_full_render )
49
54
50
55
@override
51
56
def do_render (self , surface : Surface ):
52
57
"""Render the stored texture in the size of the widget."""
53
- self .prepare_render (surface )
54
58
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