1
+ from ursina import Mesh , Entity , Vec3 , generate_properties_for_class , camera , color , ThinSlider , copy , Func , Plane , Button , Vec2 , make_gradient
2
+ from ursina .prefabs .color_picker import ColorPicker
3
+
4
+
5
+ gradient_editor_arrow = Mesh (vertices = [(v + Vec3 (0 ,- .4 ,0 ))* Vec3 (.0175 ,.025 ,1 ) for v in (Vec3 (0 ,0 ,0 ),Vec3 (- .5 ,.5 ,0 ),Vec3 (.5 ,.5 ,0 ),Vec3 (- .5 ,.75 ,0 ),Vec3 (.5 ,.75 ,0 ))], triangles = (0 ,2 ,1 ,1 ,2 ,4 ,4 ,3 ,1 ))
6
+
7
+ @generate_properties_for_class ()
8
+ class GradientEditor (Entity ):
9
+ default_values = dict (parent = camera .ui , )
10
+
11
+ def __init__ (self , value = {'0' :color .hex ('#ffffffff' ), '32' :color .hex ('#ffffffff' ),}, resolution = 32 , on_value_changed :callable = None , ** kwargs ):
12
+ super ().__init__ (** (__class__ .default_values | kwargs ))
13
+
14
+ self .color_picker = ColorPicker (parent = self , scale = .75 , enabled = False , show_exit_button = True )
15
+ self .color_picker .exit_button .on_click = self .stop_editing_color
16
+
17
+ self .resolution = resolution
18
+ self .sliders = []
19
+ for i in range (3 ):
20
+ slider = ThinSlider (parent = self , x = - .25 , step = 1 , min = 0 , max = resolution - 1 , default = lerp (0 ,resolution ,i / (3 - 1 )), dynamic = True )
21
+ self .sliders .append (slider )
22
+ slider .knob .color = color .random_color ()
23
+ def _set_value ():
24
+ self .preview_gradient ()
25
+ if self .on_value_changed :
26
+ self .on_value_changed ()
27
+
28
+ slider .on_value_changed = _set_value
29
+ slider .bg .enabled = False
30
+ slider .knob .text_entity .enabled = False
31
+ slider .knob .model = copy (gradient_editor_arrow )
32
+ slider .knob .highlight_color = slider .knob .color
33
+ slider .knob .on_double_click = Func (self .start_editing_color , slider )
34
+
35
+ self .gradient_renderer = Entity (parent = self , model = Plane ((resolution ,1 )), rotation_x = - 90 , scale = Vec3 (.5 ,1 ,.05 ), y = - .035 )
36
+ self .copy_button = Button (parent = self , scale = Vec2 (.05 ,.025 )* 1 , text = 'copy' , text_size = .5 , origin = (.5 ,- .5 ), x = - .25 - .01 , y = - .06 , on_click = self .copy )
37
+
38
+ self .on_value_changed = on_value_changed # set this to a function you want to be called when the slider changes
39
+ self .value = value
40
+
41
+
42
+ def start_editing_color (self , slider ):
43
+ if self .color_picker .enabled :
44
+ self .stop_editing_color ()
45
+
46
+ self .color_picker .enabled = True
47
+ self .color_picker .position = slider .knob .position + Vec2 (- .25 ,.25 * .75 )
48
+ self .color_picker .value = slider .knob .color
49
+
50
+ def _set_color ():
51
+ slider .knob .color = self .color_picker .color
52
+ self .value = self .value
53
+ self .color_picker .on_value_changed = _set_color
54
+
55
+
56
+ def stop_editing_color (self ):
57
+ self .color_picker .enabled = False
58
+ self .color_picker .on_value_changed = None
59
+
60
+
61
+ def preview_gradient (self ):
62
+ self .gradient_renderer .model .colors = [self .gradient [int ((v .x + .5 )* self .resolution )] for v in self .gradient_renderer .model .vertices ]
63
+ self .gradient_renderer .model .generate ()
64
+
65
+ def gradient_getter (self ): # get the final calculated gradient as a list of 32 color
66
+ index_color_dict = self .value
67
+ index_color_dict ['0' ] = min (self .sliders , key = lambda s :s .value ).knob .color
68
+ index_color_dict [str (self .resolution )] = max (self .sliders , key = lambda s :s .value ).knob .color
69
+ return make_gradient (index_color_dict )
70
+
71
+
72
+ def value_getter (self ):
73
+ return {str (slider .value ) : slider .knob .color for slider in self .sliders }
74
+
75
+ def value_setter (self , value ):
76
+ # print('soeifjwseoifjseofijoij')
77
+ for i , (key , col ) in enumerate (value .items ()):
78
+ if isinstance (col , str ):
79
+ col = color .hex (col )
80
+
81
+ self .sliders [i ].knob .color = col
82
+ self .sliders [i ].value = int (key )
83
+
84
+ self ._value = value
85
+ self .preview_gradient ()
86
+ if self .on_value_changed :
87
+ self .on_value_changed ()
88
+
89
+ def copy (self ):
90
+ # print('copied:', {key:color.rgb_to_hex(*col) for key, col in self.value.items()})
91
+ import pyperclip
92
+ pyperclip .copy (str ({key :color .rgb_to_hex (* col ) for key , col in self .value .items ()}))
93
+
94
+
95
+ if __name__ == '__main__' :
96
+ from ursina import Ursina
97
+ app = Ursina ()
98
+ GradientEditor ()
99
+ app .run ()
0 commit comments