diff options
| author | yum <yum.food.vr@gmail.com> | 2023-08-29 23:27:54 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2023-08-29 23:29:04 -0700 |
| commit | 444914a701628ca2d1937f8d5cc9a714b478917c (patch) | |
| tree | d55580cbaebf6bdd8de1a98ebe50a80de70fb1cd /Scripts | |
| parent | 2daa2c8057cf036357a64e09925487e6f5c0025e (diff) | |
Fix in-game audio indicator
Also fix prefab default size (no longer colossal).
TODO
* Add runtime & unity-time toggles
Diffstat (limited to 'Scripts')
| -rw-r--r-- | Scripts/generate_params.py | 4 | ||||
| -rw-r--r-- | Scripts/generate_utils.py | 3 | ||||
| -rw-r--r-- | Scripts/libtastt.py | 137 | ||||
| -rw-r--r-- | Scripts/libunity.py | 4 | ||||
| -rw-r--r-- | Scripts/osc_ctrl.py | 28 |
5 files changed, 174 insertions, 2 deletions
diff --git a/Scripts/generate_params.py b/Scripts/generate_params.py index 8daf2dc..1f635e6 100644 --- a/Scripts/generate_params.py +++ b/Scripts/generate_params.py @@ -61,6 +61,10 @@ def generate(): params["PARAM_NAME"] = generate_utils.getEllipsisParam() result += generate_utils.replaceMacros(BOOL_PARAM, params) + for i in range(5): + params["PARAM_NAME"] = generate_utils.getSoundParam(i+1) + result += generate_utils.replaceMacros(BOOL_PARAM, params) + params["PARAM_NAME"] = generate_utils.getScaleParam() params["DEFAULT_FLOAT"] = "0.05" result += generate_utils.replaceMacros(FLOAT_PARAM, params) diff --git a/Scripts/generate_utils.py b/Scripts/generate_utils.py index aaae3dc..395eaf7 100644 --- a/Scripts/generate_utils.py +++ b/Scripts/generate_utils.py @@ -81,6 +81,9 @@ def getSelectParam() -> str: def getEnableParam(): return "TaSTT_Enable" +def getSoundParam(i: int): + return f"TaSTT_Sound{str(i)}" + def getEllipsisParam(): return "TaSTT_Ellipsis" diff --git a/Scripts/libtastt.py b/Scripts/libtastt.py index f941cee..12f9056 100644 --- a/Scripts/libtastt.py +++ b/Scripts/libtastt.py @@ -155,6 +155,88 @@ AnimationClip: 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: 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: [] + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: [] +""" + LETTER_ANIMATION_TEMPLATE = """ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: @@ -390,6 +472,40 @@ def generateClearAnimation(anim_dir, guid_map): guid_map[anim_path] = meta.guid guid_map[meta.guid] = anim_path +# value: 0 or 1 +def generateSoundAnimation(nth_sound: int, value: int, anim_name: str, anim_dir: str, guid_map: typing.Dict[str, str]): + print(f"Generating sound {nth_sound} animation", 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 = [] + + curve = curve_template.copy() + for keyframe in curve.mapping['curve'].mapping['m_Curve'].sequence: + keyframe.mapping['value'] = str(value) + curve.mapping['path'] = f"World Constraint/Container/TaSTT/Audio {nth_sound}" + # 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_path = os.path.join(anim_dir, anim_name + ".anim") + print("Generating sound 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 + # Generate a toggle animation for a shader parameter. def generateToggleAnimations(anim_dir, shader_param, guid_map): print("Generating shader toggle animation", file=sys.stderr) @@ -482,6 +598,12 @@ def generateScaleAnimation(anim_name: str, anim_dir: str, def generateAnimations(anim_dir, guid_map): generateClearAnimation(anim_dir, guid_map) + for i in range(5): + anim_name = generate_utils.getSoundParam(i+1) + "_Off" + generateSoundAnimation(i+1, 0, anim_name, anim_dir, guid_map) + anim_name = generate_utils.getSoundParam(i+1) + "_On" + generateSoundAnimation(i+1, 1, anim_name, anim_dir, guid_map) + print("Generating letter animations", file=sys.stderr) parser = libunity.UnityParser() @@ -544,6 +666,11 @@ def generateFXController(anim: libunity.UnityAnimator) -> typing.Dict[int, libun anim.addParameter(generate_utils.getClearBoardParam(), bool) anim.addParameter(generate_utils.getScaleParam(), float) + 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] = {} @@ -724,6 +851,16 @@ def generateFX(guid_map, gen_anim_dir): "TaSTT_Emerge_000.anim", "TaSTT_Emerge_100.anim", anim, guid_map, 0.5) + + for i in range(5): + param_name = generate_utils.getSoundParam(i+1) + generateToggle(f"TaSTT_Audio{i+1}", + param_name, + gen_anim_dir, + param_name + "_Off.anim", + param_name + "_On.anim", + anim, guid_map) + generateScaleLayer(anim, gen_anim_dir, guid_map) return anim diff --git a/Scripts/libunity.py b/Scripts/libunity.py index 9168057..cd8174d 100644 --- a/Scripts/libunity.py +++ b/Scripts/libunity.py @@ -598,7 +598,7 @@ class UnityAnimator(): ctrl = param.addChildMapping('m_Controller') ctrl.mapping['fileID'] = anim.anchor - def addLayer(self, layer_name, add_to_head = False) -> UnityDocument: + def addLayer(self, layer_name, add_to_head = False, weight: float = 1.0) -> UnityDocument: # Add layer to controller anim = self.peekNodeOfClass('91') layers = anim.mapping['AnimatorController'].mapping['m_AnimatorLayers'] @@ -612,7 +612,7 @@ class UnityAnimator(): layer.addChildSequence('m_Behaviours') layer.mapping['m_BlendingMode'] = '0' layer.mapping['m_SyncedLayerIndex'] = '-1' - layer.mapping['m_DefaultWeight'] = '1' + layer.mapping['m_DefaultWeight'] = str(weight) layer.mapping['m_IKPass'] = '0' layer.mapping['m_SyncedLayerAffectsTiming'] = '0' layer.addChildMapping('m_Controller').mapping['fileID'] = anim.anchor diff --git a/Scripts/osc_ctrl.py b/Scripts/osc_ctrl.py index b1ec765..ad5667f 100644 --- a/Scripts/osc_ctrl.py +++ b/Scripts/osc_ctrl.py @@ -8,6 +8,7 @@ from pythonosc import udp_client import argparse import generate_utils +import random import time # Based on a couple experiments, this seems like about as fast as we can go @@ -76,6 +77,11 @@ def clear(osc_state: OscState): osc_state.reset() +# Note: `nth_audio` is 1-indexed +def playAudio(osc_state: OscState, nth_audio: int, value: bool): + addr="/avatar/parameters/" + generate_utils.getSoundParam(nth_audio) + osc_state.client.send_message(addr, value) + def updateRegion(client, region_idx, letter_encoded): for byte in range(0, generate_utils.config.BYTES_PER_CHAR): addr="/avatar/parameters/" + generate_utils.getBlendParam(region_idx, byte) @@ -90,7 +96,29 @@ def pageMessage(osc_state: OscState, msg: str, estate: EmotesState) -> bool: msg_slice, slice_idx = osc_state.pager.getNextSlice(msg) if slice_idx == -1: + for i in range(5): + playAudio(osc_state, i+1, False) return True + + sounds_to_make = set() + letter_i = 1 + for letter in ["a", "e", "i", "o", "u"]: + if letter in msg_slice: + sounds_to_make.add(letter_i) + letter_i += 1 + if len(sounds_to_make) == 0: + for i in range(5): + playAudio(osc_state, i+1, False) + else: + sound_to_make = random.sample(sounds_to_make, 1)[0] + for i in range(5): + if i+1 == sound_to_make: + # TODO(yum) think about making this probabilistic + print(f"Playing sound {i+1}") + playAudio(osc_state, i+1, True) + else: + playAudio(osc_state, i+1, False) + #print("sending page {}: {} ({})".format(slice_idx, msg_slice, # len(msg_slice))) |
