def test_color_blend(self): color1 = RGBColor((128, 64, 0)) color2 = RGBColor((0, 32, 64)) color_blend = RGBColor.blend(color1, color2, 0.25) self.assertEqual((96, 56, 16), color_blend.rgb) color_blend = RGBColor.blend(color1, color2, 0.5) self.assertEqual((64, 48, 32), color_blend.rgb) color_blend = RGBColor.blend(color1, color2, 0.75) self.assertEqual((32, 40, 48), color_blend.rgb)
def _get_color_and_target_time(self, stack) -> Tuple[RGBColor, int, RGBColor, int]: try: color_settings = stack[0] except IndexError: # no stack return self._off_color, -1, self._off_color, -1 dest_color = color_settings.dest_color dest_time = color_settings.dest_time # no fade if not dest_time: # if we are transparent just return the lower layer if dest_color is None: return self._get_color_and_target_time(stack[1:]) return dest_color, -1, dest_color, -1 # fade out if dest_color is None: _, _, lower_dest_color, lower_dest_time = self._get_color_and_target_time(stack[1:]) start_time = color_settings.start_time if lower_dest_time < 0: # no fade going on below current layer dest_color = lower_dest_color elif start_time < lower_dest_time < dest_time: # fade below is shorter than fade out. removing the fade will trigger a new fade in this case ratio = (lower_dest_time - dest_time) / (dest_time - start_time) dest_color = RGBColor.blend(color_settings.start_color, dest_color, ratio) dest_time = lower_dest_time else: # upper fade is longer. use color target below. this might be slightly inaccurate dest_color = lower_dest_color # return destination color and time return color_settings.start_color, color_settings.start_time, dest_color, dest_time
def _get_color_and_fade(self, max_fade_ms: int) -> Tuple[RGBColor, int]: try: color_settings = self.stack[0] except IndexError: # no stack return RGBColor('off'), -1 # no fade if not color_settings['dest_time']: return color_settings['dest_color'], -1 current_time = self.machine.clock.get_time() # fade is done if current_time >= color_settings['dest_time']: return color_settings['dest_color'], -1 target_time = current_time + (max_fade_ms / 1000.0) # check if fade will be done before max_fade_ms if target_time > color_settings['dest_time']: return color_settings['dest_time'], int((color_settings['dest_time'] - current_time) / 1000) # figure out the ratio of how far along we are try: ratio = ((target_time - color_settings['start_time']) / (color_settings['dest_time'] - color_settings['start_time'])) except ZeroDivisionError: ratio = 1.0 return RGBColor.blend(color_settings['start_color'], color_settings['dest_color'], ratio), max_fade_ms
def _get_color_and_fade(self, stack, max_fade_ms: int, *, current_time=None) -> Tuple[RGBColor, int, bool]: try: color_settings = stack[0] except IndexError: # no stack return self._off_color, -1, True dest_color = color_settings.dest_color # no fade if not color_settings.dest_time: # if we are transparent just return the lower layer if dest_color is None: return self._get_color_and_fade(stack[1:], max_fade_ms) return dest_color, -1, True if current_time is None: current_time = self.machine.clock.get_time() # fade is done if current_time >= color_settings.dest_time: # if we are transparent just return the lower layer if dest_color is None: return self._get_color_and_fade(stack[1:], max_fade_ms) return color_settings.dest_color, -1, True if dest_color is None: dest_color, lower_fade_ms, _ = self._get_color_and_fade( stack[1:], max_fade_ms) if lower_fade_ms > 0: max_fade_ms = lower_fade_ms target_time = current_time + (max_fade_ms / 1000.0) # check if fade will be done before max_fade_ms if target_time > color_settings.dest_time: return dest_color, int( (color_settings.dest_time - current_time) * 1000), True # check if we are calculating before the start_time if target_time <= color_settings.start_time: return color_settings.start_color, max_fade_ms, False # figure out the ratio of how far along we are try: ratio = ((target_time - color_settings.start_time) / (color_settings.dest_time - color_settings.start_time)) except ZeroDivisionError: ratio = 1.0 return RGBColor.blend(color_settings.start_color, dest_color, ratio), max_fade_ms, False
def _get_color_and_fade(self, stack, max_fade_ms: int) -> Tuple[RGBColor, int]: try: color_settings = stack[0] except IndexError: # no stack return RGBColor('off'), -1 dest_color = color_settings['dest_color'] # no fade if not color_settings['dest_time']: # if we are transparent just return the lower layer if dest_color is None: return self._get_color_and_fade(stack[1:], max_fade_ms) return dest_color, -1 current_time = self.machine.clock.get_time() # fade is done if current_time >= color_settings['dest_time']: # if we are transparent just return the lower layer if dest_color is None: return self._get_color_and_fade(stack[1:], max_fade_ms) return color_settings['dest_color'], -1 if dest_color is None: dest_color, lower_fade_ms = self._get_color_and_fade( stack[1:], max_fade_ms) if lower_fade_ms > 0: max_fade_ms = min(lower_fade_ms, max_fade_ms) target_time = current_time + (max_fade_ms / 1000.0) # check if fade will be done before max_fade_ms if target_time > color_settings['dest_time']: return dest_color, int( (color_settings['dest_time'] - current_time) * 1000) # figure out the ratio of how far along we are try: ratio = ( (target_time - color_settings['start_time']) / (color_settings['dest_time'] - color_settings['start_time'])) except ZeroDivisionError: ratio = 1.0 return RGBColor.blend(color_settings['start_color'], dest_color, ratio), max_fade_ms
def fade_task(self, dt): """Perform a fade depending on the current time. Args: dt: time since last call """ del dt try: color_settings = self.stack[0] except IndexError: self._stop_fade_task() return # todo if not color_settings['dest_time']: return # figure out the ratio of how far along we are try: ratio = ( (self.machine.clock.get_time() - color_settings['start_time']) / (color_settings['dest_time'] - color_settings['start_time'])) except ZeroDivisionError: ratio = 1.0 if self.debug: self.log.debug("Fade task, ratio: %s", ratio) if ratio >= 1.0: # fade is done self._end_fade() color_settings['color'] = color_settings['dest_color'] else: color_settings['color'] = (RGBColor.blend( color_settings['start_color'], color_settings['dest_color'], ratio)) Led.leds_to_update.add(self)