您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
325 行
12 KiB
325 行
12 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
|
|
namespace Unity.DemoTeam.DigitalHuman
|
|
{
|
|
[CreateAssetMenu(menuName = "Digital Human/Snappers Head Importer", fileName = "MyCharacter_SnappersHeadImporter", order = 50)]
|
|
public class SnappersHeadImporter : ScriptableObject
|
|
{
|
|
const int SB_SIZE = 65536;
|
|
|
|
[Header("Source stacks")]
|
|
public List<TextAsset> scriptsResolveControllers;
|
|
public List<TextAsset> scriptsResolveBlendShapes;
|
|
public List<TextAsset> scriptsResolveShaderParam;
|
|
|
|
[Header("Source literals")]
|
|
public string namedControllers = "Controllers";
|
|
public string namedBlendShapes = "BlendShapes";
|
|
public string namedShaderParam = "ShaderParam";
|
|
|
|
[Header("Output settings")]
|
|
public string csClassPrefix = "MyCharacter";
|
|
public string csNamespace = "MyNamespace";
|
|
|
|
[ContextMenu("Generate")]
|
|
public void Generate()
|
|
{
|
|
var includedControllers = new Dictionary<string, SnappersControllerCaps>();
|
|
var includedBlendShapes = new HashSet<string>();
|
|
var includedShaderParam = new HashSet<string>();
|
|
|
|
// generate the evaluation functions
|
|
{
|
|
GenerateEvaluationFunctions(scriptsResolveControllers, scriptsResolveBlendShapes, scriptsResolveShaderParam, includedControllers, includedBlendShapes, includedShaderParam);
|
|
}
|
|
|
|
// generate the data structures
|
|
{
|
|
GenerateDataStructure("SnappersControllers", includedControllers.Keys);
|
|
GenerateDataStructure("SnappersBlendShapes", includedBlendShapes);
|
|
// ................... SnappersShaderParam.. already defined
|
|
}
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.LogFormat("trying to create: {0}.{1}_SnappersHead", csNamespace, csClassPrefix);
|
|
var scriptInstance = CreateInstance(string.Format("{0}.{1}_SnappersHead", csNamespace, csClassPrefix));
|
|
if (scriptInstance != null)
|
|
{
|
|
var outputDir = GetWritePath();
|
|
var outputPath = string.Format("{0}/{1}_SnappersHead.asset", outputDir, csClassPrefix);
|
|
|
|
AssetDatabase.CreateAsset(scriptInstance, outputPath);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
}
|
|
|
|
public void GenerateEvaluationFunctions(List<TextAsset> resolveControllers, List<TextAsset> resolveBlendShapes, List<TextAsset> resolveShaderParam, Dictionary<string, SnappersControllerCaps> includedControllers, HashSet<string> includedBlendShapes, HashSet<string> includedShaderParam)
|
|
{
|
|
var sb = new StringBuilder(SB_SIZE);
|
|
|
|
sb.AppendLine("using UnityEngine;");
|
|
sb.AppendLine("using Unity.DemoTeam.DigitalHuman;");
|
|
sb.AppendLine("using Unity.Collections.LowLevel.Unsafe;// for UnsafeUtilityEx.AsRef<T>");
|
|
sb.AppendLine();
|
|
sb.AppendLine("using static Unity.DemoTeam.DigitalHuman.SnappersHeadDefinitionMath;");
|
|
sb.AppendLine();
|
|
sb.AppendFormat("namespace {0}\n", csNamespace);
|
|
sb.AppendLine("{");
|
|
sb.AppendFormat(" using SnappersControllers = {0}_SnappersControllers<SnappersController>;\n", csClassPrefix);
|
|
sb.AppendFormat(" using SnappersBlendShapes = {0}_SnappersBlendShapes<float>;\n", csClassPrefix);
|
|
sb.AppendLine();
|
|
sb.AppendFormat(" public class {0}_{1}\n", csClassPrefix, "SnappersHead : SnappersHeadDefinition");
|
|
sb.AppendLine(" {");
|
|
sb.AppendLine(" public override InstanceData CreateInstanceData(Mesh sourceMesh, Transform sourceRig, Warning warnings)");
|
|
sb.AppendLine(" {");
|
|
sb.AppendLine(" return CreateInstanceData<SnappersControllers, SnappersBlendShapes>(sourceMesh, sourceRig, warnings);");
|
|
sb.AppendLine(" }");
|
|
sb.AppendLine();
|
|
|
|
sb.AppendLine("#pragma warning disable 0219");
|
|
|
|
GenerateEvaluationFunction(sb, " ", "ResolveControllers", resolveControllers, includedControllers, includedBlendShapes, includedShaderParam, skipCaps: true);
|
|
sb.AppendLine();
|
|
GenerateEvaluationFunction(sb, " ", "ResolveBlendShapes", resolveBlendShapes, includedControllers, includedBlendShapes, includedShaderParam, skipCaps: false);
|
|
sb.AppendLine();
|
|
GenerateEvaluationFunction(sb, " ", "ResolveShaderParam", resolveShaderParam, includedControllers, includedBlendShapes, includedShaderParam, skipCaps: false);
|
|
sb.AppendLine();
|
|
GenerateInitializeControllerCaps(sb, " ", "InitializeControllerCaps", includedControllers);
|
|
|
|
sb.AppendLine("#pragma warning restore 0219");
|
|
|
|
sb.AppendLine(" }");
|
|
sb.AppendLine("}");
|
|
|
|
WriteScriptAsset(string.Format("{0}_{1}", csClassPrefix, "SnappersHead"), sb.ToString());
|
|
}
|
|
|
|
public void GenerateEvaluationFunction(StringBuilder sb, string tabs, string name, List<TextAsset> scripts, Dictionary<string, SnappersControllerCaps> includedControllers, HashSet<string> includedBlendShapes, HashSet<string> includedShaderParam, bool skipCaps)
|
|
{
|
|
sb.AppendFormat(" // --- {0}\n", name);
|
|
sb.AppendFormat(" public override unsafe void {0}(void* ptrSnappersControllers, void* ptrSnappersBlendShapes, void* ptrSnappersShaderParam)\n", name);
|
|
sb.AppendLine(" {");
|
|
sb.AppendFormat(" {0}(\n", name);
|
|
sb.AppendLine(" ref UnsafeUtilityEx.AsRef<SnappersControllers>(ptrSnappersControllers),");
|
|
sb.AppendLine(" ref UnsafeUtilityEx.AsRef<SnappersBlendShapes>(ptrSnappersBlendShapes),");
|
|
sb.AppendLine(" ref UnsafeUtilityEx.AsRef<SnappersShaderParam>(ptrSnappersShaderParam)");
|
|
sb.AppendLine(" );");
|
|
sb.AppendLine(" }");
|
|
sb.AppendFormat(" public void {0}(ref SnappersControllers {1}, ref SnappersBlendShapes {2}, ref SnappersShaderParam {3})\n", name, namedControllers, namedBlendShapes, namedShaderParam);
|
|
sb.AppendLine(" {");
|
|
|
|
foreach (var script in scripts)
|
|
{
|
|
if (script == null)
|
|
continue;
|
|
|
|
sb.AppendFormat(" // this segment generated from '{0}'\n", script.name);
|
|
sb.AppendLine(" {");
|
|
GenerateEvaluationFunctionSegment(sb, " ", script, includedControllers, includedBlendShapes, includedShaderParam, skipCaps);
|
|
sb.AppendLine(" }");
|
|
}
|
|
|
|
sb.AppendLine(" }");
|
|
}
|
|
|
|
public void GenerateEvaluationFunctionSegment(StringBuilder sb, string tabs, TextAsset script, Dictionary<string, SnappersControllerCaps> includedControllers, HashSet<string> includedBlendShapes, HashSet<string> includedShaderParams, bool skipCaps)
|
|
{
|
|
var regexDouble = new Regex("(\\d+\\.\\d+)([^f])");
|
|
var regexMember = new Regex("([a-zA-Z_]+[\\w]*)\\.([a-zA-Z_]+[\\w]*)");
|
|
|
|
var inputPath = AssetDatabase.GetAssetPath(script);
|
|
var inputStream = new StreamReader(inputPath);
|
|
|
|
while (inputStream.EndOfStream == false)
|
|
{
|
|
var line = inputStream.ReadLine();
|
|
if (line.Length == 0)
|
|
continue;
|
|
|
|
// add tabs
|
|
sb.Append(tabs);
|
|
|
|
// replace $ with _
|
|
line = line.Replace('$', '_');
|
|
|
|
// replace eeg. 0.0 with 0.0f
|
|
line = regexDouble.Replace(line, "$1f$2");
|
|
|
|
// replace and gather struct.member
|
|
var matches = regexMember.Matches(line);
|
|
{
|
|
int lineCursor = 0;
|
|
|
|
foreach (Match match in matches)
|
|
{
|
|
sb.Append(line, lineCursor, match.Index - lineCursor);
|
|
|
|
var nameStruct = match.Groups[1].Value;
|
|
var nameMember = match.Groups[2].Value;
|
|
if (nameStruct == namedBlendShapes)
|
|
{
|
|
includedBlendShapes.Add(nameMember);
|
|
}
|
|
//else if (nameStruct == namedControllers)
|
|
//{
|
|
// includedControllers.Add(nameMember);
|
|
//}
|
|
else if (nameStruct == namedShaderParam)
|
|
{
|
|
includedShaderParams.Add(nameMember);
|
|
}
|
|
else// controller
|
|
{
|
|
SnappersControllerCaps caps;
|
|
includedControllers.TryGetValue(nameStruct, out caps);
|
|
includedControllers[nameStruct] = caps | (skipCaps ? SnappersControllerCaps.none : TranslateControllerField(nameMember));
|
|
sb.Append(namedControllers);
|
|
sb.Append('.');
|
|
}
|
|
|
|
lineCursor = match.Index;
|
|
}
|
|
|
|
sb.Append(line, lineCursor, line.Length - lineCursor);
|
|
}
|
|
|
|
// add newline
|
|
sb.Append('\n');
|
|
}
|
|
|
|
inputStream.Close();
|
|
}
|
|
|
|
public void GenerateInitializeControllerCaps(StringBuilder sb, string tabs, string name, Dictionary<string, SnappersControllerCaps> includedControllers)
|
|
{
|
|
Func<StringBuilder, int, SnappersControllerCaps, SnappersControllerCaps, int> concatCap = (_sb, _capCount, _caps, _cap) =>
|
|
{
|
|
if ((_caps & _cap) != 0)
|
|
{
|
|
if (_capCount++ > 0)
|
|
{
|
|
sb.Append(" | ");
|
|
}
|
|
_sb.Append("SnappersControllerCaps.");
|
|
_sb.Append(_cap);
|
|
}
|
|
return _capCount;
|
|
};
|
|
|
|
sb.AppendFormat(" // --- {0}\n", name);
|
|
sb.AppendFormat(" public override unsafe void {0}(void* ptrSnappersControllers)\n", name);
|
|
sb.AppendLine(" {");
|
|
sb.AppendFormat(" {0}(\n", name);
|
|
sb.AppendLine(" ref UnsafeUtilityEx.AsRef<SnappersControllers>(ptrSnappersControllers)");
|
|
sb.AppendLine(" );");
|
|
sb.AppendLine(" }");
|
|
sb.AppendFormat(" public void {0}(ref SnappersControllers {1})\n", name, namedControllers);
|
|
sb.AppendLine(" {");
|
|
|
|
List<string> sortedFields;
|
|
sortedFields = new List<string>(includedControllers.Keys);
|
|
sortedFields.Sort();
|
|
|
|
foreach (var field in sortedFields)
|
|
{
|
|
sb.AppendFormat(" {0}.{1}.caps = ", namedControllers, field);
|
|
|
|
var caps = includedControllers[field];
|
|
var capCount = 0;
|
|
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.translateX);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.translateY);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.translateZ);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.rotateX);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.rotateY);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.rotateZ);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.scaleX);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.scaleY);
|
|
capCount = concatCap(sb, capCount, caps, SnappersControllerCaps.scaleZ);
|
|
|
|
if (capCount == 0)
|
|
sb.AppendLine("SnappersControllerCaps.none;");
|
|
else
|
|
sb.AppendLine(";");
|
|
}
|
|
|
|
sb.AppendLine(" }");
|
|
}
|
|
|
|
public void GenerateDataStructure(string name, IEnumerable<string> fields)
|
|
{
|
|
var sb = new StringBuilder(SB_SIZE);
|
|
|
|
List<string> sortedFields;
|
|
sortedFields = new List<string>(fields);
|
|
sortedFields.Sort();
|
|
|
|
sb.AppendLine("using Unity.DemoTeam.DigitalHuman;");
|
|
sb.AppendLine();
|
|
sb.AppendFormat("namespace {0}\n", csNamespace);
|
|
sb.AppendLine("{");
|
|
sb.AppendFormat(" public struct {0}_{1}<T> where T : struct\n", csClassPrefix, name);
|
|
sb.AppendLine(" {");
|
|
|
|
foreach (var field in sortedFields)
|
|
{
|
|
sb.Append(" public T ");
|
|
sb.Append(field);
|
|
sb.AppendLine(";");
|
|
}
|
|
|
|
sb.AppendLine(" }");
|
|
sb.AppendLine("}");
|
|
|
|
WriteScriptAsset(string.Format("{0}_{1}", csClassPrefix, name), sb.ToString());
|
|
}
|
|
|
|
public string GetWritePath()
|
|
{
|
|
return Path.GetDirectoryName(AssetDatabase.GetAssetPath(this)).Replace('\\', '/');
|
|
}
|
|
|
|
public string WriteScriptAsset(string identifier, string text)
|
|
{
|
|
var outputDir = GetWritePath();
|
|
var outputPath = string.Format("{0}/{1}.cs", outputDir, identifier);
|
|
var outputStream = new StreamWriter(outputPath);
|
|
|
|
outputStream.NewLine = "\n";
|
|
outputStream.Write(text.Replace("\r\n", "\n"));
|
|
outputStream.Flush();
|
|
outputStream.Close();
|
|
|
|
Debug.LogFormat("Wrote {0}", outputPath);
|
|
|
|
return outputPath;
|
|
}
|
|
|
|
static SnappersControllerCaps TranslateControllerField(string field)
|
|
{
|
|
switch (field)
|
|
{
|
|
case "translateX": return SnappersControllerCaps.translateX;
|
|
case "translateY": return SnappersControllerCaps.translateY;
|
|
case "translateZ": return SnappersControllerCaps.translateZ;
|
|
|
|
case "rotateX": return SnappersControllerCaps.rotateX;
|
|
case "rotateY": return SnappersControllerCaps.rotateY;
|
|
case "rotateZ": return SnappersControllerCaps.rotateZ;
|
|
|
|
case "scaleX": return SnappersControllerCaps.scaleX;
|
|
case "scaleY": return SnappersControllerCaps.scaleY;
|
|
case "scaleZ": return SnappersControllerCaps.scaleZ;
|
|
|
|
default: return SnappersControllerCaps.none;
|
|
}
|
|
}
|
|
}
|
|
}
|