diff --git a/displayio_effects/__init__.py b/displayio_effects/__init__.py index e69de29..021b2bf 100644 --- a/displayio_effects/__init__.py +++ b/displayio_effects/__init__.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2022 Alec Delaney for CircuitPython Organization +# +# SPDX-License-Identifier: MIT +# pylint: disable=protected-access +""" +`displayio_effects` +================================================================================ + +Add the some flair to your widgets! + + +* Author(s): Alec Delaney + +Implementation Notes +-------------------- + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://circuitpython.org/downloads +""" + + +WIDGET_TYPE_ATTR = "_widget_type" + +# pylint: disable=too-few-public-methods +class WidgetType: + """Enum values for customizable widget types. Valid options are: + + - ``WidgetType.DIAL`` - Dial widget + - ``WidgetType.GAUGE`` - Gauge widget + """ + + DIAL = 0 + GAUGE = 1 diff --git a/displayio_effects/colorwheel_effect.py b/displayio_effects/colorwheel_effect.py new file mode 100644 index 0000000..eb64bf4 --- /dev/null +++ b/displayio_effects/colorwheel_effect.py @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2022 Alec Delaney for CircuitPython Organization +# +# SPDX-License-Identifier: MIT +# pylint: disable=protected-access +""" +`displayio_effects.fluctuation_effect` +================================================================================ + +Add the colorwheel effect to your widgets + + +* Author(s): Alec Delaney + +Implementation Notes +-------------------- + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://circuitpython.org/downloads +""" + +from rainbowio import colorwheel +from adafruit_itertools.adafruit_itertools import cycle +from displayio_effects import WidgetType, WIDGET_TYPE_ATTR + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/tekktrik/CircuitPython_Org_DisplayIO_Effects.git" + + +COLORWHEEL_WIDGET_VALUES = { + WidgetType.DIAL: { + "path": ["_needle", "pixel_shader"], + "index": 0, + }, + WidgetType.GAUGE: { + "path": ["_palette"], + "index": 2, + }, +} + +COLORWHEEL_COLORS = cycle([colorwheel(color_value) for color_value in range(256)]) + + +def _get_widget_value(instance): + widget_type = getattr(instance, WIDGET_TYPE_ATTR) + return COLORWHEEL_WIDGET_VALUES[widget_type] + + +def hook_colorwheel_effect(widget_class, widget_type): + """Adds the colorwheel effect for the given class + + :param widget_class: The widget class that should have this effect hooked + into it + :param int widget_type: The enum value of this widget type, must be a + valid ~WidgetType + + For example, to hook this into the ``Dial`` widget, you would use the + following code: + + .. code-block:: python + + from displayio_dial import Dial + from displayio_effects import WidgetType, colorwheel_effect + + fluctuation_effect.hook_colorwheel_effect(Dial, WidgetType.DIAL) + + """ + + if not COLORWHEEL_WIDGET_VALUES.get(widget_type): + raise ValueError( + "The given widget does not have the ability to use this effect" + ) + + setattr(widget_class, WIDGET_TYPE_ATTR, widget_type) + + setattr(widget_class, "update_colorwheel", update_colorwheel) + + +def update_colorwheel(self): + """Updates the widget value and propagates the fluctuation effect refresh""" + + palette_map = _get_widget_value(self) + palette_attr = self + for attr_path in palette_map["path"]: + palette_attr = getattr(palette_attr, attr_path) + palette_attr[palette_map["index"]] = next(COLORWHEEL_COLORS) diff --git a/displayio_effects/fluctuation_effect.py b/displayio_effects/fluctuation_effect.py index 2312657..fef7a8c 100644 --- a/displayio_effects/fluctuation_effect.py +++ b/displayio_effects/fluctuation_effect.py @@ -22,11 +22,23 @@ """ import random +from displayio_effects import WidgetType, WIDGET_TYPE_ATTR __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/tekktrik/CircuitPython_Org_DisplayIO_Effects.git" +FLUCTUATION_WIDGET_VALUES = { + WidgetType.DIAL: "value", + WidgetType.GAUGE: "level", +} + + +def _get_value_name(instance): + widget_type = getattr(instance, WIDGET_TYPE_ATTR) + return FLUCTUATION_WIDGET_VALUES[widget_type] + + @property def fluctuation_amplitude(self): """The furtherest the fluctuation effect can randomly set the widget value relative @@ -37,10 +49,11 @@ def fluctuation_amplitude(self): @fluctuation_amplitude.setter def fluctuation_amplitude(self, amplitude): + value_name = _get_value_name(self) if amplitude < 0: raise ValueError("Fluctuation effect setting must be larger than 0") if amplitude: - self._fluctuation_hold_value = getattr(self, self._value_name) + self._fluctuation_hold_value = getattr(self, value_name) self._fluctuation_amplitude = amplitude @@ -60,6 +73,8 @@ def fluctuation_move_rate(self, rate): def update_fluctuation(self): """Updates the widget value and propagates the fluctuation effect refresh""" + value_name = _get_value_name(self) + if self._fluctuation_amplitude == 0: self._fluctuation_destination = None return @@ -71,13 +86,13 @@ def update_fluctuation(self): + self._fluctuation_hold_value ) - value = getattr(self, self._value_name) + value = getattr(self, value_name) value = ( value + self._fluctuation_move_rate if self._fluctuation_destination > value else value - self._fluctuation_move_rate ) - setattr(self, self._value_name, value) + setattr(self, value_name, value) threshold_check = ( value >= self._fluctuation_destination @@ -88,13 +103,13 @@ def update_fluctuation(self): self._fluctuation_destination = self._fluctuation_hold_value -def hook_fluctuation_effect(widget_class, value_name): +def hook_fluctuation_effect(widget_class, widget_type): """Adds the fluctuation effect for the given class - :param widget_classes: The widgets that should have this effect hooked - into them. - :param str value_name: The name of the attribute that sets the "value" - for this widget + :param widget_class: The widget class that should have this effect hooked + into it + :param int widget_type: The enum value of this widget type, must be a + valid ~WidgetType For example, to hook this into the ``Dial`` widget, you would use the following code: @@ -102,13 +117,18 @@ def hook_fluctuation_effect(widget_class, value_name): .. code-block:: python from displayio_dial import Dial - from displayio_effects import fluctuation_effect + from displayio_effects import WidgetType, fluctuation_effect - fluctuation_effect.hook_fluctuation_effect(Dial, "value") + fluctuation_effect.hook_fluctuation_effect(Dial, WidgetType.DIAL) """ - setattr(widget_class, "_value_name", value_name) + if not FLUCTUATION_WIDGET_VALUES.get(widget_type): + raise ValueError( + "The given widget does not have the ability to use this effect" + ) + + setattr(widget_class, WIDGET_TYPE_ATTR, widget_type) setattr(widget_class, "_fluctuation_destination", None) setattr(widget_class, "_fluctuation_hold_value", 0) @@ -116,6 +136,6 @@ def hook_fluctuation_effect(widget_class, value_name): setattr(widget_class, "fluctuation_amplitude", fluctuation_amplitude) setattr(widget_class, "_fluctuation_amplitude", 0) setattr(widget_class, "fluctuation_move_rate", fluctuation_move_rate) - setattr(widget_class, "_fluctuation_move_rate", 0.1) + setattr(widget_class, "_fluctuation_move_rate", 0.01) setattr(widget_class, "update_fluctuation", update_fluctuation) diff --git a/examples/displayio_effects_colorwheel.py b/examples/displayio_effects_colorwheel.py new file mode 100644 index 0000000..d772726 --- /dev/null +++ b/examples/displayio_effects_colorwheel.py @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2021 GaryZ, Alec Delaney +# SPDX-FileCopyrightText: Copyright (c) 2022 Alec Delaney for CircuitPython Organization +# +# SPDX-License-Identifier: Unlicense +############################# +""" +Use the random fluctuation effect for the Dial. +""" + +import time +import board +import displayio +import terminalio +from displayio_dial import Dial +from displayio_effects import WidgetType, colorwheel_effect + +# Fonts used for the Dial tick labels +tick_font = terminalio.FONT + +display = board.DISPLAY # create the display on the PyPortal or Clue (for example) +# otherwise change this to setup the display +# for display chip driver and pinout you have (e.g. ILI9341) + + +# Define the minimum and maximum values for the dial +minimum_value = 0 +maximum_value = 100 + +# Hook in the throttle effect for the Dial widget +colorwheel_effect.hook_colorwheel_effect(Dial, WidgetType.DIAL) + +# Create a Dial widget +my_dial = Dial( + x=20, # set x-position of the dial inside of my_group + y=20, # set y-position of the dial inside of my_group + width=180, # requested width of the dial + height=180, # requested height of the dial + padding=25, # add 25 pixels around the dial to make room for labels + start_angle=-120, # left angle position at -120 degrees + sweep_angle=240, # total sweep angle of 240 degrees + min_value=minimum_value, # set the minimum value shown on the dial + max_value=maximum_value, # set the maximum value shown on the dial + tick_label_font=tick_font, # the font used for the tick labels + tick_label_scale=2.0, # the scale factor for the tick label font +) + +my_group = displayio.Group() +my_group.append(my_dial) + +display.show(my_group) # add high level Group to the display + +# Set the dial to the value before turning on the fluctuation effect +my_dial.value = 50 + +while True: + + my_dial.update_colorwheel() + time.sleep(0.01) diff --git a/examples/displayio_effects_gauge.py b/examples/displayio_effects_gauge.py index 976ce43..122481c 100644 --- a/examples/displayio_effects_gauge.py +++ b/examples/displayio_effects_gauge.py @@ -3,8 +3,7 @@ # SPDX-License-Identifier: Unlicense """ -Create multiple gauge's and change their level. -This works on any CircuitPython device with a built-in display. +Use the random fluctuation effect for the Gauge. """ @@ -12,7 +11,7 @@ import board import displayio from displayio_gauge import Gauge -from displayio_effects import fluctuation_effect +from displayio_effects import WidgetType, fluctuation_effect display = board.DISPLAY @@ -27,7 +26,7 @@ main_group.append(bg_sprite) display.show(main_group) -fluctuation_effect.hook_fluctuation_effect(Gauge, "level") +fluctuation_effect.hook_fluctuation_effect(Gauge, WidgetType.GAUGE) my_gauge = Gauge( x=90, diff --git a/examples/displayio_effects_simpletest.py b/examples/displayio_effects_simpletest.py index f597a1e..ea7dfda 100644 --- a/examples/displayio_effects_simpletest.py +++ b/examples/displayio_effects_simpletest.py @@ -11,7 +11,7 @@ import displayio import terminalio from displayio_dial import Dial -from displayio_effects import fluctuation_effect +from displayio_effects import WidgetType, fluctuation_effect # Fonts used for the Dial tick labels tick_font = terminalio.FONT @@ -26,7 +26,7 @@ maximum_value = 100 # Hook in the throttle effect for the Dial widget -fluctuation_effect.hook_fluctuation_effect(Dial, "value") +fluctuation_effect.hook_fluctuation_effect(Dial, WidgetType.DIAL) # Create a Dial widget my_dial = Dial(