From c8ab1d9a376183102615ee2d1eb5bc75ef342e03 Mon Sep 17 00:00:00 2001
From: iggy <iggy@muc.ccc.de>
Date: Thu, 8 Jun 2023 17:13:43 +0200
Subject: [PATCH] py: cleanup and refactoring. proper split between tick() and
 draw(), menu is now bound to application, eventloop improvements (speed \o/)

---
 python_payload/apps/demo_worms.py       |  8 +--
 python_payload/apps/flow3r/__init__.py  |  7 +--
 python_payload/apps/flow3r/menu_main.py |  2 +-
 python_payload/main.py                  |  7 +--
 python_payload/st3m/application.py      | 29 +++++++----
 python_payload/st3m/event.py            | 37 +++++++++++---
 python_payload/st3m/menu.py             | 66 +++++++++++++++----------
 python_payload/st3m/ui.py               |  9 ++--
 8 files changed, 102 insertions(+), 63 deletions(-)

diff --git a/python_payload/apps/demo_worms.py b/python_payload/apps/demo_worms.py
index d45ed1d552..2231c077b7 100644
--- a/python_payload/apps/demo_worms.py
+++ b/python_payload/apps/demo_worms.py
@@ -28,7 +28,7 @@ class AppWorms(application.Application):
 
         self.worms = []
         for i in range(0):
-            worms.append(Worm())
+            self.worms.append(Worm())
     
     def on_foreground(self):
         print("on foreground")
@@ -46,6 +46,10 @@ class AppWorms(application.Application):
         #Write some text
         ctx.move_to(0,0).rgb(*ui.WHITE).text("touch me :)")
 
+    def on_draw(self):
+        for w in self.worms:
+            w.draw()
+
     def main_foreground(self):
         now = time.ticks_ms()
 
@@ -62,9 +66,7 @@ class AppWorms(application.Application):
                 self.last_report = now
 
         # Simulation is currently locked to FPS.
-
         for w in self.worms:
-            w.draw()
             w.move()
         
         self.last_render = now
diff --git a/python_payload/apps/flow3r/__init__.py b/python_payload/apps/flow3r/__init__.py
index b5febcae8f..3f6aa3969f 100644
--- a/python_payload/apps/flow3r/__init__.py
+++ b/python_payload/apps/flow3r/__init__.py
@@ -2,12 +2,9 @@ from st3m.application import Application,menu
 from . import menu_main
 class myApp(Application):
     def on_init(self):
-        self.appmenu = menu_main.get_menu()
+        self.menu = menu_main.get_menu()
 
     def on_foreground(self):
-        menu.set_active_menu(self.appmenu)
-
-    def main_foreground(self):
-        menu.render()
+        menu.set_active_menu(self.menu)
 
 app=myApp("flow3r")
diff --git a/python_payload/apps/flow3r/menu_main.py b/python_payload/apps/flow3r/menu_main.py
index 009c9ba7a3..5fb3177c42 100644
--- a/python_payload/apps/flow3r/menu_main.py
+++ b/python_payload/apps/flow3r/menu_main.py
@@ -1,7 +1,7 @@
 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 import demo_sparabo, melodic_demo, harmonic_demo
 from apps.flow3r import menu_settings,menu_tinysynth
 
 
diff --git a/python_payload/main.py b/python_payload/main.py
index 9b192358a5..49f8af1acb 100644
--- a/python_payload/main.py
+++ b/python_payload/main.py
@@ -6,9 +6,4 @@ hardware.captouch_autocalib()
 audio.set_volume_dB(0)
 
 #Start default app
-flow3r.app.run()
-
-#Start the eventloop
-event.the_engine.eventloop()    
-
-#We will never get here...
\ No newline at end of file
+flow3r.app.run()
\ No newline at end of file
diff --git a/python_payload/st3m/application.py b/python_payload/st3m/application.py
index 23fe9f9a41..45c8aef0b0 100644
--- a/python_payload/st3m/application.py
+++ b/python_payload/st3m/application.py
@@ -17,15 +17,15 @@ class Application():
         self._events_background = []
         self._events_foreground = []
         self.ui = ui.Viewport()
+        self.icon = ui.Icon(label=self.title, size=100)
         self.engine = event.the_engine
