Example #1
0
    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)
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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)