summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2022-09-30 18:44:36 -0700
committeryum <yumfood@airmail.cc>2022-09-30 18:44:36 -0700
commit2fa5bc78b5c4500301327bd6a334ab4fb8e04a17 (patch)
treed03c01d929431320686d61f7091b96f6be3d14ca
parent73bbba9de5210ae7f895ae82bd2524eb76e3a38c (diff)
Redo FX layer
Apparently the same avatar parameter can only be updated so quickly before VRChat starts dropping messages. So now we divide the board into "groups" of 8 characters. Each group can be updated relatively slowly, but all groups can be updated in parallel. Thus we can update the board group-by-group, pausing between each group. * Fix shader bugs - now there are Row05 parameters, and row00 refers to the topmost row instead of the bottom-most. * Remove outdated layer/group names files * Extend osc_ctrl.py to support encoding & sending messages * Add generate_params.py to handle creating TaSTT_params.asset * Add generate_utils.py for common code generation facilities & parameters.
-rw-r--r--README.md6
-rw-r--r--TaSTT.cs78
-rw-r--r--TaSTT.shader40
-rw-r--r--TaSTT_params.asset31
-rw-r--r--cell_names.txt84
-rw-r--r--generate_fx.py574
-rw-r--r--generate_params.py61
-rw-r--r--generate_utils.py53
-rw-r--r--group_names.txt24
-rw-r--r--osc_ctrl.py103
10 files changed, 504 insertions, 550 deletions
diff --git a/README.md b/README.md
index 986ca8b..4a6ce42 100644
--- a/README.md
+++ b/README.md
@@ -13,12 +13,6 @@ Features:
* Low-latency.
* Stable.
* Configurable.
-* Very low parameter space usage: 25 bits at the time of writing.
- * u8 TaSTT\_Letter: the letter to write at the current position
- * u8 TaSTT\_Row: the row to write on.
- * u8 TaSTT\_Col: the col to write on.
- * bool TaSTT\_Active: whether or not to overwrite (turn this off while seeking
- to a new spot).
* 6x14 display grid, 80 characters per slot.
* Each parameter - grid size, characters per slot, may be dialed up or down
as desired.
diff --git a/TaSTT.cs b/TaSTT.cs
deleted file mode 100644
index d9901d6..0000000
--- a/TaSTT.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEditor;
-using UnityEditor.Animations;
-using UnityEngine;
-using VRC.SDK3.Avatars.Components;
-using VRC.SDK3.Avatars.ScriptableObjects;
-
-namespace TaSTT
-{
- public class TaSTT : EditorWindow
- {
- private static TaSTT instance_;
- private GameObject avatar_root_;
- private AnimatorController fx_controller_;
-
- [MenuItem("Window/TaSTT")]
- private static void ShowWindow()
- {
- instance_ = GetWindow<TaSTT>();
- instance_.titleContent = new GUIContent("TaSTT");
- }
-
- private void Draw()
- {
- GUILayout.Label("TaSTT: A free VRChat STT");
- GUILayout.Label("Made with love by yum_food");
- GUILayout.Label("");
-
- avatar_root_ = (GameObject)EditorGUILayout.ObjectField(
- new GUIContent("Avatar Root"), avatar_root_,
- typeof(GameObject), true);
- fx_controller_ = (AnimatorController)EditorGUILayout.ObjectField(
- new GUIContent("FX Controller"), fx_controller_,
- typeof(AnimatorController), true);
-
- if (GUILayout.Button("Create animations!"))
- {
- if (avatar_root_ == null || !fx_controller_ == null)
- {
- // TODO(yum_food) why doesn't EditorGUILayout.HelpBox() work here?
- Debug.LogError("Avatar root or FX controller are not set! Cannot create animations.");
- return;
- }
- // TODO(yum_food)
- }
- if (GUILayout.Button("Create FX layer!"))
- {
- if (!avatar_root_ == null || !fx_controller_ == null)
- {
- Debug.LogError("Avatar root or FX controller are not set! Cannot create FX layer.");
- return;
- }
- // TODO(yum_food)
- }
- }
-
- private static void CreateAnimations()
- {
- VRCAvatarDescriptor descriptor = avatar_root_.GetComponent<VRCAvatarDescriptor>();
- if (descriptor == null)
- {
- Debug.LogError("Failed to get avatar descriptor");
- return;
- }
- AnimationClip anim = new AnimationClip();
- clip.frameRate = 1f;
- }
-
- private void OnGUI()
- {
- if (instance_ != null)
- {
- Draw();
- }
- }
- }
-}
diff --git a/TaSTT.shader b/TaSTT.shader
index 8f18dae..f5ec6af 100644
--- a/TaSTT.shader
+++ b/TaSTT.shader
@@ -74,20 +74,20 @@
_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_Row03_Col00("_Letter_Row03_Col00", float) = 0
- _Letter_Row03_Col01("_Letter_Row03_Col01", float) = 0
- _Letter_Row03_Col02("_Letter_Row03_Col02", float) = 0
- _Letter_Row03_Col03("_Letter_Row03_Col03", float) = 0
- _Letter_Row03_Col04("_Letter_Row03_Col04", float) = 0
- _Letter_Row03_Col05("_Letter_Row03_Col05", float) = 0
- _Letter_Row03_Col06("_Letter_Row03_Col06", float) = 0
- _Letter_Row03_Col07("_Letter_Row03_Col07", float) = 0
- _Letter_Row03_Col08("_Letter_Row03_Col08", float) = 0
- _Letter_Row03_Col09("_Letter_Row03_Col09", float) = 0
- _Letter_Row03_Col10("_Letter_Row03_Col10", float) = 0
- _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_Row05_Col00("_Letter_Row05_Col00", float) = 0
+ _Letter_Row05_Col01("_Letter_Row05_Col01", float) = 0
+ _Letter_Row05_Col02("_Letter_Row05_Col02", float) = 0
+ _Letter_Row05_Col03("_Letter_Row05_Col03", float) = 0
+ _Letter_Row05_Col04("_Letter_Row05_Col04", float) = 0
+ _Letter_Row05_Col05("_Letter_Row05_Col05", float) = 0
+ _Letter_Row05_Col06("_Letter_Row05_Col06", float) = 0
+ _Letter_Row05_Col07("_Letter_Row05_Col07", float) = 0
+ _Letter_Row05_Col08("_Letter_Row05_Col08", float) = 0
+ _Letter_Row05_Col09("_Letter_Row05_Col09", float) = 0
+ _Letter_Row05_Col10("_Letter_Row05_Col10", float) = 0
+ _Letter_Row05_Col11("_Letter_Row05_Col11", float) = 0
+ _Letter_Row05_Col12("_Letter_Row05_Col12", float) = 0
+ _Letter_Row05_Col13("_Letter_Row05_Col13", float) = 0
}
SubShader
{
@@ -268,7 +268,7 @@
float CHAR_ROW = floor(i.uv.y * CHAR_ROWS);
// ok now this is epic
- if (CHAR_ROW == 0) {
+ if (CHAR_ROW == 5) {
if (CHAR_COL == 0) {
return _Letter_Row00_Col00;
} else if (CHAR_COL == 1) {
@@ -298,7 +298,7 @@
} else if (CHAR_COL == 13) {
return _Letter_Row00_Col13;
}
- } else if (CHAR_ROW == 1) {
+ } else if (CHAR_ROW == 4) {
if (CHAR_COL == 0) {
return _Letter_Row01_Col00;
} else if (CHAR_COL == 1) {
@@ -328,7 +328,7 @@
} else if (CHAR_COL == 13) {
return _Letter_Row01_Col13;
}
- } else if (CHAR_ROW == 2) {
+ } else if (CHAR_ROW == 3) {
if (CHAR_COL == 0) {
return _Letter_Row02_Col00;
} else if (CHAR_COL == 1) {
@@ -358,7 +358,7 @@
} else if (CHAR_COL == 13) {
return _Letter_Row02_Col13;
}
- } else if (CHAR_ROW == 3) {
+ } else if (CHAR_ROW == 2) {
if (CHAR_COL == 0) {
return _Letter_Row03_Col00;
} else if (CHAR_COL == 1) {
@@ -388,7 +388,7 @@
} else if (CHAR_COL == 13) {
return _Letter_Row03_Col13;
}
- } else if (CHAR_ROW == 4) {
+ } else if (CHAR_ROW == 1) {
if (CHAR_COL == 0) {
return _Letter_Row04_Col00;
} else if (CHAR_COL == 1) {
@@ -418,7 +418,7 @@
} else if (CHAR_COL == 13) {
return _Letter_Row04_Col13;
}
- } else if (CHAR_ROW == 5) {
+ } else if (CHAR_ROW == 0) {
if (CHAR_COL == 0) {
return _Letter_Row05_Col00;
} else if (CHAR_COL == 1) {
diff --git a/TaSTT_params.asset b/TaSTT_params.asset
deleted file mode 100644
index 4c79902..0000000
--- a/TaSTT_params.asset
+++ /dev/null
@@ -1,31 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!114 &11400000
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 0}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: -1506855854, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3}
- m_Name: TaSTT_params
- m_EditorClassIdentifier:
- parameters:
- - name: TaSTT_Letter
- valueType: 0
- saved: 0
- defaultValue: 0
- - name: TaSTT_Row
- valueType: 0
- saved: 0
- defaultValue: 0
- - name: TaSTT_Col
- valueType: 0
- saved: 0
- defaultValue: 0
- - name: TaSTT_Active
- valueType: 2
- saved: 0
- defaultValue: 0
diff --git a/cell_names.txt b/cell_names.txt
deleted file mode 100644
index 1000cd1..0000000
--- a/cell_names.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-_Letter_Row00_Col00
-_Letter_Row00_Col01
-_Letter_Row00_Col02
-_Letter_Row00_Col03
-_Letter_Row00_Col04
-_Letter_Row00_Col05
-_Letter_Row00_Col06
-_Letter_Row00_Col07
-_Letter_Row00_Col08
-_Letter_Row00_Col09
-_Letter_Row00_Col10
-_Letter_Row00_Col11
-_Letter_Row00_Col12
-_Letter_Row00_Col13
-_Letter_Row01_Col00
-_Letter_Row01_Col01
-_Letter_Row01_Col02
-_Letter_Row01_Col03
-_Letter_Row01_Col04
-_Letter_Row01_Col05
-_Letter_Row01_Col06
-_Letter_Row01_Col07
-_Letter_Row01_Col08
-_Letter_Row01_Col09
-_Letter_Row01_Col10
-_Letter_Row01_Col11
-_Letter_Row01_Col12
-_Letter_Row01_Col13
-_Letter_Row02_Col00
-_Letter_Row02_Col01
-_Letter_Row02_Col02
-_Letter_Row02_Col03
-_Letter_Row02_Col04
-_Letter_Row02_Col05
-_Letter_Row02_Col06
-_Letter_Row02_Col07
-_Letter_Row02_Col08
-_Letter_Row02_Col09
-_Letter_Row02_Col10
-_Letter_Row02_Col11
-_Letter_Row02_Col12
-_Letter_Row02_Col13
-_Letter_Row03_Col00
-_Letter_Row03_Col01
-_Letter_Row03_Col02
-_Letter_Row03_Col03
-_Letter_Row03_Col04
-_Letter_Row03_Col05
-_Letter_Row03_Col06
-_Letter_Row03_Col07
-_Letter_Row03_Col08
-_Letter_Row03_Col09
-_Letter_Row03_Col10
-_Letter_Row03_Col11
-_Letter_Row03_Col12
-_Letter_Row03_Col13
-_Letter_Row04_Col00
-_Letter_Row04_Col01
-_Letter_Row04_Col02
-_Letter_Row04_Col03
-_Letter_Row04_Col04
-_Letter_Row04_Col05
-_Letter_Row04_Col06
-_Letter_Row04_Col07
-_Letter_Row04_Col08
-_Letter_Row04_Col09
-_Letter_Row04_Col10
-_Letter_Row04_Col11
-_Letter_Row04_Col12
-_Letter_Row04_Col13
-_Letter_Row05_Col00
-_Letter_Row05_Col01
-_Letter_Row05_Col02
-_Letter_Row05_Col03
-_Letter_Row05_Col04
-_Letter_Row05_Col05
-_Letter_Row05_Col06
-_Letter_Row05_Col07
-_Letter_Row05_Col08
-_Letter_Row05_Col09
-_Letter_Row05_Col10
-_Letter_Row05_Col11
-_Letter_Row05_Col12
-_Letter_Row05_Col13
diff --git a/generate_fx.py b/generate_fx.py
index ba1d590..28d6550 100644
--- a/generate_fx.py
+++ b/generate_fx.py
@@ -15,10 +15,18 @@
# where we're transitioning to.
# 12. %TRANSITION_THRESHOLD% - the threshold to use when transitioning.
+from generate_utils import replaceMacros
+from generate_utils import getDummyParam
+from generate_utils import getLayerParam
+from generate_utils import getSelectParam
+from generate_utils import getEnableParam
+from generate_utils import getShaderParam
+from generate_utils import getAnimationPath
+from generate_utils import NUM_LAYERS
+from generate_utils import CHARS_PER_CELL
+
# To debug, I recommend setting these values low and manually moving things
# around in the animator. Then run using Lyuma's avatar 3.0 emulator.
-NUM_ROWS=6
-NUM_COLS=14
NUM_LETTERS=80
params = {}
@@ -34,33 +42,20 @@ def get_u2(class_id, state):
# These !u! and & numbers are, respectively, a class ID and an instance ID.
# The instance ID begins with the class ID then has a 5-digit suffix.
params["ANIMATOR_CONTROLLER_U"] = "91"
-params["ANIMATOR_HEADER_U2"] = "9100000" # this is a special value
+params["ANIMATOR_HEADER_U2"] = "9100000"
params["ANIMATOR_STATE_MACHINE_U"] = "1107"
-params["TASTT_LAYER_U2"] = get_u2("1107", state)
params["MONO_BEHAVIOUR_U"] = "114"
-params["SET_LETTERS_SCRIPT_U2"] = get_u2("114", state)
params["ANIMATOR_STATE_U"] = "1102"
-params["TASTT_DEFAULT_STATE_U2"] = get_u2("1102", state)
-params["TASTT_ACTIVE_STATE_U2"] = get_u2("1102", state)
params["ANIMATOR_STATE_TRANSITION_U"] = "1101"
-params["TASTT_ACTIVE_STATE_TRANSITION_U2"] = get_u2("1101", state)
-params["TASTT_RESTART_TRANSITION_U2"] = get_u2("1101", state)
HEADER="""
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
-"""[1:]
-
-# Generates the sed cmd args required to replace all parameters defined in
-# $1, which is an associative array like `params`.
-def replaceMacros(lines, macro_defs):
- for k,v in macro_defs.items():
- lines = lines.replace("%" + k + "%", v)
- return lines
+"""[1:][:-1]
def genHeader():
return replaceMacros(HEADER, params)
@@ -75,11 +70,11 @@ AnimatorController:
m_PrefabAsset: {fileID: 0}
m_Name: TaSTT_fx
serializedVersion: 5
-"""[1:]
+"""[1:][:-1]
ANIMATOR_PARAMETER_HEADER = """
m_AnimatorParameters:
-"""[1:]
+"""[1:][:-1]
ANIMATOR_PARAMETER_INT = """
- m_Name: %ANIMATOR_PARAMETER_NAME%
@@ -88,7 +83,7 @@ ANIMATOR_PARAMETER_INT = """
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
-"""[1:]
+"""[1:][:-1]
ANIMATOR_PARAMETER_BOOL = """
- m_Name: %ANIMATOR_PARAMETER_NAME%
@@ -97,42 +92,26 @@ ANIMATOR_PARAMETER_BOOL = """
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 0}
-"""[1:]
+"""[1:][:-1]
ANIMATOR_LAYER_HEADER = """
m_AnimatorLayers:
-"""[1:]
+"""[1:][:-1]
-# We have a single animator layer which does everything.
ANIMATOR_LAYER_TASTT = """
- serializedVersion: 5
- m_Name: TaSTT
+ m_Name: %TASTT_LAYER_NAME%
m_StateMachine: {fileID: %TASTT_LAYER_U2%}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
- m_DefaultWeight: 0
- m_IKPass: 0
- m_SyncedLayerAffectsTiming: 0
- m_Controller: {fileID: %ANIMATOR_HEADER_U2%}
-"""[1:]
-
-ANIMATOR_LAYER_CELL_ANIM = """
- - serializedVersion: 5
- m_Name: %LAYER_NAME%
- m_StateMachine: {fileID: %LAYER_STATE_MACHINE_U2%}
- m_Mask: {fileID: 0}
- m_Motions: []
- m_Behaviours: []
- m_BlendingMode: 0
- m_SyncedLayerIndex: -1
m_DefaultWeight: 1
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: %ANIMATOR_HEADER_U2%}
-"""[1:]
+"""[1:][:-1]
GROUP_NAMES = [
"_Letter_Row00_Col00_03",
@@ -252,19 +231,33 @@ def genAnimator(state):
print(replaceMacros(ANIMATOR_HEADER, params))
print(ANIMATOR_PARAMETER_HEADER)
- params["ANIMATOR_PARAMETER_NAME"] = "TaSTT_Letter"
- print(replaceMacros(ANIMATOR_PARAMETER_INT, params))
- params["ANIMATOR_PARAMETER_NAME"] = "TaSTT_Row"
- print(replaceMacros(ANIMATOR_PARAMETER_INT, params))
- params["ANIMATOR_PARAMETER_NAME"] = "TaSTT_Col"
- print(replaceMacros(ANIMATOR_PARAMETER_INT, params))
- params["ANIMATOR_PARAMETER_NAME"] = "TaSTT_Active"
- print(replaceMacros(ANIMATOR_PARAMETER_BOOL, params))
- params["ANIMATOR_PARAMETER_NAME"] = "TaSTT_Dummy"
+ params["ANIMATOR_PARAMETER_NAME"] = getDummyParam()
print(replaceMacros(ANIMATOR_PARAMETER_BOOL, params))
+ for i in range(0, NUM_LAYERS):
+ params["ANIMATOR_PARAMETER_NAME"] = getLayerParam(i)
+ print(replaceMacros(ANIMATOR_PARAMETER_INT, params))
+
+ params["ANIMATOR_PARAMETER_NAME"] = getSelectParam(i, 0)
+ print(replaceMacros(ANIMATOR_PARAMETER_BOOL, params))
+
+ params["ANIMATOR_PARAMETER_NAME"] = getSelectParam(i, 1)
+ print(replaceMacros(ANIMATOR_PARAMETER_BOOL, params))
+
+ params["ANIMATOR_PARAMETER_NAME"] = getSelectParam(i, 2)
+ print(replaceMacros(ANIMATOR_PARAMETER_BOOL, params))
+
+ params["ANIMATOR_PARAMETER_NAME"] = getEnableParam(i)
+ print(replaceMacros(ANIMATOR_PARAMETER_BOOL, params))
+
+
print(replaceMacros(ANIMATOR_LAYER_HEADER, params))
- print(replaceMacros(ANIMATOR_LAYER_TASTT, params))
+
+ for i in range(0, NUM_LAYERS):
+ params[getLayerParam(i) + "_LAYER_U2"] = get_u2("1107", state)
+ params["TASTT_LAYER_U2"] = params[getLayerParam(i) + "_LAYER_U2"]
+ params["TASTT_LAYER_NAME"] = getLayerParam(i)
+ print(replaceMacros(ANIMATOR_LAYER_TASTT, params))
genAnimator(state)
TASTT_LAYER_HEADER = """
@@ -275,15 +268,15 @@ AnimatorStateMachine:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_Name: TaSTT
+ m_Name: %TASTT_LAYER_NAME%
m_ChildStates:
-"""[1:]
+"""[1:][:-1]
TASTT_LAYER_HEADER_CHILD_STATE = """
- serializedVersion: 1
m_State: {fileID: %TASTT_STATE_U2%}
m_Position: {x: 330, y: -60, z: 0}
-"""[1:]
+"""[1:][:-1]
TASTT_LAYER_FOOTER = """
m_ChildStateMachines: []
@@ -296,23 +289,26 @@ TASTT_LAYER_FOOTER = """
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: %TASTT_DEFAULT_STATE_U2%}
-"""[1:]
+"""[1:][:-1]
-# Default state.
-# One transition to TaSTT_Active.
-TASTT_DEFAULT_STATE = """
---- !u!%ANIMATOR_STATE_U% &%TASTT_DEFAULT_STATE_U2%
+# State with one transition.
+# Params:
+# %TASTT_STATE_NAME%: the name of this state
+# %TASTT_STATE_TRANSITION_U2%: the U2 of the transition to the next state
+# %TASTT_STATE_TRANSITION_U2%
+TASTT_UNARY_STATE = """
+--- !u!%ANIMATOR_STATE_U% &%TASTT_STATE_U2%
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_Name: TaSTT_Do_Nothing
+ m_Name: %TASTT_STATE_NAME%
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- - {fileID: %TASTT_ACTIVE_STATE_TRANSITION_U2%}
+ - {fileID: %TASTT_STATE_TRANSITION_U2%}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
@@ -328,61 +324,28 @@ AnimatorState:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
-"""[1:]
+"""[1:][:-1]
-# Transition from TaSTT_Do_nothing. to TaSTT_Active.
+# State with two transitions.
# Params:
-# %TASTT_ACTIVE_STATE_TRANSITION_U2%
-# %TASTT_ROW_STATE_U2% - address of row state we're transitioning to
-TASTT_ACTIVE_STATE_TRANSITION = """
---- !u!1101 &%TASTT_ACTIVE_STATE_TRANSITION_U2%
-AnimatorStateTransition:
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 1
- m_ConditionEvent: TaSTT_Active
- m_EventTreshold: 1
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: %TASTT_ACTIVE_STATE_U2%}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0
- m_TransitionOffset: 0
- m_ExitTime: 0.75
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
-"""[1:]
-
-# State reached when TaSTT_Active = True.
-# One transition per row.
-TASTT_ACTIVE_STATE_HEADER = """
---- !u!1102 &%TASTT_ACTIVE_STATE_U2%
+# %TASTT_STATE_NAME%: the name of this state
+# %TASTT_STATE_TRANSITION_0_U2%
+# %TASTT_STATE_TRANSITION_1_U2%
+# %TASTT_STATE_TRANSITION_U2%
+TASTT_BINARY_STATE = """
+--- !u!%ANIMATOR_STATE_U% &%TASTT_STATE_U2%
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_Name: TaSTT_Active
+ m_Name: %TASTT_STATE_NAME%
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
-"""[1:]
-
-TASTT_ACTIVE_STATE_HEADER_TRANSITION = """
- - {fileID: %TASTT_TRANSITION_U2%}
-"""[1:]
-
-TASTT_ACTIVE_STATE_FOOTER = """
+ - {fileID: %TASTT_STATE_TRANSITION_0_U2%}
+ - {fileID: %TASTT_STATE_TRANSITION_1_U2%}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
@@ -398,47 +361,40 @@ TASTT_ACTIVE_STATE_FOOTER = """
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
-"""[1:]
+"""[1:][:-1]
-# Transition from TaSTT_Active to TaSTT_Row*.
-# Params:
-# TRANSITION_THRESHOLD: The row to transition to (int).
-# DST_STATE_U2
-TASTT_ROW_STATE_TRANSITION = """
---- !u!1101 &%TRANSITION_U2%
-AnimatorStateTransition:
+TASTT_UNARY_STATE = """
+--- !u!%ANIMATOR_STATE_U% &%TASTT_STATE_U2%
+AnimatorState:
+ serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_Name:
- m_Conditions:
- - m_ConditionMode: 6
- m_ConditionEvent: TaSTT_Row
- m_EventTreshold: %TRANSITION_THRESHOLD%
- m_DstStateMachine: {fileID: 0}
- m_DstState: {fileID: %DST_STATE_U2%}
- m_Solo: 0
- m_Mute: 0
- m_IsExit: 0
- serializedVersion: 3
- m_TransitionDuration: 0
- m_TransitionOffset: 0
- m_ExitTime: 0.75
- m_HasExitTime: 0
- m_HasFixedDuration: 1
- m_InterruptionSource: 0
- m_OrderedInterruption: 1
- m_CanTransitionToSelf: 1
-"""[1:]
+ m_Name: %TASTT_STATE_NAME%
+ m_Speed: 1
+ m_CycleOffset: 0
+ m_Transitions:
+ - {fileID: %TASTT_STATE_TRANSITION_U2%}
+ m_StateMachineBehaviours: []
+ m_Position: {x: 50, y: 50, z: 0}
+ m_IKOnFeet: 0
+ m_WriteDefaultValues: 0
+ m_Mirror: 0
+ m_SpeedParameterActive: 0
+ m_MirrorParameterActive: 0
+ m_CycleOffsetParameterActive: 0
+ m_TimeParameterActive: 0
+ m_Motion: {fileID: 0}
+ m_Tag:
+ m_SpeedParameter:
+ m_MirrorParameter:
+ m_CycleOffsetParameter:
+ m_TimeParameter:
+"""[1:][:-1]
-# State reached after TaSTT_Active.
-# One transition per column.
-# Params:
-# %TASTT_STATE_NAME%: TaSTT_Row[0-9][0-9].
-# %TASTT_TRANSITION_U2%
-TASTT_ROW_STATE_HEADER = """
---- !u!1102 &%TASTT_STATE_U2%
+TASTT_NARY_STATE_HEADER = """
+--- !u!%ANIMATOR_STATE_U% &%TASTT_STATE_U2%
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
@@ -449,13 +405,13 @@ AnimatorState:
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
-"""[1:]
+"""[1:][:-1]
-TASTT_ROW_STATE_HEADER_TRANSITION = """
- - {fileID: %TASTT_TRANSITION_U2%}
-"""[1:]
+TASTT_NARY_STATE_HEADER_TRANSITION = """
+ - {fileID: %TASTT_STATE_TRANSITION_U2%}
+"""[1:][:-1]
-TASTT_ROW_STATE_FOOTER = """
+TASTT_NARY_STATE_FOOTER = """
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
@@ -471,14 +427,18 @@ TASTT_ROW_STATE_FOOTER = """
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
-"""[1:]
+"""[1:][:-1]
-# Transition from TaSTT_Row* to TaSTT_Row*_Col*.
+# Transition from TaSTT_Do_nothing. to TaSTT_Active.
# Params:
-# TRANSITION_THRESHOLD: The col to transition to (int).
-# DST_STATE_U2
-TASTT_COL_STATE_TRANSITION = """
---- !u!1101 &%TASTT_TRANSITION_U2%
+# %BOOL_PARAM% - the name of the parameter to branch on
+# %THRESHOLD% - the condition to branch on (1 == true)
+# %TASTT_ACTIVE_STATE_TRANSITION_U2%
+# %TASTT_ROW_STATE_U2% - address of row state we're transitioning to
+# A bizarre quirk: when branching false, m_ConditionMode = 2; else
+# m_ConditionMode = 1.
+TASTT_BOOL_STATE_TRANSITION = """
+--- !u!1101 &%TASTT_STATE_TRANSITION_U2%
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
@@ -486,9 +446,9 @@ AnimatorStateTransition:
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- - m_ConditionMode: 6
- m_ConditionEvent: TaSTT_Col
- m_EventTreshold: %TRANSITION_THRESHOLD%
+ - m_ConditionMode: %MODE%
+ m_ConditionEvent: %BOOL_PARAM%
+ m_EventTreshold: %THRESHOLD%
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: %DST_STATE_U2%}
m_Solo: 0
@@ -503,55 +463,10 @@ AnimatorStateTransition:
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
-"""[1:]
+"""[1:][:-1]
-# State reached after TaSTT_Row*.
-# One transition per letter.
-# Params:
-# %TASTT_STATE_NAME%: TaSTT_Row[0-9][0-9]_Col[0-9][0-9]
-# %TASTT_TRANSITION_U2%
-TASTT_COL_STATE_HEADER = """
---- !u!1102 &%TASTT_STATE_U2%
-AnimatorState:
- serializedVersion: 6
- m_ObjectHideFlags: 1
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: %TASTT_STATE_NAME%
- m_Speed: 1
- m_CycleOffset: 0
- m_Transitions:
-"""[1:]
-
-TASTT_COL_STATE_HEADER_TRANSITION = """
- - {fileID: %TASTT_TRANSITION_U2%}
-"""[1:]
-
-TASTT_COL_STATE_FOOTER = """
- m_StateMachineBehaviours: []
- m_Position: {x: 50, y: 50, z: 0}
- m_IKOnFeet: 0
- m_WriteDefaultValues: 0
- m_Mirror: 0
- m_SpeedParameterActive: 0
- m_MirrorParameterActive: 0
- m_CycleOffsetParameterActive: 0
- m_TimeParameterActive: 0
- m_Motion: {fileID: 0}
- m_Tag:
- m_SpeedParameter:
- m_MirrorParameter:
- m_CycleOffsetParameter:
- m_TimeParameter:
-"""
-
-# Transition from TaSTT_Row*_Col* to TaSTT_Row*_Col*_Letter*.
-# Params:
-# TRANSITION_THRESHOLD: The row to transition to (int).
-# DST_STATE_U2
-TASTT_LETTER_STATE_TRANSITION = """
---- !u!1101 &%TASTT_TRANSITION_U2%
+TASTT_INT_STATE_TRANSITION = """
+--- !u!1101 &%TASTT_STATE_TRANSITION_U2%
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
@@ -560,7 +475,7 @@ AnimatorStateTransition:
m_Name:
m_Conditions:
- m_ConditionMode: 6
- m_ConditionEvent: TaSTT_Letter
+ m_ConditionEvent: %INT_PARAM%
m_EventTreshold: %TRANSITION_THRESHOLD%
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: %DST_STATE_U2%}
@@ -568,7 +483,7 @@ AnimatorStateTransition:
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
- m_TransitionDuration: 0
+ m_TransitionDuration: 0.02
m_TransitionOffset: 0
m_ExitTime: 0.75
m_HasExitTime: 0
@@ -576,7 +491,7 @@ AnimatorStateTransition:
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
-"""[1:]
+"""[1:][:-1]
# State reached after TaSTT_Row*_Col*.
# One transition back up to TaSTT_Do_Nothing.
@@ -597,7 +512,7 @@ AnimatorState:
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- - {fileID: %TASTT_RESTART_TRANSITION_U2%}
+ - {fileID: %TASTT_STATE_TRANSITION_U2%}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
@@ -613,7 +528,7 @@ AnimatorState:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
-"""[1:]
+"""[1:][:-1]
TASTT_RESTART_TRANSITION = """
--- !u!1101 &%TASTT_RESTART_TRANSITION_U2%
@@ -641,7 +556,7 @@ AnimatorStateTransition:
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
-"""
+"""[1:][:-1]
def getAnimationGuid(anim_meta_filename):
with open(anim_meta_filename, 'r') as f:
@@ -649,108 +564,185 @@ def getAnimationGuid(anim_meta_filename):
if "guid" in line:
return line.split()[1]
-def genTasttLayer(state):
+def getDefaultStateName(which_layer):
+ return "TaSTT_Do_Nothing"
+
+def getActiveStateName(which_layer):
+ return "TaSTT_Active"
+
+def getS0StateName(which_layer, s0):
+ return "TaSTT_S%02d" % (s0)
+
+def getS1StateName(which_layer, s0, s1):
+ return "TaSTT_S%02d_S%02d" % (s0, s1)
+
+def getS2StateName(which_layer, s0, s1, s2):
+ return "TaSTT_S%02d_S%02d_S%02d" % (s0, s1, s2)
+
+def getLetterStateName(which_layer, s0, s1, s2, letter):
+ return "TaSTT_S%02d_S%02d_S%02d_L%03d" % (s0, s1, s2, letter)
+
+def genTasttLayer(state, which_layer):
# Generate return-home transition
- print(replaceMacros(TASTT_RESTART_TRANSITION, params))
+ params["TASTT_RETURN_HOME_TRANSITION_%02d_U2" % which_layer] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_U2"] = params["TASTT_RETURN_HOME_TRANSITION_%02d_U2" % which_layer]
+ params["BOOL_PARAM"] = getDummyParam()
+ params["THRESHOLD"] = str(0)
+ params["MODE"] = str(2) # See comment above TASTT_BOOL_STATE_TRANSITION.
+ params["DEFAULT_STATE_U2"] = get_u2("1102", state)
+ params["DST_STATE_U2"] = params["DEFAULT_STATE_U2"]
+ print(replaceMacros(TASTT_BOOL_STATE_TRANSITION, params))
# Default state.
- print(replaceMacros(TASTT_DEFAULT_STATE, params))
+ params["TASTT_STATE_U2"] = params["DEFAULT_STATE_U2"]
+ params["TASTT_STATE_NAME"] = getDefaultStateName(which_layer)
+ params["TASTT_STATE_TRANSITION_U2"] = get_u2("1101", state)
+ print(replaceMacros(TASTT_UNARY_STATE, params))
# Active state transition.
- print(replaceMacros(TASTT_ACTIVE_STATE_TRANSITION, params))
+ params["BOOL_PARAM"] = getEnableParam(which_layer)
+ params["THRESHOLD"] = str(1)
+ params["MODE"] = str(1) # See comment above TASTT_BOOL_STATE_TRANSITION.
+ params["ACTIVE_STATE_U2"] = get_u2("1102", state)
+ params["DST_STATE_U2"] = params["ACTIVE_STATE_U2"]
+ print(replaceMacros(TASTT_BOOL_STATE_TRANSITION, params))
# Active state.
- print(replaceMacros(TASTT_ACTIVE_STATE_HEADER, params))
- for row in range(0, NUM_ROWS):
- params["TASTT_TRANSITION_ROW%02d_U2" % row] = get_u2("1101", state)
- params["TASTT_TRANSITION_U2"] = params["TASTT_TRANSITION_ROW%02d_U2" % row]
- print(replaceMacros(TASTT_ACTIVE_STATE_HEADER_TRANSITION, params))
- print(replaceMacros(TASTT_ACTIVE_STATE_FOOTER, params))
-
- # Row state transitions (one per row).
- for row in range(0, NUM_ROWS):
- params["TRANSITION_U2"] = params["TASTT_TRANSITION_ROW%02d_U2" % row]
- params["TRANSITION_THRESHOLD"] = str(row)
- params["TASTT_ROW%02d_STATE_U2" % row] = get_u2("1102", state)
- params["DST_STATE_U2"] = params["TASTT_ROW%02d_STATE_U2" % row]
- print(replaceMacros(TASTT_ROW_STATE_TRANSITION, params))
-
- # Row states (one per row)..
- for row in range(0, NUM_ROWS):
- params["TASTT_STATE_U2"] = params["TASTT_ROW%02d_STATE_U2" % row]
- params["TASTT_STATE_NAME"] = "TaSTT_Row%02d" % row
- print(replaceMacros(TASTT_ROW_STATE_HEADER, params))
- for col in range(0, NUM_COLS):
- params["TASTT_TRANSITION_ROW%02d_COL%02d_U2" % (row, col)] = get_u2("1101", state)
- params["TASTT_TRANSITION_U2"] = params["TASTT_TRANSITION_ROW%02d_COL%02d_U2" % (row, col)]
- print(replaceMacros(TASTT_ROW_STATE_HEADER_TRANSITION, params))
- print(replaceMacros(TASTT_ROW_STATE_FOOTER, params))
-
- # Column state transitions (one per row * column).
- for row in range(0, NUM_ROWS):
- for col in range(0, NUM_COLS):
- params["TASTT_TRANSITION_U2"] = params["TASTT_TRANSITION_ROW%02d_COL%02d_U2" % (row, col)]
- params["TRANSITION_THRESHOLD"] = str(col)
- params["TASTT_ROW%02d_COL%02d_STATE_U2" % (row, col)] = get_u2("1102", state)
- params["DST_STATE_U2"] = params["TASTT_ROW%02d_COL%02d_STATE_U2" % (row, col)]
- print(replaceMacros(TASTT_COL_STATE_TRANSITION, params))
-
- # Column states (one per row * column).
- for row in range(0, NUM_ROWS):
- for col in range(0, NUM_COLS):
- params["TASTT_STATE_U2"] = params["TASTT_ROW%02d_COL%02d_STATE_U2" % (row, col)]
- params["TASTT_STATE_NAME"] = "TaSTT_Row%02d_Col%02d" % (row,
- col)
- print(replaceMacros(TASTT_COL_STATE_HEADER, params))
- for letter in range(0, NUM_LETTERS):
- params["TASTT_TRANSITION_ROW%02d_COL%02d_LETTER%02d_U2" % (row, col, letter)] = get_u2("1101", state)
- params["TASTT_TRANSITION_U2"] = params["TASTT_TRANSITION_ROW%02d_COL%02d_LETTER%02d_U2" % (row, col, letter)]
- print(replaceMacros(TASTT_COL_STATE_HEADER_TRANSITION, params))
- print(replaceMacros(TASTT_COL_STATE_FOOTER, params))
-
- # Letter state transitions (one per row * column * letter).
- for row in range(0, NUM_ROWS):
- for col in range(0, NUM_COLS):
- for letter in range(0, NUM_LETTERS):
- params["TASTT_TRANSITION_U2"] = params["TASTT_TRANSITION_ROW%02d_COL%02d_LETTER%02d_U2" % (row, col, letter)]
- params["TRANSITION_THRESHOLD"] = str(letter)
- params["TASTT_ROW%02d_COL%02d_LETTER%02d_STATE_U2" % (row, col, letter)] = get_u2("1102", state)
- params["DST_STATE_U2"] = params["TASTT_ROW%02d_COL%02d_LETTER%02d_STATE_U2" % (row, col, letter)]
- print(replaceMacros(TASTT_LETTER_STATE_TRANSITION, params))
-
- # Letter states (one per row * column * letter).
- for row in range(0, NUM_ROWS):
- for col in range(0, NUM_COLS):
- for letter in range(0, NUM_LETTERS):
- params["TASTT_STATE_U2"] = params["TASTT_ROW%02d_COL%02d_LETTER%02d_STATE_U2" % (row, col, letter)]
- params["TASTT_STATE_NAME"] = "TaSTT_Row%02d_Col%02d_Letter%02d" % (row, col, letter)
- # Get the GUID of the animation we will play here.
- anim_meta_filename = "generated/animations/_Letter_Row%02d_Col%02d_Letter%02d.anim.meta" % (row, col, letter)
- params["TASTT_ANIM_GUID"] = getAnimationGuid(anim_meta_filename)
- print(replaceMacros(TASTT_LETTER_STATE, params))
+ params["TASTT_STATE_U2"] = params["ACTIVE_STATE_U2"]
+ params["TASTT_STATE_NAME"] = getActiveStateName(which_layer)
+ params[getS0StateName(which_layer, 0) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_0_U2"] = params[getS0StateName(which_layer, 0) + "_TRANSITION_U2"]
+ params[getS0StateName(which_layer, 1) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_1_U2"] = params[getS0StateName(which_layer, 1) + "_TRANSITION_U2"]
+ print(replaceMacros(TASTT_BINARY_STATE, params))
+
+ # S0 state transition.
+ for s0 in range(0,2):
+ params["TASTT_STATE_TRANSITION_U2"] = params[getS0StateName(which_layer, s0) + "_TRANSITION_U2"]
+ params["BOOL_PARAM"] = getSelectParam(which_layer, 0)
+ params["THRESHOLD"] = str(s0)
+ params["MODE"] = str(2 - s0) # See comment above TASTT_BOOL_STATE_TRANSITION.
+ params[getS0StateName(which_layer, s0) + "_U2"] = get_u2("1102", state)
+ params["DST_STATE_U2"] = params[getS0StateName(which_layer, s0) + "_U2"]
+ print(replaceMacros(TASTT_BOOL_STATE_TRANSITION, params))
+
+ # S0 state.
+ for s0 in range(0,2):
+ params["TASTT_STATE_U2"] = params[getS0StateName(which_layer, s0) + "_U2"]
+ params["TASTT_STATE_NAME"] = getS0StateName(which_layer, s0)
+ params[getS1StateName(which_layer, s0, 0) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_0_U2"] = params[getS1StateName(which_layer, s0, 0) + "_TRANSITION_U2"]
+ params[getS1StateName(which_layer, s0, 1) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_1_U2"] = params[getS1StateName(which_layer, s0, 1) + "_TRANSITION_U2"]
+ print(replaceMacros(TASTT_BINARY_STATE, params))
+
+ # S1 state transition.
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ params["TASTT_STATE_TRANSITION_U2"] = params[getS1StateName(which_layer, s0, s1) + "_TRANSITION_U2"]
+ params["BOOL_PARAM"] = getSelectParam(which_layer, 1)
+ params["THRESHOLD"] = str(s1)
+ params["MODE"] = str(2 - s1) # See comment above TASTT_BOOL_STATE_TRANSITION.
+ params[getS1StateName(which_layer, s0, s1) + "_U2"] = get_u2("1102", state)
+ params["DST_STATE_U2"] = params[getS1StateName(which_layer, s0, s1) + "_U2"]
+ print(replaceMacros(TASTT_BOOL_STATE_TRANSITION, params))
+
+ # S1 state.
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ params["TASTT_STATE_U2"] = params[getS1StateName(which_layer, s0, s1) + "_U2"]
+ params["TASTT_STATE_NAME"] = getS1StateName(which_layer, s0, s1)
+ params[getS2StateName(which_layer, s0, s1, 0) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_0_U2"] = params[getS2StateName(which_layer, s0, s1, 0) + "_TRANSITION_U2"]
+ params[getS2StateName(which_layer, s0, s1, 1) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_1_U2"] = params[getS2StateName(which_layer, s0, s1, 1) + "_TRANSITION_U2"]
+ print(replaceMacros(TASTT_BINARY_STATE, params))
+
+ # S2 state transition.
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ for s2 in range(0,2):
+ params["TASTT_STATE_TRANSITION_U2"] = params[getS2StateName(which_layer, s0, s1, s2) + "_TRANSITION_U2"]
+ params["BOOL_PARAM"] = getSelectParam(which_layer, 2)
+ params["THRESHOLD"] = str(s2)
+ params["MODE"] = str(2 - s2) # See comment above TASTT_BOOL_STATE_TRANSITION.
+ params[getS2StateName(which_layer, s0, s1, s2) + "_U2"] = get_u2("1102", state)
+ params["DST_STATE_U2"] = params[getS2StateName(which_layer, s0, s1, s2) + "_U2"]
+ print(replaceMacros(TASTT_BOOL_STATE_TRANSITION, params))
+
+ # S2 state.
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ for s2 in range(0,2):
+ params["TASTT_STATE_U2"] = params[getS2StateName(which_layer, s0, s1, s2) + "_U2"]
+ params["TASTT_STATE_NAME"] = getS2StateName(which_layer, s0, s1, s2)
+ print(replaceMacros(TASTT_NARY_STATE_HEADER, params))
+ for letter in range(0, CHARS_PER_CELL):
+ params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_TRANSITION_U2"] = get_u2("1101", state)
+ params["TASTT_STATE_TRANSITION_U2"] = params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_TRANSITION_U2"]
+ print(replaceMacros(TASTT_NARY_STATE_HEADER_TRANSITION, params))
+ print(replaceMacros(TASTT_NARY_STATE_FOOTER, params))
+
+ # Letter state transition.
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ for s2 in range(0,2):
+ for letter in range(0, CHARS_PER_CELL):
+ params["TASTT_STATE_TRANSITION_U2"] = params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_TRANSITION_U2"]
+ params["INT_PARAM"] = getLayerParam(which_layer)
+ params["TRANSITION_THRESHOLD"] = str(letter)
+ params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_U2"] = get_u2("1102", state)
+ params["DST_STATE_U2"] = params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_U2"]
+ print(replaceMacros(TASTT_INT_STATE_TRANSITION, params))
+
+ # Letter state.
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ for s2 in range(0,2):
+ for letter in range(0, CHARS_PER_CELL):
+ params["TASTT_STATE_U2"] = params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_U2"]
+ params["TASTT_STATE_NAME"] = getLetterStateName(which_layer, s0, s1, s2, letter)
+ params["TASTT_STATE_TRANSITION_U2"] = params["TASTT_RETURN_HOME_TRANSITION_%02d_U2" % which_layer]
+ anim_meta_filename = getAnimationPath(getShaderParam(which_layer, s0, s1, s2), letter) + ".meta"
+ params["TASTT_ANIM_GUID"] = getAnimationGuid(anim_meta_filename)
+ print(replaceMacros(TASTT_LETTER_STATE, params))
# TaSTT layer.
+ params["TASTT_LAYER_U2"] = params[getLayerParam(which_layer) + "_LAYER_U2"]
+
+ params["TASTT_LAYER_NAME"] = getLayerParam(which_layer)
print(replaceMacros(TASTT_LAYER_HEADER, params))
- params["TASTT_STATE_U2"] = params["TASTT_DEFAULT_STATE_U2"]
+ params["TASTT_STATE_U2"] = params["DEFAULT_STATE_U2"]
print(replaceMacros(TASTT_LAYER_HEADER_CHILD_STATE, params))
- params["TASTT_STATE_U2"] = params["TASTT_ACTIVE_STATE_U2"]
+ params["TASTT_STATE_U2"] = params["ACTIVE_STATE_U2"]
print(replaceMacros(TASTT_LAYER_HEADER_CHILD_STATE, params))
- for row in range(0, NUM_ROWS):
- params["TASTT_STATE_U2"] = params["TASTT_ROW%02d_STATE_U2" % row]
+ for s0 in range(0,2):
+ params["TASTT_STATE_U2"] = params[getS0StateName(which_layer, s0) + "_U2"]
print(replaceMacros(TASTT_LAYER_HEADER_CHILD_STATE, params))
- for row in range(0, NUM_ROWS):
- for col in range(0, NUM_COLS):
- params["TASTT_STATE_U2"] = params["TASTT_ROW%02d_COL%02d_STATE_U2" % (row, col)]
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ params["TASTT_STATE_U2"] = params[getS1StateName(which_layer, s0, s1) + "_U2"]
print(replaceMacros(TASTT_LAYER_HEADER_CHILD_STATE, params))
- for row in range(0, NUM_ROWS):
- for col in range(0, NUM_COLS):
- for letter in range(0, NUM_LETTERS):
- params["TASTT_STATE_U2"] = params["TASTT_ROW%02d_COL%02d_LETTER%02d_STATE_U2" % (row, col, letter)]
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ for s2 in range(0,2):
+ params["TASTT_STATE_U2"] = params[getS2StateName(which_layer, s0, s1, s2) + "_U2"]
print(replaceMacros(TASTT_LAYER_HEADER_CHILD_STATE, params))
-genTasttLayer(state)
+ for s0 in range(0,2):
+ for s1 in range(0,2):
+ for s2 in range(0,2):
+ for letter in range(0, CHARS_PER_CELL):
+ params["TASTT_STATE_U2"] = params[getLetterStateName(which_layer, s0, s1, s2, letter) + "_U2"]
+ print(replaceMacros(TASTT_LAYER_HEADER_CHILD_STATE, params))
+
+ params["TASTT_DEFAULT_STATE_U2"] = params["DEFAULT_STATE_U2"]
+ print(replaceMacros(TASTT_LAYER_FOOTER, params))
+
+for i in range(0, NUM_LAYERS):
+ genTasttLayer(state, i)
diff --git a/generate_params.py b/generate_params.py
new file mode 100644
index 0000000..665a439
--- /dev/null
+++ b/generate_params.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+
+import generate_utils
+
+PARAM_HEADER = """
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: -1506855854, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3}
+ m_Name: TaSTT_params
+ m_EditorClassIdentifier:
+ parameters:
+"""[1:][0:-1]
+
+INT_PARAM = """
+ - name: %PARAM_NAME%
+ valueType: 0
+ saved: 0
+ defaultValue: 0
+"""[1:][0:-1]
+
+BOOL_PARAM = """
+ - name: %PARAM_NAME%
+ valueType: 2
+ saved: 0
+ defaultValue: 0
+"""[1:][0:-1]
+
+# We're working with an 84-character board, and each FX layer is responsible
+# for 8 of those characters.
+params = {}
+print(generate_utils.replaceMacros(PARAM_HEADER, params))
+
+# Implementation detail. We use this parameter to return from the terminal
+# state of the FX layer to the starting state.
+params["PARAM_NAME"] = "TaSTT_Dummy"
+print(generate_utils.replaceMacros(BOOL_PARAM, params))
+
+for i in range(0, generate_utils.NUM_LAYERS):
+ params["PARAM_NAME"] = generate_utils.getLayerParam(i)
+ print(generate_utils.replaceMacros(INT_PARAM, params))
+
+ params["PARAM_NAME"] = generate_utils.getSelectParam(i, 0)
+ print(generate_utils.replaceMacros(BOOL_PARAM, params))
+
+ params["PARAM_NAME"] = generate_utils.getSelectParam(i, 1)
+ print(generate_utils.replaceMacros(BOOL_PARAM, params))
+
+ params["PARAM_NAME"] = generate_utils.getSelectParam(i, 2)
+ print(generate_utils.replaceMacros(BOOL_PARAM, params))
+
+ params["PARAM_NAME"] = generate_utils.getEnableParam(i)
+ print(generate_utils.replaceMacros(BOOL_PARAM, params))
diff --git a/generate_utils.py b/generate_utils.py
new file mode 100644
index 0000000..1abb694
--- /dev/null
+++ b/generate_utils.py
@@ -0,0 +1,53 @@
+from math import ceil
+from math import floor
+
+def replaceMacros(lines, macro_defs):
+ for k,v in macro_defs.items():
+ lines = lines.replace("%" + k + "%", v)
+ return lines
+
+BOARD_ROWS=6
+BOARD_COLS=14
+INDEX_BITS=3
+CHARS_PER_CELL=80
+
+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))
+
+def getDummyParam():
+ return "TaSTT_Dummy"
+
+# Each layer controls a group of cells. There's only one letter per layer, thus
+# this is also the name of the parameter which sets the letter for a layer.
+def getLayerParam(which_layer):
+ return "TaSTT_L%02d" % which_layer
+
+def getSelectParam(which_layer, which_select):
+ return "TaSTT_L%02d_S%02d" % (which_layer, which_select)
+
+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.
+ return ((s0 * 4 + s1 * 2 + s2) * NUM_LAYERS + which_layer) % (BOARD_ROWS * BOARD_COLS)
+
+# Mapping from layer to shader param.
+def getShaderParam(which_layer, s0, s1, s2):
+ index = getBoardIndex(which_layer, s0, s1, s2)
+
+ col = index % BOARD_COLS
+ row = floor(index / BOARD_COLS)
+ return "_Letter_Row%02d_Col%02d" % (row, col)
+
+# Returns the path to the animation for the given shader parameter + letter.
+def getAnimationPath(shader_param, letter):
+ return "generated/animations/%s_Letter%02d.anim" % (shader_param, letter)
diff --git a/group_names.txt b/group_names.txt
deleted file mode 100644
index 0c39082..0000000
--- a/group_names.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-_Letter_Row00_Col00_03
-_Letter_Row00_Col04_07
-_Letter_Row00_Col08_11
-_Letter_Row00_Col12_13
-_Letter_Row01_Col00_03
-_Letter_Row01_Col04_07
-_Letter_Row01_Col08_11
-_Letter_Row01_Col12_13
-_Letter_Row02_Col00_03
-_Letter_Row02_Col04_07
-_Letter_Row02_Col08_11
-_Letter_Row02_Col12_13
-_Letter_Row03_Col00_03
-_Letter_Row03_Col04_07
-_Letter_Row03_Col08_11
-_Letter_Row03_Col12_13
-_Letter_Row04_Col00_03
-_Letter_Row04_Col04_07
-_Letter_Row04_Col08_11
-_Letter_Row04_Col12_13
-_Letter_Row05_Col00_03
-_Letter_Row05_Col04_07
-_Letter_Row05_Col08_11
-_Letter_Row05_Col12_13
diff --git a/osc_ctrl.py b/osc_ctrl.py
index 21386c4..3c19cd9 100644
--- a/osc_ctrl.py
+++ b/osc_ctrl.py
@@ -6,6 +6,15 @@ import time
import fileinput
from pythonosc import udp_client
+from math import ceil
+from math import floor
+from generate_utils import getLayerParam
+from generate_utils import getSelectParam
+from generate_utils import getEnableParam
+from generate_utils import getBoardIndex
+from generate_utils import NUM_LAYERS
+from generate_utils import BOARD_ROWS
+from generate_utils import BOARD_COLS
def usage():
print("python3 -m pip install python-osc")
@@ -18,26 +27,88 @@ args = parser.parse_args()
client = udp_client.SimpleUDPClient(args.i, args.p)
-seed = random.randrange(3) * 26
-for row in range(0, 6):
- addr="/avatar/parameters/TaSTT_Row"
- client.send_message(addr, row)
- for col in range(0, 14):
- addr="/avatar/parameters/TaSTT_Col"
- client.send_message(addr, col)
+def encodeMessage(msg):
+ 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))
+ return result
- time.sleep(.5)
+# `which_cell` is an integer in the range [0,8).
+def sendMessageCell(msg_cell, which_cell):
- addr="/avatar/parameters/TaSTT_Active"
- client.send_message(addr, True)
+ s0 = ((floor(which_cell / 4) % 2) == 1)
+ s1 = ((floor(which_cell / 2) % 2) == 1)
+ s2 = ((floor(which_cell / 1) % 2) == 1)
+
+ print("Cell s0/s1/s2: {}/{}/{}".format(s0,s1,s2))
+ # Seek each layer to the current cell.
+ for i in range(0, len(msg_cell)):
+ print("Board index: {}".format(getBoardIndex(i, s0, s1, s2)))
+
+ addr="/avatar/parameters/" + getLayerParam(i)
+ client.send_message(addr, msg_cell[i])
+
+ addr="/avatar/parameters/" + getSelectParam(i, 0)
+ client.send_message(addr, (floor(which_cell / 4) % 2) == 1)
- addr="/avatar/parameters/TaSTT_Letter"
- client.send_message(addr, (seed + row * 14 + col) % 65)
- print("sent {} at {},{}".format((seed + row * 14 + col) % 65, row, col))
+ addr="/avatar/parameters/" + getSelectParam(i, 1)
+ client.send_message(addr, (floor(which_cell / 2) % 2) == 1)
- time.sleep(.5)
+ addr="/avatar/parameters/" + getSelectParam(i, 2)
+ client.send_message(addr, (which_cell % 2) == 1)
+
+ # Wait for convergence.
+ time.sleep(0.3)
+
+ # Enable each layer.
+ # TODO(yum_food) for some reason, if we don't active every layer, the
+ # desired subset won't reliably fire. Why?
+ for i in range(0, NUM_LAYERS):
+ addr="/avatar/parameters/" + getEnableParam(i)
+ client.send_message(addr, True)
- addr="/avatar/parameters/TaSTT_Active"
+ # Wait for convergence.
+ time.sleep(0.3)
+
+ # Disable each layer.
+ for i in range(0, NUM_LAYERS):
+ addr="/avatar/parameters/" + getEnableParam(i)
client.send_message(addr, False)
-time.sleep(1000)
+ # Wait for convergence.
+ time.sleep(0.3)
+
+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)
+
+ n_cells = ceil(len(msg) / NUM_LAYERS)
+ for cell in range(0, n_cells):
+ 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)
+
+sendMessage("")
+