-
Notifications
You must be signed in to change notification settings - Fork 0
/
selection_menu.rpy
125 lines (108 loc) · 5.56 KB
/
selection_menu.rpy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
init -1700 python in _editor:
from pygame import MOUSEBUTTONDOWN
from time import time
class SelectionMenu(renpy.Displayable):
# https://renpy.org/doc/html/cdd.html
# https://lemmasoft.renai.us/forums/viewtopic.php?p=374053#p374053
#https://lemmasoft.renai.us/forums/viewtopic.php?t=11910
required_init_args = {'x', 'y', 'cw', 'ch', 'font', 'choices', 'handler', 'layer'}
def __init__(self, id="", base_menu=None, options=None, **kwargs):
for arg in self.required_init_args:
setattr(self, arg, kwargs[arg])
del kwargs[arg]
super(SelectionMenu, self).__init__(**kwargs)
self.__dict__.update({"id": id, "base_menu": base_menu, "options": options if options else {}})
wordlen_max = max(map(lambda x: len(str(x["name"] if isinstance(x, (dict, renpy.python.RevertableDict)) else x)) + 1, self.choices))
self.area = (self.x, self.y, int(wordlen_max * self.cw), int(len(self.choices) * self.ch))
self.nested_menu = []
self.focus(keep=True)
if renpy.get_screen("_editor_menu", layer=self.layer):
renpy.end_interaction("")
if base_menu:
# XXX: for some reason not shown for overlay layer.
renpy.show_screen("_editor_menu", self, _layer=self.layer)
else:
renpy.invoke_in_new_context(renpy.call_screen, "_editor_menu", self, _layer=self.layer)
def focus(self, keep=False):
if 'timeout' in self.options and keep is False:
self.timeout = self.options['timeout'][0]
self.polling = self.options['timeout'][1]
self.last_focus = time()
else:
self.timeout = 0.0
if self.base_menu:
self.base_menu.focus(keep)
def event(self, ev, x, y, st):
if ev.type == MOUSEBUTTONDOWN:# and self.timeout != 0.0:
renpy.end_interaction("")
def end(self, pick):
if pick != "" or self.timeout != 0.0:
if self.base_menu:
renpy.hide_screen("_editor_menu", layer=self.layer)
self.base_menu.nested_menu.remove(self)
if isinstance(pick, (list, renpy.python.RevertableList)):
pick.insert(0, self.id)
self.base_menu.end(pick)
else:
self.base_menu.end("" if pick == "" else [self.id, pick])
else:
renpy.end_interaction(self.handler(pick))
def act(self, pick=None, hovered=None):
"""selection, (un)hover event or timeout"""
if pick != None:
self.timeout = 0.0
for nested in self.nested_menu:
nested.end("")
index, pick = pick
if not isinstance(pick, (dict, renpy.python.RevertableDict)):
self.end(pick)
elif 'submenu' in pick:
kwargs = dict((k, getattr(self, k)) for k in self.required_init_args)
# TODO/FIXME 1. could implement stacking as cards for menus
# TODO/FIXME 2. choose other side if there's no space right of the menu
kwargs['layer'] = config.layers[config.layers.index(self.layer)+1]
# if this errors, you're using too many side menus. use a
# different solution instead.
if renpy.get_screen("_editor_menu", layer=kwargs['layer']):
renpy.hide_screen("_editor_menu", layer=kwargs['layer'])
kwargs['choices'] = pick["submenu"]
kwargs['id'] = pick['name']
kwargs['y'] = int(kwargs['y'] + index * self.ch)
kwargs['x'] = int(kwargs['x'] + self.area[2])
self.nested_menu.append(SelectionMenu(base_menu=self, **kwargs))
elif hovered is True:
self.focus(keep=True)
elif hovered is False:
self.focus()
elif self.timeout != 0.0 and time() - self.last_focus > self.timeout:
self.end("")
def render(self, width, height, st, at):
R = renpy.Render(width, height)
renpy.redraw(self, 1)
return R
def visit(self):
return self.nested_menu
screen _editor_menu(selection):
# TODO 2: vertical scroll bar with buttons if too many options
# TODO 3: do not always close for certain events
# TODO 4: move menu when scrolling up/down
if selection.timeout != 0.0:
timer selection.polling action Function(selection.act) repeat True
frame:
padding (0, 0)
background "#111a"
area selection.area
add selection
vbox:
for (index, pick) in enumerate(selection.choices):
textbutton (pick["name"] if isinstance(pick, (dict, renpy.python.RevertableDict)) else str(pick)):
padding (0, 0)
minimum (0, 0)
text_font selection.font.get_file()
text_size selection.font.size
text_color "#fff"
text_hover_color "ff2"
hovered Function(selection.act, hovered=True)
unhovered Function(selection.act, hovered=False)
action Function(selection.act, pick=(index, pick))
key "K_ESCAPE" action Function("renpy.hide_screen", "_editor_menu", layer=selection.layer)