Skip to content

Add colorwheel effect, refactor library #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 27, 2022
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