Skip to content
Merged
36 changes: 36 additions & 0 deletions displayio_effects/__init__.py
Original file line number Diff line number Diff line change
@@ -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
88 changes: 88 additions & 0 deletions displayio_effects/colorwheel_effect.py
Original file line number Diff line number Diff line change
@@ -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)
44 changes: 32 additions & 12 deletions displayio_effects/fluctuation_effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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


Expand All @@ -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
Expand All @@ -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
Expand All @@ -88,34 +103,39 @@ 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:

.. 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)

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)
58 changes: 58 additions & 0 deletions examples/displayio_effects_colorwheel.py
Original file line number Diff line number Diff line change
@@ -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)
7 changes: 3 additions & 4 deletions examples/displayio_effects_gauge.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
# 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.
"""


import time
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

Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions examples/displayio_effects_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand Down