diff options
| author | yum <yum.food.vr@gmail.com> | 2022-09-30 21:59:08 -0700 |
|---|---|---|
| committer | yum <yumfood@airmail.cc> | 2022-09-30 21:59:08 -0700 |
| commit | f47dd3efa3763eb946564bd324873d53061e398f (patch) | |
| tree | cbf998184658c221199d5b93ec6359e4a63fe0c5 | |
| parent | 2fa5bc78b5c4500301327bd6a334ab4fb8e04a17 (diff) | |
Add line wrapping and support for arbitrarily long messages
Add trivial line wrapping algorithm. Words are only added to
a line if they don't put it over the column limit, and only broken if
they alone exceed the column limit.
Extend board size to 16x6, using 145 bits of parameter memory.
Add simple generate.sh script, which generates everything needed to
use the text-to-text board.
| -rw-r--r-- | TaSTT.shader | 54 | ||||
| -rw-r--r-- | generate.sh | 27 | ||||
| -rw-r--r-- | generate_animations.sh | 2 | ||||
| -rw-r--r-- | generate_utils.py | 11 | ||||
| -rw-r--r-- | osc_ctrl.py | 103 |
5 files changed, 159 insertions, 38 deletions
diff --git a/TaSTT.shader b/TaSTT.shader index f5ec6af..3e1e19a 100644 --- a/TaSTT.shader +++ b/TaSTT.shader @@ -18,6 +18,8 @@ _Letter_Row00_Col11("_Letter_Row00_Col11", float) = 0
_Letter_Row00_Col12("_Letter_Row00_Col12", float) = 0
_Letter_Row00_Col13("_Letter_Row00_Col13", float) = 0
+ _Letter_Row00_Col14("_Letter_Row00_Col14", float) = 0
+ _Letter_Row00_Col15("_Letter_Row00_Col15", float) = 0
_Letter_Row01_Col00("_Letter_Row01_Col00", float) = 0
_Letter_Row01_Col01("_Letter_Row01_Col01", float) = 0
_Letter_Row01_Col02("_Letter_Row01_Col02", float) = 0
@@ -32,6 +34,8 @@ _Letter_Row01_Col11("_Letter_Row01_Col11", float) = 0
_Letter_Row01_Col12("_Letter_Row01_Col12", float) = 0
_Letter_Row01_Col13("_Letter_Row01_Col13", float) = 0
+ _Letter_Row01_Col14("_Letter_Row01_Col14", float) = 0
+ _Letter_Row01_Col15("_Letter_Row01_Col15", float) = 0
_Letter_Row02_Col00("_Letter_Row02_Col00", float) = 0
_Letter_Row02_Col01("_Letter_Row02_Col01", float) = 0
_Letter_Row02_Col02("_Letter_Row02_Col02", float) = 0
@@ -46,6 +50,8 @@ _Letter_Row02_Col11("_Letter_Row02_Col11", float) = 0
_Letter_Row02_Col12("_Letter_Row02_Col12", float) = 0
_Letter_Row02_Col13("_Letter_Row02_Col13", float) = 0
+ _Letter_Row02_Col14("_Letter_Row02_Col14", float) = 0
+ _Letter_Row02_Col15("_Letter_Row02_Col15", float) = 0
_Letter_Row03_Col00("_Letter_Row03_Col00", float) = 0
_Letter_Row03_Col01("_Letter_Row03_Col01", float) = 0
_Letter_Row03_Col02("_Letter_Row03_Col02", float) = 0
@@ -60,6 +66,8 @@ _Letter_Row03_Col11("_Letter_Row03_Col11", float) = 0
_Letter_Row03_Col12("_Letter_Row03_Col12", float) = 0
_Letter_Row03_Col13("_Letter_Row03_Col13", float) = 0
+ _Letter_Row03_Col14("_Letter_Row03_Col14", float) = 0
+ _Letter_Row03_Col15("_Letter_Row03_Col15", float) = 0
_Letter_Row04_Col00("_Letter_Row04_Col00", float) = 0
_Letter_Row04_Col01("_Letter_Row04_Col01", float) = 0
_Letter_Row04_Col02("_Letter_Row04_Col02", float) = 0
@@ -74,6 +82,8 @@ _Letter_Row04_Col11("_Letter_Row04_Col11", float) = 0
_Letter_Row04_Col12("_Letter_Row04_Col12", float) = 0
_Letter_Row04_Col13("_Letter_Row04_Col13", float) = 0
+ _Letter_Row04_Col14("_Letter_Row04_Col14", float) = 0
+ _Letter_Row04_Col15("_Letter_Row04_Col15", float) = 0
_Letter_Row05_Col00("_Letter_Row05_Col00", float) = 0
_Letter_Row05_Col01("_Letter_Row05_Col01", float) = 0
_Letter_Row05_Col02("_Letter_Row05_Col02", float) = 0
@@ -88,6 +98,8 @@ _Letter_Row05_Col11("_Letter_Row05_Col11", float) = 0
_Letter_Row05_Col12("_Letter_Row05_Col12", float) = 0
_Letter_Row05_Col13("_Letter_Row05_Col13", float) = 0
+ _Letter_Row05_Col14("_Letter_Row05_Col14", float) = 0
+ _Letter_Row05_Col15("_Letter_Row05_Col15", float) = 0
}
SubShader
{
@@ -132,6 +144,8 @@ float _Letter_Row00_Col11;
float _Letter_Row00_Col12;
float _Letter_Row00_Col13;
+ float _Letter_Row00_Col14;
+ float _Letter_Row00_Col15;
float _Letter_Row01_Col00;
float _Letter_Row01_Col01;
float _Letter_Row01_Col02;
@@ -146,6 +160,8 @@ float _Letter_Row01_Col11;
float _Letter_Row01_Col12;
float _Letter_Row01_Col13;
+ float _Letter_Row01_Col14;
+ float _Letter_Row01_Col15;
float _Letter_Row02_Col00;
float _Letter_Row02_Col01;
float _Letter_Row02_Col02;
@@ -160,6 +176,8 @@ float _Letter_Row02_Col11;
float _Letter_Row02_Col12;
float _Letter_Row02_Col13;
+ float _Letter_Row02_Col14;
+ float _Letter_Row02_Col15;
float _Letter_Row03_Col00;
float _Letter_Row03_Col01;
float _Letter_Row03_Col02;
@@ -174,6 +192,8 @@ float _Letter_Row03_Col11;
float _Letter_Row03_Col12;
float _Letter_Row03_Col13;
+ float _Letter_Row03_Col14;
+ float _Letter_Row03_Col15;
float _Letter_Row04_Col00;
float _Letter_Row04_Col01;
float _Letter_Row04_Col02;
@@ -188,6 +208,8 @@ float _Letter_Row04_Col11;
float _Letter_Row04_Col12;
float _Letter_Row04_Col13;
+ float _Letter_Row04_Col14;
+ float _Letter_Row04_Col15;
float _Letter_Row05_Col00;
float _Letter_Row05_Col01;
float _Letter_Row05_Col02;
@@ -202,6 +224,8 @@ float _Letter_Row05_Col11;
float _Letter_Row05_Col12;
float _Letter_Row05_Col13;
+ float _Letter_Row05_Col14;
+ float _Letter_Row05_Col15;
v2f vert (appdata v)
{
@@ -223,7 +247,7 @@ // Thus given UV, I need to know a few things:
// 1. What grid cell I'm in. This is simply u * m, v * n.
float CHAR_ROWS = 6.0;
- float CHAR_COLS = 14.0;
+ float CHAR_COLS = 16.0;
float CHAR_COL = floor(i.uv.x * CHAR_COLS);
float CHAR_ROW = floor(i.uv.y * CHAR_ROWS);
@@ -263,7 +287,7 @@ float GetLetterParameter(v2f i)
{
float CHAR_ROWS = 6.0;
- float CHAR_COLS = 14.0;
+ float CHAR_COLS = 16.0;
float CHAR_COL = floor(i.uv.x * CHAR_COLS);
float CHAR_ROW = floor(i.uv.y * CHAR_ROWS);
@@ -297,6 +321,10 @@ return _Letter_Row00_Col12;
} else if (CHAR_COL == 13) {
return _Letter_Row00_Col13;
+ } else if (CHAR_COL == 14) {
+ return _Letter_Row00_Col14;
+ } else if (CHAR_COL == 15) {
+ return _Letter_Row00_Col15;
}
} else if (CHAR_ROW == 4) {
if (CHAR_COL == 0) {
@@ -327,6 +355,10 @@ return _Letter_Row01_Col12;
} else if (CHAR_COL == 13) {
return _Letter_Row01_Col13;
+ } else if (CHAR_COL == 14) {
+ return _Letter_Row01_Col14;
+ } else if (CHAR_COL == 15) {
+ return _Letter_Row01_Col15;
}
} else if (CHAR_ROW == 3) {
if (CHAR_COL == 0) {
@@ -357,6 +389,10 @@ return _Letter_Row02_Col12;
} else if (CHAR_COL == 13) {
return _Letter_Row02_Col13;
+ } else if (CHAR_COL == 14) {
+ return _Letter_Row02_Col14;
+ } else if (CHAR_COL == 15) {
+ return _Letter_Row02_Col15;
}
} else if (CHAR_ROW == 2) {
if (CHAR_COL == 0) {
@@ -387,6 +423,10 @@ return _Letter_Row03_Col12;
} else if (CHAR_COL == 13) {
return _Letter_Row03_Col13;
+ } else if (CHAR_COL == 14) {
+ return _Letter_Row03_Col14;
+ } else if (CHAR_COL == 15) {
+ return _Letter_Row03_Col15;
}
} else if (CHAR_ROW == 1) {
if (CHAR_COL == 0) {
@@ -417,6 +457,10 @@ return _Letter_Row04_Col12;
} else if (CHAR_COL == 13) {
return _Letter_Row04_Col13;
+ } else if (CHAR_COL == 14) {
+ return _Letter_Row04_Col14;
+ } else if (CHAR_COL == 15) {
+ return _Letter_Row04_Col15;
}
} else if (CHAR_ROW == 0) {
if (CHAR_COL == 0) {
@@ -447,6 +491,10 @@ return _Letter_Row05_Col12;
} else if (CHAR_COL == 13) {
return _Letter_Row05_Col13;
+ } else if (CHAR_COL == 14) {
+ return _Letter_Row05_Col14;
+ } else if (CHAR_COL == 15) {
+ return _Letter_Row05_Col15;
}
}
@@ -458,7 +506,7 @@ float letter = GetLetterParameter(i);
float2 uv = GetLetter(i, letter);
fixed4 ret = tex2D(_MainTex, uv);
- if (uv.x == 0 && uv.y == 0) {
+ if (uv.x == 0 || uv.y == 0 || uv.x == 1 || uv.y == 1) {
ret.xyz = 0;
ret.w = 0;
}
diff --git a/generate.sh b/generate.sh new file mode 100644 index 0000000..a476f24 --- /dev/null +++ b/generate.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -o pipefail +set -o errexit +set -o xtrace + +echo 'Generating animations' + +./generate_animations + +echo 'Tab into unity and wait for it to import animations, then press enter.' +echo +echo 'This is necessary because the FX layer will reference animations by ' +echo 'their Unity GUID which is generated during import.' +read -r line + +echo 'Generating FX layer' + +./generate_fx.py > TaSTT_fx.controller + +echo 'Generating parameters' + +./generate_params.py > TaSTT_params.asset + +echo 'Done! Assign the parameters and fx layer, then upload.' + + diff --git a/generate_animations.sh b/generate_animations.sh index 4ff4c3a..ce367f6 100644 --- a/generate_animations.sh +++ b/generate_animations.sh @@ -13,7 +13,7 @@ mkdir -p generated/animations for row in `seq 0 5`; do ROW_PADDED=$(printf '%02d' $row) - for col in `seq 0 13`; do + for col in `seq 0 16`; do COL_PADDED=$(printf '%02d' $col) LETTER_SHADER_PARAM=_Letter_Row${ROW_PADDED}_Col${COL_PADDED} for letter in `seq 0 79`; do diff --git a/generate_utils.py b/generate_utils.py index 1abb694..e50a656 100644 --- a/generate_utils.py +++ b/generate_utils.py @@ -7,7 +7,7 @@ def replaceMacros(lines, macro_defs): return lines BOARD_ROWS=6 -BOARD_COLS=14 +BOARD_COLS=16 INDEX_BITS=3 CHARS_PER_CELL=80 @@ -34,10 +34,11 @@ def getEnableParam(which_layer): return "TaSTT_L%02d_E" % which_layer def getBoardIndex(which_layer, s0, s1, s2): - # TODO(yum_food) because we divide the board into a multiple of 8 cells, - # some cells describe animations which don't exist. We work around this by - # simply wrapping those animations back to the top of the board, and rely - # on the OSC controller to simply not reference those cells. Clean this up. + # Because we divide the board into a multiple of 8 cells, some cells may + # describe animations which don't exist, depending on the size of the board. + # We work around this by simply wrapping those animations back to the top + # of the board, and rely on the OSC controller to simply not reference + # those cells. return ((s0 * 4 + s1 * 2 + s2) * NUM_LAYERS + which_layer) % (BOARD_ROWS * BOARD_COLS) # Mapping from layer to shader param. diff --git a/osc_ctrl.py b/osc_ctrl.py index 3c19cd9..23b63c2 100644 --- a/osc_ctrl.py +++ b/osc_ctrl.py @@ -16,6 +16,9 @@ from generate_utils import NUM_LAYERS from generate_utils import BOARD_ROWS from generate_utils import BOARD_COLS +#MSG_DELAY_S=0.3 +MSG_DELAY_S=0.1 + def usage(): print("python3 -m pip install python-osc") print("python3 ./osc_ctrl.py") @@ -27,24 +30,26 @@ args = parser.parse_args() client = udp_client.SimpleUDPClient(args.i, args.p) -def encodeMessage(msg): +def encodeMessage(lines): result = [] - for char in msg: - char_int = ord(char) - if char_int >= ord('A') and char_int <= ord('Z'): - result.append(ord(char) - ord('A')) - elif char >= 'a' and char <= 'z': - result.append((ord(char) - ord('a')) + 26) - elif char >= '0' and char <= '9': - result.append((ord(char) - ord('0')) + 52) - elif char == '.': - result.append(62) - elif char == ',': - result.append(63) - elif char == ' ': - result.append(64) - # Pad message with spaces so that it overwrites any leftover text. - result += [65] * (BOARD_ROWS * BOARD_COLS - len(result)) + for line in lines: + for char in line: + char_int = ord(char) + if char_int >= ord('A') and char_int <= ord('Z'): + result.append(ord(char) - ord('A')) + elif char >= 'a' and char <= 'z': + result.append((ord(char) - ord('a')) + 26) + elif char >= '0' and char <= '9': + result.append((ord(char) - ord('0')) + 52) + elif char == '.': + result.append(63) + elif char == ',': + result.append(62) + elif char == ' ': + result.append(64) + # Pad message with spaces so that it overwrites any leftover text. + result += [65] * (BOARD_COLS - len(line)) + #print("Encoded message: {}".format(result)) return result # `which_cell` is an integer in the range [0,8). @@ -72,7 +77,7 @@ def sendMessageCell(msg_cell, which_cell): client.send_message(addr, (which_cell % 2) == 1) # Wait for convergence. - time.sleep(0.3) + time.sleep(MSG_DELAY_S) # Enable each layer. # TODO(yum_food) for some reason, if we don't active every layer, the @@ -82,7 +87,7 @@ def sendMessageCell(msg_cell, which_cell): client.send_message(addr, True) # Wait for convergence. - time.sleep(0.3) + time.sleep(MSG_DELAY_S) # Disable each layer. for i in range(0, NUM_LAYERS): @@ -90,25 +95,65 @@ def sendMessageCell(msg_cell, which_cell): client.send_message(addr, False) # Wait for convergence. - time.sleep(0.3) + time.sleep(MSG_DELAY_S) + +# The board is broken down into contiguous collections of characters called +# cells. Each cell contains `NUM_LAYERS` characters. We can update one cell +# every ~1.0 seconds. Going faster causes the board to display garbage to +# remote players. +def splitMessage(msg): + lines = [] + line = "" + for word in msg.split(): + 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)) + lines.append(word_prefix) + word = word_suffix + + if len(line) == 0: + line = word + continue + + if len(line) + len(" ") + len(word) <= BOARD_COLS: + line += " " + word + continue + + print("append line {}".format(line)) + lines.append(line) + line = word + + if len(line) > 0: + lines.append(line) + + return lines def sendMessage(msg): - # The board is broken down into contiguous collections of characters called - # cells. Each cell contains `NUM_LAYERS` characters. We can update one cell - # every ~1.0 seconds; going faster causes the board to display garbage to - # remote players. - msg = encodeMessage(msg) + lines = splitMessage(msg) + msg = encodeMessage(lines) + msg_len = len(msg) + + print("Encoded message: {}".format(msg)) - n_cells = ceil(len(msg) / NUM_LAYERS) + n_cells = ceil(msg_len / NUM_LAYERS) + print("n_cells: {}".format(n_cells)) for cell in range(0, n_cells): + # Really long messages just wrap back around. + cell = cell % NUM_LAYERS + cell_begin = cell * NUM_LAYERS cell_end = (cell + 1) * NUM_LAYERS cell_msg = msg[cell_begin:cell_end] print("Send cell {}".format(cell)) sendMessageCell(cell_msg, cell) -for line in fileinput.input(): - sendMessage(line) +if __name__ == "__main__": + for line in fileinput.input(): + sendMessage(line) -sendMessage("") + sendMessage("") |
