├── .github └── FUNDING.yml ├── LICENSE ├── README.md ├── color_picker.gif ├── color_picker.rpy └── color_picker_examples.rpy /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: fen 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 shawna-p 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # renpy-color-picker 2 | 3 | A simple color picker for Ren'Py. 4 | 5 | ![Preview](color_picker.gif) 6 | 7 | ## How to Use 8 | 9 | 1. Download the ZIP of this repository using the green button in the top right. The file `color_picker.rpy` is require; the file `color_picker_examples.rpy` is optional but will show you possible ways to use the tool. 10 | 2. Put `color_picker.rpy` inside your Ren'Py project folder (with your other `rpy` files). 11 | 3. There is a test label, `label how_to_use_color_picker`, included in `color_picker.rpy`. You can jump to it to test out the color picker (e.g. `jump how_to_use_color_picker`). 12 | 13 | In particular, the example screen `screen color_picker` should be used as a guide for adding the picker to your own screens. The picker, hue bars, preview swatch, hex code information, etc. are all separate screen elements and can be resized and moved around the screen however you like. 14 | 15 | ## Terms of Use 16 | 17 | You are free to use this code however you wish. Credit as `Feniks` is not required but is appreciated if you found the code useful. This tool can also be found on itch.io: https://feniksdev.itch.io/color-picker-for-renpy 18 | 19 | You can check out my website, https://feniksdev.com/ for Ren'Py coding tutorials. 20 | 21 | ## Like my work? 22 | 23 | [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/fen) 24 | -------------------------------------------------------------------------------- /color_picker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shawna-p/renpy-color-picker/a2ac13b80db138654bb7739684fdf07db440cb46/color_picker.gif -------------------------------------------------------------------------------- /color_picker.rpy: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ## 3 | ## Color Picker for Ren'Py by Feniks (feniksdev.itch.io / feniksdev.com) 4 | ## 5 | ################################################################################ 6 | ## This file contains code for a colour picker in Ren'Py. 7 | ## If you use this code in your projects, credit me as Feniks @ feniksdev.com 8 | ## 9 | ## If you'd like to see how to use this tool, check the other file, 10 | ## color_picker_examples.rpy! 11 | ## You can also see this tool in action in the image tint tool, also on itch: 12 | ## https://feniksdev.itch.io/image-tint-tool 13 | ## 14 | ## Leave a comment on the tool page on itch.io or an issue on the GitHub 15 | ## if you run into any issues. 16 | ## https://feniksdev.itch.io/color-picker-for-renpy 17 | ## https://github.com/shawna-p/renpy-color-picker 18 | ################################################################################ 19 | ################################################################################ 20 | ## SHADERS & TRANSFORMS 21 | ################################################################################ 22 | init python: 23 | ## A shader which creates a gradient for a colour picker. 24 | renpy.register_shader("feniks.color_picker", variables=""" 25 | uniform vec4 u_gradient_top_right; 26 | uniform vec4 u_gradient_top_left; 27 | uniform vec4 u_gradient_bottom_left; 28 | uniform vec4 u_gradient_bottom_right; 29 | uniform vec2 u_model_size; 30 | varying float v_gradient_x_done; 31 | varying float v_gradient_y_done; 32 | attribute vec4 a_position; 33 | """, vertex_300=""" 34 | v_gradient_x_done = a_position.x / u_model_size.x; 35 | v_gradient_y_done = a_position.y / u_model_size.y; 36 | """, fragment_300=""" 37 | // Mix the two top colours 38 | vec4 top = mix(u_gradient_top_left, u_gradient_top_right, v_gradient_x_done); 39 | // Mix the two bottom colours 40 | vec4 bottom = mix(u_gradient_bottom_left, u_gradient_bottom_right, v_gradient_x_done); 41 | // Mix the top and bottom 42 | gl_FragColor = mix(bottom, top, 1.0-v_gradient_y_done); 43 | """) 44 | 45 | ## A shader which creates a spectrum. Generally for colour pickers. 46 | renpy.register_shader("feniks.spectrum", variables=""" 47 | uniform float u_lightness; 48 | uniform float u_saturation; 49 | uniform float u_horizontal; 50 | uniform vec2 u_model_size; 51 | varying float v_gradient_x_done; 52 | varying float v_gradient_y_done; 53 | attribute vec4 a_position; 54 | """, vertex_300=""" 55 | v_gradient_x_done = a_position.x / u_model_size.x; 56 | v_gradient_y_done = a_position.y / u_model_size.y; 57 | """, fragment_functions=""" 58 | // HSL to RGB conversion adapted from 59 | // https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion 60 | float hue2rgb(float p, float q, float t){ 61 | if(t < 0.0) t += 1.0; 62 | if(t > 1.0) t -= 1.0; 63 | if(t < 1.0/6.0) return p + (q - p) * 6.0 * t; 64 | if(t < 1.0/2.0) return q; 65 | if(t < 2.0/3.0) return p + (q - p) * (2.0/3.0 - t) * 6.0; 66 | return p; 67 | } 68 | vec3 hslToRgb(float h, float l, float s) { 69 | float q = l < 0.5 ? l * (1.0 + s) : l + s - l * s; 70 | float p = 2.0 * l - q; 71 | float r = hue2rgb(p, q, h + 1.0/3.0); 72 | float g = hue2rgb(p, q, h); 73 | float b = hue2rgb(p, q, h - 1.0/3.0); 74 | return vec3(r, g, b); 75 | } 76 | """, fragment_300=""" 77 | float hue = u_horizontal > 0.5 ? v_gradient_x_done : 1.0-v_gradient_y_done; 78 | vec3 rgb = hslToRgb(hue, u_lightness, u_saturation); 79 | gl_FragColor = vec4(rgb.r, rgb.g, rgb.b, 1.0); 80 | """) 81 | 82 | ## A transform which creates a spectrum. 83 | ## If horizontal is True, the spectrum goes from left to right instead of 84 | ## top to bottom. You can also adjust the lightness and saturation 85 | ## (between 0 and 1). 86 | transform spectrum(horizontal=True, light=0.5, sat=1.0): 87 | shader "feniks.spectrum" 88 | u_lightness light 89 | u_saturation sat 90 | u_horizontal float(horizontal) 91 | 92 | ## A transform which creates a square with a gradient. By default, only the 93 | ## top right colour is required (to make a colour picker gradient) but four 94 | ## corner colours may also be provided clockwise from the top-right. 95 | transform color_picker(top_right, bottom_right="#000", bottom_left="#000", 96 | top_left="#fff"): 97 | shader "feniks.color_picker" 98 | u_gradient_top_right Color(top_right).rgba 99 | u_gradient_top_left Color(top_left).rgba 100 | u_gradient_bottom_left Color(bottom_left).rgba 101 | u_gradient_bottom_right Color(bottom_right).rgba 102 | 103 | ################################################################################ 104 | ## CLASSES AND FUNCTIONS 105 | ################################################################################ 106 | init python: 107 | 108 | import pygame 109 | class ColorPicker(renpy.Displayable): 110 | """ 111 | A CDD which allows the player to pick a colour between four 112 | corner colours, with the typical setup used for a colour picker. 113 | 114 | Attributes 115 | ---------- 116 | xsize : int 117 | The width of the colour picker. 118 | ysize : int 119 | The height of the colour picker. 120 | top_left : Color 121 | The colour of the top-left corner. 122 | top_right : Color 123 | The colour of the top-right corner. 124 | bottom_left : Color 125 | The colour of the bottom-left corner. 126 | bottom_right : Color 127 | The colour of the bottom-right corner. 128 | color : Color 129 | The current colour the colour picker is focused over. 130 | selector_xpos : float 131 | The xpos of the colour selector. 132 | selector_ypos : float 133 | The ypos of the colour selector. 134 | picker : Displayable 135 | A square that is used to display the colour picker. 136 | hue_rotation : float 137 | The amount the current hue is rotated by. 138 | dragging : bool 139 | True if the indicator is currently being dragged around. 140 | saved_colors : dict 141 | A dictionary of key - Color pairs corresponding to colours the 142 | picker has selected in the past. 143 | last_saved_color : any 144 | The dictionary key of the last colour saved. 145 | mouseup_callback : callable 146 | An optional callback or list of callbacks which will be called when 147 | the player lifts their mouse after selecting a colour. 148 | """ 149 | RED = Color("#f00") 150 | def __init__(self, xsize, ysize, start_color=None, four_corners=None, 151 | saved_colors=None, last_saved_color=None, mouseup_callback=None, 152 | **kwargs): 153 | """ 154 | Create a ColorPicker object. 155 | 156 | Parameters: 157 | ----------- 158 | xsize : int 159 | The width of the colour picker. 160 | ysize : int 161 | The height of the colour picker. 162 | start_color : str 163 | A hexadecimal colour code corresponding to the starting colour. 164 | four_corners : tuple(Color, Color, Color, Color) 165 | A tuple of four colours corresponding to the four corners of the 166 | colour picker. The order is top right, bottom right, bottom 167 | left, top left. If this is not None, it will override the 168 | start_color parameter. 169 | saved_colors : dict 170 | A dictionary of key - Color pairs corresponding to colours 171 | the picker has selected in the past. 172 | last_saved_color : any 173 | The dictionary key of the last colour saved. 174 | mouseup_callback : callable 175 | An optional callback or list of callbacks which will be called 176 | when the player lifts their mouse after selecting a colour. 177 | """ 178 | super(ColorPicker, self).__init__(**kwargs) 179 | self.xsize = xsize 180 | self.ysize = ysize 181 | 182 | self.top_left = None 183 | self.top_right = None 184 | self.bottom_left = None 185 | self.bottom_right = None 186 | 187 | self.last_saved_color = last_saved_color 188 | self.saved_colors = saved_colors or dict() 189 | self.mouseup_callback = mouseup_callback 190 | 191 | if start_color is None and four_corners is None: 192 | ## Automatically start with red 193 | self.set_color("#f00") 194 | elif four_corners is None: 195 | self.set_color(start_color) 196 | else: 197 | all_corners = [Color(c) if not isinstance(c, Color) else c for c in four_corners] 198 | self.top_right, self.bottom_right, self.bottom_left, self.top_left = all_corners 199 | self.set_color(self.top_right) 200 | 201 | self.picker = Transform("#fff", xysize=(self.xsize, self.ysize)) 202 | self.dragging = False 203 | 204 | self.save_color(self.last_saved_color) 205 | 206 | def set_color(self, color): 207 | """ 208 | Set the current colour of the colour picker. 209 | 210 | Parameters 211 | ---------- 212 | color : Color 213 | The new colour to set the colour picker to. 214 | """ 215 | if not isinstance(color, Color): 216 | self.color = Color(color) 217 | else: 218 | self.color = color 219 | self.dragging = False 220 | 221 | ## Check if this has four custom corners 222 | if self.top_left is None: 223 | ## No; set to saturation/value 224 | self.selector_xpos = round(self.color.hsv[1]*255.0)/255.0 225 | self.selector_ypos = 1.0 - round(self.color.hsv[2]*255.0)/255.0 226 | self._hue_rotation = self.color.hsv[0] 227 | else: 228 | ## There isn't a good way to guess the position of a colour 229 | ## with custom corners, so just set it to the top right 230 | self.selector_xpos = 1.0 231 | self.selector_ypos = 0.0 232 | self._hue_rotation = 0.0 233 | 234 | @property 235 | def hue_rotation(self): 236 | """ 237 | The hue rotation of the colour picker. 238 | """ 239 | return self._hue_rotation 240 | 241 | @hue_rotation.setter 242 | def hue_rotation(self, value): 243 | """ 244 | Set the hue rotation of the colour picker. 245 | """ 246 | if value > 1.0: 247 | value = value % 1.0 248 | if round(self._hue_rotation*255.0) == round(value*255): 249 | return 250 | self._hue_rotation = value 251 | self.update_hue() 252 | 253 | def set_saved_color(self, key, new_color): 254 | """ 255 | Set the colour saved with key as the key to new_color. 256 | 257 | Parameters 258 | ---------- 259 | key : any 260 | The key of the colour to change. Must be a valid dictionary key. 261 | new_color : Color 262 | The new colour to set the saved colour to. 263 | """ 264 | if not isinstance(new_color, Color): 265 | self.saved_colors[key] = Color(new_color) 266 | else: 267 | self.saved_colors[key] = new_color 268 | 269 | def save_color(self, key): 270 | """ 271 | Save the current colour to the saved dictionary with key as the key. 272 | """ 273 | self.saved_colors[key] = self.color 274 | 275 | def get_color(self, key): 276 | """ 277 | Retrieve the colour saved in the dictionary with key as the key. 278 | """ 279 | return self.saved_colors.get(key, Color("#000")) 280 | 281 | def swap_to_saved_color(self, key): 282 | """ 283 | Swap to the saved colour with key as the key. 284 | """ 285 | self.set_color(self.saved_colors.get(key, Color("#000"))) 286 | self.last_saved_color = key 287 | renpy.redraw(self, 0) 288 | 289 | def render(self, width, height, st, at): 290 | """ 291 | Render the displayable to the screen. 292 | """ 293 | r = renpy.Render(self.xsize, self.ysize) 294 | 295 | if self.top_left is None: 296 | trc = self.RED.rotate_hue(self.hue_rotation) 297 | # Colorize the picker into a gradient 298 | picker = At(self.picker, color_picker(trc)) 299 | else: 300 | # Custom four corners; no spectrum sliders 301 | picker = At(self.picker, color_picker( 302 | self.top_right.rotate_hue(self.hue_rotation), 303 | self.bottom_right.rotate_hue(self.hue_rotation), 304 | self.bottom_left.rotate_hue(self.hue_rotation), 305 | self.top_left.rotate_hue(self.hue_rotation))) 306 | # Position the selector 307 | selector = Transform("selector", anchor=(0.5, 0.5), 308 | xpos=self.selector_xpos, ypos=self.selector_ypos) 309 | final = Fixed(picker, selector, xysize=(self.xsize, self.ysize)) 310 | # Render it to the screen 311 | ren = renpy.render(final, self.xsize, self.ysize, st, at) 312 | r.blit(ren, (0, 0)) 313 | return r 314 | 315 | def update_hue(self): 316 | """ 317 | Update the colour based on the hue in the top-right corner 318 | (or in all 4 corners). 319 | """ 320 | # Figure out the colour under the selector 321 | if self.top_left is None: 322 | trc = self.RED.rotate_hue(self.hue_rotation) 323 | tlc = Color("#fff") 324 | brc = Color("#000") 325 | blc = Color("#000") 326 | else: 327 | tlc = self.top_left.rotate_hue(self.hue_rotation) 328 | trc = self.top_right.rotate_hue(self.hue_rotation) 329 | brc = self.bottom_right.rotate_hue(self.hue_rotation) 330 | blc = self.bottom_left.rotate_hue(self.hue_rotation) 331 | 332 | self.color = tlc.interpolate(trc, self.selector_xpos) 333 | bottom = blc.interpolate(brc, self.selector_xpos) 334 | self.color = self.color.interpolate(bottom, self.selector_ypos) 335 | self.save_color(self.last_saved_color) 336 | renpy.redraw(self, 0) 337 | 338 | def event(self, ev, x, y, st): 339 | """Allow the user to drag their mouse to select a colour.""" 340 | relative_x = round(x/float(self.xsize)*255.0)/255.0 341 | relative_y = round(y/float(self.ysize)*255.0)/255.0 342 | 343 | in_range = (0.0 <= relative_x <= 1.0) and (0.0 <= relative_y <= 1.0) 344 | 345 | if renpy.map_event(ev, "mousedown_1") and in_range: 346 | self.dragging = True 347 | self.selector_xpos = relative_x 348 | self.selector_ypos = relative_y 349 | elif ev.type == pygame.MOUSEMOTION and self.dragging: 350 | self.selector_xpos = relative_x 351 | self.selector_ypos = relative_y 352 | elif renpy.map_event(ev, "mouseup_1") and self.dragging: 353 | self.dragging = False 354 | ## Update the screen 355 | renpy.restart_interaction() 356 | if self.mouseup_callback is not None: 357 | renpy.run(self.mouseup_callback, self) 358 | return 359 | else: 360 | return 361 | 362 | # Limit x/ypos 363 | self.selector_xpos = min(max(self.selector_xpos, 0.0), 1.0) 364 | self.selector_ypos = min(max(self.selector_ypos, 0.0), 1.0) 365 | self.update_hue() 366 | return None 367 | 368 | def picker_color(st, at, picker, xsize=100, ysize=100): 369 | """ 370 | A DynamicDisplayable function to update the colour picker swatch. 371 | 372 | Parameters: 373 | ----------- 374 | picker : ColorPicker 375 | The picker this swatch is made from. 376 | xsize : int 377 | The width of the swatch. 378 | ysize : int 379 | The height of the swatch. 380 | """ 381 | return Transform(picker.color, xysize=(xsize, ysize)), 0.01 382 | 383 | def picker_hexcode(st, at, picker): 384 | """ 385 | A brief DynamicDisplayable demonstration of how to display color 386 | information in real-time. 387 | """ 388 | return Text(picker.color.hexcode, style='picker_hexcode'), 0.01 389 | 390 | ################################################################################ 391 | ## IMAGES 392 | ################################################################################ 393 | init offset = -1 394 | init python: 395 | def construct_selector(w=2, sz=5): 396 | """ 397 | Constructs a white box surrounded by a black box, to use as a 398 | selector for the colour picker. 399 | 400 | Parameters 401 | ---------- 402 | w : int 403 | The width of the lines. 404 | sz : int 405 | The size of the inner box. 406 | """ 407 | ## First, the sides of the box 408 | box_leftright = [ 409 | Transform("#000", xysize=(w, sz+2*3*w), align=(0.5, 0.5)), 410 | Transform("#fff", xysize=(w, sz+2*2*w), align=(0.5, 0.5)), 411 | Transform("#000", xysize=(w, sz+2*1*w), align=(0.5, 0.5)), 412 | ] 413 | ## Then the top and bottom 414 | box_topbottom = [ 415 | Transform("#000", xysize=(sz+2*2*w, w), align=(0.5, 0.5)), 416 | Transform("#fff", xysize=(sz+2*1*w, w), align=(0.5, 0.5)), 417 | Transform("#000", xysize=(sz, w), align=(0.5, 0.5)), 418 | ] 419 | final_vbox = box_topbottom + [Null(height=sz)] + box_topbottom[::-1] 420 | final_hbox = (box_leftright + [Null(width=-w*2)] 421 | + [VBox(*final_vbox, style='empty', spacing=0)] 422 | + [Null(width=-w*2)] + box_leftright[::-1]) 423 | ## Now put it together 424 | return HBox(*final_hbox, spacing=0, style='empty') 425 | 426 | ## These can be changed; see color_picker_examples.rpy for more. 427 | ## Feel free to remove the constructor function above if you don't use these. 428 | ## Used for both the spectrum thumb and the colour indicator. 429 | image selector_img = construct_selector(2, 3) 430 | image selector_bg = Frame("selector_img", 7, 7) 431 | ## The image used for the indicator showing the current colour. 432 | image selector = Transform("selector_bg", xysize=(15, 15)) 433 | 434 | style picker_hexcode: 435 | color "#fff" 436 | font "DejaVuSans.ttf" 437 | -------------------------------------------------------------------------------- /color_picker_examples.rpy: -------------------------------------------------------------------------------- 1 | 2 | ################################################################################ 3 | ################################################################################ 4 | ## 5 | ## COLOR PICKER EXAMPLES 6 | ## 7 | ################################################################################ 8 | ## To quickly test these examples in your game, jump to the label 9 | ## how_to_use_color_picker i.e. 10 | # jump how_to_use_color_picker 11 | 12 | ################################################################################ 13 | ## IMAGES 14 | ################################################################################ 15 | ## In order to avoid including unnecessary image files, the default version of 16 | ## these images constructs an image in code. You may, however, want to change 17 | ## it. The following code is provided as an example of how to do so. 18 | 19 | ## Used for both the spectrum thumb and the colour indicator. Can be changed. 20 | # image selector_bg = Frame("selector.webp", 5, 5) 21 | 22 | ## The image used for the indicator showing the current colour. 23 | # image selector = Transform("selector_bg", xysize=(15, 15)) 24 | 25 | ################################################################################ 26 | ## SCREENS 27 | ################################################################################ 28 | ## EXAMPLE 1 29 | ## A sample screen to demonstrate the colour picker. 30 | ## Simply write `call screen color_picker()` to test it. 31 | screen color_picker(): 32 | 33 | ## The picker itself. Its size is 600x600 with the starting colour #ff8335. 34 | ## You may declare this outside of the screen to make it easier to access; 35 | ## see color_picker_v2 for an example of this. 36 | default picker = ColorPicker(600, 600, "#ff8335") 37 | ## The preview swatch. Needs to be provided the picker variable from above. 38 | ## You can specify its size as well. 39 | default picker_swatch = DynamicDisplayable(picker_color, picker=picker, 40 | xsize=100, ysize=100) 41 | ## The hexcode of the current colour. Demonstrates updating the picker 42 | ## colour information in real-time. 43 | default picker_hex = DynamicDisplayable(picker_hexcode, picker=picker) 44 | 45 | style_prefix 'cpicker' ## Simplifies some of the style property code 46 | 47 | add "#21212d" ## The background 48 | 49 | hbox: 50 | ## A vertical bar which lets you change the hue of the picker. 51 | vbar value FieldValue(picker, "hue_rotation", 1.0) 52 | 53 | vbox: 54 | ## The picker itself 55 | add picker 56 | ## A horizontal bar that lets you change the hue of the picker 57 | bar value FieldValue(picker, "hue_rotation", 1.0) 58 | vbox: 59 | xsize 200 spacing 10 align (0.0, 0.0) 60 | ## The swatch 61 | add picker_swatch 62 | 63 | ## You can display other information on the color here, as desired 64 | ## Some examples are provided. Note that these do not update in 65 | ## tandem with the picker, but when the mouse is released. You 66 | ## will need to use a DynamicDisplayable for real-time updates. 67 | ## The hex code is provided as an example. 68 | add picker_hex ## The DynamicDisplayable from earlier 69 | ## These update when the mouse button is released 70 | ## since they aren't a dynamic displayable 71 | text "R: [picker.color.rgb[0]:.2f]" 72 | text "G: [picker.color.rgb[1]:.2f]" 73 | text "B: [picker.color.rgb[2]:.2f]" 74 | 75 | ## In this case, the screen returns the picker's colour. The colour itself 76 | ## is always stored in the picker's `color` attribute. 77 | textbutton "Return" action Return(picker.color) align (1.0, 1.0) 78 | 79 | ################################################################################ 80 | ## Styles 81 | style cpicker_vbox: 82 | align (0.5, 0.5) 83 | spacing 25 84 | style cpicker_hbox: 85 | align (0.5, 0.5) 86 | spacing 25 87 | style cpicker_vbar: 88 | xysize (50, 600) 89 | base_bar At(Transform("#000", xysize=(50, 600)), spectrum(horizontal=False)) 90 | thumb Transform("selector_bg", xysize=(50, 20)) 91 | thumb_offset 10 92 | style cpicker_bar: 93 | xysize (600, 50) 94 | base_bar At(Transform("#000", xysize=(600, 50)), spectrum()) 95 | thumb Transform("selector_bg", xysize=(20, 50)) 96 | thumb_offset 10 97 | style cpicker_text: 98 | color "#fff" 99 | style cpicker_button: 100 | padding (4, 4) insensitive_background "#fff" 101 | style cpicker_button_text: 102 | color "#aaa" 103 | hover_color "#fff" 104 | style cpicker_image_button: 105 | xysize (104, 104) 106 | padding (4, 4) 107 | hover_foreground "#fff2" 108 | 109 | ################################################################################ 110 | ## EXAMPLE 2 111 | ## The picker itself. This one is declared outside of the screen. 112 | default picker2 = ColorPicker(600, 600, "#f93c3e", 113 | ## This sets up two saved colours for the picker. These can be accessed 114 | ## later to allow the picker to swap between two different colours. 115 | ## You could add more keys and default colours, if desired. The keys don't 116 | ## have to be numbers, either; they could be names like "background". 117 | saved_colors={0 : "#f93c3e", 1 : "#ff8335"}, 118 | ## This sets up the first dictionary key as the "current" colour at 119 | ## the start. It will be updated automatically later. 120 | last_saved_color=0) 121 | ## The preview swatch. Needs to be provided the picker variable from above. 122 | ## You can specify its size as well. 123 | default picker_swatch_v2 = DynamicDisplayable(picker_color, picker=picker2, 124 | xsize=100, ysize=100) 125 | ## The hexcode of the current colour. Demonstrates updating the picker 126 | ## colour information in real-time. 127 | default picker_hex_v2 = DynamicDisplayable(picker_hexcode, picker=picker2) 128 | 129 | screen color_picker_v2(): 130 | 131 | ## This is an example of how you can swap between multiple colour swatches 132 | default current_color = 0 133 | 134 | style_prefix 'cpicker' 135 | 136 | add "#21212d" 137 | 138 | hbox: 139 | ## A vertical bar which lets you change the hue of the picker. 140 | vbar value FieldValue(picker2, "hue_rotation", 1.0) 141 | 142 | ## The picker itself 143 | vbox: 144 | add picker2 145 | ## A horizontal bar that lets you change the hue of the picker 146 | bar value FieldValue(picker2, "hue_rotation", 1.0) 147 | 148 | vbox: 149 | xsize 200 spacing 10 align (0.0, 0.0) 150 | ## The following code lets you switch between 151 | ## two different swatches to choose more than one colour: 152 | for color_key in [0, 1]: 153 | if current_color == color_key: 154 | button: 155 | ## An insensitive button which just shows the currently 156 | ## selected colour. 157 | add picker_swatch_v2 158 | else: 159 | imagebutton: 160 | ## This fetches the colour from the picker's saved 161 | ## dictionary according to the passed-in key. 162 | idle picker2.get_color(color_key) 163 | ## This does three things: first, it saves the current 164 | ## colour to the picker's dictionary. Next it updates 165 | ## current_colour to the new key. Finally, it swaps 166 | ## the picker's colour to the colour at that key. 167 | action [Function(picker2.save_color, current_color), 168 | SetScreenVariable("current_color", color_key), 169 | Function(picker2.swap_to_saved_color, color_key)] 170 | 171 | ## The hex code 172 | add picker_hex_v2 ## The DynamicDisplayable from earlier 173 | ## The RGB values 174 | text "R: [picker2.color.rgb[0]:.2f]" 175 | text "G: [picker2.color.rgb[1]:.2f]" 176 | text "B: [picker2.color.rgb[2]:.2f]" 177 | 178 | textbutton "Return" align (1.0, 1.0) action Return() 179 | 180 | ################################################################################ 181 | ## EXAMPLE 3 182 | ## A sample screen to demonstrate the four corner colour picker. 183 | ## Simply write `call screen four_corner_picker()` to test it. 184 | screen four_corner_picker(): 185 | 186 | ## The picker itself. Its size is 600x600, and it's given a colour for 187 | ## all four corners (top right, bottom right, bottom left, top left) 188 | ## You may declare this outside of the screen to make it easier to access. 189 | default picker = ColorPicker(600, 600, 190 | four_corners=("#ff8335", "#f93c3e", "#292835", "#f7f7ed")) 191 | ## The preview swatch. Needs to be provided the picker variable from above. 192 | ## You can specify its size as well. 193 | default picker_swatch = DynamicDisplayable(picker_color, picker=picker, 194 | xsize=100, ysize=100) 195 | ## The hexcode of the current colour. Demonstrates updating the picker 196 | ## colour information in real-time. 197 | default picker_hex = DynamicDisplayable(picker_hexcode, picker=picker) 198 | 199 | style_prefix 'cpicker' 200 | 201 | add "#21212d" 202 | 203 | hbox: 204 | spacing 25 align (0.5, 0.5) 205 | 206 | vbox: 207 | ## The picker itself 208 | add picker 209 | ## A horizontal bar that lets you change the hue of the picker 210 | ## For a four-corner picker, you may not need this. 211 | bar value FieldValue(picker, "hue_rotation", 1.0) base_bar "#fff" 212 | vbox: 213 | xsize 200 spacing 10 align (0.0, 0.0) 214 | ## The swatch 215 | add picker_swatch 216 | 217 | ## The hex code 218 | add picker_hex ## The DynamicDisplayable from earlier 219 | ## The RGB values 220 | text "R: [picker.color.rgb[0]:.2f]" 221 | text "G: [picker.color.rgb[1]:.2f]" 222 | text "B: [picker.color.rgb[2]:.2f]" 223 | 224 | ## In this case, the screen returns the picker's colour. The colour itself 225 | ## is always stored in the picker's `color` attribute. 226 | textbutton "Return" action Return(picker.color) align (1.0, 1.0) 227 | 228 | ################################################################################ 229 | ## TESTING LABEL 230 | ################################################################################ 231 | default chosen_color = "#8b0f55" 232 | label how_to_use_color_picker(): 233 | "Soon, you will be shown a colour picker." 234 | 235 | ## EXAMPLE 1 236 | call screen color_picker() 237 | ## The colour the picker returns is a Color object. It has a hexcode 238 | ## field to easily get the hexadecimal colour code. 239 | $ chosen_color = _return.hexcode 240 | ## This is used to put the returned colour into a colour text tag 241 | $ color_tag = "{color=%s}" % chosen_color 242 | "[color_tag]You chose the colour [chosen_color].{/color}" 243 | 244 | ## EXAMPLE 2 245 | "The next picker will let you select two different colours." 246 | call screen color_picker_v2() 247 | ## The get_color method lets you pass in the dictionary key and retrieve 248 | ## the colour saved in the picker at that key. 249 | $ chosen_color1 = picker2.get_color(0).hexcode 250 | $ color1_tag = "{color=%s}" % chosen_color1 251 | $ chosen_color2 = picker2.get_color(1).hexcode 252 | $ color2_tag = "{color=%s}" % chosen_color2 253 | "[color1_tag]The first colour was [chosen_color1],{/color}[color2_tag] and the second was [chosen_color2].{/color}" 254 | 255 | ## EXAMPLE 3 256 | "Next, you will be shown a four-corner colour picker." 257 | call screen four_corner_picker() 258 | $ chosen_color = _return.hexcode 259 | $ color_tag = "{color=%s}" % chosen_color 260 | "[color_tag]You chose the colour [chosen_color].{/color}" 261 | return 262 | --------------------------------------------------------------------------------