+        self.menu = None
 
         self.add_event(event.Event(
                 name="exit",
             action=self.exit,
             condition=lambda e: e["type"]=="button" and e.get("from")==2 and e["change"]
         ))
-
-        self.ui.add(ui.Icon(label=self.title, size=100))
         
     def __repr__(self):
         return "App "+self.title
@@ -69,11 +69,19 @@ class Application():
     def kill(self):
         #disable all events
         engine.register_service_loop(self.main_always,False)
-        engine.register_main_loop(self.main_forground,False)
+        
+        engine.foreground_app = None
         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):
         if not is_background:
             self._events_foreground.append(event)
@@ -95,21 +103,17 @@ class Application():
         
         if self._events_foreground:
             self._set_events(self._events_foreground,True)
-        #TODO should this really happen here??
-        menu.menu_disable()
-        if self.ui:
-            self.ui.draw()
         self.on_foreground()
         
-        self.engine.register_main_loop(self.main_foreground,True)
-        
+        #self.engine.register_main_loop(self.main_foreground,True)
+        self.engine.foreground_app = self
           
     def _to_background(self):
         self.state = STATE_BACKGROUND
         if self._events_foreground:
             self._set_events(self._events_foreground,False)
 
-        self.engine.register_main_loop(self.main_foreground,False)
+        self.engine.foreground_app = None
         if self.has_background:
             self.state = STATE_BACKGROUND
         self.on_background()
@@ -134,6 +138,11 @@ class Application():
     def on_kill(self): 
         pass
 
+    def on_draw(self):
+        #self.ui.ctx.rgb(*ui.RED).rectangle(-120,-120,120,120).fill()
+        #self.icon.draw()
+        pass
+
     def main_foreground(self):
         pass
     
diff --git a/python_payload/st3m/event.py b/python_payload/st3m/event.py
index d8eeffc5b4..6aa5f8be94 100644
--- a/python_payload/st3m/event.py
+++ b/python_payload/st3m/event.py
@@ -18,7 +18,9 @@ class Engine():
         self.last_input_state = None
         self.userloop = None
         self.is_running = False
-    
+        self.foreground_app = None
+        self.active_menu = None
+
     def add(self,event):
         if isinstance(event,EventTimed):
             self.add_timed(event)
@@ -127,17 +129,25 @@ class Engine():
         self.last_input_state=input_state        
         
     def _handle_userloop(self):
-        if not self.userloop is None:
-            #print("userloop",self.userloop)
-            self.userloop()
-        
+        if self.foreground_app:
+            self.foreground_app.tick()
+
+    
+    def _handle_draw(self):
+        if self.foreground_app:
+            self.foreground_app.draw()
+        if self.active_menu:
+            self.active_menu.draw()
+        hardware.display_update()
+
+
+
     def _eventloop_single(self):
         self._handle_timed()
         self._handle_input()
         self._handle_userloop()
-        hardware.display_update()
         
-            
+        
     def eventloop(self):
         if self.is_running:
             print ("eventloop already running")
@@ -145,10 +155,20 @@ class Engine():
         else:
             print("eventloop started")
         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")
+                self._handle_draw()
+                last_draw = time.ticks_ms()
 
-            time.sleep(0.005)
+            #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):
@@ -165,6 +185,7 @@ class Event():
         
         if enabled:
             self.set_enabled()
+
             
             
         
diff --git a/python_payload/st3m/menu.py b/python_payload/st3m/menu.py
index 31d7f762ae..f3c2c57395 100644
--- a/python_payload/st3m/menu.py
+++ b/python_payload/st3m/menu.py
@@ -6,7 +6,6 @@ import time
 import math
 
 menu_stack = []
-active_menu = None
 
 class Menu():
     def __init__(self,name="menu",has_back=True):
@@ -21,6 +20,7 @@ class Menu():
         
         self.angle = 0
         self.angle_step= 0.2
+
         if has_back:
             self.add(MenuItemBack())
 
@@ -42,8 +42,7 @@ class Menu():
 
     def start(self):
         print(self)
-        active_menu = self
-        render()
+        set_active_menu(self)
 
     def scroll(self, n=0):
         self.__index= (self.__index+n)%len(self.items)
@@ -83,7 +82,12 @@ class Menu():
     
 
     def draw(self):
