summaryrefslogtreecommitdiffstats
path: root/Scripts/libtastt.py
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-07-23 22:53:08 -0700
committeryum <yum.food.vr@gmail.com>2025-07-23 22:53:08 -0700
commit4539f87e36cb3ca554e1e174c19206b552107c57 (patch)
tree6f9aca818989773cc10f3c465224a07f847eb279 /Scripts/libtastt.py
parentf6b93a20d754579008076e85f5c0a97e1bcbc258 (diff)
Delete unused filesv1.0.0-beta00
Diffstat (limited to 'Scripts/libtastt.py')
-rw-r--r--Scripts/libtastt.py1085
1 files changed, 0 insertions, 1085 deletions
diff --git a/Scripts/libtastt.py b/Scripts/libtastt.py
deleted file mode 100644
index 81baa8b..0000000
--- a/Scripts/libtastt.py
+++ /dev/null
@@ -1,1085 +0,0 @@
-#!/usr/bin/env python3
-
-import app_config
-import argparse
-import array
-import generate_utils
-import libunity
-import os
-import pickle
-import sys
-import typing
-
-# TODO(yum) we're getting the encoding scheme from here, but I think it should
-# be in a different layer.
-import osc_ctrl
-
-SCALE_ANIMATION_TEMPLATE = """
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!74 &7400000
-AnimationClip:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: TaSTT_Scale_0
- serializedVersion: 6
- m_Legacy: 0
- m_Compressed: 0
- m_UseHighQualityCurve: 1
- m_RotationCurves: []
- m_CompressedRotationCurves: []
- m_EulerCurves: []
- m_PositionCurves: []
- m_ScaleCurves:
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: {x: 5, y: 5, z: 5}
- inSlope: {x: 0, y: 0, z: 0}
- outSlope: {x: 0, y: 0, z: 0}
- tangentMode: 0
- weightedMode: 0
- inWeight: {x: 0, y: 0.33333334, z: 0.33333334}
- outWeight: {x: 0, y: 0.33333334, z: 0.33333334}
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- path: World Constraint/Container/TaSTT
- m_FloatCurves: []
- m_PPtrCurves: []
- m_SampleRate: 60
- m_WrapMode: 0
- m_Bounds:
- m_Center: {x: 0, y: 0, z: 0}
- m_Extent: {x: 0, y: 0, z: 0}
- m_ClipBindingConstant:
- genericBindings:
- - serializedVersion: 2
- path: 1272388438
- attribute: 3
- script: {fileID: 0}
- typeID: 4
- customType: 0
- isPPtrCurve: 0
- - serializedVersion: 2
- path: 1272388438
- attribute: 1225223716
- script: {fileID: 0}
- typeID: 23
- customType: 0
- isPPtrCurve: 0
- pptrCurveMapping: []
- m_AnimationClipSettings:
- serializedVersion: 2
- m_AdditiveReferencePoseClip: {fileID: 0}
- m_AdditiveReferencePoseTime: 0
- m_StartTime: 0
- m_StopTime: 0.016666668
- m_OrientationOffsetY: 0
- m_Level: 0
- m_CycleOffset: 0
- m_HasAdditiveReferencePose: 0
- m_LoopTime: 1
- m_LoopBlend: 0
- m_LoopBlendOrientation: 0
- m_LoopBlendPositionY: 0
- m_LoopBlendPositionXZ: 0
- m_KeepOriginalOrientation: 0
- m_KeepOriginalPositionY: 1
- m_KeepOriginalPositionXZ: 0
- m_HeightFromFeet: 0
- m_Mirror: 0
- m_EditorCurves:
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: 5
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: m_LocalScale.x
- path: World Constraint/Container/TaSTT
- classID: 4
- script: {fileID: 0}
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: 5
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: m_LocalScale.y
- path: World Constraint/Container/TaSTT
- classID: 4
- script: {fileID: 0}
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: 5
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: m_LocalScale.z
- path: World Constraint/Container/TaSTT
- classID: 4
- script: {fileID: 0}
- m_EulerEditorCurves: []
- m_HasGenericRootTransform: 0
- m_HasMotionFloatCurves: 0
- m_Events: []
-"""
-
-SOUND_ANIMATION_TEMPLATE = """
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!74 &7400000
-AnimationClip:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Sound1_On
- serializedVersion: 6
- m_Legacy: 0
- m_Compressed: 0
- m_UseHighQualityCurve: 1
- m_RotationCurves: []
- m_CompressedRotationCurves: []
- m_EulerCurves: []
- m_PositionCurves: []
- m_ScaleCurves: []
- m_FloatCurves:
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: 1
- inSlope: Infinity
- outSlope: Infinity
- tangentMode: 103
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: m_IsActive
- path: World Constraint/Container/TaSTT/Audio 1
- classID: 1
- script: {fileID: 0}
- m_PPtrCurves: []
- m_SampleRate: 60
- m_WrapMode: 0
- m_Bounds:
- m_Center: {x: 0, y: 0, z: 0}
- m_Extent: {x: 0, y: 0, z: 0}
- m_ClipBindingConstant:
- genericBindings:
- - serializedVersion: 2
- path: 2267216663
- attribute: 2086281974
- script: {fileID: 0}
- typeID: 1
- customType: 0
- isPPtrCurve: 0
- pptrCurveMapping: []
- m_AnimationClipSettings:
- serializedVersion: 2
- m_AdditiveReferencePoseClip: {fileID: 0}
- m_AdditiveReferencePoseTime: 0
- m_StartTime: 0
- m_StopTime: 0
- m_OrientationOffsetY: 0
- m_Level: 0
- m_CycleOffset: 0
- m_HasAdditiveReferencePose: 0
- m_LoopTime: 0
- m_LoopBlend: 0
- m_LoopBlendOrientation: 0
- m_LoopBlendPositionY: 0
- m_LoopBlendPositionXZ: 0
- m_KeepOriginalOrientation: 0
- m_KeepOriginalPositionY: 1
- m_KeepOriginalPositionXZ: 0
- m_HeightFromFeet: 0
- m_Mirror: 0
- m_EditorCurves: []
- m_EulerEditorCurves: []
- m_HasGenericRootTransform: 0
- m_HasMotionFloatCurves: 0
- m_Events: []
-"""
-
-LETTER_ANIMATION_TEMPLATE = """
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!74 &7400000
-AnimationClip:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: REPLACEME_ANIMATION_NAME
- serializedVersion: 6
- m_Legacy: 0
- m_Compressed: 0
- m_UseHighQualityCurve: 1
- m_RotationCurves: []
- m_CompressedRotationCurves: []
- m_EulerCurves: []
- m_PositionCurves: []
- m_ScaleCurves: []
- m_FloatCurves:
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- - serializedVersion: 3
- time: 0.016666668
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: material.REPLACEME_LETTER_PARAM
- path: TaSTT
- classID: 23
- script: {fileID: 0}
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- - serializedVersion: 3
- time: 0.016666668
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: material.REPLACEME_LETTER_PARAM
- path: TaSTT
- classID: 137
- script: {fileID: 0}
- m_PPtrCurves: []
- m_SampleRate: 60
- m_WrapMode: 0
- m_Bounds:
- m_Center: {x: 0, y: 0, z: 0}
- m_Extent: {x: 0, y: 0, z: 0}
- m_ClipBindingConstant:
- genericBindings:
- - serializedVersion: 2
- path: 2794480623
- attribute: 2284639795
- script: {fileID: 0}
- typeID: 137
- customType: 22
- isPPtrCurve: 0
- pptrCurveMapping: []
- m_AnimationClipSettings:
- serializedVersion: 2
- m_AdditiveReferencePoseClip: {fileID: 0}
- m_AdditiveReferencePoseTime: 0
- m_StartTime: 0
- m_StopTime: 0
- m_OrientationOffsetY: 0
- m_Level: 0
- m_CycleOffset: 0
- m_HasAdditiveReferencePose: 0
- m_LoopTime: 1
- m_LoopBlend: 0
- m_LoopBlendOrientation: 0
- m_LoopBlendPositionY: 0
- m_LoopBlendPositionXZ: 0
- m_KeepOriginalOrientation: 0
- m_KeepOriginalPositionY: 1
- m_KeepOriginalPositionXZ: 0
- m_HeightFromFeet: 0
- m_Mirror: 0
- m_EditorCurves:
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- - serializedVersion: 3
- time: 0.016666668
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: material.REPLACEME_LETTER_PARAM
- path: TaSTT
- classID: 23
- script: {fileID: 0}
- - curve:
- serializedVersion: 2
- m_Curve:
- - serializedVersion: 3
- time: 0
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- - serializedVersion: 3
- time: 0.016666668
- value: REPLACEME_LETTER_VALUE
- inSlope: 0
- outSlope: 0
- tangentMode: 136
- weightedMode: 0
- inWeight: 0
- outWeight: 0
- m_PreInfinity: 2
- m_PostInfinity: 2
- m_RotationOrder: 4
- attribute: material.REPLACEME_LETTER_PARAM
- path: TaSTT
- classID: 137
- script: {fileID: 0}
- m_EulerEditorCurves: []
- m_HasGenericRootTransform: 0
- m_HasMotionFloatCurves: 0
- m_Events: []
-"""
-
-ANIMATOR_TEMPLATE = """
---- !u!91 &9100000
-AnimatorController:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: TaSTT_fx
- serializedVersion: 5
- m_AnimatorParameters: []
- m_AnimatorLayers: []
-"""
-
-# For whatever reason, running unrelated animations s.a.
-# facial expressions can have a slight effect on supposedly
-# unrelated parameters, causing letter to flip. Add a
-# little buffer to reduce the odds that this effect causes
-# a letter to change after it has been written.
-UNITY_ANIMATION_FUDGE_MARGIN = 0.1
-
-def generateClearAnimation(anim_dir: str, guid_map: typing.Dict[str, str]):
- print("Generating board clearing animation", file=sys.stderr)
-
- parser = libunity.UnityParser()
- parser.parse(LETTER_ANIMATION_TEMPLATE)
-
- anim_node = parser.nodes[0]
- anim_clip = anim_node.mapping['AnimationClip']
- curve_template = anim_clip.mapping['m_FloatCurves'].sequence[0]
- anim_clip.mapping['m_FloatCurves'].sequence = []
- anim_clip.mapping['m_EditorCurves'].sequence = []
-
- letter = 0
-
- for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
- for row in range(0, generate_utils.config.BOARD_ROWS):
- for col in range(0, generate_utils.config.BOARD_COLS):
- curve = curve_template.copy()
- for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence:
- keyframe.mapping['value'] = str(letter +
- UNITY_ANIMATION_FUDGE_MARGIN)
- curve.mapping['attribute'] = "material.{}".format(generate_utils.getShaderParamByRowColByte(row, col, byte))
- curve.mapping['path'] = "World Constraint/Container/TaSTT"
- # Add curve to animation
- anim_clip.mapping['m_FloatCurves'].sequence.append(curve)
- anim_clip.mapping['m_EditorCurves'].sequence.append(curve)
- # Serialize animation to file
- anim_name = generate_utils.getClearAnimationName()
- anim_path = os.path.join(anim_dir, anim_name + ".anim")
- print("Generating clear animation at {}".format(anim_path), file=sys.stderr)
- with open(anim_path, "w", encoding="utf-8") as f:
- f.write(libunity.unityYamlToString([anim_node]))
- # Generate metadata
- meta = libunity.Metadata()
- with open(anim_path + ".meta", "w", encoding="utf-8") as f:
- f.write(str(meta))
- # Add metadata to guid map
- guid_map[anim_path] = meta.guid
- guid_map[meta.guid] = anim_path
-
-# sound_chord: whether to play a, e, i, o, u
-# value: 0 or 1
-def generateSoundAnimation(sound_chord: typing.Tuple[int,int,int,int,int],
- value: int,
- anim_name: str,
- anim_dir: str, guid_map: typing.Dict[str, str],
- anim_delay_frames = 2):
- print(f"Generating sound animation {sound_chord} / {anim_name}", file=sys.stderr)
-
- parser = libunity.UnityParser()
- parser.parse(SOUND_ANIMATION_TEMPLATE)
-
- anim_node = parser.nodes[0]
- anim_clip = anim_node.mapping['AnimationClip']
- curve_template = anim_clip.mapping['m_FloatCurves'].sequence[0]
- anim_clip.mapping['m_FloatCurves'].sequence = []
- anim_clip.mapping['m_EditorCurves'].sequence = []
-
- # Animate all notes.
- for note_i in range(len(sound_chord)):
- curve = curve_template.copy()
-
- keyframe_template = curve.mapping['curve'].mapping['m_Curve'].sequence[0]
- curve.mapping['curve'].mapping['m_Curve'].sequence = []
-
- # First keyframe: zero all but first note
- if note_i != 0:
- keyframe = keyframe_template.copy()
- keyframe.mapping['time'] = 0
- keyframe.mapping['value'] = 0
- curve.mapping['path'] = f"World Constraint/Container/TaSTT/Audio {note_i + 1}"
- curve.mapping['curve'].mapping['m_Curve'].sequence.append(keyframe)
-
- # Subsequent keyframes: animate as normal
- keyframe = keyframe_template.copy()
- keyframe.mapping['time']= str(note_i * anim_delay_frames * 1.0 / 60.0)
- keyframe.mapping['value'] = str(sound_chord[note_i])
- curve.mapping['path'] = f"World Constraint/Container/TaSTT/Audio {note_i + 1}"
- curve.mapping['curve'].mapping['m_Curve'].sequence.append(keyframe)
-
- # Add curve to animation
- anim_clip.mapping['m_FloatCurves'].sequence.append(curve)
- anim_clip.mapping['m_EditorCurves'].sequence.append(curve)
-
- anim_clip.mapping['m_AnimationClipSettings'].mapping['m_StopTime'] = str((len(sound_chord)-1) * anim_delay_frames * 1.0 / 60.0)
-
- # Serialize animation to file
- anim_path = os.path.join(anim_dir, anim_name + ".anim")
- with open(anim_path, "w", encoding="utf-8") as f:
- f.write(libunity.unityYamlToString([anim_node]))
- # Generate metadata
- meta = libunity.Metadata()
- with open(anim_path + ".meta", "w", encoding="utf-8") as f:
- f.write(str(meta))
- # Add metadata to guid map
- guid_map[anim_path] = meta.guid
- guid_map[meta.guid] = anim_path
-
-# Generate a toggle animation for a shader parameter.
-def generateToggleAnimations(anim_dir, shader_param, guid_map):
- print("Generating shader toggle animation", file=sys.stderr)
-
- parser = libunity.UnityParser()
- parser.parse(LETTER_ANIMATION_TEMPLATE)
-
- # 0.0 represents false, 1.0 represents true. Don't forget that we add
- # `UNITY_ANIMATION_FUDGE_MARGIN` to everything.
- for shader_value in range(0, 2):
- anim_node = parser.nodes[0]
- anim_clip = anim_node.mapping['AnimationClip']
- curve_template = anim_clip.mapping['m_FloatCurves'].sequence[0]
- anim_clip.mapping['m_FloatCurves'].sequence = []
- anim_clip.mapping['m_EditorCurves'].sequence = []
-
- curve = curve_template.copy()
- for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence:
- keyframe.mapping['value'] = str(float(shader_value) +
- UNITY_ANIMATION_FUDGE_MARGIN)
- curve.mapping['attribute'] = "material.{}".format(shader_param)
- curve.mapping['path'] = "World Constraint/Container/TaSTT"
- # Add curve to animation
- anim_clip.mapping['m_FloatCurves'].sequence.append(curve)
- anim_clip.mapping['m_EditorCurves'].sequence.append(curve)
-
- # Serialize animation to file
- anim_name = generate_utils.getClearAnimationName()
- anim_suffix = "_Off"
- if shader_value == 1:
- anim_suffix = "_On"
- anim_path = os.path.join(anim_dir, shader_param + anim_suffix +
- ".anim")
- with open(anim_path, "w", encoding="utf-8") as f:
- f.write(libunity.unityYamlToString([anim_node]))
- # Generate metadata
- meta = libunity.Metadata()
- with open(anim_path + ".meta", "w", encoding="utf-8") as f:
- f.write(str(meta))
- # Add metadata to guid map
- guid_map[anim_path] = meta.guid
- guid_map[meta.guid] = anim_path
-
-# Generate a toggle animation for a shader parameter.
-def generateScaleAnimation(anim_name: str, anim_dir: str,
- path: str,
- value: float,
- guid_map: typing.Dict[str, str]) -> str:
- print("Generating scale animation {}".format(path),
- file=sys.stderr)
-
- parser = libunity.UnityParser()
- parser.parse(SCALE_ANIMATION_TEMPLATE)
-
- #print("kill me", file=sys.stderr)
- #print(libunity.unityYamlToString([parser.nodes[0]]), file=sys.stdout)
- #print("NOW", file=sys.stdout)
-
- # 0.0 represents false, 1.0 represents true. Don't forget that we add
- # `UNITY_ANIMATION_FUDGE_MARGIN` to everything.
- anim_node = parser.nodes[0]
- anim_clip = anim_node.mapping['AnimationClip']
- #print("here 3", file=sys.stderr)
- for curve in anim_clip.mapping['m_ScaleCurves'].sequence:
- for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence:
- keyframe.mapping['value'].mapping['x'] = str(value)
- keyframe.mapping['value'].mapping['y'] = str(value)
- keyframe.mapping['value'].mapping['z'] = str(value)
- #print("here 4", file=sys.stderr)
- for curve in anim_clip.mapping['m_EditorCurves'].sequence:
- for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence:
- keyframe.mapping['value'] = value
-
- #print("here 5", file=sys.stderr)
-
- # Serialize animation to file
- anim_path = os.path.join(anim_dir, anim_name + ".anim")
- with open(anim_path, "w", encoding="utf-8") as f:
- f.write(libunity.unityYamlToString([anim_node]))
- # Generate metadata
- meta = libunity.Metadata()
- with open(anim_path + ".meta", "w", encoding="utf-8") as f:
- f.write(str(meta))
- # Add metadata to guid map
- guid_map[anim_path] = meta.guid
- guid_map[meta.guid] = anim_path
-
- return meta.guid
-
-def generateAnimations(anim_dir: str, guid_map: typing.Dict[str, str]):
- generateClearAnimation(anim_dir, guid_map)
-
- for chord_bits in range(2**5):
- chord = [0, 0, 0, 0, 0]
- for i in range(5):
- if (chord_bits >> i) % 2 == 1:
- chord[i] = 1
- print(f"Generating chord {chord}", file=sys.stderr)
- anim_name = f"Sound_a{chord[0]}_e{chord[1]}_i{chord[2]}_o{chord[3]}_u{chord[4]}"
- generateSoundAnimation(chord, 0, anim_name, anim_dir, guid_map)
-
- print("Generating letter animations", file=sys.stderr)
-
- parser = libunity.UnityParser()
- parser.parse(LETTER_ANIMATION_TEMPLATE)
-
- anim_node = parser.nodes[0]
- anim_clip = anim_node.mapping['AnimationClip']
- curve_template = anim_clip.mapping['m_FloatCurves'].sequence[0]
- anim_clip.mapping['m_FloatCurves'].sequence = []
- anim_clip.mapping['m_EditorCurves'].sequence = []
-
- # To support more languages, we use 2 bytes per character, giving us a 64K character set.
- for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
- for row in range(0, generate_utils.config.BOARD_ROWS):
- print("Generating letter animations (row {}/{}) (byte {}/2)".format(row,
- generate_utils.config.BOARD_ROWS, byte), file=sys.stderr)
- for col in range(0, generate_utils.config.BOARD_COLS):
- for letter in range(0, 2):
- if letter == 1:
- letter = generate_utils.config.CHARS_PER_CELL - 1
-
- # Make a deep copy of the templates
- node = anim_node.copy()
- curve = curve_template.copy()
- clip = node.mapping['AnimationClip']
- # Populate animation name
- anim_name = generate_utils.getLetterAnimationName(row, col, letter, byte)
- clip.mapping['m_Name'] = anim_name
- # Populate letter value
- for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence:
- keyframe.mapping['value'] = str(letter + UNITY_ANIMATION_FUDGE_MARGIN)
- # Populate path to letter parameter
- curve.mapping['attribute'] = "material.{}".format(generate_utils.getShaderParamByRowColByte(row, col, byte))
- curve.mapping['path'] = "World Constraint/Container/TaSTT"
- # Add curve to animation
- clip.mapping['m_FloatCurves'].sequence.append(curve)
- clip.mapping['m_EditorCurves'].sequence.append(curve)
- # Serialize animation to file
- anim_path = os.path.join(anim_dir, anim_name + ".anim")
- with open(anim_path, "w", encoding="utf-8") as f:
- f.write(libunity.unityYamlToString([node]))
- # Generate metadata
- meta = libunity.Metadata()
- with open(anim_path + ".meta", "w", encoding="utf-8") as f:
- f.write(str(meta))
- # Add metadata to guid map
- guid_map[anim_path] = meta.guid
- guid_map[meta.guid] = anim_path
-
-def generateFXController(anim: libunity.UnityAnimator) -> typing.Dict[int, libunity.UnityDocument]:
- parser = libunity.UnityParser()
- parser.parse(ANIMATOR_TEMPLATE)
- anim.addNodes(parser.nodes)
-
- anim.addParameter(generate_utils.getEnableParam(), bool)
- anim.addParameter(generate_utils.getDummyParam(), bool)
- anim.addParameter(generate_utils.getToggleParam(), bool)
- anim.addParameter(generate_utils.getClearBoardParam(), bool)
- anim.addParameter(generate_utils.getScaleParam(), float)
- anim.addParameter(generate_utils.getEnablePhonemeParam(), bool)
-
- for i in range(5):
- anim.addParameter(generate_utils.getSoundParam(i+1), bool)
-
- anim.addLayer("=== TaSTT ===", weight=0.0)
-
- layers = {}
- for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
- layers[byte] = {}
- for i in range(0, generate_utils.config.CHARS_PER_SYNC):
- anim.addParameter(generate_utils.getBlendParam(i, byte), float)
-
- layer = anim.addLayer(generate_utils.getLayerName(i, byte))
- layers[byte][i] = layer
- anim.addParameter(generate_utils.getSelectParam(), int)
-
- return layers
-
-def generateFXLayer(which_layer: int, anim: libunity.UnityAnimator, layer:
- libunity.UnityDocument, gen_anim_dir: str, byte: int):
- is_default_state = True
- default_state = anim.addAnimatorState(layer,
- generate_utils.getDefaultStateName(which_layer, byte), is_default_state)
-
- dy = 100
- active_state = anim.addAnimatorState(layer,
- generate_utils.getActiveStateName(which_layer, byte), dy = dy)
-
- active_state_transition = anim.addTransition(active_state)
- enable_param = generate_utils.getEnableParam()
- anim.addTransitionBooleanCondition(default_state, active_state_transition,
- enable_param, True)
-
- select_states = {}
- for i in range(0, generate_utils.config.numRegions(which_layer)):
- dx = i * 200
- dy = 200
-
- # Create blend tree for this region.
- anim_lo_path = os.path.join(gen_anim_dir,
- generate_utils.getAnimationNameByLayerAndIndex(
- which_layer, i, 0, byte) + \
- ".anim")
- guid_lo = guid_map[anim_lo_path]
- anim_hi_path = os.path.join(gen_anim_dir,
- generate_utils.getAnimationNameByLayerAndIndex(
- which_layer, i, generate_utils.config.CHARS_PER_CELL - 1, byte) + \
- ".anim")
- guid_hi = guid_map[anim_hi_path]
-
- select_states[i] = anim.addAnimatorBlendTree(layer,
- generate_utils.getBlendStateName(which_layer, i, byte),
- generate_utils.getBlendParam(which_layer, byte),
- guid_lo, guid_hi, dx = dx, dy = dy)
- state = select_states[i]
-
- # Create transition to state.
- select_state_transition = anim.addTransition(state)
- select_param = generate_utils.getSelectParam()
- anim.addTransitionIntegerEqualityCondition(active_state,
- select_state_transition, select_param, i)
-
- # Create return-home transition.
- home_state_transition = anim.addTransition(default_state)
- home_state_transition.mapping['AnimatorStateTransition'].mapping['m_InterruptionSource'] = '0'
- dummy_param = generate_utils.getDummyParam()
- anim.addTransitionBooleanCondition(state,
- home_state_transition, dummy_param, False)
-
- if generate_utils.config.layerNeedsParity(which_layer):
- # There may be layers which never write to the text box. In this case,
- # when those layers are turned on to write to that last region, they
- # simply transition back to the default (idle) state.
- home_state_transition = anim.addTransition(default_state)
- select_param = generate_utils.getSelectParam()
- i = generate_utils.config.numRegions(0) - 1
- anim.addTransitionIntegerEqualityCondition(active_state,
- home_state_transition, select_param, i)
-
-# Generic toggle adding utility.
-# Generates the layer and parameter.
-# Returns a map containing the off and on states, as well as the
-# transitions between them.
-def generateToggle(layer_name: str,
- parameter_name: str,
- gen_anim_dir: str,
- off_anim_basename: str,
- on_anim_basename: str,
- anim: libunity.UnityAnimator,
- guid_map: typing.Dict[str, str],
- duration_s: float = 0.0) -> typing.Dict[str,
- libunity.UnityDocument]:
- layer = anim.addLayer(layer_name)
-
- # For simplicity, use the layer name as the parameter name.
- anim.addParameter(parameter_name, bool)
-
- off_state = anim.addAnimatorState(layer, layer_name + "_Off",
- is_default_state = True)
- on_state = anim.addAnimatorState(layer, layer_name + "_On", dy=100)
-
- if off_anim_basename:
- off_anim_path = os.path.join(gen_anim_dir, off_anim_basename)
- off_anim_meta = libunity.Metadata()
- off_anim_meta.loadOrCreate(off_anim_path, guid_map)
- anim.setAnimatorStateAnimation(off_state, off_anim_meta.guid)
-
- if on_anim_basename:
- on_anim_path = os.path.join(gen_anim_dir, on_anim_basename)
- on_anim_meta = libunity.Metadata()
- on_anim_meta.loadOrCreate(on_anim_path, guid_map)
- anim.setAnimatorStateAnimation(on_state, on_anim_meta.guid)
-
- off_to_on_trans = anim.addTransition(on_state, duration_s)
- anim.addTransitionBooleanCondition(off_state,
- off_to_on_trans, parameter_name, True)
-
- on_to_off_trans = anim.addTransition(off_state, duration_s)
- anim.addTransitionBooleanCondition(on_state,
- on_to_off_trans, parameter_name, False)
-
- result = {}
- result["off"] = off_state
- result["on"] = on_state
- result["off_to_on"] = off_to_on_trans
- result["on_to_off"] = on_to_off_trans
-
- return result
-
-def generateScaleLayer(anim: libunity.UnityAnimator,
- gen_anim_dir: str,
- guid_map: typing.Dict[str, str]):
-
- scale_layer = anim.addLayer(generate_utils.getScaleParam())
-
- path = "World Constraint/Container/TaSTT"
- attribute = "blendShape.Scale"
-
- guid_lo = generateScaleAnimation("TaSTT_Scale_0", gen_anim_dir,
- path,
- 5.0, guid_map)
- guid_hi = generateScaleAnimation("TaSTT_Scale_100", gen_anim_dir,
- path,
- 100.0, guid_map)
-
- anim.addAnimatorBlendTree(scale_layer,
- generate_utils.getScaleParam(),
- generate_utils.getScaleParam(),
- guid_lo, guid_hi,
- lo_threshold = 0.0, hi_threshold = 1.0);
-
- pass
-
-def generateSoundLayer(anim: libunity.UnityAnimator,
- gen_anim_dir: str,
- guid_map: typing.Dict[str, str],
- anim_len_s = 12.0/60.0):
-
- layer = anim.addLayer("TaSTT_Sound")
-
- idle_state = anim.addAnimatorState(layer, "Idle", is_default_state=True, dy=-100)
- a_state = anim.addAnimatorState(layer, "a")
-
- trans = anim.addTransition(a_state)
- param = generate_utils.getEnablePhonemeParam()
- anim.addTransitionBooleanCondition(idle_state, trans, param, True)
-
- for a_bool in range(2):
- dy = 100
- dx = a_bool * 800
- # Create `e` state.
- ax_e_state = anim.addAnimatorState(layer,
- f"a{a_bool}_e",
- dy=dy, dx=dx)
- # Create transition based on whether `a` is set.
- trans = anim.addTransition(ax_e_state)
- param = generate_utils.getSoundParam(1)
- anim.addTransitionBooleanCondition(a_state, trans, param, a_bool)
-
- for e_bool in range(2):
- dy = 200
- dx = a_bool * 800 + e_bool * 400
-
- # Create `i` state.
- ax_ex_i_state = anim.addAnimatorState(layer,
- f"a{a_bool}_e{e_bool}_i",
- dy=dy, dx=dx)
-
- # Create transition based on whether `e` is set.
- trans = anim.addTransition(ax_ex_i_state)
- param = generate_utils.getSoundParam(2)
- anim.addTransitionBooleanCondition(ax_e_state, trans, param, e_bool)
-
- for i_bool in range(2):
- dy = 300
- dx = a_bool * 800 + e_bool * 400 + i_bool * 200
-
- # Create `o` state.
- ax_ex_ix_o_state = anim.addAnimatorState(layer,
- f"a{a_bool}_e{e_bool}_i{i_bool}_o",
- dy=dy, dx=dx)
- # Create transition based on whether `i` is set.
- trans = anim.addTransition(ax_ex_ix_o_state)
- param = generate_utils.getSoundParam(3)
- anim.addTransitionBooleanCondition(ax_ex_i_state, trans, param, i_bool)
-
- for o_bool in range(2):
- dy = 400
- dx = a_bool * 800 + e_bool * 400 + i_bool * 200 + o_bool * 100
-
- # Create `u` state.
- ax_ex_ix_ox_u_state = anim.addAnimatorState(layer,
- f"a{a_bool}_e{e_bool}_i{i_bool}_o{o_bool}_u",
- dy=dy, dx=dx)
- # Create transition based on whether `o` is set.
- trans = anim.addTransition(ax_ex_ix_ox_u_state)
- param = generate_utils.getSoundParam(4)
- anim.addTransitionBooleanCondition(ax_ex_ix_o_state,
- trans, param, o_bool)
-
- for u_bool in range(2):
- dy = 500
- dx = a_bool * 800 + e_bool * 400 + i_bool * 200 + o_bool * 100 + u_bool * 50
- if u_bool == 1:
- dy = 550
-
- # Create `u` state.
- ax_ex_ix_ox_ux_state = anim.addAnimatorState(layer,
- f"a{a_bool}_e{e_bool}_i{i_bool}_o{o_bool}_u{u_bool}",
- dy=dy, dx=dx)
- # Create transition based on whether `u` is set.
- trans = anim.addTransition(ax_ex_ix_ox_ux_state)
- param = generate_utils.getSoundParam(5)
- anim.addTransitionBooleanCondition(ax_ex_ix_ox_u_state,
- trans, param, u_bool)
-
- chord = [a_bool, e_bool, i_bool, o_bool, u_bool]
- anim_name = f"Sound_a{chord[0]}_e{chord[1]}_i{chord[2]}_o{chord[3]}_u{chord[4]}"
- anim_path = os.path.join(gen_anim_dir, anim_name + ".anim")
- anim_guid = guid_map[anim_path]
- anim.setAnimatorStateAnimation(ax_ex_ix_ox_ux_state, anim_guid)
-
- # Create return-home transitions.
- trans = anim.addTransition(idle_state, dur_s = anim_len_s)
- trans.mapping['AnimatorStateTransition'].mapping['m_InterruptionSource'] = '0'
- param = generate_utils.getSoundParam(1)
- anim.addTransitionBooleanCondition(ax_ex_ix_ox_ux_state, trans, param, 1 - a_bool)
-
- trans = anim.addTransition(idle_state, dur_s = anim_len_s)
- trans.mapping['AnimatorStateTransition'].mapping['m_InterruptionSource'] = '0'
- param = generate_utils.getSoundParam(2)
- anim.addTransitionBooleanCondition(ax_ex_ix_ox_ux_state, trans, param, 1 - e_bool)
-
- trans = anim.addTransition(idle_state, dur_s = anim_len_s)
- trans.mapping['AnimatorStateTransition'].mapping['m_InterruptionSource'] = '0'
- param = generate_utils.getSoundParam(3)
- anim.addTransitionBooleanCondition(ax_ex_ix_ox_ux_state, trans, param, 1 - i_bool)
-
- trans = anim.addTransition(idle_state, dur_s = anim_len_s)
- trans.mapping['AnimatorStateTransition'].mapping['m_InterruptionSource'] = '0'
- param = generate_utils.getSoundParam(4)
- anim.addTransitionBooleanCondition(ax_ex_ix_ox_ux_state, trans, param, 1 - o_bool)
-
- trans = anim.addTransition(idle_state, dur_s = anim_len_s)
- trans.mapping['AnimatorStateTransition'].mapping['m_InterruptionSource'] = '0'
- param = generate_utils.getSoundParam(5)
- anim.addTransitionBooleanCondition(ax_ex_ix_ox_ux_state, trans, param, 1 - u_bool)
-
-def generateFX(guid_map, gen_anim_dir):
- anim = libunity.UnityAnimator()
-
- layers = generateFXController(anim)
-
- # TODO(yum) parallelize
- for byte in range(0, generate_utils.config.BYTES_PER_CHAR):
- for which_layer, layer in layers[byte].items():
- print("Generating layer {}/{}".format(which_layer, len(layers[byte].items())), file=sys.stderr)
- generateFXLayer(which_layer, anim, layer, gen_anim_dir, byte)
-
- generateToggle(generate_utils.getToggleParam(),
- generate_utils.getToggleParam(),
- gen_anim_dir,
- "TaSTT_Toggle_Off.anim",
- "TaSTT_Toggle_On.anim",
- anim, guid_map)
- generateToggle(generate_utils.getLockWorldParam(),
- generate_utils.getLockWorldParam(),
- gen_anim_dir,
- "TaSTT_Lock_World_Disable.anim",
- "TaSTT_Lock_World_Enable.anim",
- anim, guid_map)
- generateToggle(generate_utils.getEllipsisParam(),
- generate_utils.getEllipsisParam(),
- gen_anim_dir,
- "TaSTT_Ellipsis_Off.anim",
- "TaSTT_Ellipsis_On.anim",
- anim, guid_map)
- generateToggle(
- generate_utils.getClearBoardParam(),
- generate_utils.getClearBoardParam(),
- gen_anim_dir,
- None, # No animation in the `off` state.
- generate_utils.getClearAnimationName() + ".anim",
- anim, guid_map)
- generateToggle("TaSTT_Expand",
- generate_utils.getToggleParam(),
- gen_anim_dir,
- "TaSTT_Emerge_000.anim",
- "TaSTT_Emerge_100.anim",
- anim, guid_map, 0.5)
-
- generateScaleLayer(anim, gen_anim_dir, guid_map)
- generateSoundLayer(anim, gen_anim_dir, guid_map)
-
- return anim
-
-def parseArgs():
- print("args: {}".format(" ".join(sys.argv)))
-
- parser = argparse.ArgumentParser()
- parser.add_argument("cmd", type=str, help="")
- parser.add_argument("--config", type=str, help="The app config.")
- parser.add_argument("--gen_dir", type=str, help="The directory under " +
- "which all generated assets are placed")
- parser.add_argument("--gen_anim_dir", type=str, help="The directory under " +
- "which all generated animations are placed.")
- parser.add_argument("--guid_map", type=str, help="The path to a file which will store guids")
- parser.add_argument("--fx_dest", type=str, help="The path at which to save the generated FX controller")
- args = parser.parse_args()
-
- if not args.gen_dir:
- args.gen_dir = "generated/"
-
- if not args.config:
- print("--config required")
- sys.exit(1)
-
- if not args.gen_anim_dir:
- args.gen_anim_dir = args.gen_dir + "animations/"
-
- if not args.guid_map:
- args.guid_map = "guid.map"
-
- if not args.fx_dest:
- args.fx_dest = args.gen_dir + "TaSTT_fx.controller"
-
- return args
-
-if __name__ == "__main__":
- args = parseArgs()
- cfg = app_config.getConfig(args.config)
-
- print(f"chdir to {os.path.dirname(os.path.abspath(__file__))}")
- os.chdir(os.path.dirname(os.path.abspath(__file__)))
-
- if args.cmd == "gen_anims":
- generate_utils.config.BYTES_PER_CHAR = int(cfg["bytes_per_char"])
- generate_utils.config.CHARS_PER_SYNC = int(cfg["chars_per_sync"])
- generate_utils.config.BOARD_ROWS = int(cfg["rows"])
- generate_utils.config.BOARD_COLS = int(cfg["cols"])
-
- guid_map = {}
- with open(args.guid_map, 'rb') as f:
- guid_map = pickle.load(f)
-
- os.makedirs(args.gen_anim_dir, exist_ok=True)
- generateAnimations(args.gen_anim_dir, guid_map)
-
- with open(args.guid_map, 'wb') as f:
- pickle.dump(guid_map, f)
- elif args.cmd == "gen_fx":
- generate_utils.config.BYTES_PER_CHAR = int(cfg["bytes_per_char"])
- generate_utils.config.CHARS_PER_SYNC = int(cfg["chars_per_sync"])
- generate_utils.config.BOARD_ROWS = int(cfg["rows"])
- generate_utils.config.BOARD_COLS = int(cfg["cols"])
-
- guid_map = {}
- with open(args.guid_map, 'rb') as f:
- guid_map = pickle.load(f)
- os.makedirs(os.path.dirname(args.fx_dest), exist_ok=True)
- with open(args.fx_dest, "w", encoding="utf-8") as f:
- f.write(str(generateFX(guid_map, args.gen_anim_dir)))
- with open(args.guid_map, 'wb') as f:
- pickle.dump(guid_map, f)
-
- # If we don't do this, then VRChat will fail to update the animator
- # when users update their avatars.
- if os.path.exists(args.fx_dest + ".meta"):
- os.remove(args.fx_dest + ".meta")
-