1from arcade.glui.dialog import Dialog
2from arcade.glui.gamecenterrunner import GameCenterRunner
3from arcade.glui.input import InputHandler
4from arcade.glui.menu import Menu
5from arcade.glui.opengl import gl, fs_emu_texturing, fs_emu_blending
6from arcade.glui.render import Render
7from arcade.glui.state import State
8from arcade.glui.texture import Texture
9from arcade.glui.topmenu import GameCenterItem
10from arcade.glui.window import set_current_menu, render_fade
11from arcade.glui.window import set_ingame_status, back_to_menu_from_game
12
13STATE_STARTING = 0
14STATE_PREPARING = 1
15STATE_WAITRUN = 2
16STATE_RUNNING = 3
17STATE_STOPPING = 4
18STATE_ABORTING = 5
19STATE_ABORTED = 6
20
21FADE_TIME = 0.5
22
23
24class LaunchMenu(Menu):
25    def __init__(self, item, controller):
26        Menu.__init__(self)
27        # self.top_menu_transition = 0.0
28        self.items.append(item)
29        if self.use_game_center_item():
30            self.top.left.append(GameCenterItem())
31        # self.top.left.append(HomeItem())
32        # self.top.left.append(MenuItem(item.title))
33        self.top.set_selected_index(
34            len(self.top.left) + len(self.top.right) - 1
35        )
36        self.state = STATE_STARTING
37        self.gc_runner = None
38        self.controller = controller
39        self.throbber = Throbber()
40        self.wait_run_time = 0
41
42    # noinspection PyMethodMayBeStatic
43    def on_status(self, status):
44        print("received status", status)
45
46    def update_state(self):
47        if self.state == STATE_STARTING:
48            self.gc_runner = GameCenterRunner(controller=self.controller)
49            # prepare will unpack the game and prepare game files
50            self.gc_runner.prepare()
51            self.state = STATE_PREPARING
52            self.throbber.throbber_start_time = 0
53
54        elif self.state == STATE_PREPARING:
55            if self.gc_runner.error:
56                pass
57            elif self.gc_runner.done:
58                self.wait_run_time = State.get().time
59                FadeDialog(self.wait_run_time).show()
60                self.state = STATE_WAITRUN
61
62        elif self.state == STATE_WAITRUN:
63            if State.get().time - self.wait_run_time > FADE_TIME:
64                set_ingame_status()
65                self.gc_runner.run()
66                self.state = STATE_RUNNING
67
68        elif self.state == STATE_RUNNING:
69            InputHandler.set_inhibited(True)
70            if self.gc_runner.error:
71                pass
72            elif self.gc_runner.done:
73                self.state = STATE_STOPPING
74
75        elif self.state == STATE_STOPPING:
76            InputHandler.set_inhibited(False)
77            State.get().history.pop()
78            State.get().history.pop()
79            State.get().history.pop()
80            set_current_menu(State.get().history[-1])
81            back_to_menu_from_game()
82            Dialog.get_current().close()
83
84            from arcade.glui.window import main_window
85
86            main_window.restore_window_if_necessary()
87
88        elif self.state == STATE_ABORTING:
89            pass
90
91    def go_back(self):
92        print("LaunchMenu.go_back")
93        if self.state in [STATE_STARTING, STATE_PREPARING]:
94            if self.gc_runner:
95                self.gc_runner.abort()
96                self.state = STATE_ABORTING
97        if self.state in [STATE_ABORTED]:
98            State.get().history.pop()
99            set_current_menu(State.get().history[-1])
100
101    def activate(self):
102        print("LaunchMenu.activate")
103
104    def update(self):
105        self.update_state()
106
107    def render(self):
108        Render.get().hd_perspective()
109        fs_emu_texturing(True)
110        fs_emu_blending(False)
111        Texture.sidebar_background.render(
112            0, 0, 1920, Texture.sidebar_background.h
113        )
114
115        if self.state in [STATE_PREPARING, STATE_WAITRUN]:
116            self.throbber.render()
117            # elif self.state in [STATE_RUNNING, STATE_STOPPING]:
118            #     pass
119            # gl.glDisable(gl.GL_DEPTH_TEST)
120            # render_fade(0.0, 0.0, 0.0, 1.0)
121            # gl.glEnable(gl.GL_DEPTH_TEST)
122
123
124class FadeDialog(Dialog):
125    def __init__(self, wait_run_time):
126        super().__init__()
127        self.wait_run_time = wait_run_time
128
129    def render(self):
130        gl.glDisable(gl.GL_DEPTH_TEST)
131        alpha = (State.get().time - self.wait_run_time) / FADE_TIME
132        render_fade(0.0, 0.0, 0.0, alpha)
133        gl.glEnable(gl.GL_DEPTH_TEST)
134
135
136class Throbber:
137    def __init__(self):
138        self.throbber_colors = [1.0, 0.8, 0.6, 0.2, 0.2, 0.2, 0.2, 0.2]
139        self.throbber_start_time = 0
140        self.throbber_progress = 0
141        self.throbber_opacity = 1.0
142        # self.start_time = 0
143
144    def render(self):
145        Render.get().hd_perspective()
146        if self.throbber_start_time == 0:
147            self.throbber_start_time = State.get().time
148        dt = State.get().time - self.throbber_start_time
149        # run animation with 15 fps
150        self.throbber_progress = int(dt * 15)
151
152        # bg_fade = (State.get().time - State.get().dialog_time) / 0.5
153        # if bg_fade > 1.0:
154        #     bg_fade = 1.0
155        # elif bg_fade < 0.0:
156        #     bg_fade = 0.0
157        fs_emu_texturing(False)
158        fs_emu_blending(True)
159        gl.glDisable(gl.GL_DEPTH_TEST)
160        gl.glDepthMask(False)
161
162        # gl.glBegin(gl.GL_QUADS)
163        # gl.glColor4f(0.0, 0.0, 0.0, bg_fade)
164        # gl.glVertex2f(0, 0)
165        # gl.glVertex2f(1920, 0)
166        # gl.glVertex2f(1920, 1020)
167        # gl.glVertex2f(0, 1020)
168        # gl.glEnd()
169
170        # gl.glBegin(gl.GL_QUADS)
171        # gl.glColor4f(0.0, 0.0, 0.0, bg_fade * 0.5)
172        # gl.glVertex2f(0, 1020)
173        # gl.glVertex2f(1920, 1020)
174        # gl.glVertex2f(1920, 1080)
175        # gl.glVertex2f(0, 1080)
176        # gl.glEnd()
177
178        # y = 0.0
179        # tw, th = Render.get().text("LAUNCHING GAME", self.title_font,
180        #         0.0, y, w=32 / 9, h=self.height,
181        #         color=(1.0, 1.0, 1.0, 1.0), halign=0.0)
182        #
183        fs_emu_blending(True)
184        # if bg_fade > 0.5:
185        #     self.throbber_opacity = (bg_fade - 0.5) / 0.5
186        #     #self.throbber_opacity = bg_fade
187        #     self.render_throbber()
188        # if bg_fade == 1.0:
189        # if State.get().time - State.get().dialog_time > 1.0:
190        #     # gradually show over 1/4 second
191        #     self.throbber_opacity = (
192        #         (State.get().time - State.get().dialog_time - 1.0) * 4)
193        #     if self.throbber_opacity > 1.0:
194        #         self.throbber_opacity = 1.0
195        #     self.render_throbber()
196        if State.get().time - self.throbber_start_time > 0.25:
197            # gradually show over 1/3 second
198            self.throbber_opacity = (
199                State.get().time - self.throbber_start_time - 0.25
200            ) * 4
201            if self.throbber_opacity > 1.0:
202                self.throbber_opacity = 1.0
203            self.render_throbber()
204
205        gl.glEnable(gl.GL_DEPTH_TEST)
206        gl.glDepthMask(True)
207        # fs_emu_texturing(1)
208        # fs_emu_blending(0)
209        # print("Setting dirty..")
210        Render.get().dirty = True
211
212    def render_throbber(self):
213        cell_width = 32
214        cell_spacing = 16
215        throbber_width = 3 * cell_width + 2 * cell_spacing
216        # throbber_height = throbber_width
217        left = (1920 - throbber_width) / 2
218        bottom = (1080 - throbber_width) / 2
219
220        self.render_cell(0, left, bottom)
221        self.render_cell(1, left + 1 * cell_width + 1 * cell_spacing, bottom)
222        self.render_cell(2, left + 2 * cell_width + 2 * cell_spacing, bottom)
223        self.render_cell(
224            3,
225            left + 2 * cell_width + 2 * cell_spacing,
226            bottom + 1 * cell_width + 1 * cell_spacing,
227        )
228        self.render_cell(
229            4,
230            left + 2 * cell_width + 2 * cell_spacing,
231            bottom + 2 * cell_width + 2 * cell_spacing,
232        )
233        self.render_cell(
234            5,
235            left + 1 * cell_width + 1 * cell_spacing,
236            bottom + 2 * cell_width + 2 * cell_spacing,
237        )
238        self.render_cell(6, left, bottom + 2 * cell_width + 2 * cell_spacing)
239        self.render_cell(7, left, bottom + 1 * cell_width + 1 * cell_spacing)
240
241    def render_cell(self, index, x, y):
242        color = self.throbber_colors[(self.throbber_progress + index) % 8]
243        color *= self.throbber_opacity
244        gl.glColor4f(color, color, color, self.throbber_opacity)
245        gl.glBegin(gl.GL_QUADS)
246        gl.glVertex2f(x, y)
247        gl.glVertex2f(x + 32, y)
248        gl.glVertex2f(x + 32, y + 32)
249        gl.glVertex2f(x, y + 32)
250        gl.glEnd()
251