-        
+
+        #TODO this is more like a hack...
+        #if not self==active_menu: 
+        #    active_menu.draw()
+        #    return
+        #print("draw",self.name)
         hovered_index = self._get_hovered_index()
         for i in range(len(self.items)):
             item = self.items[i]
@@ -96,6 +100,10 @@ class Menu():
                 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()
 
@@ -122,6 +130,9 @@ class MenuItemApp(MenuItem):
     
     def enter(self,data={}):
         if self.target:
+            global menu_stack
+            menu_stack.append(get_active_menu())
+            set_active_menu(None)
             self.target.run()
 
 class MenuItemSubmenu(MenuItem):
@@ -132,7 +143,7 @@ class MenuItemSubmenu(MenuItem):
     
     def enter(self,data={}):
         print("Enter Submenu {}".format(self.target.name))
-        menu_stack.append(active_menu)
+        menu_stack.append(get_active_menu())
         set_active_menu(self.target)
         
 class MenuItemBack(MenuItem):
@@ -160,6 +171,7 @@ class MenuItemControl(MenuItem):
         self.control.touch_1d(x,z)
         
 def on_scroll(d):
+    active_menu = get_active_menu()
     if active_menu is None:
         return
 
@@ -177,30 +189,32 @@ def on_scroll(d):
         elif d["value"] == 1:
             active_menu.rotate_steps(1)
 
-    render()
+
 
 def on_scroll_captouch(d):
-    
+    active_menu = get_active_menu()
     if active_menu is None:
         return
     
-    render()
-    return 
+    return
     if abs(d["radius"]) < 10000:
         return
     print(d["angle"])
     active_menu.rotate_to(d["angle"]+math.pi)
-    render()
 
 def on_release(d):
+    active_menu = get_active_menu()
+    
     if active_menu is None:
         return
 
     active_menu.angle_step = 0.2
-    render()
+
     
 
 def on_touch_1d(d):
+    active_menu = get_active_menu()
+    
     if active_menu is None:
         return
     #print(d["radius"])
@@ -224,9 +238,10 @@ def on_touch_1d(d):
         print("hastouch")
         hovered.touch_1d(v,z)
     
-    render()
 
 def on_enter(d):
+    active_menu = get_active_menu()
+    
     if active_menu is None:
         
         #TODO this should not bee needed...
@@ -236,10 +251,7 @@ def on_enter(d):
 
     if active_menu:
         active_menu.get_hovered_item().enter()
-        render()
-    else:
-        return
-
+    
     
 event.Event(name="menu rotation button",group_id="menu",
     condition=lambda e: e["type"] =="button" and not e["change"] and abs(e["value"])==1,
@@ -267,8 +279,10 @@ event.Event(name="menu button enter",group_id="menu",
     action=on_enter, enabled=True
 )
 
-def render():
+def old_render():
+
     print (active_menu)
+    return
     if active_menu is None:
         return
     
@@ -277,21 +291,21 @@ def render():
     #hardware.display_update()
 
 def set_active_menu(menu):
-    global active_menu
-    active_menu = menu
+    event.the_engine.active_menu = menu
 
-def menu_disable():
-    global active_menu
-    if active_menu:
-        menu_stack.append(active_menu)
-        active_menu=None
+def get_active_menu():
+    return event.the_engine.active_menu
+
+#def menu_disable():
+#    global active_menu
+#    if active_menu:
+#        menu_stack.append(active_menu)
+#        active_menu=None
 
 def menu_back():
     if not menu_stack:
         return
 
     previous = menu_stack.pop()
-
     set_active_menu(previous)
-    render()
     
\ No newline at end of file
diff --git a/python_payload/st3m/ui.py b/python_payload/st3m/ui.py
index dae5093e25..ea187b94ef 100644
--- a/python_payload/st3m/ui.py
+++ b/python_payload/st3m/ui.py
@@ -59,7 +59,8 @@ class UIElement():
 
 class Viewport(UIElement):
     def _draw(self,pos):
-        self.ctx.rgb(0.3,0.3,0.3).rectangle(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT).fill()
+        pass
+        #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):
@@ -136,8 +137,8 @@ class IconLabel(Icon):
 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_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)
@@ -159,7 +160,7 @@ class IconFlower(Icon):
             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(-3,3)
+            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()
-- 
GitLab