diff options
| author | yum <yum.food.vr@gmail.com> | 2022-12-20 14:20:17 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2022-12-20 14:20:17 -0800 |
| commit | a048e2c1b1940805c0dcb29bc162f804ca463214 (patch) | |
| tree | 3c8d35007fcc4e3470650b80db72a3ce3c04fa28 | |
| parent | 8d225cfd66dfb60998b4eab43d8aa3b287375695 (diff) | |
GUI can now generate animator
Still need to generate params & merge menus. Getting close....
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.cpp | 147 | ||||
| -rw-r--r-- | GUI/package.ps1 | 1 | ||||
| -rw-r--r-- | Scripts/generate_params.py | 1 | ||||
| -rw-r--r-- | Scripts/libtastt.py | 38 | ||||
| -rw-r--r-- | Scripts/libunity.py | 70 |
5 files changed, 226 insertions, 31 deletions
diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp index 62a002a..a2e1313 100644 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -158,8 +158,43 @@ bool PythonWrapper::GenerateAnimator( tastt_generated_dir_path / unity_parameters_generated_name; std::filesystem::path tastt_menu_path = tastt_generated_dir_path / unity_menu_generated_name; + // This is the initial, pre-merge FX controller. + std::filesystem::path tastt_fx0_path = + tastt_generated_dir_path / "FX0.controller"; + std::filesystem::path tastt_fx1_path = + tastt_generated_dir_path / "FX1.controller"; + std::filesystem::path tastt_fx2_path = + tastt_generated_dir_path / "FX2.controller"; + std::filesystem::path tastt_fx3_path = + tastt_generated_dir_path / "FX3.controller"; { + if (std::filesystem::exists(tastt_generated_dir_path)) { + std::ostringstream oss; + oss << "Erasing " << tastt_generated_dir_path << std::endl; + out->AppendText(oss.str()); + std::filesystem::remove_all(tastt_generated_dir_path); + } + std::ostringstream oss; + oss << "Creating " << tastt_generated_dir_path << std::endl; + out->AppendText(oss.str()); + std::filesystem::create_directories(tastt_generated_dir_path); + } + { + out->AppendText("Copying canned animations... "); + auto opts = std::filesystem::copy_options(); + opts |= std::filesystem::copy_options::overwrite_existing; + opts |= std::filesystem::copy_options::recursive; + std::error_code error; + std::filesystem::copy("Resources/Animations", tastt_animations_path, opts, error); + if (error.value()) { + wxLogError("Failed to copy animations: %s (%d)", error.message(), error.value()); + out->AppendText("failed!\n"); + return false; + } + out->AppendText("success!\n"); + } + { out->AppendText("Generating guid.map... "); std::string py_stdout, py_stderr; if (InvokeWithArgs({ libunity_path, "guid_map", @@ -168,11 +203,18 @@ bool PythonWrapper::GenerateAnimator( &py_stdout, &py_stderr)) { out->AppendText("success!\n"); out->AppendText(py_stdout.c_str()); + if (!py_stdout.empty()) { + out->AppendText("\n"); + } out->AppendText(py_stderr.c_str()); + if (!py_stderr.empty()) { + out->AppendText("\n"); + } } else { wxLogError("Failed to generate guid.map: %s", py_stderr.c_str()); out->AppendText("failed!\n"); + return false; } } { @@ -184,11 +226,116 @@ bool PythonWrapper::GenerateAnimator( &py_stdout, &py_stderr)) { out->AppendText("success!\n"); out->AppendText(py_stdout.c_str()); + if (!py_stdout.empty()) { + out->AppendText("\n"); + } out->AppendText(py_stderr.c_str()); + if (!py_stderr.empty()) { + out->AppendText("\n"); + } } else { wxLogError("Failed to generate animations: %s", py_stderr.c_str()); out->AppendText("failed!\n"); + return false; + } + } + { + out->AppendText("Generating FX layer... "); + std::string py_stdout, py_stderr; + if (InvokeWithArgs({ libtastt_path, "gen_fx", + "--fx_dest", tastt_fx0_path.string(), + "--gen_anim_dir", tastt_animations_path.string(), + "--guid_map", guid_map_path.string() }, + &py_stdout, &py_stderr)) { + out->AppendText("success!\n"); + out->AppendText(py_stdout.c_str()); + if (!py_stdout.empty()) { + out->AppendText("\n"); + } + out->AppendText(py_stderr.c_str()); + if (!py_stderr.empty()) { + out->AppendText("\n"); + } + } + else { + wxLogError("Failed to generate FX layer: %s", py_stderr.c_str()); + out->AppendText("failed!\n"); + return false; + } + } + { + out->AppendText("Adding enable/disable toggle... "); + std::string py_stdout, py_stderr; + if (InvokeWithArgs({ libunity_path, "add_toggle", + "--fx0", tastt_fx0_path.string(), + "--fx_dest", tastt_fx1_path.string(), + "--gen_anim_dir", tastt_animations_path.string(), + "--guid_map", guid_map_path.string() }, + &py_stdout, &py_stderr)) { + out->AppendText("success!\n"); + out->AppendText(py_stdout.c_str()); + if (!py_stdout.empty()) { + out->AppendText("\n"); + } + out->AppendText(py_stderr.c_str()); + if (!py_stderr.empty()) { + out->AppendText("\n"); + } + } + else { + wxLogError("Failed to add enable/disable toggle: %s", py_stderr.c_str()); + out->AppendText("failed!\n"); + return false; + } + } + { + out->AppendText("Merging with user animator... "); + std::string py_stdout, py_stderr; + if (InvokeWithArgs({ libunity_path, "merge", + "--fx0", unity_animator_path, + "--fx1", tastt_fx1_path.string(), + "--fx_dest", tastt_fx2_path.string() }, + &py_stdout, &py_stderr)) { + out->AppendText("success!\n"); + out->AppendText(py_stdout.c_str()); + if (!py_stdout.empty()) { + out->AppendText("\n"); + } + out->AppendText(py_stderr.c_str()); + if (!py_stderr.empty()) { + out->AppendText("\n"); + } + } + else { + wxLogError("Failed to merge animators: %s", py_stderr.c_str()); + out->AppendText("failed!\n"); + return false; + } + } + { + out->AppendText("Setting noop animations... "); + std::string py_stdout, py_stderr; + if (InvokeWithArgs({ libunity_path, "set_noop_anim", + "--fx0", tastt_fx2_path.string(), + "--fx_dest", tastt_fx3_path.string(), + "--gen_anim_dir", tastt_animations_path.string(), + "--guid_map", guid_map_path.string() }, + &py_stdout, &py_stderr)) { + out->AppendText("success!\n"); + out->AppendText(py_stdout.c_str()); + if (!py_stdout.empty()) { + out->AppendText("\n"); + } + out->AppendText(py_stderr.c_str()); + if (!py_stderr.empty()) { + out->AppendText("\n"); + } + } + else { + wxLogError("Failed to set noop animations: %s", py_stderr.c_str()); + out->AppendText("failed!\n"); + return false; } } diff --git a/GUI/package.ps1 b/GUI/package.ps1 index 703518a..fc51b41 100644 --- a/GUI/package.ps1 +++ b/GUI/package.ps1 @@ -6,6 +6,7 @@ if (Test-Path $install_dir) { mkdir $install_dir > $null
mkdir $install_dir/Resources > $null
+cp -Recurse ../Animations TaSTT/Resources/Animations
cp -Recurse ../Images TaSTT/Resources/Images
cp -Recurse ../Python TaSTT/Resources/Python
cp -Recurse ../Scripts TaSTT/Resources/Scripts
diff --git a/Scripts/generate_params.py b/Scripts/generate_params.py index 323502c..0444780 100644 --- a/Scripts/generate_params.py +++ b/Scripts/generate_params.py @@ -89,3 +89,4 @@ for byte in range(0, generate_utils.BYTES_PER_CHAR): for i in range(0, generate_utils.NUM_LAYERS): params["PARAM_NAME"] = generate_utils.getBlendParam(i, byte) print(generate_utils.replaceMacros(FLOAT_PARAM, params)) + diff --git a/Scripts/libtastt.py b/Scripts/libtastt.py index f448117..cc9c751 100644 --- a/Scripts/libtastt.py +++ b/Scripts/libtastt.py @@ -419,7 +419,8 @@ def generateToggle(layer_name: str, gen_anim_dir: str, off_anim_basename: str, on_anim_basename: str, - anim: libunity.UnityAnimator) -> typing.Dict[str, + anim: libunity.UnityAnimator, + guid_map: typing.Dict[str, str]) -> typing.Dict[str, libunity.UnityDocument]: layer = anim.addLayer(layer_name) @@ -434,13 +435,13 @@ def generateToggle(layer_name: str, if off_anim_basename: off_anim_path = os.path.join(gen_anim_dir, off_anim_basename) off_anim_meta = libunity.Metadata() - off_anim_meta.load(off_anim_path) + 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.load(on_anim_path) + 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) @@ -496,10 +497,10 @@ def generateFX(guid_map, gen_anim_dir): states = generateToggle( generate_utils.getSpeechNoiseToggleParam(), - "Animations/", + gen_anim_dir, "TaSTT_Speech_Noise_Off.anim", "TaSTT_Speech_Noise_On.anim", - anim) + anim, guid_map) # Enable beeping only if user has turned it on. anim.addTransitionBooleanCondition(states["off"], states["off_to_on"], generate_utils.getSpeechNoiseEnableParam(), True) @@ -508,31 +509,31 @@ def generateFX(guid_map, gen_anim_dir): states["off_to_on"], generate_utils.getToggleParam(), True) generateToggle(generate_utils.getToggleParam(), - "Animations/", + gen_anim_dir, "TaSTT_Toggle_Off.anim", "TaSTT_Toggle_On.anim", - anim) + anim, guid_map) generateToggle(generate_utils.getLockWorldParam(), - "Animations/", + gen_anim_dir, "TaSTT_Lock_World_Disable.anim", "TaSTT_Lock_World_Enable.anim", - anim) + anim, guid_map) generateToggle( generate_utils.getClearBoardParam(), gen_anim_dir, None, # No animation in the `off` state. generate_utils.getClearAnimationName() + ".anim", - anim) + anim, guid_map) generateToggle(generate_utils.getIndicator0Param(), gen_anim_dir, generate_utils.getIndicator0Param() + "_Off.anim", generate_utils.getIndicator0Param() + "_On.anim", - anim) + anim, guid_map) generateToggle(generate_utils.getIndicator1Param(), gen_anim_dir, generate_utils.getIndicator1Param() + "_Off.anim", generate_utils.getIndicator1Param() + "_On.anim", - anim) + anim, guid_map) generateScaleLayer(anim, gen_anim_dir, guid_map) return anim @@ -545,6 +546,7 @@ def parseArgs(): 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: @@ -556,9 +558,14 @@ def parseArgs(): 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__": + os.chdir(os.path.dirname(os.path.abspath(__file__))) + args = parseArgs() if args.cmd == "gen_anims": @@ -575,6 +582,9 @@ if __name__ == "__main__": guid_map = {} with open(args.guid_map, 'rb') as f: guid_map = pickle.load(f) - - print(str(generateFX(guid_map, args.gen_anim_dir))) + os.makedirs(os.path.dirname(args.fx_dest), exist_ok=True) + with open(args.fx_dest, "w") 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) diff --git a/Scripts/libunity.py b/Scripts/libunity.py index 7223568..0c5228a 100644 --- a/Scripts/libunity.py +++ b/Scripts/libunity.py @@ -228,6 +228,23 @@ class Metadata: if line.startswith("guid"): self.guid = line.split()[1] + def loadOrCreate(self, path, guid_map): + if not path.endswith(".meta"): + path = path + ".meta" + + if os.path.exists(path): + self.load(path) + return + + self.persist(path, guid_map) + + def persist(self, path, guid_map): + with open(path, "w") as f: + f.write(str(self)) + + guid_map[self.guid] = path + guid_map[path] = self.guid + def __str__(self): return METADATA_TEMPLATE.replace("REPLACEME_GUID", self.guid) @@ -911,14 +928,15 @@ class UnityAnimator(): from_state_trans.mapping['fileID'] = trans.anchor # TODO(yum) this should be factored out into generate_fx.py - def addTasttToggle(self, off_anim_path, on_anim_path, toggle_param): + def addTasttToggle(self, off_anim_path, on_anim_path, toggle_param, + guid_map): self.addParameter(toggle_param, bool) off_anim_meta = Metadata() - off_anim_meta.load(off_anim_path) + off_anim_meta.loadOrCreate(off_anim_path, guid_map) on_anim_meta = Metadata() - on_anim_meta.load(on_anim_path) + on_anim_meta.loadOrCreate(on_anim_path, guid_map) layer = self.addLayer('TaSTT_Toggle') off_anim = self.addAnimatorState(layer, 'TaSTT_Toggle_Off', is_default_state = True) @@ -936,7 +954,7 @@ class UnityAnimator(): def setNoopAnimations(self, guid_map, noop_anim_path): noop_anim_meta = Metadata() - noop_anim_meta.load(noop_anim_path) + noop_anim_meta.loadOrCreate(noop_anim_path, guid_map) for node in self.nodes: if node.class_id != "1102": @@ -1215,10 +1233,14 @@ def getGuidMap(d): return result if __name__ == "__main__": + os.chdir(os.path.dirname(os.path.abspath(__file__))) + parser = argparse.ArgumentParser() parser.add_argument("cmd", type=str, help="One of merge, guid_map, fix_write_defaults") parser.add_argument("--fx0", type=str, help="The first animator to merge") parser.add_argument("--fx1", type=str, help="The second animator to merge") + parser.add_argument("--fx_dest", type=str, help="The path at which to " + + "save the generated/merged animator") parser.add_argument("--project_root", type=str, help="The path to the " + "Unity project Assets folder") parser.add_argument("--save_to", type=str, help="The path to save the " + @@ -1227,11 +1249,12 @@ if __name__ == "__main__": "generated by a previous call to `guid_map`") parser.add_argument("--guid_map_append", type=bool, help="If set, " + "append to GUID map instead of overwriting.") + parser.add_argument("--gen_anim_dir", type=str, help="The folder under which generated animations are stored") args = parser.parse_args() if args.cmd == "merge": - if not args.fx0 or not args.fx1: - print("--fx0 and --fx1 required", file=sys.stderr) + if not args.fx0 or not args.fx1 or not args.fx_dest: + print("--fx0, --fx1, and --fx_dest required", file=sys.stderr) parser.print_help() parser.exit(1) @@ -1247,8 +1270,9 @@ if __name__ == "__main__": print("Merging animators", file=sys.stderr) anim0.merge(anim1) - print("Serializing", file=sys.stderr) - print(unityYamlToString(anim0.nodes)) + print("Serializing to {}".format(args.fx_dest), file=sys.stderr) + with open(args.fx_dest, "w") as f: + f.write(unityYamlToString(anim0.nodes)) elif args.cmd == "guid_map": if not args.project_root or not args.save_to: @@ -1312,19 +1336,30 @@ if __name__ == "__main__": anim.generateOffAnimations(guid_map, "generated/animations") elif args.cmd == "add_toggle": - if not args.fx0: - print("--fx0 required") + if not args.fx0 or not args.fx_dest or not args.gen_anim_dir or not args.guid_map: + print("--fx0, --fx_dest, --gen_anim_dir and --guid_map required") parser.print_help() parser.exit(1) + guid_map = {} + with open(args.guid_map, 'rb') as f: + guid_map = pickle.load(f) + print("Parsing {}".format(args.fx0), file=sys.stderr) parser0 = MulticoreUnityParser() anim = parser0.parseFile(args.fx0) print("Adding toggle", file=sys.stderr) - anim.addTasttToggle("Animations/TaSTT_Toggle_Off.anim", - "Animations/TaSTT_Toggle_On.anim", "TaSTT_Toggle") - print(str(anim)) + anim.addTasttToggle(args.gen_anim_dir + "/TaSTT_Toggle_Off.anim", + args.gen_anim_dir + "/TaSTT_Toggle_On.anim", "TaSTT_Toggle", + guid_map) + + print("Serializing to {}".format(args.fx_dest), file=sys.stderr) + with open(args.fx_dest, "w") as f: + f.write(str(anim)) + + with open(args.guid_map, 'wb') as f: + pickle.dump(guid_map, f) elif args.cmd == "fast_parse_test": if not args.fx0: @@ -1338,8 +1373,8 @@ if __name__ == "__main__": print(str(anim)) elif args.cmd == "set_noop_anim": - if not args.fx0 or not args.guid_map: - print("--fx0 and --guid_map required") + if not args.fx0 or not args.fx_dest or not args.gen_anim_dir or not args.guid_map: + print("--fx0, --fx_dest, --gen_anim_dir and --guid_map required") parser.print_help() parser.exit(1) @@ -1351,9 +1386,10 @@ if __name__ == "__main__": parser = MulticoreUnityParser() anim = parser.parseFile(args.fx0) - anim.setNoopAnimations(guid_map, "Animations/TaSTT_Do_Nothing.anim") + anim.setNoopAnimations(guid_map, args.gen_anim_dir + "/TaSTT_Do_Nothing.anim") - print(str(anim)) + with open(args.fx_dest, "w") as f: + f.write(str(anim)) else: print("Unrecognized command: {}".format(args.cmd)) |
