using System; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEditor; using UnityEditorInternal; public class SkeletonImporter : AssetPostprocessor { uint m_Version = 2; public override uint GetVersion() {return m_Version;} List m_TwistConfigs = new List(); List m_FanConfigs = new List(); List m_TranslateScaleConfigs = new List(); enum ComponentType { TwistComponent, FanComponent, TranslateScaleComponent, } [Serializable] public class ComponentConfig { public List twistConfig = new List(); public List fanConfig = new List(); public List translateScaleConfig = new List(); } [Serializable] public class TypeData { public string type = ""; public TypeData() {} public TypeData(string type) { this.type = type; } } [Serializable] public class TwistConfig { public string driver; public string aimAxis = ""; public List twistJoints = new List(); public List twistFactors = new List(); public TwistConfig() {} public TwistConfig(string driver, string aimAxis, List twistJoints, List twistFactors) { this.driver = driver; this.aimAxis = aimAxis; this.twistJoints = twistJoints; this.twistFactors = twistFactors; } } [Serializable] public class FanConfig { public string driverA; public string driverB; public string driven; public FanConfig() {} public FanConfig(string driverA, string driverB, string driven) { this.driverA = driverA; this.driverB = driverB; this.driven = driven; } } [Serializable] public class TranslateScaleConfig { public string driver; public string aimAxis = ""; public List stretchBones = new List(); public List stretchFactors = new List(); public List scaleFactors = new List(); public TranslateScaleConfig() {} public TranslateScaleConfig(string driver, string aimAxis, List stretchBones, List stretchFactors, List scaleFactors) { this.driver = driver; this.aimAxis = aimAxis; this.stretchBones = stretchBones; this.stretchFactors = stretchFactors; this.scaleFactors = scaleFactors; } } void OnPostprocessGameObjectWithUserProperties(GameObject go, string[] propNames, System.Object[] values) { string stringValue; for (int i = 0; i < propNames.Length; i++) { if (propNames[i] == "sampleGame_compData") { stringValue = values[i] as System.String; if (!String.IsNullOrEmpty(stringValue)) { ComponentConfig componentConfig = new ComponentConfig(); componentConfig = JsonUtility.FromJson(stringValue); foreach (var twistConfig in componentConfig.twistConfig) { m_TwistConfigs.Add(twistConfig); } foreach (var fanConfig in componentConfig.fanConfig) { m_FanConfigs.Add(fanConfig); } foreach (var translateScaleConfig in componentConfig.translateScaleConfig) { m_TranslateScaleConfigs.Add(translateScaleConfig); } } } } } void OnPostprocessModel(GameObject root) { // Attempt to find skeleton root var skeletonRoot = root.transform.Find("Skeleton"); // TODO: (sunek) Be able to setup skeleton within the editor and get rid of this? if (skeletonRoot == null) { var animator = root.GetComponent(); if (animator != null && animator.isHuman) { var hips = animator.GetBoneTransform(HumanBodyBones.Hips); if (hips != null) { skeletonRoot = animator.GetBoneTransform(HumanBodyBones.Hips).parent; } } } if (skeletonRoot == null) return; if (skeletonRoot.GetComponent() || skeletonRoot.GetComponent() || skeletonRoot.GetComponent()) { return; } var skeletonComponent = root.AddComponent(); skeletonComponent.StoreBoneData(skeletonRoot); AddTwistComponents(root, m_TwistConfigs); AddFanComponents(root, m_FanConfigs); AddTranslateScaleComponents(root, m_TranslateScaleConfigs); } static void AddTwistComponents(GameObject root, List twistConfigs) { if (twistConfigs.Count == 0) return; var twistComponent = root.AddComponent(); for (var i = 0; i < twistConfigs.Count; i++) { var twistConfig = twistConfigs[i]; var twistChain = new Twist.TwistChain(); twistChain.driver = FindInChildren(root.transform, twistConfig.driver); if (!twistChain.driver) continue; // TODO: Support variable axis // switch (twistConfig.aimAxis) // { // case "X": // twistComponent.aimAxis = Twist.AimAxis.X; // break; // case "Y": // twistComponent.aimAxis = Twist.AimAxis.Y; // break; // case "Z": // twistComponent.aimAxis = Twist.AimAxis.Z; // break; // default: // twistComponent.aimAxis = Twist.AimAxis.X; // break; // } twistChain.twistJoints = new List(); for (var j = 0; j < twistConfig.twistJoints.Count; j++) { var twistJoint = new Twist.TwistJoint(); twistJoint.joint = FindInChildren(root.transform, twistConfig.twistJoints[j]); twistJoint.factor = twistConfig.twistFactors[j]; twistChain.twistJoints.Add(twistJoint); } if (twistChain.HasValidData()) twistComponent.twistChains.Add(twistChain); } twistComponent.SetBindpose(); } static void AddFanComponents(GameObject root, List fanConfigs) { if (fanConfigs.Count == 0) return; var fanComponent = root.AddComponent(); for (var i = 0; i < fanConfigs.Count; i++) { var fanData = new Fan.FanData(); fanData.driven = FindInChildren(root.transform, fanConfigs[i].driven); fanData.driverA = FindInChildren(root.transform, fanConfigs[i].driverA); fanData.driverB = FindInChildren(root.transform, fanConfigs[i].driverB); if (fanData.HasValidData()) { fanComponent.fanDatas.Add(fanData); } } } static void AddTranslateScaleComponents(GameObject root, List translateScaleConfigs) { if (translateScaleConfigs.Count == 0) return; var component = root.AddComponent(); for (var i = 0; i < translateScaleConfigs.Count; i++) { var config = translateScaleConfigs[i]; var chain = new TranslateScale.TranslateScaleChain(); chain.driver = FindInChildren(root.transform, config.driver); if (!chain.driver) continue; chain.drivenJoints = new List(); for (var j = 0; j < config.stretchBones.Count; j++) { var driven = new TranslateScale.Driven(); driven.joint = FindInChildren(root.transform,config.stretchBones[j]); driven.scaleFactor = config.scaleFactors[j]; driven.strectchFactor = config.stretchFactors[j]; chain.drivenJoints.Add(driven); } if (chain.HasValidData()) component.chains.Add(chain); } component.SetBindpose(); } static Transform FindInChildren(Transform parent, string name) { var result = parent.Find(name); if (result != null) return result; foreach (Transform child in parent) { result = FindInChildren(child, name); if (result != null) return result; } return null; } }