summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Shaders/TaSTT.shader140
-rw-r--r--emotes.py123
-rw-r--r--generate_utils.py12
-rw-r--r--libtastt.py2
-rw-r--r--osc_ctrl.py58
5 files changed, 296 insertions, 39 deletions
diff --git a/Shaders/TaSTT.shader b/Shaders/TaSTT.shader
index 79a1bfc..66becaf 100644
--- a/Shaders/TaSTT.shader
+++ b/Shaders/TaSTT.shader
@@ -9,6 +9,7 @@
_Font_0x8000_0x9FFF ("Font 4 (unicode 0x8000 - 0x9FFFF)", 2D) = "white" {}
_Font_0xA000_0xBFFF ("Font 5 (unicode 0xA000 - 0xBFFFF)", 2D) = "white" {}
_Font_0xC000_0xDFFF ("Font 6 (unicode 0xC000 - 0xDFFFF)", 2D) = "white" {}
+ _Img_0xE000_0xE03F ("Images 0", 2D) = "white" {}
TaSTT_Backplate("TaSTT_Backplate", 2D) = "black" {}
@@ -60,6 +61,10 @@
_Letter_Row00_Col41_Byte0("_Letter_Row00_Col41_Byte0", float) = 0
_Letter_Row00_Col42_Byte0("_Letter_Row00_Col42_Byte0", float) = 0
_Letter_Row00_Col43_Byte0("_Letter_Row00_Col43_Byte0", float) = 0
+ _Letter_Row00_Col44_Byte0("_Letter_Row00_Col44_Byte0", float) = 0
+ _Letter_Row00_Col45_Byte0("_Letter_Row00_Col45_Byte0", float) = 0
+ _Letter_Row00_Col46_Byte0("_Letter_Row00_Col46_Byte0", float) = 0
+ _Letter_Row00_Col47_Byte0("_Letter_Row00_Col47_Byte0", float) = 0
_Letter_Row01_Col00_Byte0("_Letter_Row01_Col00_Byte0", float) = 0
_Letter_Row01_Col01_Byte0("_Letter_Row01_Col01_Byte0", float) = 0
_Letter_Row01_Col02_Byte0("_Letter_Row01_Col02_Byte0", float) = 0
@@ -104,6 +109,10 @@
_Letter_Row01_Col41_Byte0("_Letter_Row01_Col41_Byte0", float) = 0
_Letter_Row01_Col42_Byte0("_Letter_Row01_Col42_Byte0", float) = 0
_Letter_Row01_Col43_Byte0("_Letter_Row01_Col43_Byte0", float) = 0
+ _Letter_Row01_Col44_Byte0("_Letter_Row01_Col44_Byte0", float) = 0
+ _Letter_Row01_Col45_Byte0("_Letter_Row01_Col45_Byte0", float) = 0
+ _Letter_Row01_Col46_Byte0("_Letter_Row01_Col46_Byte0", float) = 0
+ _Letter_Row01_Col47_Byte0("_Letter_Row01_Col47_Byte0", float) = 0
_Letter_Row02_Col00_Byte0("_Letter_Row02_Col00_Byte0", float) = 0
_Letter_Row02_Col01_Byte0("_Letter_Row02_Col01_Byte0", float) = 0
_Letter_Row02_Col02_Byte0("_Letter_Row02_Col02_Byte0", float) = 0
@@ -148,6 +157,10 @@
_Letter_Row02_Col41_Byte0("_Letter_Row02_Col41_Byte0", float) = 0
_Letter_Row02_Col42_Byte0("_Letter_Row02_Col42_Byte0", float) = 0
_Letter_Row02_Col43_Byte0("_Letter_Row02_Col43_Byte0", float) = 0
+ _Letter_Row02_Col44_Byte0("_Letter_Row02_Col44_Byte0", float) = 0
+ _Letter_Row02_Col45_Byte0("_Letter_Row02_Col45_Byte0", float) = 0
+ _Letter_Row02_Col46_Byte0("_Letter_Row02_Col46_Byte0", float) = 0
+ _Letter_Row02_Col47_Byte0("_Letter_Row02_Col47_Byte0", float) = 0
_Letter_Row03_Col00_Byte0("_Letter_Row03_Col00_Byte0", float) = 0
_Letter_Row03_Col01_Byte0("_Letter_Row03_Col01_Byte0", float) = 0
_Letter_Row03_Col02_Byte0("_Letter_Row03_Col02_Byte0", float) = 0
@@ -192,6 +205,10 @@
_Letter_Row03_Col41_Byte0("_Letter_Row03_Col41_Byte0", float) = 0
_Letter_Row03_Col42_Byte0("_Letter_Row03_Col42_Byte0", float) = 0
_Letter_Row03_Col43_Byte0("_Letter_Row03_Col43_Byte0", float) = 0
+ _Letter_Row03_Col44_Byte0("_Letter_Row03_Col44_Byte0", float) = 0
+ _Letter_Row03_Col45_Byte0("_Letter_Row03_Col45_Byte0", float) = 0
+ _Letter_Row03_Col46_Byte0("_Letter_Row03_Col46_Byte0", float) = 0
+ _Letter_Row03_Col47_Byte0("_Letter_Row03_Col47_Byte0", float) = 0
_Letter_Row00_Col00_Byte1("_Letter_Row00_Col00_Byte1", float) = 0
_Letter_Row00_Col01_Byte1("_Letter_Row00_Col01_Byte1", float) = 0
_Letter_Row00_Col02_Byte1("_Letter_Row00_Col02_Byte1", float) = 0
@@ -236,6 +253,10 @@
_Letter_Row00_Col41_Byte1("_Letter_Row00_Col41_Byte1", float) = 0
_Letter_Row00_Col42_Byte1("_Letter_Row00_Col42_Byte1", float) = 0
_Letter_Row00_Col43_Byte1("_Letter_Row00_Col43_Byte1", float) = 0
+ _Letter_Row00_Col44_Byte1("_Letter_Row00_Col44_Byte1", float) = 0
+ _Letter_Row00_Col45_Byte1("_Letter_Row00_Col45_Byte1", float) = 0
+ _Letter_Row00_Col46_Byte1("_Letter_Row00_Col46_Byte1", float) = 0
+ _Letter_Row00_Col47_Byte1("_Letter_Row00_Col47_Byte1", float) = 0
_Letter_Row01_Col00_Byte1("_Letter_Row01_Col00_Byte1", float) = 0
_Letter_Row01_Col01_Byte1("_Letter_Row01_Col01_Byte1", float) = 0
_Letter_Row01_Col02_Byte1("_Letter_Row01_Col02_Byte1", float) = 0
@@ -280,6 +301,10 @@
_Letter_Row01_Col41_Byte1("_Letter_Row01_Col41_Byte1", float) = 0
_Letter_Row01_Col42_Byte1("_Letter_Row01_Col42_Byte1", float) = 0
_Letter_Row01_Col43_Byte1("_Letter_Row01_Col43_Byte1", float) = 0
+ _Letter_Row01_Col44_Byte1("_Letter_Row01_Col44_Byte1", float) = 0
+ _Letter_Row01_Col45_Byte1("_Letter_Row01_Col45_Byte1", float) = 0
+ _Letter_Row01_Col46_Byte1("_Letter_Row01_Col46_Byte1", float) = 0
+ _Letter_Row01_Col47_Byte1("_Letter_Row01_Col47_Byte1", float) = 0
_Letter_Row02_Col00_Byte1("_Letter_Row02_Col00_Byte1", float) = 0
_Letter_Row02_Col01_Byte1("_Letter_Row02_Col01_Byte1", float) = 0
_Letter_Row02_Col02_Byte1("_Letter_Row02_Col02_Byte1", float) = 0
@@ -324,6 +349,10 @@
_Letter_Row02_Col41_Byte1("_Letter_Row02_Col41_Byte1", float) = 0
_Letter_Row02_Col42_Byte1("_Letter_Row02_Col42_Byte1", float) = 0
_Letter_Row02_Col43_Byte1("_Letter_Row02_Col43_Byte1", float) = 0
+ _Letter_Row02_Col44_Byte1("_Letter_Row02_Col44_Byte1", float) = 0
+ _Letter_Row02_Col45_Byte1("_Letter_Row02_Col45_Byte1", float) = 0
+ _Letter_Row02_Col46_Byte1("_Letter_Row02_Col46_Byte1", float) = 0
+ _Letter_Row02_Col47_Byte1("_Letter_Row02_Col47_Byte1", float) = 0
_Letter_Row03_Col00_Byte1("_Letter_Row03_Col00_Byte1", float) = 0
_Letter_Row03_Col01_Byte1("_Letter_Row03_Col01_Byte1", float) = 0
_Letter_Row03_Col02_Byte1("_Letter_Row03_Col02_Byte1", float) = 0
@@ -368,6 +397,10 @@
_Letter_Row03_Col41_Byte1("_Letter_Row03_Col41_Byte1", float) = 0
_Letter_Row03_Col42_Byte1("_Letter_Row03_Col42_Byte1", float) = 0
_Letter_Row03_Col43_Byte1("_Letter_Row03_Col43_Byte1", float) = 0
+ _Letter_Row03_Col44_Byte1("_Letter_Row03_Col44_Byte1", float) = 0
+ _Letter_Row03_Col45_Byte1("_Letter_Row03_Col45_Byte1", float) = 0
+ _Letter_Row03_Col46_Byte1("_Letter_Row03_Col46_Byte1", float) = 0
+ _Letter_Row03_Col47_Byte1("_Letter_Row03_Col47_Byte1", float) = 0
}
SubShader
{
@@ -407,6 +440,7 @@
Texture2D _Font_0x8000_0x9FFF;
Texture2D _Font_0xA000_0xBFFF;
Texture2D _Font_0xC000_0xDFFF;
+ Texture2D _Img_0xE000_0xE03F;
float3 HUEtoRGB(in float H)
{
@@ -483,6 +517,10 @@
float _Letter_Row00_Col41_Byte0;
float _Letter_Row00_Col42_Byte0;
float _Letter_Row00_Col43_Byte0;
+ float _Letter_Row00_Col44_Byte0;
+ float _Letter_Row00_Col45_Byte0;
+ float _Letter_Row00_Col46_Byte0;
+ float _Letter_Row00_Col47_Byte0;
float _Letter_Row01_Col00_Byte0;
float _Letter_Row01_Col01_Byte0;
float _Letter_Row01_Col02_Byte0;
@@ -527,6 +565,10 @@
float _Letter_Row01_Col41_Byte0;
float _Letter_Row01_Col42_Byte0;
float _Letter_Row01_Col43_Byte0;
+ float _Letter_Row01_Col44_Byte0;
+ float _Letter_Row01_Col45_Byte0;
+ float _Letter_Row01_Col46_Byte0;
+ float _Letter_Row01_Col47_Byte0;
float _Letter_Row02_Col00_Byte0;
float _Letter_Row02_Col01_Byte0;
float _Letter_Row02_Col02_Byte0;
@@ -571,6 +613,10 @@
float _Letter_Row02_Col41_Byte0;
float _Letter_Row02_Col42_Byte0;
float _Letter_Row02_Col43_Byte0;
+ float _Letter_Row02_Col44_Byte0;
+ float _Letter_Row02_Col45_Byte0;
+ float _Letter_Row02_Col46_Byte0;
+ float _Letter_Row02_Col47_Byte0;
float _Letter_Row03_Col00_Byte0;
float _Letter_Row03_Col01_Byte0;
float _Letter_Row03_Col02_Byte0;
@@ -615,6 +661,10 @@
float _Letter_Row03_Col41_Byte0;
float _Letter_Row03_Col42_Byte0;
float _Letter_Row03_Col43_Byte0;
+ float _Letter_Row03_Col44_Byte0;
+ float _Letter_Row03_Col45_Byte0;
+ float _Letter_Row03_Col46_Byte0;
+ float _Letter_Row03_Col47_Byte0;
float _Letter_Row00_Col00_Byte1;
float _Letter_Row00_Col01_Byte1;
float _Letter_Row00_Col02_Byte1;
@@ -659,6 +709,10 @@
float _Letter_Row00_Col41_Byte1;
float _Letter_Row00_Col42_Byte1;
float _Letter_Row00_Col43_Byte1;
+ float _Letter_Row00_Col44_Byte1;
+ float _Letter_Row00_Col45_Byte1;
+ float _Letter_Row00_Col46_Byte1;
+ float _Letter_Row00_Col47_Byte1;
float _Letter_Row01_Col00_Byte1;
float _Letter_Row01_Col01_Byte1;
float _Letter_Row01_Col02_Byte1;
@@ -703,6 +757,10 @@
float _Letter_Row01_Col41_Byte1;
float _Letter_Row01_Col42_Byte1;
float _Letter_Row01_Col43_Byte1;
+ float _Letter_Row01_Col44_Byte1;
+ float _Letter_Row01_Col45_Byte1;
+ float _Letter_Row01_Col46_Byte1;
+ float _Letter_Row01_Col47_Byte1;
float _Letter_Row02_Col00_Byte1;
float _Letter_Row02_Col01_Byte1;
float _Letter_Row02_Col02_Byte1;
@@ -747,6 +805,10 @@
float _Letter_Row02_Col41_Byte1;
float _Letter_Row02_Col42_Byte1;
float _Letter_Row02_Col43_Byte1;
+ float _Letter_Row02_Col44_Byte1;
+ float _Letter_Row02_Col45_Byte1;
+ float _Letter_Row02_Col46_Byte1;
+ float _Letter_Row02_Col47_Byte1;
float _Letter_Row03_Col00_Byte1;
float _Letter_Row03_Col01_Byte1;
float _Letter_Row03_Col02_Byte1;
@@ -791,6 +853,10 @@
float _Letter_Row03_Col41_Byte1;
float _Letter_Row03_Col42_Byte1;
float _Letter_Row03_Col43_Byte1;
+ float _Letter_Row03_Col44_Byte1;
+ float _Letter_Row03_Col45_Byte1;
+ float _Letter_Row03_Col46_Byte1;
+ float _Letter_Row03_Col47_Byte1;
v2f vert (appdata v)
{
@@ -825,7 +891,11 @@
// Write the nth letter in the current cell and return the value of the
// pixel.
- float2 GetLetter(float2 uv, int nth_letter)
+ // `texture_rows` and `texture_cols` indicate how many rows and columns are
+ // in the texture being sampled.
+ float2 GetLetter(float2 uv, int nth_letter,
+ float texture_cols, float texture_rows,
+ float board_cols, float board_rows)
{
// UV spans from [0,1] to [0,1].
// 'U' is horizontal; cols.
@@ -833,13 +903,11 @@
//
// I want to divide the mesh into an m x n grid.
// I want to know what grid cell I'm in. This is simply u * m, v * n.
- int CHAR_ROWS = 4;
- int CHAR_COLS = 44;
// OK, I know what cell I'm in. Now I need to know how far across it I
// am. Produce a float in the range [0, 1).
- float CHAR_FRAC_COL = uv.x * CHAR_COLS - floor(uv.x * CHAR_COLS);
- float CHAR_FRAC_ROW = uv.y * CHAR_ROWS - floor(uv.y * CHAR_ROWS);
+ float CHAR_FRAC_COL = uv.x * board_cols - floor(uv.x * board_cols);
+ float CHAR_FRAC_ROW = uv.y * board_rows - floor(uv.y * board_rows);
// Avoid rendering pixels right on the edge of the slot. If we were to
// do this, then that value would get stretched due to clamping
@@ -851,15 +919,11 @@
return float2(0, 0);
}
- // This is the number of rows and columns in the actual texture.
- float LETTER_COLS = 128.0;
- float LETTER_ROWS = 64.0;
+ float LETTER_COL = fmod(nth_letter, floor(texture_cols));
+ float LETTER_ROW = floor(texture_rows) - floor(nth_letter / floor(texture_cols));
- float LETTER_COL = fmod(nth_letter, floor(LETTER_COLS));
- float LETTER_ROW = floor(LETTER_ROWS) - floor(nth_letter / floor(LETTER_COLS));
-
- float LETTER_UV_ROW = (LETTER_ROW + CHAR_FRAC_ROW - 1.00) / LETTER_ROWS;
- float LETTER_UV_COL = (LETTER_COL + CHAR_FRAC_COL) / LETTER_COLS;
+ float LETTER_UV_ROW = (LETTER_ROW + CHAR_FRAC_ROW - 1.00) / texture_rows;
+ float LETTER_UV_COL = (LETTER_COL + CHAR_FRAC_COL) / texture_cols;
float2 result;
result.x = LETTER_UV_COL;
@@ -896,7 +960,7 @@
float2 GetLetterParameter(float2 uv)
{
float CHAR_ROWS = 4.0;
- float CHAR_COLS = 44.0;
+ float CHAR_COLS = 48.0;
float CHAR_COL = floor(uv.x * CHAR_COLS);
float CHAR_ROW = floor(uv.y * CHAR_ROWS);
@@ -992,6 +1056,14 @@
return float2(_Letter_Row00_Col42_Byte0, _Letter_Row00_Col42_Byte1);
case 43:
return float2(_Letter_Row00_Col43_Byte0, _Letter_Row00_Col43_Byte1);
+ case 44:
+ return float2(_Letter_Row00_Col44_Byte0, _Letter_Row00_Col44_Byte1);
+ case 45:
+ return float2(_Letter_Row00_Col45_Byte0, _Letter_Row00_Col45_Byte1);
+ case 46:
+ return float2(_Letter_Row00_Col46_Byte0, _Letter_Row00_Col46_Byte1);
+ case 47:
+ return float2(_Letter_Row00_Col47_Byte0, _Letter_Row00_Col47_Byte1);
default:
return float2(0, 0);
}
@@ -1085,6 +1157,14 @@
return float2(_Letter_Row01_Col42_Byte0, _Letter_Row01_Col42_Byte1);
case 43:
return float2(_Letter_Row01_Col43_Byte0, _Letter_Row01_Col43_Byte1);
+ case 44:
+ return float2(_Letter_Row01_Col44_Byte0, _Letter_Row01_Col44_Byte1);
+ case 45:
+ return float2(_Letter_Row01_Col45_Byte0, _Letter_Row01_Col45_Byte1);
+ case 46:
+ return float2(_Letter_Row01_Col46_Byte0, _Letter_Row01_Col46_Byte1);
+ case 47:
+ return float2(_Letter_Row01_Col47_Byte0, _Letter_Row01_Col47_Byte1);
default:
return float2(0, 0);
}
@@ -1178,6 +1258,14 @@
return float2(_Letter_Row02_Col42_Byte0, _Letter_Row02_Col42_Byte1);
case 43:
return float2(_Letter_Row02_Col43_Byte0, _Letter_Row02_Col43_Byte1);
+ case 44:
+ return float2(_Letter_Row02_Col44_Byte0, _Letter_Row02_Col44_Byte1);
+ case 45:
+ return float2(_Letter_Row02_Col45_Byte0, _Letter_Row02_Col45_Byte1);
+ case 46:
+ return float2(_Letter_Row02_Col46_Byte0, _Letter_Row02_Col46_Byte1);
+ case 47:
+ return float2(_Letter_Row02_Col47_Byte0, _Letter_Row02_Col47_Byte1);
default:
return float2(0, 0);
}
@@ -1271,6 +1359,14 @@
return float2(_Letter_Row03_Col42_Byte0, _Letter_Row03_Col42_Byte1);
case 43:
return float2(_Letter_Row03_Col43_Byte0, _Letter_Row03_Col43_Byte1);
+ case 44:
+ return float2(_Letter_Row03_Col44_Byte0, _Letter_Row03_Col44_Byte1);
+ case 45:
+ return float2(_Letter_Row03_Col45_Byte0, _Letter_Row03_Col45_Byte1);
+ case 46:
+ return float2(_Letter_Row03_Col46_Byte0, _Letter_Row03_Col46_Byte1);
+ case 47:
+ return float2(_Letter_Row03_Col47_Byte0, _Letter_Row03_Col47_Byte1);
default:
return float2(0, 0);
}
@@ -1325,8 +1421,18 @@
int2 letter_bytes = (int2) floor(GetLetterParameter(uv));
int letter = letter_bytes[0] | (letter_bytes[1] << 8);
-
- uv = GetLetter(uv, letter);
+
+ float texture_cols;
+ float texture_rows;
+ if (letter < 0xE000) {
+ texture_cols = 128.0;
+ texture_rows = 64.0;
+ uv = GetLetter(uv, letter, texture_cols, texture_rows, 48, 4);
+ } else {
+ texture_cols = 8.0;
+ texture_rows = 8.0;
+ uv = GetLetter(uv, letter, texture_cols, texture_rows, 8, 4);
+ }
fixed4 background = TaSTT_Backplate.Sample(sampler_linear_repeat, uv);
fixed4 text;
@@ -1356,7 +1462,7 @@
text = _Font_0xC000_0xDFFF.Sample(sampler_linear_repeat, uv);
break;
default:
- text = _Font_0x0000_0x1FFF.Sample(sampler_linear_repeat, uv);
+ text = _Img_0xE000_0xE03F.Sample(sampler_linear_repeat, uv);
break;
}
fixed4 black = fixed4(0,0,0,0);
diff --git a/emotes.py b/emotes.py
new file mode 100644
index 0000000..0fd41d8
--- /dev/null
+++ b/emotes.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+
+import argparse
+from math import floor
+import os
+# python3 -m pip install pillow
+from PIL import Image
+import sys
+
+# (row, col)
+TEX_SZ = (2048, 2048)
+
+IMG_SZ_PX = 256
+IMG_PER_ROW = int(TEX_SZ[0] / IMG_SZ_PX)
+IMG_PER_COL = int(TEX_SZ[1] / IMG_SZ_PX)
+
+# TODO(yum) this should live in a config file.
+# Note: the name of the emote must be no longer than 6 characters.
+IMG_TEX_DATA = []
+IMG_TEX_DATA.append(("Images/Emotes/xdd.png", "xdd"))
+IMG_TEX_DATA.append(("Images/Emotes/pog.png", "pog"))
+IMG_TEX_DATA.append(("Images/Emotes/lulw.png", "laugh"))
+IMG_TEX_DATA.append(("Images/Emotes/bighardo.png", "hard"))
+IMG_TEX_DATA.append(("Images/Emotes/peepoHappy.png", "happy"))
+IMG_TEX_DATA.append(("Images/Emotes/peepoSad.png", "sad"))
+IMG_TEX_DATA.append(("Images/Emotes/bedge.png", "bed"))
+IMG_TEX_DATA.append(("Images/Emotes/reallymad.png", "mad"))
+
+IMG_TEX_KEYWORD_TO_COORD = {}
+for i in range(0, len(IMG_TEX_DATA)):
+ IMG_TEX_KEYWORD_TO_COORD[IMG_TEX_DATA[i][1]] = i
+
+# We treat images like words. To keep things simple, they're the same height as
+# a word, and they're a fixed width.
+IMG_SZ_LETTER_ROWS = 1
+IMG_SZ_LETTER_COLS = 6
+
+def lookup(word: str):
+ word = word.lower()
+ word = ''.join(c for c in word.lower() if c.isalpha())
+ if word in IMG_TEX_KEYWORD_TO_COORD.keys():
+ return word, IMG_TEX_KEYWORD_TO_COORD[word]
+ return None, None
+
+def openTexture(tex_path: str):
+ if not os.path.exists(args.texture_path):
+ return Image.new("RGB", TEX_SZ)
+ tex = Image.open(args.texture_path)
+ if tex.size != TEX_SZ:
+ print("Texture at {} has mismatching size {}, creating new texture".format(
+ tex_path, tex.size), file=sys.stderr)
+ return Image.new("RGB", TEX_SZ)
+ return tex
+
+# Add an image to the texture at the coordinates (x, y). x and y should be in
+# the range [0, IMG_PER_COL) and [0, IMG_PER_ROW) respectively.
+def addImageToTexture(tex: Image, img_path: str, x: int, y:int):
+ # Transparent images will be composited on top of a black background.
+ img = Image.open(img_path).convert('RGBA')
+ img_bg = Image.new('RGBA', img.size, (0, 0, 0))
+ img = Image.alpha_composite(img_bg, img).convert('RGB')
+
+ max_px = IMG_SZ_PX
+
+ # Scale the image up so it uses as much space as is given to it.
+ # I originally planned to support multiple scales, but this proved to be
+ # too much work - getting line wrapping to work with this would be a pain.
+ # So for now, all images are the same height as words.
+ scale = 1
+ img_x, img_y = img.size
+ max_dim = max(img_x, img_y)
+ img_scale = (max_px / max_dim) * scale
+ new_sz = (int(floor(img.size[0] * img_scale)),
+ int(floor(img.size[1] * img_scale)))
+ print("Original size: {}".format(img.size))
+ print("Scaled size: {}".format(new_sz))
+ img = img.resize(new_sz)
+
+ # Center the image within its new coordinate space.
+ padded_img_sz = (IMG_SZ_PX * scale, IMG_SZ_PX * scale)
+ padded_img = Image.new("RGB", padded_img_sz)
+ centered_x = int(floor((padded_img_sz[0] - new_sz[0]) / 2))
+ centered_y = int(floor((padded_img_sz[1] - new_sz[1]) / 2))
+ padded_img.paste(img, box=(centered_x, centered_y))
+ img = padded_img
+
+ # Break the image into tiles and write them into the texture.
+ for slot in range(0, scale * scale):
+ tile_x = slot % scale
+ tile_y = int(floor(slot / scale))
+ tile_bbox = (tile_x * IMG_SZ_PX, tile_y * IMG_SZ_PX, (tile_x + 1) * IMG_SZ_PX, (tile_y + 1) * IMG_SZ_PX)
+ tile = img.crop(tile_bbox)
+ print("tile {},{} (bbox={})".format(tile_x, tile_y, tile_bbox))
+
+ slot_x = x + slot % IMG_PER_ROW
+ slot_y = y + int(floor(slot / IMG_PER_ROW))
+ slot_x_px = slot_x * IMG_SZ_PX
+ slot_y_px = slot_y * IMG_SZ_PX
+ print("Add img at {},{} (px {},{})".format(slot_x, slot_y, slot_x_px, slot_y_px))
+
+ tex.paste(tile, box=(slot_x_px, slot_y_px))
+
+def parseArgs():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--texture_path", type=str, help="Path to save the generated texture.")
+ args = parser.parse_args()
+
+ if not args.texture_path:
+ args.texture_path = "img_texture.png"
+
+ return args
+
+if __name__ == "__main__":
+ args = parseArgs()
+
+ tex = openTexture(args.texture_path)
+ for i in range(0, len(IMG_TEX_DATA)):
+ filename = IMG_TEX_DATA[i][0]
+ x = i % IMG_PER_ROW
+ y = int(floor(i / IMG_PER_ROW))
+ addImageToTexture(tex, filename, x, y)
+ tex.save(args.texture_path)
+
diff --git a/generate_utils.py b/generate_utils.py
index e8c60b8..0480c3c 100644
--- a/generate_utils.py
+++ b/generate_utils.py
@@ -10,18 +10,12 @@ def replaceMacros(lines, macro_defs):
# the last cell will (with the current implementation) wrap around to the front
# of the board.
BOARD_ROWS=4
-BOARD_COLS=44
-INDEX_BITS=4
+BOARD_COLS=48
+NUM_REGIONS = 16
CHARS_PER_CELL=256
BYTES_PER_CHAR=2
-NUM_LAYERS=ceil((BOARD_ROWS * BOARD_COLS) / (2**INDEX_BITS))
-
-# The bits per layer are:
-# 8 bits: letter selection (256 possible letters per slot)
-# 3 bits: slot selection (each layer controls 8 slots)
-# 1 bit: enable bit (turns layer off while we index to a new slot)
-NUM_PARAM_BITS=(NUM_LAYERS * (8 + INDEX_BITS + 1))
+NUM_LAYERS=ceil((BOARD_ROWS * BOARD_COLS) / NUM_REGIONS)
# Implementation detail. We use this parameter to return from the terminal
# state of the FX layer to the starting state.
diff --git a/libtastt.py b/libtastt.py
index 36ccec7..bee535f 100644
--- a/libtastt.py
+++ b/libtastt.py
@@ -373,7 +373,7 @@ def generateFXLayer(which_layer: int, anim: libunity.UnityAnimator, layer:
enable_param, True)
select_states = {}
- for i in range(0, 2 ** generate_utils.INDEX_BITS):
+ for i in range(0, generate_utils.NUM_REGIONS):
dx = i * 200
dy = 200
diff --git a/osc_ctrl.py b/osc_ctrl.py
index 46c7997..34d1a36 100644
--- a/osc_ctrl.py
+++ b/osc_ctrl.py
@@ -20,6 +20,8 @@ from generate_utils import NUM_LAYERS
from generate_utils import BOARD_ROWS
from generate_utils import BOARD_COLS
+import emotes
+
# Based on a couple experiments, this seems like about as fast as we can go
# before players start losing events.
SYNC_FREQ_HZ = 5.0
@@ -53,12 +55,33 @@ def encodeMessage(lines):
result = []
lines_tmp = lines + [" "] * ((BOARD_ROWS - len(lines)) % BOARD_ROWS)
for line in lines_tmp:
- #print("encode line {}".format(line))
- for char in line:
- if not char in state.encoding:
- print("skip unrecognized char {}".format(char))
+ first_word = True
+ for word in line.split():
+ if first_word:
+ first_word = False
+ else:
+ result.append(state.encoding[' '])
+
+ emote_word, emote_word_idx = emotes.lookup(word)
+ if emote_word:
+
+ word_align = 0
+ if len(result) > 0:
+ word_align = (6 - len(result) % 6) % 6
+ word = ' ' * word_align + word
+
+ for i in range(0, word_align):
+ result.append(state.encoding[' '])
+
+ for i in range(0, 6):
+ result.append((emote_word_idx, 0xE0))
continue
- result.append(state.encoding[char])
+
+ for char in word:
+ if not char in state.encoding:
+ print("skip unrecognized char {}".format(char))
+ continue
+ result.append(state.encoding[char])
result += [state.encoding[' ']] * (BOARD_COLS - len(line))
return result
@@ -77,7 +100,7 @@ def disable(client):
client.send_message(addr, False)
# Send a cell all at once.
-# `which_cell` is an integer in the range [0,2**INDEX_BITS).
+# `which_cell` is an integer in the range [0,NUM_REGIONS)
def sendMessageCellDiscrete(client, msg_cell, which_cell):
empty_cell = [state.encoding[' ']] * NUM_LAYERS
@@ -86,7 +109,7 @@ def sendMessageCellDiscrete(client, msg_cell, which_cell):
client.send_message(addr, True)
# Really long messages just wrap back around.
- which_cell = (which_cell % (2 ** generate_utils.INDEX_BITS))
+ which_cell = (which_cell % generate_utils.NUM_REGIONS)
enable(client)
@@ -113,10 +136,26 @@ def splitMessage(msg):
lines = []
line = ""
for word in msg.split():
+ # Hack: if the word is an emote, we make it 6 characters wide, then
+ # encode it differently later on.
+ emote_word, emote_word_idx = emotes.lookup(word)
+ if emote_word:
+ word = word.ljust(6)
+ # Due to some fuckery I do in the shader, emotes have to be rendered on
+ # a 6-character boundary. So pad the word on the left with spaces
+ # to get it onto that boundary.
+ word_align = 0
+ if len(line) > 0:
+ word_align = (6 - (len(line) + 1) % 6) % 6
+ print("len line: {}".format(len(line)))
+ print("word align: {}".format(word_align))
+ word = ' ' * word_align + word
+
while len(word) > BOARD_COLS:
if len(line) != 0:
lines.append(line)
line = ""
+
word_prefix = word[0:BOARD_COLS-1] + "-"
word_suffix = word[BOARD_COLS-1:]
#print("append prefix {}".format(word_prefix))
@@ -308,11 +347,6 @@ if __name__ == "__main__":
state.encoding = generateEncoding()
- sendRawMessage(client, [ \
- (65,0), \
- (0x20,0xAD), \
- ])
-
tx_state = OscTxState()
for line in fileinput.input():
while sendMessageLazy(client, line, tx_state) != SEND_MSG_LAZY_DONE: