Skip to content
Snippets Groups Projects
Commit 2ce5451a authored by Anon's avatar Anon Committed by iggy
Browse files

py: run Black

parent c0b3cb04
No related branches found
No related tags found
No related merge requests found
Showing
with 1047 additions and 824 deletions
......@@ -7,25 +7,36 @@ from st3m import utils
ctx = hardware.get_ctx()
def init():
pass
def run():
ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
time.sleep_ms(30)
for i in range(10):
size = (hardware.get_captouch(i) * 4) + 4
size += int(max(0, sum([hardware.captouch_get_petal_pad(i, x) for x in range(0, 3+1)]) / 8000))
x = 70 + (hardware.captouch_get_petal_rad(i)/1000)
x += (hardware.captouch_get_petal_phi(i)/600)*1j
size += int(
max(
0,
sum([hardware.captouch_get_petal_pad(i, x) for x in range(0, 3 + 1)])
/ 8000,
)
)
x = 70 + (hardware.captouch_get_petal_rad(i) / 1000)
x += (hardware.captouch_get_petal_phi(i) / 600) * 1j
rot = cmath.exp(2j * math.pi * i / 10)
x = x * rot
col = (1.0, 0.0, 1.0)
if i%2:
if i % 2:
col = (0.0, 1.0, 1.0)
ctx.rgb(*col).rectangle(-int(x.imag-(size/2)), -int(x.real-(size/2)), size, size).fill()
ctx.rgb(*col).rectangle(
-int(x.imag - (size / 2)), -int(x.real - (size / 2)), size, size
).fill()
hardware.display_update()
def foreground():
pass
......
from st3m.application import Application
import ui
class MandelbrotApp(Application):
def on_init(self):
pass
......@@ -9,23 +10,25 @@ class MandelbrotApp(Application):
print("on foreground")
ctx = self.ui.ctx
#center the text horizontally and vertically
# center the text horizontally and vertically
ctx.text_align = ctx.CENTER
ctx.text_baseline = ctx.MIDDLE
#ctx.rgb() expects individual values for the channels, so unpack a list/tuple with *
#operations on ctx can be chained
#create a blue background
ctx.rgb(*ui.RED).rectangle(-ui.WIDTH/2,-ui.HEIGHT/2,ui.WIDTH,ui.HEIGHT).fill()
# ctx.rgb() expects individual values for the channels, so unpack a list/tuple with *
# operations on ctx can be chained
# create a blue background
ctx.rgb(*ui.RED).rectangle(
-ui.WIDTH / 2, -ui.HEIGHT / 2, ui.WIDTH, ui.HEIGHT
).fill()
#Write some text
ctx.move_to(0,0).rgb(*ui.WHITE).text("Mandelbrot")
# Write some text
ctx.move_to(0, 0).rgb(*ui.WHITE).text("Mandelbrot")
def main_forground():
for x in range(-240,240):
for y in range(-240,240):
for x in range(-240, 240):
for y in range(-240, 240):
pass
app=MandelbrotApp("Mandelbrot")
app.run()
\ No newline at end of file
app = MandelbrotApp("Mandelbrot")
app.run()
#python
# python
import math
#badge23
from st3m import event,application,ui
from st3m.system import hardware,audio
# badge23
from st3m import event, application, ui
from st3m.system import hardware, audio
from synth import tinysynth
popcorn = [9,7,9,5,0,5,-3,999]
popcorn = [9, 7, 9, 5, 0, 5, -3, 999]
def on_step(data):
ctx = app.ui.ctx
......@@ -15,41 +16,39 @@ def on_step(data):
if note != 999:
synth.tone(note)
synth.start()
if not app.is_foreground(): return
if not app.is_foreground():
return
ctx.text_align = ctx.CENTER
ctx.text_baseline = ctx.MIDDLE
ctx.rgb(1,1,0).rectangle(-120,-120,240,240).fill()
(x,y) = ui.xy_from_polar(90,-2*math.pi/8*data["step"]+math.pi)
size=180
ctx.rgb(0.8,0.8,0)
ctx.round_rectangle(
x-size/2,
y-size/2,
size,size,size//2
).fill()
ctx.move_to(x,y).rgb(0.5,0.5,0).text("{}".format(data["step"]))
ctx.rgb(1, 1, 0).rectangle(-120, -120, 240, 240).fill()
(x, y) = ui.xy_from_polar(90, -2 * math.pi / 8 * data["step"] + math.pi)
size = 180
ctx.rgb(0.8, 0.8, 0)
ctx.round_rectangle(x - size / 2, y - size / 2, size, size, size // 2).fill()
ctx.move_to(x, y).rgb(0.5, 0.5, 0).text("{}".format(data["step"]))
class AppSparabo(application.Application):
def on_init(self):
audio.set_volume_dB(0)
self.synth = tinysynth(440,1)
self.synth = tinysynth(440, 1)
self.synth.decay(25)
print ("here")
print("here")
self.sequencer = event.Sequence(bpm=160, steps=8, action=on_step, loop=True)
self.sequencer.start()
if self.sequencer.repeat_event:
self.add_event(self.sequencer.repeat_event)
def on_foreground(self):
self.sequencer.start()
def on_exit(self):
self.sequencer.stop()
app = AppSparabo("sequencer")
#python imports
# python imports
import random
import time
import math
#flow3r imports
from st3m import event,application,ui
# flow3r imports
from st3m import event, application, ui
# Subclass Application
class AppWorms(application.Application):
def on_init(self):
print("on init")
......@@ -19,32 +19,37 @@ class AppWorms(application.Application):
self.frame_slack = None
self.last_report = None
self.add_event(event.Event(
name="worms_control",
action=self.handle_input,
condition=lambda data: data.get("type","")=="captouch" and data.get("value")==1 and data["change"],
self.add_event(
event.Event(
name="worms_control",
action=self.handle_input,
condition=lambda data: data.get("type", "") == "captouch"
and data.get("value") == 1
and data["change"],
)
)
self.worms = []
for i in range(0):
self.worms.append(Worm())
def on_foreground(self):
print("on foreground")
ctx = app.ui.ctx
#center the text horizontally and vertically
# center the text horizontally and vertically
ctx.text_align = ctx.CENTER
ctx.text_baseline = ctx.MIDDLE
#ctx.rgb() expects individual values for the channels, so unpack a list/tuple with *
#operations on ctx can be chained
#create a blue background
ctx.rgb(*ui.BLUE).rectangle(-ui.WIDTH/2,-ui.HEIGHT/2,ui.WIDTH,ui.HEIGHT).fill()
# ctx.rgb() expects individual values for the channels, so unpack a list/tuple with *
# operations on ctx can be chained
# create a blue background
ctx.rgb(*ui.BLUE).rectangle(
-ui.WIDTH / 2, -ui.HEIGHT / 2, ui.WIDTH, ui.HEIGHT
).fill()
#Write some text
ctx.move_to(0,0).rgb(*ui.WHITE).text("touch me :)")
# Write some text
ctx.move_to(0, 0).rgb(*ui.WHITE).text("touch me :)")
def on_draw(self):
for w in self.worms:
......@@ -61,85 +66,88 @@ class AppWorms(application.Application):
return
if self.last_report is None or (now - self.last_report) > 1000:
fps = 1000/delta
print(f'fps: {fps:.3}, frame budget slack: {self.frame_slack:.3}ms')
fps = 1000 / delta
print(f"fps: {fps:.3}, frame budget slack: {self.frame_slack:.3}ms")
self.last_report = now
# Simulation is currently locked to FPS.
for w in self.worms:
w.move()
self.last_render = now
def handle_input(self,data):
def handle_input(self, data):
worms = self.worms
worms.append(Worm(data.get("index",0)*2*math.pi/10+math.pi ))
if len(worms)>10:
worms.append(Worm(data.get("index", 0) * 2 * math.pi / 10 + math.pi))
if len(worms) > 10:
worms.pop(0)
class Worm():
def __init__(self,direction=None):
class Worm:
def __init__(self, direction=None):
self.color = ui.randrgb()
if direction:
self.direction = direction
else:
self.direction = random.random()*math.pi*2
self.direction = random.random() * math.pi * 2
self.size = 50
self.speed = self.size/5
(x,y) = ui.xy_from_polar(100, self.direction)
self.speed = self.size / 5
(x, y) = ui.xy_from_polar(100, self.direction)
self.x = x
self.y= y
#(self.dx,self.dy) = xy_from_polar(1,self.direction)
self.y = y
# (self.dx,self.dy) = xy_from_polar(1,self.direction)
self._lastdist = 0.0
def draw(self):
app.ui.ctx.rgb(*self.color)
app.ui.ctx.round_rectangle(
self.x-self.size/2,
self.y-self.size/2,
self.size,self.size,self.size//2
self.x - self.size / 2,
self.y - self.size / 2,
self.size,
self.size,
self.size // 2,
).fill()
def mutate(self):
self.color = ([max(0,min(1,x+((random.random()-0.5)*0.3))) for x in self.color])
self.color = [
max(0, min(1, x + ((random.random() - 0.5) * 0.3))) for x in self.color
]
def move(self):
dist = math.sqrt(self.x**2+self.y**2)
target_size = (130-dist)/3
if self.size>target_size: self.size-=1
if self.size<target_size: self.size+=1
self.speed = self.size/5
self.direction += (random.random()-0.5)*math.pi/4
(dx,dy) = ui.xy_from_polar(self.speed,self.direction)
self.x+=dx
self.y+=dy
if dist>120-self.size/2 and dist>self._lastdist:
polar_position=math.atan2(self.y,self.x)
dx=dx*-abs(math.cos(polar_position))
dy=dy*-abs(math.sin(polar_position))
self.direction=-math.atan2(dy,dx)
dist = math.sqrt(self.x**2 + self.y**2)
target_size = (130 - dist) / 3
if self.size > target_size:
self.size -= 1
if self.size < target_size:
self.size += 1
self.speed = self.size / 5
self.direction += (random.random() - 0.5) * math.pi / 4
(dx, dy) = ui.xy_from_polar(self.speed, self.direction)
self.x += dx
self.y += dy
if dist > 120 - self.size / 2 and dist > self._lastdist:
polar_position = math.atan2(self.y, self.x)
dx = dx * -abs(math.cos(polar_position))
dy = dy * -abs(math.sin(polar_position))
self.direction = -math.atan2(dy, dx)
self.mutate()
self._lastdist = dist
app = AppWorms("worms")
# To run standalone:
#app.run()
#app.engine.eventloop()
# app.run()
# app.engine.eventloop()
#Known problems:
#ctx.rotate(math.pi) turns the display black until powercycled
#ctx.clip() causes crashes
\ No newline at end of file
# Known problems:
# ctx.rotate(math.pi) turns the display black until powercycled
# ctx.clip() causes crashes
from st3m import logging
log = logging.Log(__name__,level=logging.INFO)
log = logging.Log(__name__, level=logging.INFO)
log.info(f"running {__name__}")
from st3m.application import Application
log.info(f"import app")
from . import menu_main
log.info(f"import menu")
class myApp(Application):
def on_init(self):
self.menu = menu_main.get_menu()
......@@ -13,4 +17,5 @@ class myApp(Application):
def on_foreground(self):
self.menu.start()
app=myApp("flow3r", exit_on_menu_enter=False)
app = myApp("flow3r", exit_on_menu_enter=False)
from synth import tinysynth
from st3m import menu,event,control,ui
from st3m.system import hardware,audio
from st3m import menu, event, control, ui
from st3m.system import hardware, audio
synths = [tinysynth(440, 0), tinysynth(440, 0), tinysynth(440, 0)]
# synth = tinysynth(440,0)
synths = [tinysynth(440,0),tinysynth(440,0),tinysynth(440,0)]
#synth = tinysynth(440,0)
def set_play(value):
print ("set_controls_overlay")
print("set_controls_overlay")
if value:
for synth in synths: synth.start()
for synth in synths:
synth.start()
else:
for synth in synths: synth.stop()
for synth in synths:
synth.stop()
the_freq = 440
def set_frequency(value):
global the_freq
the_freq = value
for synth in synths:
synth.freq(the_freq)
def set_pitch0(value):
synths[0].freq(the_freq+the_freq*value)
synths[0].freq(the_freq + the_freq * value)
def set_pitch1(value):
synths[1].freq(the_freq+the_freq*value)
synths[1].freq(the_freq + the_freq * value)
def set_pitch2(value):
synths[2].freq(the_freq+the_freq*value)
synths[2].freq(the_freq + the_freq * value)
def get_menu():
m = menu.Menu("crazysynth")
freq=control.ControlKnob(
freq = control.ControlKnob(
name="freq",
on_set=set_frequency,
default=the_freq,
min=220,max=440*4,step=10
min=220,
max=440 * 4,
step=10,
)
# m.add_petal(menu.MenuItemControl("freq",freq), petal_index=7)
m.add(menu.MenuItemControl("freq", freq))
m.add(
menu.MenuItemControl(
"mute",
control.ControlSwitch(
name="mute", on_set=audio.set_mute, on_get=audio.get_mute
),
)
)
#m.add_petal(menu.MenuItemControl("freq",freq), petal_index=7)
m.add(menu.MenuItemControl("freq",freq))
m.add(menu.MenuItemControl("mute",control.ControlSwitch(
name="mute",
on_set=audio.set_mute,
on_get=audio.get_mute
)))
pitch0 = control.ControlSlide(
name="pitch",
on_set=set_pitch0,
default=0,
min=-0.5,max=0.5
name="pitch", on_set=set_pitch0, default=0, min=-0.5, max=0.5
)
m.add_petal(menu.MenuItemControl("pitch0",pitch0), petal_index=3)
m.add_petal(menu.MenuItemControl("pitch0", pitch0), petal_index=3)
pitch1 = control.ControlSlide(
name="pitch",
on_set=set_pitch1,
default=0,
min=-0.5,max=0.5
name="pitch", on_set=set_pitch1, default=0, min=-0.5, max=0.5
)
m.add_petal(menu.MenuItemControl("pitch1",pitch1), petal_index=5)
m.add_petal(menu.MenuItemControl("pitch1", pitch1), petal_index=5)
pitch2 = control.ControlSlide(
name="pitch",
on_set=set_pitch2,
default=0,
min=-0.5,max=0.5
name="pitch", on_set=set_pitch2, default=0, min=-0.5, max=0.5
)
m.add_petal(menu.MenuItemControl("pitch2",pitch2), petal_index=7)
m.add_petal(menu.MenuItemControl("pitch2", pitch2), petal_index=7)
vol = control.ControlKnob(name="vol",
on_mod=audio.adjust_volume_dB,
on_get=audio.get_volume_relative
vol = control.ControlKnob(
name="vol", on_mod=audio.adjust_volume_dB, on_get=audio.get_volume_relative
)
mi_vol = menu.MenuItemControl("volume",vol)
mi_vol = menu.MenuItemControl("volume", vol)
m.add(mi_vol)
#m.add_petal(mi_vol,1)
# m.add_petal(mi_vol,1)
play = control.ControlSwitch(name="play", on_set=set_play, default=False)
# m.add_petal(menu.MenuItemControl("play",play), petal_index=5)
m.add(menu.MenuItemControl("play", play))
play = control.ControlSwitch(name="play",on_set=set_play,default=False)
#m.add_petal(menu.MenuItemControl("play",play), petal_index=5)
m.add(menu.MenuItemControl("play",play))
m.ui.r = 60
return m
m = get_menu()
\ No newline at end of file
m = get_menu()
from st3m import menu,event,control
from st3m import menu, event, control
from apps import demo_worms, cap_touch_demo
from apps import demo_sparabo, melodic_demo, harmonic_demo
from apps.flow3r import menu_settings,menu_tinysynth,menu_crazysynth
from apps.flow3r import menu_settings, menu_tinysynth, menu_crazysynth
import time
def get_menu():
menu_main = menu.Menu("flow3r",has_back=False)
menu_main = menu.Menu("flow3r", has_back=False)
menu_badge = menu.Menu("badge")
menu_apps = menu.Menu("apps")
menu_music = menu.Menu("music")
for app_module in [demo_sparabo,melodic_demo,harmonic_demo]:
for app_module in [demo_sparabo, melodic_demo, harmonic_demo]:
menu_music.add(menu.MenuItemApp(app_module.app))
for app_module in [demo_worms,cap_touch_demo,]:
for app_module in [
demo_worms,
cap_touch_demo,
]:
menu_apps.add(menu.MenuItemApp(app_module.app))
testmenu = menu.Menu("test")
item_add = menu.MenuItem("+")
item_add.action = lambda x: testmenu.add(menu.MenuItem("new {}".format(len(testmenu.items))))
item_add.action = lambda x: testmenu.add(
menu.MenuItem("new {}".format(len(testmenu.items)))
)
item_sub = menu.MenuItem("-")
item_sub.action = lambda x: testmenu.pop() if len(testmenu.items) > 4 else None
......@@ -41,4 +47,3 @@ def get_menu():
menu_music.add(menu.MenuItemSubmenu(menu_crazysynth.get_menu()))
return menu_main
from st3m import menu,event,control,ui
from st3m.system import audio,hardware
from st3m import menu, event, control, ui
from st3m.system import audio, hardware
ui_input = ui.Icon("")
def render_input_data(data):
ui_input.label = str(data["angle"])
print("xxx")
ui_input.draw()
def set_controls_overlay(value):
print ("set_controls_overlay")
print("set_controls_overlay")
if value:
event_input_overlay = event.Event(
name="show input overlay", group_id="input-overlay",
#condition=lambda d: d['type'] in ["captouch","button"],
condition=lambda d: d['type'] in ["captouch"] and d['value']==1,
action=render_input_data
name="show input overlay",
group_id="input-overlay",
# condition=lambda d: d['type'] in ["captouch","button"],
condition=lambda d: d["type"] in ["captouch"] and d["value"] == 1,
action=render_input_data,
)
else:
print("REMOVE")
event.the_engine.remove("input-overlay")
def set_volume(value):
db = int(value*60-40)
print("DB",db)
db = int(value * 60 - 40)
print("DB", db)
audio.set_volume_dB(db)
def get_menu():
m = menu.Menu("settings")
control_debug_input=control.ControlSwitch(
name="show inputs",
on_set=set_controls_overlay,
default=False
control_debug_input = control.ControlSwitch(
name="show inputs", on_set=set_controls_overlay, default=False
)
item_input_overlay = menu.MenuItemControl("input overlay", control_debug_input)
m.add(item_input_overlay)
m_audio = menu.Menu("audio")
m_speaker = menu.Menu("speaker")
m_head = menu.Menu("headphones")
vol = control.ControlKnob(name="vol",
on_mod=audio.adjust_volume_dB,
on_get=audio.get_volume_relative
vol = control.ControlKnob(
name="vol", on_mod=audio.adjust_volume_dB, on_get=audio.get_volume_relative
)
m_audio.add(menu.MenuItemControl("volume", vol))
m_head.add(
menu.MenuItemControl(
"vol head",
control.ControlKnob(
name="vol",
on_mod=audio.headphones_adjust_volume_dB,
on_get=audio.headphones_get_volume_relative,
),
)
)
m_speaker.add(
menu.MenuItemControl(
"vol speaker",
control.ControlKnob(
name="vol",
on_mod=audio.speaker_adjust_volume_dB,
on_get=audio.speaker_get_volume_relative,
),
)
)
m_audio.add(
menu.MenuItemControl(
"mute",
control.ControlSwitch(
name="mute", on_set=audio.set_mute, on_get=audio.get_mute
),
)
)
m_head.add(
menu.MenuItemControl(
"mute head",
control.ControlSwitch(
name="mute",
on_set=audio.headphones_set_mute,
on_get=audio.headphones_get_mute,
),
)
)
m_head.add(
menu.MenuItemControl(
"detected headphones",
control.ControlSwitch(
name="connected?", on_get=audio.headphones_are_connected
),
)
)
m_speaker.add(
menu.MenuItemControl(
"mute speaker",
control.ControlSwitch(
name="mute",
on_set=audio.speaker_set_mute,
on_get=audio.speaker_get_mute,
),
)
)
m_speaker.add(
menu.MenuItemControl(
"min vol speaker",
control.ControlKnob(
name="min",
min=-40,
max=14,
step=1,
on_set=audio.speaker_set_minimum_volume_dB,
on_get=audio.speaker_get_minimum_volume_dB,
),
)
)
m_speaker.add(
menu.MenuItemControl(
"max vol speaker",
control.ControlKnob(
name="max",
min=-40,
max=14,
step=1,
on_set=audio.speaker_set_maximum_volume_dB,
on_get=audio.speaker_get_maximum_volume_dB,
),
)
)
m_head.add(
menu.MenuItemControl(
"min vol headphones",
control.ControlKnob(
name="min",
min=-40,
max=14,
step=1,
on_set=audio.headphones_set_minimum_volume_dB,
on_get=audio.headphones_get_minimum_volume_dB,
),
)
)
m_head.add(
menu.MenuItemControl(
"max vol headphones",
control.ControlKnob(
name="max",
min=-40,
max=14,
step=1,
on_set=audio.headphones_set_maximum_volume_dB,
on_get=audio.headphones_get_maximum_volume_dB,
),
)
)
m_audio.add(menu.MenuItemControl("volume",vol))
m_head.add(menu.MenuItemControl("vol head",control.ControlKnob(
name="vol",
on_mod=audio.headphones_adjust_volume_dB,
on_get=audio.headphones_get_volume_relative
)))
m_speaker.add(menu.MenuItemControl("vol speaker",control.ControlKnob(
name="vol",
on_mod=audio.speaker_adjust_volume_dB,
on_get=audio.speaker_get_volume_relative
)))
m_audio.add(menu.MenuItemControl("mute",control.ControlSwitch(
name="mute",
on_set=audio.set_mute,
on_get=audio.get_mute
)))
m_head.add(menu.MenuItemControl("mute head",control.ControlSwitch(
name="mute",
on_set=audio.headphones_set_mute,
on_get=audio.headphones_get_mute
)))
m_head.add(menu.MenuItemControl("detected headphones",control.ControlSwitch(
name="connected?",
on_get=audio.headphones_are_connected
)))
m_speaker.add(menu.MenuItemControl("mute speaker",control.ControlSwitch(
name="mute",
on_set=audio.speaker_set_mute,
on_get=audio.speaker_get_mute
)))
m_speaker.add(menu.MenuItemControl("min vol speaker",control.ControlKnob(
name="min",
min = -40, max =14, step=1,
on_set=audio.speaker_set_minimum_volume_dB,
on_get=audio.speaker_get_minimum_volume_dB
)))
m_speaker.add(menu.MenuItemControl("max vol speaker",control.ControlKnob(
name="max",
min = -40, max =14, step=1,
on_set=audio.speaker_set_maximum_volume_dB,
on_get=audio.speaker_get_maximum_volume_dB
)))
m_head.add(menu.MenuItemControl("min vol headphones",control.ControlKnob(
name="min",
min = -40, max =14, step=1,
on_set=audio.headphones_set_minimum_volume_dB,
on_get=audio.headphones_get_minimum_volume_dB
)))
m_head.add(menu.MenuItemControl("max vol headphones",control.ControlKnob(
name="max",
min = -40, max =14, step=1,
on_set=audio.headphones_set_maximum_volume_dB,
on_get=audio.headphones_get_maximum_volume_dB
)))
m.add(menu.MenuItemSubmenu(m_audio))
m_audio.add(menu.MenuItemSubmenu(m_speaker))
m_audio.add(menu.MenuItemSubmenu(m_head))
return m
m = get_menu()
from synth import tinysynth
from st3m import menu,event,control,ui
from st3m.system import hardware,audio
from st3m import menu, event, control, ui
from st3m.system import hardware, audio
synth = tinysynth(440, 0)
synth = tinysynth(440,0)
def set_play(value):
print ("set_controls_overlay")
print("set_controls_overlay")
if value:
synth.start()
else:
synth.stop()
the_freq = 440
def set_frequency(value):
global the_freq
the_freq = value
synth.freq(the_freq)
def set_pitch(value):
synth.freq(the_freq+the_freq*value)
synth.freq(the_freq + the_freq * value)
print("value")
def get_menu():
m = menu.Menu("tinysynth")
m.add(menu.MenuItemControl("mute",control.ControlSwitch(
name="mute",
on_set=audio.set_mute,
on_get=audio.get_mute
)))
freq=control.ControlKnob(
m.add(
menu.MenuItemControl(
"mute",
control.ControlSwitch(
name="mute", on_set=audio.set_mute, on_get=audio.get_mute
),
)
)
freq = control.ControlKnob(
name="freq",
on_set=set_frequency,
default=the_freq,
min=220,max=440*4,step=10
min=220,
max=440 * 4,
step=10,
)
m.add_petal(menu.MenuItemControl("freq",freq), petal_index=7)
m.add_petal(menu.MenuItemControl("freq", freq), petal_index=7)
pitch = control.ControlSlide(
name="pitch",
on_set=set_pitch,
default=0,
min=-0.5,max=0.5
name="pitch", on_set=set_pitch, default=0, min=-0.5, max=0.5
)
m.add_petal(menu.MenuItemControl("pitch",pitch), petal_index=9)
m.add_petal(menu.MenuItemControl("pitch", pitch), petal_index=9)
vol = control.ControlKnob(name="vol",
on_mod=audio.adjust_volume_dB,
on_get=audio.get_volume_relative
vol = control.ControlKnob(
name="vol", on_mod=audio.adjust_volume_dB, on_get=audio.get_volume_relative
)
mi_vol = menu.MenuItemControl("volume",vol)
mi_vol = menu.MenuItemControl("volume", vol)
# m.add(mi_vol)
m.add_petal(mi_vol, 1)
#m.add(mi_vol)
m.add_petal(mi_vol,1)
play = control.ControlSwitch(name="play", on_set=set_play, default=False)
m.add_petal(menu.MenuItemControl("play", play), petal_index=5)
play = control.ControlSwitch(name="play",on_set=set_play,default=False)
m.add_petal(menu.MenuItemControl("play",play), petal_index=5)
m.ui.r = 60
return m
m = get_menu()
......@@ -2,23 +2,30 @@ from st3m.application import SimpleApplication
app = SimpleApplication("flow3rdroids")
def on_init():
ship_position = complex(0,0)
ship_direction = complex(0,0)
ship_position = complex(0, 0)
ship_direction = complex(0, 0)
def on_tick():
if abs(ship_position.real)>240: ship_position.real*=-1
if abs(ship_position.imag)>240: ship_position.imag*=-1
if abs(ship_position.real) > 240:
ship_position.real *= -1
if abs(ship_position.imag) > 240:
ship_position.imag *= -1
ship_position += ship_direction
def on_draw():
ui.Pointer(x=ship_position.imag,y=ship_position.real)
ui.Pointer(x=ship_position.imag, y=ship_position.real)
def on_scroll_step(direction):
#TODO: ship_direction += direction * angle
# TODO: ship_direction += direction * angle
pass
def on_enter():
#TODO:ship_direction += speed
# TODO:ship_direction += speed
pass
from synth import tinysynth
from hardware import *
chords = [\
[-4,0,3,8,10],\
[-3,0,5,7,12],\
[-1,2,5,7,11],\
[0,3,7,12,14],\
[3,7,10,14,15]\
chords = [
[-4, 0, 3, 8, 10],
[-3, 0, 5, 7, 12],
[-1, 2, 5, 7, 11],
[0, 3, 7, 12, 14],
[3, 7, 10, 14, 15],
]
chord_index = 3
chord = chords[3]
synths = []
def set_chord(i):
global chord_index
global chord
if(i != chord_index):
if i != chord_index:
chord_index = i
for j in range(40):
hue = int(72*(i+0.5)) % 360
hue = int(72 * (i + 0.5)) % 360
set_led_hsv(j, hue, 1, 0.2)
chord = chords[i]
update_leds()
......@@ -30,27 +31,29 @@ def run():
global chord
global synths
for i in range(10):
if(get_captouch(i)):
if(i%2):
k = int((i-1)/2)
if get_captouch(i):
if i % 2:
k = int((i - 1) / 2)
set_chord(k)
else:
k = int(i/2)
k = int(i / 2)
synths[k].tone(chord[k])
synths[k].start()
def init():
global chord_index
global chord
global synths
for i in range(5):
synths += [tinysynth(440,1)]
synths += [tinysynth(440, 1)]
for synth in synths:
synth.decay(100)
synth.waveform(1)
def foreground():
global chord_index
global chord
......@@ -59,17 +62,21 @@ def foreground():
chord_index = -1
set_chord(tmp)
from st3m.application import Application
class HarmonicApp(Application):
def on_init(self):
init()
#foreground()
# foreground()
def on_foreground(self):
#foreground()
# foreground()
pass
def main_foreground(self):
run()
app=HarmonicApp("harmonic")
\ No newline at end of file
app = HarmonicApp("harmonic")
......@@ -3,14 +3,16 @@ from hardware import *
octave = 0
synths = []
scale = [0,2,4,5,7,9,11]
scale = [0, 2, 4, 5, 7, 9, 11]
def highlight_bottom_petal(num, r, g, b):
start = 4 + 8*num
start = 4 + 8 * num
for i in range(7):
set_led_rgb(((i+start)%40), r, g, b)
set_led_rgb(((i + start) % 40), r, g, b)
def change_playing_field_color(r,g,b):
def change_playing_field_color(r, g, b):
highlight_bottom_petal(0, r, g, b)
highlight_bottom_petal(1, r, g, b)
highlight_bottom_petal(3, r, g, b)
......@@ -22,60 +24,67 @@ def change_playing_field_color(r,g,b):
set_led_rgb(28, 55, 0, 55)
update_leds()
def adjust_playing_field_to_octave():
global octave
if(octave == -1):
change_playing_field_color(0,0,55)
elif(octave == 0):
change_playing_field_color(0,27,27)
elif(octave == 1):
change_playing_field_color(0,55,0)
if octave == -1:
change_playing_field_color(0, 0, 55)
elif octave == 0:
change_playing_field_color(0, 27, 27)
elif octave == 1:
change_playing_field_color(0, 55, 0)
def run():
global scale
global octave
global synths
for i in range(10):
if(get_captouch(i)):
if(i == 4):
if get_captouch(i):
if i == 4:
octave = -1
adjust_playing_field_to_octave()
elif(i == 5):
elif i == 5:
octave = 0
adjust_playing_field_to_octave()
elif(i == 6):
elif i == 6:
octave = 1
adjust_playing_field_to_octave()
else:
k = i
if(k>3):
if k > 3:
k -= 10
k = 3 - k
note = scale[k] + 12 * octave
synths[0].tone(note)
synths[0].start()
def init():
global synths
for i in range(1):
synths += [tinysynth(440,1)]
synths += [tinysynth(440, 1)]
for synth in synths:
synth.decay(100)
synth.waveform(1)
def foreground():
adjust_playing_field_to_octave()
from st3m.application import Application
class MelodicApp(Application):
def on_init(self):
init()
def on_foreground(self):
foreground()
def main_foreground(self):
run()
app=MelodicApp("melodic")
\ No newline at end of file
app = MelodicApp("melodic")
import gc,time
import gc, time
from st3m import logging
log = logging.Log(__name__,level=logging.INFO)
log = logging.Log(__name__, level=logging.INFO)
log.info(f"starting main")
log.info(f"free memory: {gc.mem_free()}")
from st3m import control,application,ui,menu
from st3m import control, application, ui, menu
from apps import flow3r
log.info("import apps done")
log.info(f"free memory: {gc.mem_free()}")
#TODO persistent settings
from st3m.system import hardware,audio
# TODO persistent settings
from st3m.system import hardware, audio
log.info("calibrating captouch, reset volume")
hardware.captouch_autocalib()
audio.set_volume_dB(0)
#Start default app
# Start default app
default_app = flow3r.app
log.info(f"running default app '{default_app.title}'")
default_app.run()
\ No newline at end of file
default_app.run()
from st3m import logging
log = logging.Log(__name__,level=logging.INFO)
log = logging.Log(__name__, level=logging.INFO)
log.info("import")
from . import ui,event,menu
from . import ui, event, menu
STATE_OFF = 0
STATE_INIT = 10
......@@ -10,8 +11,12 @@ STATE_FOREGROUND = 300
STATE_ERROR = 500
log.info("setting up application")
class Application():
def __init__(self,title="badge23 app", author="someone@earth", exit_on_menu_enter=True):
class Application:
def __init__(
self, title="badge23 app", author="someone@earth", exit_on_menu_enter=True
):
log.info(f"__init__ app '{title}'")
self.title = title
self.author = author
......@@ -25,23 +30,27 @@ class Application():
self.engine = event.the_engine
self.menu = None
if exit_on_menu_enter:
self.add_event(event.Event(
self.add_event(
event.Event(
name="exit",
action=self.exit,
condition=lambda e: e["type"]=="button" and e.get("from")==2 and e["change"]
))
action=self.exit,
condition=lambda e: e["type"] == "button"
and e.get("from") == 2
and e["change"],
)
)
def __repr__(self):
return "App "+self.title
return "App " + self.title
def init(self):
log.info(f"init app '{self.title}'")
self.state = STATE_INIT
self.on_init()
if self.has_background:
if self._events_background:
self._set_events(self._events_background,True)
engine.register_service_loop(self.main_always,True)
self._set_events(self._events_background, True)
engine.register_service_loop(self.main_always, True)
def run(self):
log.info(f"run app '{self.title}' from state {self.state}")
......@@ -53,39 +62,39 @@ class Application():
elif self.has_background:
self._to_background()
else:
log.warning(f"App {self.title} has neither foreground nor background, not doing anything")
log.warning(
f"App {self.title} has neither foreground nor background, not doing anything"
)
#start the eventloop if it is not already running
# start the eventloop if it is not already running
if not event.the_engine.is_running:
log.info("eventloop not yet running, starting")
event.the_engine.eventloop()
def exit(self,data={}):
def exit(self, data={}):
log.info(f"exit app '{self.title}' from state {self.state}")
self.on_exit()
if self.state == STATE_FOREGROUND:
self._to_background()
def kill(self):
#disable all events
# disable all events
log.info(f"kill app '{self.title}' from state {self.state}")
engine.register_service_loop(self.main_always,False)
engine.register_service_loop(self.main_always, False)
engine.foreground_app = None
self._set_events(self._events_background,False)
self._set_events(self._events_forground,False)
self._set_events(self._events_background, False)
self._set_events(self._events_forground, False)
self.state = STATE_OFF
def draw(self):
self.ui.draw()
self.on_draw()
def tick(self):
self.main_foreground()
def add_event(self,event,is_background=False):
def add_event(self, event, is_background=False):
if not is_background:
self._events_foreground.append(event)
else:
......@@ -99,33 +108,33 @@ class Application():
if not self.has_foreground:
log.error(f"app has no foreground!")
return
if self._events_background:
self._set_events(self_events_background,False)
self._set_events(self_events_background, False)
self.state = STATE_FOREGROUND
if self._events_foreground:
self._set_events(self._events_foreground,True)
self.ui.ctx.rgb(*ui.BLACK).rectangle(-120,-120,240,240).fill()
self._set_events(self._events_foreground, True)
self.ui.ctx.rgb(*ui.BLACK).rectangle(-120, -120, 240, 240).fill()
self.icon.draw()
self.on_foreground()
self.engine.foreground_app = self
def _to_background(self):
log.info(f"to_background app '{self.title}' from state {self.state}")
self.state = STATE_BACKGROUND
if self._events_foreground:
self._set_events(self._events_foreground,False)
self._set_events(self._events_foreground, False)
self.engine.foreground_app = None
if self.has_background:
self.state = STATE_BACKGROUND
self.on_background()
def _set_events(self,events,enabled=True):
def _set_events(self, events, enabled=True):
for e in events:
e.set_enabled(enabled)
......@@ -137,11 +146,11 @@ class Application():
def on_background(self):
log.info(f"app {self.title}: on_background()")
def on_exit(self):
log.info(f"app {self.title}: on_exit()")
def on_kill(self):
def on_kill(self):
log.info(f"app {self.title}: on_kill()")
def on_draw(self):
......@@ -149,10 +158,9 @@ class Application():
def main_foreground(self):
pass
def main_always(self):
pass
def main(self):
self.main_foreground()
from st3m import logging,menu
log = logging.Log(__name__,level=logging.INFO)
from st3m import logging, menu
log = logging.Log(__name__, level=logging.INFO)
log.info("import")
from . import ui
class Control():
def __init__(self,name, default=0, on_set=None, on_get=None, on_mod=None):
#TODO inheritance from Control()
self.name=name
class Control:
def __init__(self, name, default=0, on_set=None, on_get=None, on_mod=None):
# TODO inheritance from Control()
self.name = name
self.on_set = on_set
self.on_get = on_get
self.on_mod = on_mod
if not self.on_get:
self._value = default
self.ui = ui.IconValue(label=self.name,size=60, value=self.get_value())
self.ui = ui.IconValue(label=self.name, size=60, value=self.get_value())
self.ui.get_value = self.get_normal_value
self.menu = menu.MenuControl(self)
......@@ -25,10 +27,10 @@ class Control():
def get_normal_value(self):
v = self.get_value()
n = min(1,max(0,v))
n = min(1, max(0, v))
return n
def get_value(self,update=True):
def get_value(self, update=True):
if update and self.on_get:
self._value = self.on_get()
return self._value
......@@ -38,45 +40,46 @@ class Control():
if do_trigger:
if self.on_set:
self.on_set(value)
def mod_value(self,delta):
def mod_value(self, delta):
self._value = self.on_mod(delta)
def enter_menu(self):
menu.submenu_push(self.menu)
def scroll(self,delta):
def scroll(self, delta):
pass
def touch_1d(self,x,z):
def touch_1d(self, x, z):
pass
class ControlSwitch(Control):
def enter(self):
self.set_value(not self.get_value())
self.draw()
def scroll(self,delta):
def scroll(self, delta):
self.enter()
def touch_1d(self,x,z):
if z<0: #Release
def touch_1d(self, x, z):
if z < 0: # Release
self.enter()
class ControlFloat(Control):
def __init__(self, min=0.0,max=1.0,step=0.1, *args, **kwargs):
self.min=min
self.max=max
self.step=step
def __init__(self, min=0.0, max=1.0, step=0.1, *args, **kwargs):
self.min = min
self.max = max
self.step = step
super().__init__(*args, **kwargs)
def get_normal_value(self):
v = self.get_value()
n = (v-self.min)/(self.max-self.min)
n = (v - self.min) / (self.max - self.min)
return n
class ControlKnob(ControlFloat):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
......@@ -84,63 +87,64 @@ class ControlKnob(ControlFloat):
self._touch_started_here = False
def enter(self):
#repeat action with current value
# repeat action with current value
self.set_value(self.get_value())
self.draw()
def scroll(self,delta):
def scroll(self, delta):
if self.on_mod:
#print("control: on mod")
# print("control: on mod")
self.on_mod(delta)
elif self.on_set:
v = self.get_value()
v_new = max(self.min,min(self.max,v+delta*self.step))
v_new = max(self.min, min(self.max, v + delta * self.step))
self.set_value(v_new)
self.draw()
def touch_1d(self,x,z):
if z>0: #Inital Contact
def touch_1d(self, x, z):
if z > 0: # Inital Contact
self._x_init = x
self._touch_started_here=True
self._touch_started_here = True
if z==0: #Continous contact
if not self._touch_started_here:
if z == 0: # Continous contact
if not self._touch_started_here:
return
diff = self._x_init-x
self.scroll(5*diff)
if z<0: #Release
diff = self._x_init - x
self.scroll(5 * diff)
if z < 0: # Release
self._touch_started_here = False
class ControlSlide(ControlFloat):
def __init__(self, do_reset=True, *args, **kwargs):
self.do_reset=do_reset
self.do_reset = do_reset
self._saved_value = None
super().__init__(*args, **kwargs)
def touch_1d(self,x,z):
if z>0: #Inital Contact
def touch_1d(self, x, z):
if z > 0: # Inital Contact
self._saved_value = self.get_value()
if self._saved_value is None: return
if self._saved_value is None:
return
if z==0: #Continous contact
v = (self.max-self.min)*x+self.min
if z == 0: # Continous contact
v = (self.max - self.min) * x + self.min
self.set_value(v)
#print("c",x,v,self.max,self.min)
# print("c",x,v,self.max,self.min)
if z<0: #Release
if z < 0: # Release
if self.do_reset:
self.set_value(self._saved_value)
self._saved_value = None
self.draw()
class ControlString(Control):
pass
class ControlTextField():
pass
\ No newline at end of file
class ControlTextField:
pass
from st3m import logging
log = logging.Log(__name__,level=logging.INFO)
log = logging.Log(__name__, level=logging.INFO)
log.info("import")
from st3m.system import hardware
import time
import time
import math
import random
EVENTTYPE_TIMED = 1
EVENTTYPE_INPUT = 2
#EVENTTYPE_BUTTON = 2
#EVENTTYPE_CAPTOUCH = 3
#EVENTTYPE_CAPCROSS = 4
# EVENTTYPE_BUTTON = 2
# EVENTTYPE_CAPTOUCH = 3
# EVENTTYPE_CAPCROSS = 4
class Engine():
class Engine:
def __init__(self):
self.events_timed = []
self.events_input = []
......@@ -26,109 +28,110 @@ class Engine():
self.foreground_app = None
self.active_menu = None
def add(self,event):
if isinstance(event,EventTimed):
def add(self, event):
if isinstance(event, EventTimed):
self.add_timed(event)
elif isinstance(event,Event):
elif isinstance(event, Event):
self.add_input(event)
def add_timed(self,event):
def add_timed(self, event):
self.events_timed.append(event)
self._sort_timed()
def add_input(self,event):
def add_input(self, event):
self.events_input.append(event)
def remove(self,group_id):
def remove(self, group_id):
self.remove_input(group_id)
self.remove_timed(group_id)
def remove_timed(self,group_id):
#print("before:",len(self.events_timed))
self.events_timed = [event for event in self.events_timed if event.group_id!=group_id]
def remove_timed(self, group_id):
# print("before:",len(self.events_timed))
self.events_timed = [
event for event in self.events_timed if event.group_id != group_id
]
self._sort_timed()
#print("after",len(self.events_timed))
def remove_input(self,group_id):
self.events_input = [event for event in self.events_input if event.group_id!=group_id]
# print("after",len(self.events_timed))
def remove_input(self, group_id):
self.events_input = [
event for event in self.events_input if event.group_id != group_id
]
def _sort_timed(self):
self.events_timed = sorted(self.events_timed, key = lambda event: event.deadline)
self.events_timed = sorted(self.events_timed, key=lambda event: event.deadline)
def _handle_timed(self):
if not self.next_timed and self.events_timed:
self.next_timed = self.events_timed.pop(0)
now = time.ticks_ms()
if self.next_timed:
diff = time.ticks_diff(self.next_timed.deadline, now)
if diff <= 0:
self.next_timed.trigger({"ticks_ms":now, "ticks_delay": -diff})
self.next_timed.trigger({"ticks_ms": now, "ticks_delay": -diff})
self.next_timed = None
def _handle_input(self):
input_state = []
#buttons
input_state.append({
"type" : "button",
"index" : 0,
"value" : hardware.menu_button_get()
})
input_state.append({
"type" : "button",
"index" : 1,
"value" : hardware.application_button_get()
})
#captouch
for i in range(0,10):
input_state.append({
"type" : "captouch",
"index" : i,
"value" : hardware.get_captouch(i),
"radius" : hardware.captouch_get_petal_rad(i),
"angle" : hardware.captouch_get_petal_phi(i)/10000
})
# buttons
input_state.append(
{"type": "button", "index": 0, "value": hardware.menu_button_get()}
)
input_state.append(
{"type": "button", "index": 1, "value": hardware.application_button_get()}
)
# captouch
for i in range(0, 10):
input_state.append(
{
"type": "captouch",
"index": i,
"value": hardware.get_captouch(i),
"radius": hardware.captouch_get_petal_rad(i),
"angle": hardware.captouch_get_petal_phi(i) / 10000,
}
)
if not self.last_input_state:
self.last_input_state=input_state
#tprint (input_state)
self.last_input_state = input_state
# tprint (input_state)
return
for i in range(len(input_state)):
entry = input_state[i]
last_entry = self.last_input_state[i]
#update for all
# update for all
entry["ticks_ms"] = time.ticks_ms()
if entry["value"] != last_entry["value"]:
#update only when value changed
# update only when value changed
entry["change"] = True
entry["from"] = last_entry["value"]
else:
#update only when value did not change
entry["change"] = False
# update only when value did not change
entry["change"] = False
#find and trigger the events q
triggered_events = list(filter(lambda e: e.enabled and e.condition(entry),self.events_input))
#print (triggered_events)
#map(lambda e: e.trigger(d), triggered_events)
# find and trigger the events q
triggered_events = list(
filter(lambda e: e.enabled and e.condition(entry), self.events_input)
)
# print (triggered_events)
# map(lambda e: e.trigger(d), triggered_events)
for e in triggered_events:
e.trigger(entry)
self.last_input_state=input_state
self.last_input_state = input_state
def _handle_userloop(self):
if self.foreground_app:
self.foreground_app.tick()
def _handle_draw(self):
if self.foreground_app:
self.foreground_app.draw()
......@@ -136,38 +139,44 @@ class Engine():
self.active_menu.draw()
hardware.display_update()
def _eventloop_single(self):
self._handle_timed()
self._handle_input()
self._handle_userloop()
def eventloop(self):
log.info("starting eventloop")
if self.is_running:
log.warning("eventloop already running, doing nothing")
return
self.is_running=True
self.is_running = True
last_draw = 0
while self.is_running:
self._eventloop_single()
now = time.ticks_ms()
diff = time.ticks_diff(now,last_draw)
#print("diff:",diff)
if diff>10:
#print("eventloop draw")
diff = time.ticks_diff(now, last_draw)
# print("diff:",diff)
if diff > 10:
# print("eventloop draw")
self._handle_draw()
last_draw = time.ticks_ms()
#self.deadline = time.ticks_add(time.ticks_ms(),ms)
# self.deadline = time.ticks_add(time.ticks_ms(),ms)
time.sleep_ms(1)
class Event():
def __init__(self,name="unknown",data={},action=None,condition=None,group_id=None,enabled=False):
#print (action)
class Event:
def __init__(
self,
name="unknown",
data={},
action=None,
condition=None,
group_id=None,
enabled=False,
):
# print (action)
self.name = name
self.eventtype = None
self.data = data
......@@ -176,22 +185,19 @@ class Event():
self.enabled = enabled
if not condition:
self.condition = lambda x: True
self.group_id=group_id
self.group_id = group_id
if enabled:
self.set_enabled()
def trigger(self,triggerdata={}):
log.debug("triggered {} (with {})".format(self.name,triggerdata))
def trigger(self, triggerdata={}):
log.debug("triggered {} (with {})".format(self.name, triggerdata))
if not self.action is None:
triggerdata.update(self.data)
self.action(triggerdata)
def set_enabled(self,enabled=True):
self.enabled=enabled
def set_enabled(self, enabled=True):
self.enabled = enabled
if enabled:
the_engine.add(self)
else:
......@@ -200,27 +206,28 @@ class Event():
def remove(self):
log.info(f"remove {self}")
while self in the_engine.events_input:
#print ("from input")
# print ("from input")
the_engine.events_input.remove(self)
while self in the_engine.events_timed:
#print("from timed")
# print("from timed")
the_engine.events_timed.remove(self)
the_engine._sort_timed()
class EventTimed(Event):
def __init__(self,ms,name="timer", *args, **kwargs):
#super().__init__(name,data,action)
self.deadline = time.ticks_add(time.ticks_ms(),ms)
def __init__(self, ms, name="timer", *args, **kwargs):
# super().__init__(name,data,action)
self.deadline = time.ticks_add(time.ticks_ms(), ms)
super().__init__(*args, **kwargs)
self.name=name
self.type=EVENTTYPE_TIMED
self.name = name
self.type = EVENTTYPE_TIMED
def __repr__(self):
return ("event on tick {} ({})".format(self.deadline,self.name))
return "event on tick {} ({})".format(self.deadline, self.name)
#hack, make this oo
# hack, make this oo
def on_restart(data):
print("loop sequence")
obj = data["object"]
......@@ -228,40 +235,57 @@ def on_restart(data):
obj.start()
class Sequence():
def __init__(self,bpm=60,loop=True,steps=16,action=None):
self.group_id = random.randint(0,100000000)
class Sequence:
def __init__(self, bpm=60, loop=True, steps=16, action=None):
self.group_id = random.randint(0, 100000000)
self.bpm = bpm
self.steps = steps
self.repeat_event = None
self.loop = loop
self.events = []
self.is_running = False
if not action:
self.action = lambda data: log.info("step {}".format(data.get("step")))
else:
self.action = action
def start(self):
if self.is_running: self.stop()
stepsize_ms = int(60*1000/self.bpm)
if self.is_running:
self.stop()
stepsize_ms = int(60 * 1000 / self.bpm)
for i in range(self.steps):
log.debug(f"adding sequence event {i}")
self.events.append(EventTimed(stepsize_ms*i,name="seq{}".format(i),action=self.action, data={'step':i}, group_id=self.group_id,enabled=True))
self.events.append(
EventTimed(
stepsize_ms * i,
name="seq{}".format(i),
action=self.action,
data={"step": i},
group_id=self.group_id,
enabled=True,
)
)
if self.loop:
self.repeat_event=EventTimed(stepsize_ms*self.steps,name="loop", group_id=self.group_id, enabled=True, action=on_restart, data={"object":self})
self.is_running=True
self.repeat_event = EventTimed(
stepsize_ms * self.steps,
name="loop",
group_id=self.group_id,
enabled=True,
action=on_restart,
data={"object": self},
)
self.is_running = True
def stop(self):
#for e in self.events: e.remove()
# for e in self.events: e.remove()
log.info("sequence stop")
the_engine.remove_timed(group_id=self.group_id)
self.events = []
if self.repeat_event: self.repeat_event.remove()
self.is_running=False
if self.repeat_event:
self.repeat_event.remove()
self.is_running = False
global the_engine
the_engine = Engine()
......@@ -5,36 +5,38 @@ INFO = 1
WARNING = 2
ERROR = 3
#this is so ugly, but works
levels = ["DEBUG","INFO","WARNING","ERROR"]
# this is so ugly, but works
levels = ["DEBUG", "INFO", "WARNING", "ERROR"]
class Log():
def __init__(self,name="log",level=INFO):
class Log:
def __init__(self, name="log", level=INFO):
self.name = name
self.level = level
self.logstring = "{timestamp} {name} ({level}): {msg}"
def debug(self,msg):
self.message(msg,DEBUG)
def info(self,msg):
self.message(msg,INFO)
def warning(self,msg):
self.message(msg,WARNING)
def error(self,msg):
self.message(msg,ERROR)
def message(self,msg,level):
def debug(self, msg):
self.message(msg, DEBUG)
def info(self, msg):
self.message(msg, INFO)
def warning(self, msg):
self.message(msg, WARNING)
def error(self, msg):
self.message(msg, ERROR)
def message(self, msg, level):
if self.level <= level:
self._emit(self.logstring.format(
timestamp = time.ticks_ms()/1000,
name=self.name,
msg = msg,
level = levels[level])
)
def _emit(self,line):
print(line)
\ No newline at end of file
self._emit(
self.logstring.format(
timestamp=time.ticks_ms() / 1000,
name=self.name,
msg=msg,
level=levels[level],
)
)
def _emit(self, line):
print(line)
from st3m import logging
log = logging.Log(__name__,level=logging.INFO)
log = logging.Log(__name__, level=logging.INFO)
log.info("import")
from . import ui,event
from . import ui, event
import time
......@@ -10,34 +11,36 @@ import math
menu_stack = []
class Menu():
def __init__(self,name="menu",has_back=True):
self.name=name
self.items=[]
self.items_petal=[None for i in range(10)]
class Menu:
def __init__(self, name="menu", has_back=True):
self.name = name
self.items = []
self.items_petal = [None for i in range(10)]
self.__index = 0
self.ui = ui.GroupRing(r=80)
self.ui2 = ui.GroupPetals(r=100) #TODO(iggy) hack, this should be composed together in ui
self.icon = ui.IconFlower(label=name,size=80)
self.ui2 = ui.GroupPetals(
r=100
) # TODO(iggy) hack, this should be composed together in ui
self.icon = ui.IconFlower(label=name, size=80)
self.ui.element_center = self.icon
self.angle = 0
self.angle_step= 0.2
self.angle_step = 0.2
if has_back:
self.add(MenuItemBack())
def __repr__(self):
return "{} ({}): {}".format(self.name, self.__index, self.items)
def add(self, item):
self.items.append(item)
self.ui.add(item.ui)
def add_petal(self, item, petal_index):
self.items_petal[petal_index]=item
self.ui2.children[petal_index]=item.ui
self.items_petal[petal_index] = item
self.ui2.children[petal_index] = item.ui
def pop(self):
self.items.pop()
......@@ -47,161 +50,164 @@ class Menu():
log.info(f"starting menu {self.name}")
set_active_menu(self)
#def scroll(self, n=0):
# def scroll(self, n=0):
# self.__index= (self.__index+n)%len(self.items)
# return self.items[self.__index]
def scroll_app(self, delta):
hovered=self.get_hovered_item()
hovered = self.get_hovered_item()
if hasattr(hovered, "scroll"):
hovered.scroll(delta)
def scroll_menu(self, delta):
if self.angle_step<0.5:
self.angle_step+=0.025
if self.angle_step < 0.5:
self.angle_step += 0.025
self.rotate_steps(delta)
def enter_menu(self,data={}):
hovered=self.get_hovered_item()
def enter_menu(self, data={}):
hovered = self.get_hovered_item()
if hasattr(hovered, "enter_menu"):
hovered.enter_menu()
else:
hovered.enter()
def enter_app(self,data={}):
hovered=self.get_hovered_item()
def enter_app(self, data={}):
hovered = self.get_hovered_item()
if hasattr(hovered, "enter_app"):
hovered.enter_app()
else:
hovered.enter()
def rotate_by(self,angle):
self.rotate_to(self.angle+angle)
def rotate_by(self, angle):
self.rotate_to(self.angle + angle)
def rotate_to(self, angle):
self.angle = angle%(math.pi*2)
self.angle = angle % (math.pi * 2)
self.ui.angle_offset = self.angle
#for child in self.ui.children:
# for child in self.ui.children:
# child.angle_offset = self.angle*2
self.icon.phi_offset = self.angle
def rotate_steps(self, steps=1):
self.rotate_by(-self.angle_step*steps)
self.rotate_by(-self.angle_step * steps)
def _get_hovered_index(self):
index = round(-self.angle/(math.pi*2)*len(self.items))
i = index%len(self.items)
index = round(-self.angle / (math.pi * 2) * len(self.items))
i = index % len(self.items)
return i
def get_hovered_item(self):
return self.items[self._get_hovered_index()]
def _get_angle_for_index(self,index):
return (math.pi*2/len(self.items)*(index)+self.angle)%(math.pi*2)
def _get_topness_for_index(self,index):
def _get_angle_for_index(self, index):
return (math.pi * 2 / len(self.items) * (index) + self.angle) % (math.pi * 2)
def _get_topness_for_index(self, index):
angle = self._get_angle_for_index(index)
dist = min(angle,math.pi*2-angle)
topness = 1-(dist/math.pi)
dist = min(angle, math.pi * 2 - angle)
topness = 1 - (dist / math.pi)
return topness
def draw(self):
#TODO this is more like a hack...
#if not self==active_menu:
# TODO this is more like a hack...
# if not self==active_menu:
# active_menu.draw()
# return
#print("draw",self.name)
# print("draw",self.name)
hovered_index = self._get_hovered_index()
for i in range(len(self.items)):
item = self.items[i]
my_extra = abs(self._get_topness_for_index(i))*40
my_extra = abs(self._get_topness_for_index(i)) * 40
if i == hovered_index:
item.ui.has_highlight=True
my_extra+=20
item.ui.has_highlight = True
my_extra += 20
else:
item.ui.has_highlight=False
item.ui.size=30+my_extra
#black background
#TODO transparent menu with compositing
ui.the_ctx.rectangle(-120,-120,240,240).rgb(*ui.BLACK).fill()
item.ui.has_highlight = False
item.ui.size = 30 + my_extra
# black background
# TODO transparent menu with compositing
ui.the_ctx.rectangle(-120, -120, 240, 240).rgb(*ui.BLACK).fill()
self.ui2.draw()
self.ui.draw()
class MenuControl(Menu):
def __init__(self,control,*args,**kwargs):
super().__init__(*args,**kwargs)
def __init__(self, control, *args, **kwargs):
super().__init__(*args, **kwargs)
self.control = control
self.ui.element_center = self.control.ui
def scroll_app(self, delta):
hovered=self.get_hovered_item()
hovered = self.get_hovered_item()
if hasattr(hovered, "scroll"):
hovered.scroll(delta)
else:
self.control.scroll(delta)
def enter_app(self,data={}):
hovered=self.get_hovered_item()
def enter_app(self, data={}):
hovered = self.get_hovered_item()
if hasattr(hovered, "enter_app"):
hovered.enter_app()
else:
self.control.enter()
class MenuItem():
def __init__(self,name="item",action=None):
self.name= name
self.action= action
class MenuItem:
def __init__(self, name="item", action=None):
self.name = name
self.action = action
self.ui = ui.IconFlower(label=name)
def __repr__(self):
return "item: {} (action: {})".format(self.name,"?")
return "item: {} (action: {})".format(self.name, "?")
def enter(self,data={}):
def enter(self, data={}):
log.info("enter MenuItem {}".format(self.name))
if self.action:
self.action(data)
class MenuItemApp(MenuItem):
def __init__(self,app):
def __init__(self, app):
super().__init__(name=app.title)
self.target = app
def enter(self,data={}):
def enter(self, data={}):
if self.target:
submenu_push(None)
self.target.run()
class MenuItemSubmenu(MenuItem):
def __init__(self,submenu):
def __init__(self, submenu):
super().__init__(name=submenu.name)
self.ui = submenu.icon
self.target = submenu
def enter_menu(self,data={}):
def enter_menu(self, data={}):
log.info("item submenu enter")
submenu_push(self.target)
class MenuItemBack(MenuItem):
def __init__(self):
super().__init__(name="")
self.ui = ui.IconLabel(label="back")
def enter_menu(self,data={}):
log.info (f"item back selected")
def enter_menu(self, data={}):
log.info(f"item back selected")
menu_back()
class MenuItemControl(MenuItem):
def __init__(self,name,control):
def __init__(self, name, control):
super().__init__(name=name)
self.control=control
self.ui=control.ui
self.control = control
self.ui = control.ui
def enter_menu(self):
log.info(f"item {self.name} (MenuItemControl): enter_menu->enter")
......@@ -211,133 +217,154 @@ class MenuItemControl(MenuItem):
log.info(f"item {self.name} (MenuItemControl): enter->enter menu")
self.control.enter_menu()
def scroll(self,delta):
def scroll(self, delta):
self.control.scroll(delta)
def touch_1d(self,x,z):
self.control.touch_1d(x,z)
def touch_1d(self, x, z):
self.control.touch_1d(x, z)
def on_scroll(d):
active_menu = get_active_menu()
if active_menu is None:
return
if d["index"]==0:#right button
if d["index"] == 0: # right button
active_menu.scroll_app(d["value"])
else: #index=1, #left button
else: # index=1, #left button
active_menu.scroll_menu(d["value"])
def on_scroll_captouch(d):
active_menu = get_active_menu()
if active_menu is None:
return
return
if abs(d["radius"]) < 10000:
return
active_menu.rotate_to(d["angle"]+math.pi)
active_menu.rotate_to(d["angle"] + math.pi)
def on_release(d):
active_menu = get_active_menu()
if active_menu is None:
return
active_menu.angle_step = 0.2
def on_touch_1d(d):
active_menu = get_active_menu()
if active_menu is None:
return
v = min(1.0,max(0.0,((d["radius"]+25000.0)/50000.0)))
v = min(1.0, max(0.0, ((d["radius"] + 25000.0) / 50000.0)))
z = 0
if d["change"]:
if d["value"] == 1: z=1
else: z=-1
if d["value"] == 1:
z = 1
else:
z = -1
log.debug(f"menu: touch_1d ({v},{z})")
hovered=active_menu.get_hovered_item()
hovered = active_menu.get_hovered_item()
petal_idx = d["index"]
petal_item = active_menu.items_petal[petal_idx]
if petal_item:
petal_item.touch_1d(v,z)
petal_item.touch_1d(v, z)
if hasattr(hovered, "touch_1d"):
hovered.touch_1d(v,z)
hovered.touch_1d(v, z)
def on_enter(d):
active_menu = get_active_menu()
#if active_menu is None:
# if active_menu is None:
# log.info("menu enter without active menu, opening last menu")
# menu_back()
# return
if active_menu:
if d["index"]==0: #right button
if d["index"] == 0: # right button
log.info("menu enter_app")
active_menu.enter_app()
else:
log.info("menu enter_menu")
active_menu.enter_menu()
event.Event(name="menu rotation button",group_id="menu",
condition=lambda e: e["type"] =="button" and not e["change"] and abs(e["value"])==1,
action=on_scroll, enabled=True
event.Event(
name="menu rotation button",
group_id="menu",
condition=lambda e: e["type"] == "button"
and not e["change"]
and abs(e["value"]) == 1,
action=on_scroll,
enabled=True,
)
#event.Event(name="menu rotation captouch",group_id="menu",
# event.Event(name="menu rotation captouch",group_id="menu",
# condition=lambda e: e["type"] =="captouch" and not e["change"] and abs(e["value"])==1 and e["index"]==2,
# action=on_scroll_captouch, enabled=True
#)
# )
event.Event(name="menu rotation button release",group_id="menu",
condition=lambda e: e["type"] =="button" and e["change"] and e["value"] ==0,
action=on_release, enabled=True
event.Event(
name="menu rotation button release",
group_id="menu",
condition=lambda e: e["type"] == "button" and e["change"] and e["value"] == 0,
action=on_release,
enabled=True,
)
event.Event(name="menu 1d captouch",group_id="menu",
condition=lambda e: e["type"] =="captouch" and (e["value"]==1 or e["change"]) and e["index"]%2==1,
action=on_touch_1d, enabled=True
event.Event(
name="menu 1d captouch",
group_id="menu",
condition=lambda e: e["type"] == "captouch"
and (e["value"] == 1 or e["change"])
and e["index"] % 2 == 1,
action=on_touch_1d,
enabled=True,
)
event.Event(name="menu button enter",group_id="menu",
condition=lambda e: e["type"] =="button" and e["change"] and e["from"] == 2,
action=on_enter, enabled=True
event.Event(
name="menu button enter",
group_id="menu",
condition=lambda e: e["type"] == "button" and e["change"] and e["from"] == 2,
action=on_enter,
enabled=True,
)
def set_active_menu(menu):
event.the_engine.active_menu = menu
def get_active_menu():
return event.the_engine.active_menu
def menu_back():
previous = menu_stack.pop()
log.info(f"back to previous menu {previous.name} (Stack: {len(menu_stack)})")
set_active_menu(previous)
def submenu_push(new_menu):
active = get_active_menu()
menu_stack.append(active)
active.rotate_to(0)
if new_menu:
log.info(f"enter submenu {new_menu.name} from {active.name} (Stack: {len(menu_stack)})")
log.info(
f"enter submenu {new_menu.name} from {active.name} (Stack: {len(menu_stack)})"
)
else:
log.info(f"leaving menu from {active.name}")
set_active_menu(new_menu)
\ No newline at end of file
set_active_menu(new_menu)
import hardware as _hardware
class NamedObject():
def __init__(self,name="foo"):
class NamedObject:
def __init__(self, name="foo"):
self.__name = name
def __repr__(self):
return self.__name
class MockObject(NamedObject):
def __getattr__(self,attr):
attr_name = "{}.{}".format(str(self),attr)
print ("mock attr", attr_name)
def __getattr__(self, attr):
attr_name = "{}.{}".format(str(self), attr)
print("mock attr", attr_name)
return MockObject(attr_name)
def __call__(self,*args,**kwargs):
call_name = "{}({}{})".format(str(self),args,kwargs)
print ("mock call",call_name)
def __call__(self, *args, **kwargs):
call_name = "{}({}{})".format(str(self), args, kwargs)
print("mock call", call_name)
return MockObject(call_name)
......@@ -37,4 +38,4 @@ except ModuleNotFoundError:
hardware = _hardware
audio = _audio
ctx =hardware.get_ctx()
\ No newline at end of file
ctx = hardware.get_ctx()
from st3m import logging
log = logging.Log(__name__,level=logging.INFO)
log = logging.Log(__name__, level=logging.INFO)
log.info("import")
from st3m.system import ctx
import random
import math
import time
from math import sin,cos,pi
from math import sin, cos, pi
import gc
WIDTH = 240
HEIGHT = 240
#Define a few RGB (0.0 to 1.0) colors
BLACK = (0,0,0)
RED = (1,0,0)
GREEN = (0,1,0)
BLUE = (0,0,1)
WHITE = (1,1,1)
GREY = (0.5,0.5,0.5)
GO_GREEN = (63/255,255/255,33/53)
PUSH_RED = (251/255,72/255,196/255)
# Define a few RGB (0.0 to 1.0) colors
BLACK = (0, 0, 0)
RED = (1, 0, 0)
GREEN = (0, 1, 0)
BLUE = (0, 0, 1)
WHITE = (1, 1, 1)
GREY = (0.5, 0.5, 0.5)
GO_GREEN = (63 / 255, 255 / 255, 33 / 53)
PUSH_RED = (251 / 255, 72 / 255, 196 / 255)
the_ctx = ctx
# Utility functions
def xy_from_polar(r,phi):
return (
r * math.sin(phi), #x
r * math.cos(phi) #y
)
def xy_from_polar(r, phi):
return (r * math.sin(phi), r * math.cos(phi)) # x # y
#def ctx_circle(self, x,y, radius, arc_from = -math.pi, arc_to = math.pi):
# def ctx_circle(self, x,y, radius, arc_from = -math.pi, arc_to = math.pi):
# return self.arc(x,y,radius,arc_from,arc_to,True)
#the_ctx.circle = ctx_circle
# the_ctx.circle = ctx_circle
def randrgb():
return ((random.random(),random.random(),random.random()))
return (random.random(), random.random(), random.random())
class UIElement():
def __init__(self,origin=(0,0)):
class UIElement:
def __init__(self, origin=(0, 0)):
self.children = []
self.origin = origin
self.ctx = the_ctx
def draw(self, offset=(0,0)):
pos = (self.origin[0]+offset[0],self.origin[1]+offset[1])
def draw(self, offset=(0, 0)):
pos = (self.origin[0] + offset[0], self.origin[1] + offset[1])
self._draw(pos)
for child in self.children:
child.draw(pos)
def _draw(self,pos):
def _draw(self, pos):
pass
def add(self, child):
self.children.append(child)
class Viewport(UIElement):
def _draw(self,pos):
def _draw(self, pos):
pass
#self.ctx.rgb(0.3,0.3,0.3).rectangle(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT).fill()
# self.ctx.rgb(0.3,0.3,0.3).rectangle(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT).fill()
class Circle(UIElement):
def __init__(self,radius,color=PUSH_RED,arc_from=-math.pi, arc_to=math.pi, *args, **kwargs):
def __init__(
self, radius, color=PUSH_RED, arc_from=-math.pi, arc_to=math.pi, *args, **kwargs
):
self.radius = radius
self.color = color
self.arc_from = arc_from
self.arc_to = arc_to
super().__init__()
def _draw(self,pos):
(x,y)=pos
self.ctx.move_to(x,y).rgb(*self.color).arc(x,y,self.radius,self.arc_from,self.arc_to,True).fill()
def _draw(self, pos):
(x, y) = pos
self.ctx.move_to(x, y).rgb(*self.color).arc(
x, y, self.radius, self.arc_from, self.arc_to, True
).fill()
class Text(UIElement):
def __init__(self,s="foo"):
def __init__(self, s="foo"):
self.s = s
super().__init__()
......@@ -88,101 +94,132 @@ class Text(UIElement):
self.ctx.text_align = self.ctx.CENTER
self.ctx.text_baseline = self.ctx.MIDDLE
self.ctx.font_size = 30
self.ctx.rgb(1,1,1).move_to(pos[0],pos[1]).text(self.s)
self.ctx.rgb(1, 1, 1).move_to(pos[0], pos[1]).text(self.s)
class Icon(UIElement):
def __init__(self,label="?", size=60):
self.bg = (random.random(),random.random(),random.random())
def __init__(self, label="?", size=60):
self.bg = (random.random(), random.random(), random.random())
self.fg = 0
self.label=label
self.size=size
self.label = label
self.size = size
self.has_highlight = False
super().__init__()
def _draw(self,pos):
def _draw(self, pos):
self.ctx.text_align = self.ctx.CENTER
self.ctx.text_baseline = self.ctx.MIDDLE
self.ctx.font_size=self.size/3
self.ctx.font_size = self.size / 3
(x,y)=pos
(x, y) = pos
hs = 5
if self.has_highlight:
self.ctx.rgb(*GO_GREEN).arc(x,y, self.size/2+hs,-math.pi,math.pi,True).fill()
self.ctx.move_to(x,y).rgb(*self.bg).arc(x,y,self.size/2,-math.pi,math.pi,True).fill()
y += self.size/3
width = max(self.size-10, self.ctx.text_width(self.label))+10
height = self.size/3+8
if self.has_highlight:
self.ctx.rgb(*BLACK).move_to(x,y-height/2).round_rectangle(x-width/2,y-height/2,width,height,width//2).fill()
self.ctx.rgb(*GO_GREEN).move_to(x,y).text(self.label)
self.ctx.rgb(*GO_GREEN).arc(
x, y, self.size / 2 + hs, -math.pi, math.pi, True
).fill()
self.ctx.move_to(x, y).rgb(*self.bg).arc(
x, y, self.size / 2, -math.pi, math.pi, True
).fill()
y += self.size / 3
width = max(self.size - 10, self.ctx.text_width(self.label)) + 10
height = self.size / 3 + 8
if self.has_highlight:
self.ctx.rgb(*BLACK).move_to(x, y - height / 2).round_rectangle(
x - width / 2, y - height / 2, width, height, width // 2
).fill()
self.ctx.rgb(*GO_GREEN).move_to(x, y).text(self.label)
else:
self.ctx.rgb(*PUSH_RED).move_to(x,y-height/2).round_rectangle(x-width/2,y-height/2,width,height,width//2).fill()
self.ctx.rgb(*BLACK).move_to(x,y).text(self.label)
self.ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
x - width / 2, y - height / 2, width, height, width // 2
).fill()
self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
class IconLabel(Icon):
def _draw(self,pos):
def _draw(self, pos):
self.ctx.text_align = self.ctx.CENTER
self.ctx.text_baseline = self.ctx.MIDDLE
self.ctx.font_size=self.size/2
self.ctx.font_size = self.size / 2
(x,y)=pos
(x, y) = pos
hs = 5
width = self.ctx.text_width(self.label)+10
height = self.size/2
width = self.ctx.text_width(self.label) + 10
height = self.size / 2
if self.has_highlight:
self.ctx.rgb(*GO_GREEN).move_to(x,y-height/2).round_rectangle(x-width/2,y-height/2,width,height,width//2).fill()
self.ctx.rgb(*BLACK).move_to(x,y).text(self.label)
self.ctx.rgb(*GO_GREEN).move_to(x, y - height / 2).round_rectangle(
x - width / 2, y - height / 2, width, height, width // 2
).fill()
self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
else:
self.ctx.rgb(*PUSH_RED).move_to(x,y-height/2).round_rectangle(x-width/2,y-height/2,width,height,width//2).fill()
self.ctx.rgb(*BLACK).move_to(x,y).text(self.label)
self.ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
x - width / 2, y - height / 2, width, height, width // 2
).fill()
self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
class IconFlower(Icon):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.petal_count= random.randint(3,5)
#self.petal_count = 0
self.petal_color = (random.random(),random.random(),random.random())
self.petal_count = random.randint(3, 5)
# self.petal_count = 0
self.petal_color = (random.random(), random.random(), random.random())
self.phi_offset = random.random()
self.size_offset = random.randint(0,20)
#self.bg=PUSH_RED
def _draw(self,pos):
self.size_offset = random.randint(0, 20)
# self.bg=PUSH_RED
def _draw(self, pos):
self.ctx.text_align = self.ctx.CENTER
self.ctx.text_baseline = self.ctx.MIDDLE
self.ctx.font_size=self.size/3
self.ctx.font_size = self.size / 3
(x,y)=pos
petal_size=0
(x, y) = pos
petal_size = 0
if self.petal_count:
petal_size=2.3*self.size/self.petal_count+self.size_offset
petal_size = 2.3 * self.size / self.petal_count + self.size_offset
hs = 5
for i in range(self.petal_count):
phi = math.pi*2 / self.petal_count * i + self.phi_offset
r = self.size/2
(x_,y_) = xy_from_polar(r, phi)
size_rnd = random.randint(-1,1)
phi = math.pi * 2 / self.petal_count * i + self.phi_offset
r = self.size / 2
(x_, y_) = xy_from_polar(r, phi)
size_rnd = random.randint(-1, 1)
if self.has_highlight:
self.ctx.move_to(x+x_,y+y_).rgb(*GO_GREEN).arc(x+x_,y+y_, petal_size/2+hs+size_rnd,-math.pi,math.pi,True).fill()
self.ctx.move_to(x+x_,y+y_).rgb(*self.petal_color).arc(x+x_,y+y_, petal_size/2+size_rnd,-math.pi,math.pi,True).fill()
if self.has_highlight:
self.ctx.rgb(*GO_GREEN).arc(x,y, self.size/2+hs,-math.pi,math.pi,True).fill()
self.ctx.move_to(x,y).rgb(*self.bg).arc(x,y,self.size/2,-math.pi,math.pi,True).fill()
self.ctx.move_to(x + x_, y + y_).rgb(*GO_GREEN).arc(
x + x_,
y + y_,
petal_size / 2 + hs + size_rnd,
-math.pi,
math.pi,
True,
).fill()
self.ctx.move_to(x + x_, y + y_).rgb(*self.petal_color).arc(
x + x_, y + y_, petal_size / 2 + size_rnd, -math.pi, math.pi, True
).fill()
y += self.size/3
width = max(self.size, self.ctx.text_width(self.label)+10)
height = self.size/3+8
if self.has_highlight:
self.ctx.rgb(*BLACK).move_to(x,y-height/2).round_rectangle(x-width/2,y-height/2,width,height,width//2).fill()
self.ctx.rgb(*GO_GREEN).move_to(x,y).text(self.label)
self.ctx.rgb(*GO_GREEN).arc(
x, y, self.size / 2 + hs, -math.pi, math.pi, True
).fill()
self.ctx.move_to(x, y).rgb(*self.bg).arc(
x, y, self.size / 2, -math.pi, math.pi, True
).fill()
y += self.size / 3
width = max(self.size, self.ctx.text_width(self.label) + 10)
height = self.size / 3 + 8
if self.has_highlight:
self.ctx.rgb(*BLACK).move_to(x, y - height / 2).round_rectangle(
x - width / 2, y - height / 2, width, height, width // 2
).fill()
self.ctx.rgb(*GO_GREEN).move_to(x, y).text(self.label)
else:
self.ctx.rgb(*PUSH_RED).move_to(x,y-height/2).round_rectangle(x-width/2,y-height/2,width,height,width//2).fill()
self.ctx.rgb(*BLACK).move_to(x,y).text(self.label)
self.ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
x - width / 2, y - height / 2, width, height, width // 2
).fill()
self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
class IconValue(Icon):
......@@ -190,9 +227,9 @@ class IconValue(Icon):
super().__init__(*args, **kwargs)
self.value = value
self.get_value = None
def _draw(self,pos):
(x,y) = pos
def _draw(self, pos):
(x, y) = pos
v = self.value
if self.get_value:
......@@ -201,50 +238,55 @@ class IconValue(Icon):
self.ctx.text_align = self.ctx.CENTER
self.ctx.text_baseline = self.ctx.MIDDLE
self.ctx.font_size=self.size/3
self.ctx.font_size = self.size / 3
if self.has_highlight:
self.ctx.move_to(x,y).rgb(*WHITE).arc(x,y,self.size/2+5,-pi,pi,True).fill()
self.ctx.move_to(x,y).rgb(*PUSH_RED).arc(x,y,self.size/2,-pi,pi,True).fill()
self.ctx.move_to(x,y).rgb(*GO_GREEN).arc(x,y,self.size/2-5,v*2*pi,0,1).fill()
self.ctx.rgb(0,0,0).move_to(x,y).text(self.label)
self.ctx.move_to(x, y).rgb(*WHITE).arc(
x, y, self.size / 2 + 5, -pi, pi, True
).fill()
self.ctx.move_to(x, y).rgb(*PUSH_RED).arc(
x, y, self.size / 2, -pi, pi, True
).fill()
self.ctx.move_to(x, y).rgb(*GO_GREEN).arc(
x, y, self.size / 2 - 5, v * 2 * pi, 0, 1
).fill()
self.ctx.rgb(0, 0, 0).move_to(x, y).text(self.label)
class GroupStackedVertical(UIElement):
pass
class GroupRing(UIElement):
def __init__(self,r=100,origin=(0,0),element_center=None):
def __init__(self, r=100, origin=(0, 0), element_center=None):
self.r = r
self.angle_offset = 0
self.element_center=element_center
self.element_center = element_center
super().__init__(origin)
def draw(self, offset=(0,0)):
pos = (self.origin[0]+offset[0],self.origin[1]+offset[1])
def draw(self, offset=(0, 0)):
pos = (self.origin[0] + offset[0], self.origin[1] + offset[1])
self._draw(pos)
for index in range(len(self.children)):
#print("child",index)
# print("child",index)
child = self.children[index]
if not child:
continue
angle = 2*math.pi/len(self.children)*index+self.angle_offset
#print(angle,self.r,pos[0])
x = -math.sin(angle)*self.r+pos[0]
y = -math.cos(angle)*self.r+pos[1]
#print("pos",(x,y))
child.draw(offset=(x,y))
def _draw(self,pos):
angle = 2 * math.pi / len(self.children) * index + self.angle_offset
# print(angle,self.r,pos[0])
x = -math.sin(angle) * self.r + pos[0]
y = -math.cos(angle) * self.r + pos[1]
# print("pos",(x,y))
child.draw(offset=(x, y))
def _draw(self, pos):
if self.element_center:
self.element_center.has_highlight = False
self.element_center._draw(pos)
class GroupPetals(GroupRing):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.children = [None for i in range(10)]
\ No newline at end of file
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.children = [None for i in range(10)]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment