Skip to content
Snippets Groups Projects
Commit ddca99c4 authored by q3k's avatar q3k
Browse files

py: st4m -> st3m

parent 3bd77c9e
Branches
Tags
1 merge request!35py: grand st3m unification
Showing
with 62 additions and 326 deletions
from st4m import application, logging from st3m import application, logging
from st4m.goose import List from st3m.goose import List
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
from st4m.input import InputState from st3m.input import InputState
log = logging.Log(__name__, level=logging.INFO) log = logging.Log(__name__, level=logging.INFO)
log.info("import") log.info("import")
......
...@@ -4,11 +4,11 @@ import time ...@@ -4,11 +4,11 @@ import time
import math import math
# flow3r imports # flow3r imports
from st4m import application from st3m import application
from st4m import Ctx, InputState from st3m import Ctx, InputState
from st4m.property import BLUE, WHITE from st3m.property import BLUE, WHITE
from st4m.goose import Optional from st3m.goose import Optional
from st4m.utils import xy_from_polar from st3m.utils import xy_from_polar
tau = 2 * math.pi tau = 2 * math.pi
......
...@@ -3,9 +3,9 @@ import captouch ...@@ -3,9 +3,9 @@ import captouch
import leds import leds
import hardware import hardware
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
from st4m.goose import List from st3m.goose import List
from st4m.input import InputState from st3m.input import InputState
chords = [ chords = [
[-4, 0, 3, 8, 10], [-4, 0, 3, 8, 10],
...@@ -16,7 +16,7 @@ chords = [ ...@@ -16,7 +16,7 @@ chords = [
] ]
from st4m.application import Application from st3m.application import Application
class HarmonicApp(Application): class HarmonicApp(Application):
......
...@@ -3,9 +3,9 @@ from hardware import * ...@@ -3,9 +3,9 @@ from hardware import *
import captouch import captouch
import leds import leds
from st4m.goose import List from st3m.goose import List
from st4m.input import InputState from st3m.input import InputState
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
octave = 0 octave = 0
synths: List[tinysynth] = [] synths: List[tinysynth] = []
...@@ -78,7 +78,7 @@ def foreground() -> None: ...@@ -78,7 +78,7 @@ def foreground() -> None:
adjust_playing_field_to_octave() adjust_playing_field_to_octave()
from st4m.application import Application from st3m.application import Application
# TODO(q3k): properly port this app # TODO(q3k): properly port this app
......
from st4m.application import Application from st3m.application import Application
from st4m.property import PUSH_RED, GO_GREEN, BLACK from st3m.property import PUSH_RED, GO_GREEN, BLACK
from st4m.goose import Dict, Any from st3m.goose import Dict, Any
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
from st4m.input import InputState from st3m.input import InputState
import leds import leds
import json import json
......
...@@ -2,23 +2,23 @@ import time, gc ...@@ -2,23 +2,23 @@ import time, gc
ts_start = time.time() ts_start = time.time()
from st4m import logging 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"starting main")
log.info(f"free memory: {gc.mem_free()}") log.info(f"free memory: {gc.mem_free()}")
import st4m import st3m
from st4m.goose import Optional, List, ABCBase, abstractmethod from st3m.goose import Optional, List, ABCBase, abstractmethod
from st4m.ui.view import View, ViewManager, ViewTransitionBlend from st3m.ui.view import View, ViewManager, ViewTransitionBlend
from st4m.ui.menu import ( from st3m.ui.menu import (
MenuItemBack, MenuItemBack,
MenuItemForeground, MenuItemForeground,
MenuItemNoop, MenuItemNoop,
) )
from st4m.ui.elements.menus import FlowerMenu, SimpleMenu, SunMenu from st3m.ui.elements.menus import FlowerMenu, SimpleMenu, SunMenu
log.info("import apps done") log.info("import apps done")
log.info(f"free memory: {gc.mem_free()}") log.info(f"free memory: {gc.mem_free()}")
...@@ -26,7 +26,7 @@ ts_end = time.time() ...@@ -26,7 +26,7 @@ ts_end = time.time()
log.info(f"boot took {ts_end-ts_start} seconds") log.info(f"boot took {ts_end-ts_start} seconds")
# TODO persistent settings # TODO persistent settings
from st4m.system import audio, captouch from st3m.system import audio, captouch
log.info("calibrating captouch, reset volume") log.info("calibrating captouch, reset volume")
captouch.calibration_request() captouch.calibration_request()
...@@ -95,7 +95,7 @@ menu_main = SunMenu( ...@@ -95,7 +95,7 @@ menu_main = SunMenu(
vm.push(menu_main) vm.push(menu_main)
reactor = st4m.Reactor() reactor = st3m.Reactor()
reactor.set_top(vm) reactor.set_top(vm)
# reactor.set_top(pr) # reactor.set_top(pr)
reactor.run() reactor.run()
"""
Experimental/Research UI/UX framework (st4m).
To run, rename this file to main.py.
See st4m/README.md for more information.
"""
import st4m
from st4m.goose import Optional, List, ABCBase, abstractmethod
from st4m.ui.view import View, ViewManager, ViewTransitionBlend
from st4m.ui.menu import (
MenuItem,
MenuController,
MenuItemBack,
MenuItemForeground,
MenuItemNoop,
)
from st4m import Responder, InputState, Ctx
import math, hardware
from st4m.ui.elements.menus import SunMenu, SimpleMenu
vm = ViewManager(ViewTransitionBlend())
menu_music = SimpleMenu(
[
MenuItemBack(),
MenuItemNoop("Harmonic"),
MenuItemNoop("Melodic"),
MenuItemNoop("TinySynth"),
MenuItemNoop("CrazySynth"),
MenuItemNoop("Sequencer"),
],
vm,
)
menu_apps = SimpleMenu(
[
MenuItemBack(),
MenuItemNoop("captouch"),
MenuItemNoop("worms"),
],
vm,
)
class USBIcon(Responder):
"""
Found in the bargain bin at an Aldi Süd.
"""
def draw(self, ctx: Ctx) -> None:
ctx.gray(1.0)
ctx.arc(-90, 0, 20, 0, 6.28, 0).fill()
ctx.line_width = 10.0
ctx.move_to(-90, 0).line_to(90, 0).stroke()
ctx.move_to(100, 0).line_to(70, 15).line_to(70, -15).line_to(100, 0).fill()
ctx.move_to(-50, 0).line_to(-10, -40).line_to(20, -40).stroke()
ctx.arc(20, -40, 15, 0, 6.28, 0).fill()
ctx.move_to(-30, 0).line_to(10, 40).line_to(40, 40).stroke()
ctx.rectangle(40 - 15, 40 - 15, 30, 30).fill()
def think(self, ins: InputState, delta_ms: int) -> None:
pass
class REPLIcon(Responder):
def draw(self, ctx: Ctx) -> None:
ctx.gray(1.0)
ctx.line_width = 10.0
for i in range(3):
x = i * 40
ctx.move_to(-60 + x, -60).line_to(0 + x, 0).line_to(-60 + x, 60).stroke()
def think(self, ins: InputState, delta_ms: int) -> None:
pass
class Sun(Responder):
"""
A rotating sun widget.
"""
def __init__(self) -> None:
self.x = 0.0
self.y = 0.0
self.size = 50.0
self.ts = 1.0
def think(self, ins: InputState, delta_ms: int) -> None:
self.ts += delta_ms
pass
def draw(self, ctx: Ctx) -> None:
nrays = 10
angle_per_ray = 6.28 / nrays
for i in range(nrays):
angle = i * angle_per_ray + self.ts / 4000
angle %= 3.14159 * 2
if angle > 2 and angle < 4:
continue
ctx.save()
ctx.rgb(0.5, 0.5, 0)
ctx.line_width = 30
ctx.translate(-120, 0).rotate(angle)
ctx.move_to(20, 0)
ctx.line_to(260, 0)
ctx.stroke()
ctx.restore()
ctx.save()
ctx.rgb(0.92, 0.89, 0)
ctx.translate(-120, 0)
ctx.arc(self.x, self.y, self.size, 0, 6.29, 0)
ctx.fill()
ctx.restore()
class MainMenu(MenuController):
"""
A circular menu with a rotating sun.
"""
__slots__ = (
"_ts",
"_sun",
)
def __init__(self, items: List[MenuItem], vm: ViewManager) -> None:
self._ts = 0
self._sun = Sun()
super().__init__(items, vm)
def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms)
self._sun.think(ins, delta_ms)
self._ts += delta_ms
def _draw_text_angled(
self, ctx: Ctx, text: str, angle: float, activity: float
) -> None:
size = lerp(20, 40, activity)
color = lerp(0, 1, activity)
if color < 0.01:
return
ctx.save()
ctx.translate(-120, 0).rotate(angle).translate(140, 0)
ctx.font_size = size
ctx.rgba(1.0, 1.0, 1.0, color).move_to(0, 0).text(text)
ctx.restore()
def draw(self, ctx: Ctx) -> None:
ctx.gray(0)
ctx.rectangle(-120, -120, 240, 240).fill()
self._sun.draw(ctx)
ctx.font_size = 40
ctx.text_align = ctx.CENTER
ctx.text_baseline = ctx.MIDDLE
angle_per_item = 0.4
current = self._scroll_controller.current_position()
for ix, item in enumerate(self._items):
rot = (ix - current) * angle_per_item
self._draw_text_angled(ctx, item.label(), rot, 1 - abs(rot))
class SimpleMenu(MenuController):
"""
A simple line-by-line menu.
"""
def draw(self, ctx: Ctx) -> None:
ctx.gray(0)
ctx.rectangle(-120, -120, 240, 240).fill()
ctx.text_align = ctx.CENTER
ctx.text_baseline = ctx.MIDDLE
current = self._scroll_controller.current_position()
ctx.gray(1)
for ix, item in enumerate(self._items):
offs = (ix - current) * 30
size = lerp(30, 20, abs(offs / 20))
ctx.font_size = size
ctx.move_to(0, offs).text(item.label())
menu_music = SimpleMenu(
[
MenuItemBack(),
MenuItemNoop("Harmonic"),
MenuItemNoop("Melodic"),
MenuItemNoop("TinySynth"),
MenuItemNoop("CrazySynth"),
MenuItemNoop("Sequencer"),
],
vm,
)
menu_apps = SimpleMenu(
[
MenuItemBack(),
MenuItemNoop("captouch"),
MenuItemNoop("worms"),
],
vm,
)
menu_main = SunMenu(
[
MenuItemForeground("Music", menu_music),
MenuItemForeground("Apps", menu_apps),
MenuItemNoop("Settings"),
],
vm,
)
vm.push(menu_main)
class Viewport(Responder):
def __init__(self, vm: ViewManager) -> None:
self.vm = vm
self.usb = USBIcon()
self.repl = REPLIcon()
self.visible: List[Responder] = []
def think(self, ins: InputState, delta_ms: int) -> None:
self.vm.think(ins, delta_ms)
self.visible = []
usb = hardware.usb_connected()
console = hardware.usb_console_active()
if not usb:
console = False
if usb:
self.visible.append(self.usb)
# if console:
# self.visible.append(self.repl)
for v in self.visible:
v.think(ins, delta_ms)
def draw(self, ctx: Ctx) -> None:
self.vm.draw(ctx)
nicons = len(self.visible)
dist = 20
width = (nicons - 1) * dist
x0 = width / -2
for i, v in enumerate(self.visible):
x = x0 + i * dist
ctx.save()
ctx.translate(x, -100)
ctx.scale(0.1, 0.1)
v.draw(ctx)
ctx.restore()
reactor = st4m.Reactor()
reactor.set_top(Viewport(vm))
reactor.run()
import time import time
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
def freertos_sleep(ms: int) -> None: ... def freertos_sleep(ms: int) -> None: ...
def get_ctx() -> Ctx: ... def get_ctx() -> Ctx: ...
......
from st4m.reactor import Reactor, Responder from st3m.reactor import Reactor, Responder
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
from st4m.input import InputState, InputController from st3m.input import InputState, InputController
__all__ = [ __all__ = [
"Reactor", "Reactor",
......
from st4m.ui.view import ViewWithInputState, ViewTransitionSwipeRight, ViewManager from st3m.ui.view import ViewWithInputState, ViewTransitionSwipeRight, ViewManager
from st4m.input import InputState from st3m.input import InputState
from st4m.goose import Optional from st3m.goose import Optional
class Application(ViewWithInputState): class Application(ViewWithInputState):
......
""" """
Goose implements Goose Typing (tm), a set of shims which allows the st4m Goose implements Goose Typing (tm), a set of shims which allows the st3m
codebase to use both Python type annotations, Abstract Base Classes and run codebase to use both Python type annotations, Abstract Base Classes and run
under Micropython. under Micropython.
""" """
......
from st4m.goose import List, Optional, Enum, Tuple from st3m.goose import List, Optional, Enum, Tuple
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
import hardware import hardware
import captouch import captouch
......
import sys import sys
import time import time
from st4m.goose import Enum from st3m.goose import Enum
class Level(Enum): class Level(Enum):
......
File moved
from st4m.goose import ABCBase, abstractmethod, List, Optional from st3m.goose import ABCBase, abstractmethod, List, Optional
from st4m.input import InputState from st3m.input import InputState
from st4m.ui.ctx import Ctx from st3m.ui.ctx import Ctx
import time, hardware import time, hardware
...@@ -50,7 +50,7 @@ class Responder(ABCBase): ...@@ -50,7 +50,7 @@ class Responder(ABCBase):
class Reactor: class Reactor:
""" """
The Reactor is the main Micropython scheduler of the st4m system and any The Reactor is the main Micropython scheduler of the st3m system and any
running payloads. running payloads.
It will attempt to run a top Responder with a fixed tickrate a framerate It will attempt to run a top Responder with a fixed tickrate a framerate
......
File moved
from st4m.goose import ABCBase, abstractmethod, List from st3m.goose import ABCBase, abstractmethod, List
class Ctx(ABCBase): class Ctx(ABCBase):
""" """
Ctx is the rendering/rasterization API used by st4m. Ctx is the rendering/rasterization API used by st3m.
It's a WebCanvas-style vector API, with an implicit pen which can be moved It's a WebCanvas-style vector API, with an implicit pen which can be moved
and can draw lines, arcs, text, etc. and can draw lines, arcs, text, etc.
In st4m, the Ctx object is backed by a drawlist generator. That is, any In st3m, the Ctx object is backed by a drawlist generator. That is, any
operation performed on the ctx object will cause an entry to be added to an operation performed on the ctx object will cause an entry to be added to an
in-memory draw list. Then, when the rasterizer is ready, it will rasterize in-memory draw list. Then, when the rasterizer is ready, it will rasterize
said drawlist to pixels in a separate thread. said drawlist to pixels in a separate thread.
......
from st4m.goose import Optional, List, ABCBase, abstractmethod from st3m.goose import Optional, List, ABCBase, abstractmethod
from st4m.ui.view import ViewManager from st3m.ui.view import ViewManager
from st4m.ui.elements.visuals import Sun, GroupRing, FlowerIcon from st3m.ui.elements.visuals import Sun, GroupRing, FlowerIcon
from st4m.ui.menu import MenuController, MenuItem from st3m.ui.menu import MenuController, MenuItem
from st4m import Ctx, InputState from st3m import Ctx, InputState
from st4m.utils import lerp, tau from st3m.utils import lerp, tau
import math import math
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment