from PIL import Image class ProotState: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance.current_blink_state = 0 cls._instance.desired_blink_state = 0 cls._instance.blinks_frames_ready = False cls._instance.loading_screen = True cls._instance.loading_time = 0 cls._instance.frame_canvas_prootScreen_1 = False cls._instance.frame_canvas_prootScreen_2 = False cls._instance.frame_canvas_prootScreen_3 = False cls._instance.matrix = False cls._instance.bean_states = [False] * 4 cls._instance.desired_face = 0 # 0=default, 1=blink, 2=owo, 3=angry return cls._instance def set_matrix(self, matrix): self.matrix = matrix def next_blink_frame_number(self) -> int: if self.current_blink_state == self.desired_blink_state == 10: self.desired_blink_state = 0 return self.current_blink_state if self.current_blink_state == self.desired_blink_state == 0: return self.current_blink_state if self.current_blink_state < self.desired_blink_state: self.current_blink_state += 1 else: self.current_blink_state -= 1 return self.current_blink_state def blink(self, state = 10): self.set_desired_blink_state(state) def set_desired_blink_state(self, state: int): self.desired_blink_state = state def set_blinks_frames_ready(self, ready: bool): self.blinks_frames_ready = ready def get_desired_blink_state(self) -> int: return self.desired_blink_state def get_blinks_frames_ready(self) -> bool: return self.blinks_frames_ready # This function animates the loading screen. It asumes that the function gets called frequently(every frame update) def set_ProotScreen(self, matrix): self.loading_time += 1 self.loading_time = self.loading_time % 75 if not self.frame_canvas_prootScreen_1: self.frame_canvas_prootScreen_1 = matrix.CreateFrameCanvas() image_proot_screen_1 = Image.open("faces/ProotScreen1.png").convert('RGB') self.frame_canvas_prootScreen_1.SetImage(image_proot_screen_1, unsafe=False) matrix.SwapOnVSync(self.frame_canvas_prootScreen_1) if not self.frame_canvas_prootScreen_2: self.frame_canvas_prootScreen_2 = matrix.CreateFrameCanvas() image_proot_screen_2 = Image.open("faces/ProotScreen2.png").convert('RGB') self.frame_canvas_prootScreen_2.SetImage(image_proot_screen_2, unsafe=False) matrix.SwapOnVSync(self.frame_canvas_prootScreen_2) if not self.frame_canvas_prootScreen_3: self.frame_canvas_prootScreen_3 = matrix.CreateFrameCanvas() image_proot_screen_3 = Image.open("faces/ProotScreen3.png").convert('RGB') self.frame_canvas_prootScreen_3.SetImage(image_proot_screen_3, unsafe=False) matrix.SwapOnVSync(self.frame_canvas_prootScreen_3) if self.loading_time < 25: matrix.SwapOnVSync(self.frame_canvas_prootScreen_1) elif self.loading_time < 50: matrix.SwapOnVSync(self.frame_canvas_prootScreen_2) else: matrix.SwapOnVSync(self.frame_canvas_prootScreen_3) def set_bean(self, bean_number, bean_state): self.bean_states[bean_number] = bean_state def update_screen(self, blinkFrameCanvases, matrix): proot_state = ProotState() if proot_state.get_blinks_frames_ready(): # TODO move blinking animation writing logic to the ProotState class matrix.SwapOnVSync(blinkFrameCanvases[proot_state.next_blink_frame_number()]) else: proot_state.set_ProotScreen(matrix)