1# Copyright 2004-2021 Tom Rothamel <pytom@bishoujo.us>
2#
3# Permission is hereby granted, free of charge, to any person
4# obtaining a copy of this software and associated documentation files
5# (the "Software"), to deal in the Software without restriction,
6# including without limitation the rights to use, copy, modify, merge,
7# publish, distribute, sublicense, and/or sell copies of the Software,
8# and to permit persons to whom the Software is furnished to do so,
9# subject to the following conditions:
10#
11# The above copyright notice and this permission notice shall be
12# included in all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22#
23# Please see the LICENSE.txt distributed with Ren'Py for permission to
24# copy and modify.
25
26init -1100:
27    python:
28
29        theme = object()
30
31        def RoundRect(color, small=False):
32            """
33            Creates a roundrect displayable. Size should be one of
34            6 or 12, while color is the color of the roundrect.
35            """
36
37            if small:
38                size = 6
39            else:
40                if config.screen_width <= 640:
41                    size = 6
42                else:
43                    size = 12
44
45            return Frame(theme.OneOrTwoColor("_roundrect/rr%dg.png" % size, color), size, size)
46
47        def _display_button_menu(menuitems):
48
49            narration = [ s for s, i in menuitems if i is None and s ]
50            menuitems = [ (s, i) for s, i in menuitems if i is not None or not s ]
51
52            if narration:
53                renpy.say(None, "\n".join(narration), interact=False)
54
55            return renpy.display_menu(menuitems)
56
57        def _button_menu():
58
59            store.menu = _display_button_menu
60
61            style.menu.clear()
62            style.menu.box_spacing = 2
63
64            style.menu_window.clear()
65            style.menu_window.take(style.default)
66            style.menu_window.xpos = 0.5
67            style.menu_window.xanchor = 0.5
68            style.menu_window.ypos = 0.5
69            style.menu_window.yanchor = 0.5
70
71            style.menu_choice.clear()
72            style.menu_choice.take(style.button_text)
73
74            style.menu_choice_button.clear()
75            style.menu_choice_button.take(style.button)
76
77            style.menu_choice_chosen.clear()
78            style.menu_choice_chosen_button.clear()
79
80            style.menu_choice_button.xminimum = int(config.screen_width * 0.75)
81            style.menu_choice_button.xmaximum = int(config.screen_width * 0.75)
82
83
84        theme.button_menu = _button_menu
85
86    python hide:
87
88        def OneOrTwoColor(image, color):
89            if len(color) == 2:
90                return im.Twocolor(image, color[0], color[1])
91            else:
92                return im.Twocolor(image, color, color)
93
94        theme.OneOrTwoColor = OneOrTwoColor
95
96
97        def theme_roundrect(
98            widget = (0, 60, 120, 255),
99            widget_hover = (0, 80, 160, 255),
100            widget_text = (200, 225, 255, 255),
101            widget_selected = (255, 255, 200, 255),
102            disabled = (64, 64, 64, 255),
103            disabled_text = (200, 200, 200, 255),
104            label = (255, 255, 255, 255),
105            frame = (100, 150, 200, 255),
106            window = (0, 0, 0, 192),
107            mm_root = Solid((220, 235, 255, 255)),
108            gm_root = Solid((220, 235, 255, 255)),
109            centered = False,
110            button_menu = True,
111            launcher = False,
112            rounded_window = True,
113            less_rounded = False,
114            ):
115
116            """This enables the use of the roundrect theme. By
117               default, this theme styles the game in a blue color
118               scheme. However, by supplying one or more of the
119               parameters given below, the color scheme can be
120               changed.
121
122               @param widget: The background color of non-focued
123               buttons and sliders.
124
125               @param widget_hover: The background color of focused
126               buttons and sliders.
127
128               @param widget_text: The text color of non-selected buttons.
129
130               @param widget_selected: The text color of selected buttons.
131
132               @param disabled: The background color of disabled buttons.
133
134               @param disabled_text: The text color of disabled buttons.
135
136               @param label: The text color of non-selected labels.
137
138               @param frame: The background color of frames.
139
140               @param mm_root: A displayable (such as
141               an Image or Solid) that will be used as
142               the background for the main menu.
143
144               @param gm_root: A displayable (such as
145               an Image or Solid) that will be used as
146               the background for the game menu.
147
148               @param centered: If True, the buttons and sliders will
149               be centered in the frames or windows that contain
150               them. If False, the default, they will be pushed to the
151               right side.
152               """
153
154            if config.screen_width <= 640:
155                size = 18
156                small = 12
157
158                big = False
159
160                spacing = 0
161                pref_spacing = 5
162                title_spacing = 6
163
164                frame_width = 200
165                widget_width = 160
166
167                config.thumbnail_width = 60
168                config.thumbnail_height = 45
169
170                config.file_page_cols = 2
171                config.file_page_rows = 4
172                # style.file_picker_frame.xmaximum = 450
173
174                prefcols = [ 110, 320, 530 ]
175
176                nav_xpos = 530
177
178            else:
179
180                size = 22
181                small = 16
182
183                big = True
184
185                spacing = 0
186                pref_spacing = 10
187                title_spacing = 12
188
189                frame_width = 250
190                widget_width = 200
191
192                prefcols = [ 137, 400, 663 ]
193
194                nav_xpos = 663
195
196            rrslider_empty = "_roundrect/rrslider_empty.png"
197            rrslider_full = "_roundrect/rrslider_full.png"
198            rrslider_thumb = "_roundrect/rrslider_thumb.png"
199
200            rrslider_radius = 6
201            rrslider_height = 24
202
203            rrvslider_empty = "_roundrect/rrvslider_empty.png"
204            rrvslider_full = "_roundrect/rrvslider_full.png"
205            rrvslider_thumb = "_roundrect/rrvslider_thumb.png"
206
207            rrscrollbar = "_roundrect/rrscrollbar.png"
208            rrscrollbar_thumb = "_roundrect/rrscrollbar_thumb.png"
209            rrvscrollbar = "_roundrect/rrvscrollbar.png"
210            rrvscrollbar_thumb = "_roundrect/rrvscrollbar_thumb.png"
211
212            rrvslider_radius = 6
213            rrvslider_width = 24
214
215
216            def rrframe(sty):
217                sty.background = RoundRect(frame, less_rounded)
218                sty.xpadding = 6
219                sty.ypadding = 6
220
221            if big and not less_rounded:
222                store._roundrect_radius = 12
223            else:
224                store._roundrect_radius = 6
225
226            style.button.clear()
227            style.button.background = RoundRect(widget, less_rounded)
228            style.button.hover_background = RoundRect(widget_hover, less_rounded)
229            style.button.xminimum = widget_width
230            style.button.ypadding = 1
231            style.button.xpadding = _roundrect_radius
232            style.button.xmargin = 1
233            style.button.ymargin = 1
234
235            style.button_text.clear()
236            style.button_text.drop_shadow = None
237            style.button_text.color = widget_text
238            style.button_text.size = size
239            style.button_text.xpos = 0.5
240            style.button_text.xanchor = 0.5
241            style.button_text.ypos = 0.5
242            style.button_text.yanchor = 0.5
243            style.button_text.textalign = 0.5
244
245            style.button.insensitive_background = RoundRect(disabled, less_rounded)
246            style.button_text.insensitive_color = disabled_text
247
248            style.button_text.selected_color = widget_selected
249
250            style.menu_button.clear()
251
252            style.mm_root.background = mm_root
253            style.gm_root.background = gm_root
254
255            style.mm_menu_frame_vbox.box_spacing = spacing
256            rrframe(style.mm_menu_frame)
257            style.mm_menu_frame.xpos = nav_xpos
258            style.mm_menu_frame.xanchor = 0.5
259
260            style.gm_nav_vbox.box_spacing = spacing
261            rrframe(style.gm_nav_frame)
262            style.gm_nav_frame.xpos = nav_xpos
263            style.gm_nav_frame.xanchor = 0.5
264
265
266            rrframe(style.prefs_pref_frame)
267            del style.prefs_pref_frame.bottom_margin
268            style.prefs_pref_frame.xfill = True
269
270            style.prefs_pref_vbox.box_spacing = spacing
271            style.prefs_pref_vbox.box_first_spacing = title_spacing
272            style.prefs_pref_vbox.xfill = True
273
274            style.prefs_frame.ypadding = pref_spacing
275
276            rrframe(style.prefs_column)
277            style.prefs_column.box_spacing = pref_spacing
278            style.prefs_column.xmaximum = frame_width
279
280            style.prefs_left.xpos = prefcols[0]
281            style.prefs_center.xpos = prefcols[1]
282            style.prefs_right.xpos = prefcols[2]
283
284            style.prefs_label.color = label
285            style.prefs_label.size = size
286            style.prefs_label.drop_shadow = None
287            style.prefs_label.xpos = 0
288            style.prefs_label.xanchor = 0
289
290            if centered:
291                style.prefs_button.xpos = 0.5
292                style.prefs_button.xanchor = 0.5
293            else:
294                style.prefs_button.xpos = 1.0
295                style.prefs_button.xanchor = 1.0
296
297
298
299            style.bar.ymaximum = rrslider_height
300            style.bar.left_gutter = rrslider_radius
301            style.bar.right_gutter = rrslider_radius
302            style.bar.thumb_offset = -rrslider_radius
303
304            style.bar.left_bar = Frame(theme.OneOrTwoColor(rrslider_full, widget), rrslider_radius * 2, 0)
305            style.bar.right_bar = Frame(theme.OneOrTwoColor(rrslider_empty, widget), rrslider_radius * 2, 0)
306            style.bar.thumb = theme.OneOrTwoColor(rrslider_thumb, widget)
307
308            style.bar.hover_left_bar = Frame(theme.OneOrTwoColor(rrslider_full, widget_hover), rrslider_radius * 2, 0)
309            style.bar.hover_right_bar = Frame(theme.OneOrTwoColor(rrslider_empty, widget_hover), rrslider_radius * 2, 0)
310            style.bar.hover_thumb = theme.OneOrTwoColor(rrslider_thumb, widget_hover)
311
312            style.scrollbar.clear()
313            style.scrollbar.left_bar = Frame(theme.OneOrTwoColor(rrscrollbar, widget), 6, 0)
314            style.scrollbar.right_bar = Frame(theme.OneOrTwoColor(rrscrollbar, widget), 6, 0)
315            style.scrollbar.hover_left_bar = Frame(theme.OneOrTwoColor(rrscrollbar, widget_hover), 6, 0)
316            style.scrollbar.hover_right_bar = Frame(theme.OneOrTwoColor(rrscrollbar, widget_hover), 6, 0)
317            style.scrollbar.thumb = Frame(theme.OneOrTwoColor(rrscrollbar_thumb, widget), 6, 0)
318            style.scrollbar.hover_thumb = Frame(theme.OneOrTwoColor(rrscrollbar_thumb, widget_hover), 6, 0)
319            style.scrollbar.left_gutter = 6
320            style.scrollbar.right_gutter = 6
321            style.scrollbar.ymaximum = 12
322            style.scrollbar.thumb_offset = 6
323
324            style.vbar.xmaximum = rrvslider_width
325            style.vbar.top_gutter = rrvslider_radius
326            style.vbar.bottom_gutter = rrvslider_radius
327            style.vbar.thumb_offset = -rrvslider_radius
328
329            style.vbar.bottom_bar = Frame(theme.OneOrTwoColor(rrvslider_full, widget), 0, rrvslider_radius * 2)
330            style.vbar.top_bar = Frame(theme.OneOrTwoColor(rrvslider_empty, widget), 0, rrvslider_radius * 2)
331            style.vbar.thumb = theme.OneOrTwoColor(rrvslider_thumb, widget)
332
333            style.vbar.hover_bottom_bar = Frame(theme.OneOrTwoColor(rrvslider_full, widget_hover), 0, rrvslider_radius * 2)
334            style.vbar.hover_top_bar = Frame(theme.OneOrTwoColor(rrvslider_empty, widget_hover), 0, rrvslider_radius * 2)
335            style.vbar.hover_thumb = theme.OneOrTwoColor(rrvslider_thumb, widget_hover)
336
337            style.vscrollbar.clear()
338            style.vscrollbar.bar_invert = True
339            style.vscrollbar.top_bar = Frame(theme.OneOrTwoColor(rrvscrollbar, widget), 0, 6)
340            style.vscrollbar.bottom_bar = Frame(theme.OneOrTwoColor(rrvscrollbar, widget), 0, 6)
341            style.vscrollbar.hover_top_bar = Frame(theme.OneOrTwoColor(rrvscrollbar, widget_hover), 0, 6)
342            style.vscrollbar.hover_bottom_bar = Frame(theme.OneOrTwoColor(rrvscrollbar, widget_hover), 0, 6)
343            style.vscrollbar.thumb = Frame(theme.OneOrTwoColor(rrvscrollbar_thumb, widget), 0, 6)
344            style.vscrollbar.hover_thumb = Frame(theme.OneOrTwoColor(rrvscrollbar_thumb, widget_hover), 0, 6)
345            style.vscrollbar.top_gutter = 6
346            style.vscrollbar.bottom_gutter = 6
347            style.vscrollbar.xmaximum = 12
348            style.vscrollbar.thumb_offset = 6
349
350            style.prefs_slider.xmaximum=widget_width
351            del style.prefs_slider.ymaximum
352
353            if centered:
354                style.prefs_slider.xpos = 0.5
355                style.prefs_slider.xanchor = 0.5
356            else:
357                style.prefs_slider.xpos = 1.0
358                style.prefs_slider.xanchor = 1.0
359
360            style.soundtest_button.xminimum = 0
361
362            # Joystick
363
364            style.prefs_joystick.xmaximum = 600
365            style.prefs_joystick.xpos = 0.5
366            style.prefs_joystick.xanchor = 0.5
367            style.prefs_js_button.background = RoundRect(widget, True)
368            style.prefs_js_button.hover_background = RoundRect(widget_hover, True)
369            style.prefs_js_button_text.drop_shadow = None
370            style.prefs_js_button_text.size = small
371            style.prefs_js_button.xminimum = 450
372
373            rrframe(style.js_frame)
374            del style.js_frame.yminimum
375            style.js_frame.ypadding = .05
376            style.js_frame.xpadding = rrslider_radius
377            style.js_frame.xmargin = .05
378            style.js_frame.ypos = .1
379            style.js_frame.yanchor = 0
380
381            style.js_function_label.xpos = 0.5
382            style.js_function_label.xanchor = 0.5
383
384            style.js_prompt_label.xpos = 0.5
385            style.js_prompt_label.xanchor = 0.5
386
387            # Yes/No
388
389            rrframe(style.yesno_frame)
390            del style.yesno_frame.yminimum
391            style.yesno_frame.ypadding = .05
392            style.yesno_frame.xpadding = rrslider_radius
393            style.yesno_frame.xmargin = .05
394            style.yesno_frame.ypos = .1
395            style.yesno_frame.yanchor = 0
396
397            style.yesno_label.color = label
398            style.yesno_label.drop_shadow = None
399
400            # File Picker
401
402            rrframe(style.file_picker_frame)
403            style.file_picker_frame.xmargin = 6
404            style.file_picker_frame.ymargin = 6
405
406            style.file_picker_frame_vbox.box_spacing = 4
407            style.file_picker_nav_button.xminimum = 0
408
409            style.file_picker_navbox.box_spacing = spacing
410            del style.file_picker_navbox.xpos
411
412            style.file_picker_entry.background = RoundRect(widget, less_rounded)
413            style.file_picker_entry.hover_background = RoundRect(widget_hover, less_rounded)
414            style.file_picker_entry.xpadding = _roundrect_radius
415            style.file_picker_entry.xmargin = 2
416
417            style.file_picker_text.size = small
418            style.file_picker_text.drop_shadow = None
419            style.file_picker_text.color = widget_text
420            style.file_picker_new.color = widget_selected
421
422            style.file_picker_old.minwidth = 40
423            style.file_picker_new.minwidth = 40
424
425            style.file_picker_old.text_align = 1.0
426            style.file_picker_new.text_align = 1.0
427
428            if config.script_version is None or config.script_version > (6, 0, 0):
429                style.file_picker_text.insensitive_color = disabled_text
430                style.file_picker_entry.insensitive_background = RoundRect(disabled, less_rounded)
431
432
433            config.file_quick_access_pages = 8
434
435            # In-game.
436
437            if rounded_window:
438
439                style.window.background = RoundRect(window, less_rounded)
440                style.window.xpadding = 6
441                style.window.ypadding = 6
442                style.window.xmargin = 6
443                style.window.ymargin = 6
444
445            else:
446
447                style.window.background = Solid(window)
448                style.window.xpadding = 6
449                style.window.ypadding = 6
450                style.window.xmargin = 0
451                style.window.ymargin = 0
452
453
454            style.default.size = size
455            style.default.drop_shadow = None
456
457            rrframe(style.frame)
458            style.frame.xpadding = 6
459            style.frame.ypadding = 6
460            style.frame.xmargin = 6
461            style.frame.ymargin = 6
462
463            if button_menu:
464                _button_menu()
465
466            if launcher:
467                style.launcher_mid_vbox.xpos = 80
468                style.launcher_mid_vbox.ypos = 50
469
470                style.launcher_bottom_vbox.xpos = 80
471                style.launcher_bottom_vbox.ypos = 360
472                style.launcher_bottom_vbox.yanchor = 1.0
473
474                style.launcher_button.xpos = 20
475                style.launcher_button.xminimum = 240
476
477                style.launcher_title_label.color = label
478                style.launcher_title_label.size = 28
479
480                style.launcher_text.xpos = 140
481                style.launcher_text.xanchor = 0.5
482                style.launcher_text.xmaximum = 240
483                style.launcher_text.color = label
484                style.launcher_text.text_align = 0.5
485
486
487                style.launcher_label.xpos = 140
488                style.launcher_label.xanchor = 0.5
489                style.launcher_label.xmaximum = 240
490                style.launcher_label.color = label
491                style.launcher_label.text_align = 0.5
492
493                style.launcher_input.xpos = 140
494                style.launcher_input.xanchor = 0.5
495                style.launcher_input.xmaximum = 240
496                style.launcher_input.color = widget
497                style.launcher_input.text_align = 0.5
498
499                store._launcher_per_page = 9
500
501        theme.roundrect = theme_roundrect
502
503        def theme_roundrect_red(**params):
504            """
505            This sets up a red/pink variant of the roundrect theme.
506            """
507
508            args = dict(widget=(150, 50, 50, 255),
509                        widget_hover=(200, 50, 50, 255),
510                        widget_text=(255, 225, 225, 255),
511                        frame=(225, 115, 115, 192),
512                        mm_root=Solid((255, 225, 225, 255)),
513                        gm_root=Solid((255, 225, 225, 255)),
514                        )
515
516            args.update(params)
517            theme.roundrect(**args)
518
519        theme.roundrect_red = theme_roundrect_red
520
521