summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2024-03-08 18:21:22 -0800
committeryum <yum.food.vr@gmail.com>2024-03-08 18:21:22 -0800
commitcdc079fb59832fce46708df36ac80ede6d2bd046 (patch)
tree669ba5e6447467a9fb61f7f25062a30ab45e6f5f
parentb3983d3274b92b6f96efca894a56b1cb5422b621 (diff)
Add "simple" text-to-text demo for the modular avatar chatbox
To use it: $ python3 -m pip install python-osc pillow $ cd Scripts $ python3 ./text_to_text_demo.py
-rw-r--r--Scripts/text_to_text_demo.py98
1 files changed, 98 insertions, 0 deletions
diff --git a/Scripts/text_to_text_demo.py b/Scripts/text_to_text_demo.py
new file mode 100644
index 0000000..d5f0ada
--- /dev/null
+++ b/Scripts/text_to_text_demo.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+# python3 -m pip install python-osc pillow
+
+from math import ceil
+from paging import MultiLinePager
+from pythonosc import udp_client
+
+import generate_utils
+import osc_ctrl
+import paging
+import pythonosc
+import time
+
+class AppConfig:
+ def __init__(self,
+ rows: int = 4,
+ cols: int = 40,
+ chars_per_sync: int = 10,
+ osc_sync_rate_hz: int = 3):
+ self.rows = rows
+ self.cols = cols
+ self.chars_per_sync = chars_per_sync
+ self.osc_sync_rate_hz = osc_sync_rate_hz
+ self.client = osc_ctrl.getClient()
+
+def encodeMessage(msg):
+ encoded = []
+ for char in msg:
+ encoded.append(ord(char))
+ return encoded
+
+class OSCSyncHelper:
+ def __init__(self,
+ config: AppConfig):
+ self.sync_delay_s = 1.0 / config.osc_sync_rate_hz
+ self.last = time.time() - self.sync_delay_s
+
+ def waitForSync(self) -> None:
+ # sleep() can sleep for too short a time, so use a loop to ensure that
+ # we sleep at least a full sync window's worth of time.
+ while time.time() - self.last < self.sync_delay_s:
+ time.sleep(0.01)
+ self.last = time.time()
+
+def sendMessage(msg: str, cfg: AppConfig, osc: OSCSyncHelper) -> None:
+ num_cells = cfg.rows * cfg.cols
+ num_regions = ceil(num_cells / cfg.chars_per_sync)
+
+ pager = MultiLinePager(cfg.chars_per_sync, cfg.rows, cfg.cols)
+
+ # Show the chatbox
+ osc.waitForSync()
+ osc_ctrl.toggleBoard(cfg.client, True)
+ osc_ctrl.ellipsis(cfg.client, False)
+ osc_ctrl.disable(cfg.client)
+
+ # Ensure that the chatbox is cleared.
+ addr="/avatar/parameters/" + generate_utils.getClearBoardParam()
+ cfg.client.send_message(addr, True)
+ osc.waitForSync()
+ cfg.client.send_message(addr, False)
+
+ slice_idx = 0
+ while slice_idx != -1:
+
+ msg_slice, slice_idx = pager.getNextSlice(msg)
+ which_region = slice_idx % num_regions
+
+ print(f"Sending slice '{msg_slice}' to region {which_region}")
+
+ # Wait until OSC has had enough time to sync the previous window of
+ # data.
+ osc.waitForSync()
+
+ # Enable chatbox animations.
+ osc_ctrl.enable(cfg.client)
+
+ # Seek to the current region.
+ addr="/avatar/parameters/" + generate_utils.getSelectParam()
+ cfg.client.send_message(addr, which_region)
+
+ # Send all characters in the current region.
+ encoded = encodeMessage(msg_slice)
+ for i in range(0, len(msg_slice)):
+ print(f"Sending char {msg_slice[i]} / {encoded[i]}")
+ addr="/avatar/parameters/" + generate_utils.getBlendParam(i, 0)
+ letter_remapped = (-127.5 + encoded[i]) / 127.5
+ cfg.client.send_message(addr, letter_remapped)
+
+ # Disable chatbox animations to ensure stability.
+ osc.waitForSync()
+ osc_ctrl.disable(cfg.client)
+
+if __name__ == "__main__":
+ cfg = AppConfig()
+ osc = OSCSyncHelper(cfg)
+ sendMessage("Hello, world! aiueo aiueo aiueo aiueo aiueo eeeeeeeeeeeeeeeeeeeeeeee", cfg, osc)
+