You've already forked UniversalViewer
							
							DanMachi:
-compatibility improvements Core: -simplified object and keyframe serialization -complicated assetbundle loading
This commit is contained in:
		| @@ -1,64 +1,80 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using UnityEditor.Graphs; | ||||
| using UnityEngine; | ||||
|  | ||||
| public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
| public class DanMachiCharacterContainer : ObjectContainer, IAnimated | ||||
| { | ||||
|     protected override System.Type _serializeType => typeof(DanMachiCharacterSerializable); | ||||
|     protected override System.Type _keyframeType => typeof(DanMachiCharacterKeyframeData); | ||||
|  | ||||
|     public CharacterAsset Data; | ||||
|     public string AnimationSet; | ||||
|     public string Animation; | ||||
|  | ||||
|     public GameObject Body; | ||||
|     public MorphPanel MorphPanel; | ||||
|     public CharacterPanel CharacterPanel; | ||||
|     public List<AnimationClip> Animations; | ||||
|     private Animator _animator; | ||||
|     private AnimatorOverrideController _animatorController; | ||||
|     private Dictionary<HumanBodyBones, Transform> _humanBones = new Dictionary<HumanBodyBones, Transform>(); | ||||
|     public List<Transform> Bones = new List<Transform>(); | ||||
|  | ||||
|     public override void Select() | ||||
|     public void Init() | ||||
|     { | ||||
|         if(MorphPanel != null) | ||||
|         _animator = GetComponentInChildren<Animator>(); | ||||
|         if(_animator != null) | ||||
|         { | ||||
|             MorphPanel.gameObject.SetActive(true); | ||||
|             _animator.applyRootMotion = false; | ||||
|             _animator.runtimeAnimatorController = _animatorController = Instantiate(SharedResources.Instance.GenericAnimatorController); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             Error.Log(Color.red, $"{name} has no animator"); | ||||
|         } | ||||
|         CreateMorphPanel(); | ||||
|         CreateCharacterPanel(); | ||||
|         SetBones(); | ||||
|     } | ||||
|  | ||||
|     public override void Deselect() | ||||
|     public void Rebuild(CharacterAsset model) | ||||
|     { | ||||
|         if (MorphPanel != null) | ||||
|         { | ||||
|             MorphPanel.gameObject.SetActive(false); | ||||
|         } | ||||
|         DestroyImmediate(Body); | ||||
|         Build(model); | ||||
|     } | ||||
|  | ||||
|     public void Build(CharacterAsset model) | ||||
|     { | ||||
|         Data = model; | ||||
|         var characterAsset = AssetBundle.LoadFromFile(model.FilePath); | ||||
|         var animationSets = DanMachiAssetLibrary.Instance.Animations.Where(a => a.Category == model.Category && a.Id == model.Id); | ||||
|         var assetPath = Path.Combine(DanMachiAssetLibrary.Instance.LocalFilesPath, model.FilePath); | ||||
|         var characterAsset = AssetLibrary.LoadFromFile(assetPath); | ||||
|         var assetNames = characterAsset.GetAllAssetNames(); | ||||
|         var characterModel = assetNames.FirstOrDefault(a => Path.GetFileName(a).StartsWith("CP_") && a.EndsWith(".prefab")); | ||||
|  | ||||
|         foreach (var go in characterAsset.LoadAllAssets<GameObject>()) | ||||
|         if(!string.IsNullOrEmpty(characterModel)) | ||||
|         { | ||||
|             Instantiate(go, transform); | ||||
|             Body = Instantiate(characterAsset.LoadAsset(characterModel), transform) as GameObject; | ||||
|         } | ||||
|         characterAsset.Unload(false); | ||||
|         else | ||||
|         { | ||||
|             Body = new GameObject(); | ||||
|             Body.transform.SetParent(transform); | ||||
|             foreach (var go in characterAsset.LoadAllAssets<GameObject>()) | ||||
|             { | ||||
|                 Instantiate(go, Body.transform); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         LoadedAssets = new List<AssetBundleEntry>() { new AssetBundleEntry(model.AssetName, assetPath, characterAsset) }; | ||||
|         AssetLibrary.UnloadAsset(assetPath); | ||||
|  | ||||
|         SetDefaultMaterials(transform); | ||||
|  | ||||
|         Init(); | ||||
|  | ||||
|         var defaultAnimSet = animationSets.FirstOrDefault(a => a.Costume == "common"); | ||||
|         LoadAnimationSet(defaultAnimSet); | ||||
|     } | ||||
|  | ||||
|     public void Init() | ||||
|     { | ||||
|         _animator = GetComponentInChildren<Animator>(); | ||||
|         _animator.applyRootMotion = false; | ||||
|         _animator.runtimeAnimatorController = _animatorController = Instantiate(SharedResources.Instance.GenericAnimatorController); | ||||
|         CreateMorphPanel(); | ||||
|         CreateCharacterPanel(); | ||||
|         SetBones(); | ||||
|     } | ||||
|  | ||||
|     public void LoadAnimationSet(CharacterAsset animationSet) | ||||
| @@ -67,7 +83,7 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|         { | ||||
|             AnimationSet = animationSet.Costume; | ||||
|             Animation = ""; | ||||
|             var animationAsset = AssetBundle.LoadFromFile(animationSet.FilePath); | ||||
|             var animationAsset = AssetBundle.LoadFromFile(Path.Combine(DanMachiAssetLibrary.Instance.LocalFilesPath, animationSet.FilePath)); | ||||
|             Animations = animationAsset.LoadAllAssets<AnimationClip>().ToList(); | ||||
|             animationAsset.Unload(false); | ||||
|         } | ||||
| @@ -81,6 +97,12 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|  | ||||
|     public void PlayAnimation(AnimationClip anim) | ||||
|     { | ||||
|         if(_animator == null) | ||||
|         { | ||||
|             Error.Log(Color.red, $"{name} has no animator"); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if(anim == null) | ||||
|         { | ||||
|             Animation = ""; | ||||
| @@ -110,8 +132,20 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|  | ||||
|     public void SetBones() | ||||
|     { | ||||
|         _humanBones.Clear(); | ||||
|         Bones.Clear(); | ||||
|  | ||||
|         if (_animator == null) return; | ||||
|  | ||||
|         var humanBones = new Dictionary<HumanBodyBones, Transform>(); | ||||
|         var allBones = _animator.transform.GetComponentsInChildren<Transform>().ToDictionary(b=>b.name, b=>b); | ||||
|         var allBones = new Dictionary<string, Transform>(); | ||||
|         foreach(var bone in _animator.transform.GetComponentsInChildren<Transform>()) | ||||
|         { | ||||
|             if (!allBones.ContainsKey(bone.name)) | ||||
|             { | ||||
|                 allBones[bone.name] = bone; | ||||
|             } | ||||
|         } | ||||
|         humanBones.Add(HumanBodyBones.Hips,                     TryGet(allBones,"Hips")); | ||||
|         humanBones.Add(HumanBodyBones.Spine,                    TryGet(allBones,"Spine")); | ||||
|         humanBones.Add(HumanBodyBones.RightUpperLeg,            TryGet(allBones,"RightUpLeg")); | ||||
| @@ -186,6 +220,7 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|         } | ||||
|  | ||||
|         _humanBones = humanBones; | ||||
|         Bones = allBones.Values.ToList(); | ||||
|     } | ||||
|  | ||||
|     public T TryGet<T>(Dictionary<string, T> dict, string key) | ||||
| @@ -199,11 +234,6 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|  | ||||
|     public void CreateMorphPanel() | ||||
|     { | ||||
|         if(MorphPanel != null) | ||||
|         { | ||||
|             Destroy(MorphPanel.gameObject); | ||||
|         } | ||||
|  | ||||
|         var morphRenderers = new Dictionary<SkinnedMeshRenderer, List<MorphHelper>>(); | ||||
|         foreach (var rend in gameObject.GetComponentsInChildren<SkinnedMeshRenderer>()) | ||||
|         { | ||||
| @@ -213,29 +243,59 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (morphRenderers.Count == 0) return; | ||||
|         if (morphRenderers.Count == 0) | ||||
|         { | ||||
|             if(MorphPanel != null) | ||||
|             { | ||||
|                 Destroy(MorphPanel.gameObject); | ||||
|                 MorphPanel = null; | ||||
|                 InstantiatedObjects.Remove(MorphPanel.gameObject); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         MorphPanel = MorphPanel.Create(morphRenderers.Select(mr=>mr.Key.sharedMesh.name).ToList()); | ||||
|         MorphPanel.name = $"Chr_{Data.Id} Morphs"; | ||||
|         if(MorphPanel != null) | ||||
|         { | ||||
|             MorphPanel.Init(morphRenderers.Select(mr => mr.Key.sharedMesh.name).ToList()); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             MorphPanel = MorphPanel.Create(morphRenderers.Select(mr => mr.Key.sharedMesh.name).ToList()); | ||||
|             MorphPanel.name = $"Chr_{Data.Id} Morphs"; | ||||
|             InstantiatedObjects.Add(MorphPanel.gameObject); | ||||
|             DanMachiInterface.Instance.SelectedObjectToolbar.AttachToThis(MorphPanel.GetComponent<UIElementDragger>()); | ||||
|         } | ||||
|  | ||||
|         foreach(var rend in morphRenderers) | ||||
|         foreach (var rend in morphRenderers) | ||||
|         { | ||||
|             var mesh = rend.Key.sharedMesh; | ||||
|             for(int i = 0; i < mesh.blendShapeCount; i++) | ||||
|             { | ||||
|                 MorphPanel.CreateMorph(mesh.name, this, rend.Key, i, mesh.GetBlendShapeName(i).Replace("blendShape1.","")); | ||||
|                 var panel = MorphPanel.CreateMorph(mesh.name, this, rend.Key, i, mesh.GetBlendShapeName(i).Replace("blendShape1.","")); | ||||
|                 var helper = panel.MorphHelper;  | ||||
|                 if (morphRenderers.ContainsKey(rend.Key)) | ||||
|                     morphRenderers[rend.Key].Add(helper); | ||||
|                 else | ||||
|                     morphRenderers.Add(rend.Key, new List<MorphHelper>() { helper }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Morphs = morphRenderers; | ||||
|         DanMachiModelViewerInterface.Instance.SelectedObjectToolbar.AttachToThis(MorphPanel.GetComponent<UIElementDragger>()); | ||||
|     } | ||||
|  | ||||
|     public void CreateCharacterPanel() | ||||
|     { | ||||
|         CharacterPanel = CharacterPanel.Create(this); | ||||
|         CharacterPanel.name = $"Chr_{Data.Id} Settings"; | ||||
|         DanMachiModelViewerInterface.Instance.SelectedObjectToolbar.AttachToThis(CharacterPanel.GetComponent<UIElementDragger>()); | ||||
|         if(CharacterPanel != null) | ||||
|         { | ||||
|             CharacterPanel.Init(this); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             CharacterPanel = CharacterPanel.Create(this); | ||||
|             CharacterPanel.name = $"Chr_{Data.Id} Settings"; | ||||
|             InstantiatedObjects.Add(CharacterPanel.gameObject); | ||||
|             DanMachiInterface.Instance.SelectedObjectToolbar.AttachToThis(CharacterPanel.GetComponent<UIElementDragger>()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public override Vector3 GetCenter() | ||||
| @@ -247,19 +307,45 @@ public class DanMachiCharacterContainer : DanMachiObjectContainer, IAnimated | ||||
|         return base.GetCenter(); | ||||
|     } | ||||
|  | ||||
|     protected override void OnDestroy() | ||||
|     { | ||||
|         if (_applicationQuitting) return; | ||||
|         if(MorphPanel != null) | ||||
|         { | ||||
|             Destroy(MorphPanel.gameObject); | ||||
|         } | ||||
|         Destroy(CharacterPanel.gameObject); | ||||
|         base.OnDestroy(); | ||||
|     } | ||||
|  | ||||
|     public Animator GetAnimator() | ||||
|     { | ||||
|         return _animator; | ||||
|     } | ||||
|  | ||||
|     public override void PastePose(KeyframeData frame, PoseLoadOptions pasteParams) | ||||
|     { | ||||
|         PlayAnimation(""); | ||||
|  | ||||
|         if (pasteParams.Root) | ||||
|         { | ||||
|             transform.SetTransform(frame.Root); | ||||
|         } | ||||
|  | ||||
|         var frameData = frame as DanMachiCharacterKeyframeData; | ||||
|         if (frameData == null) return; | ||||
|  | ||||
|         foreach (var bone in frameData.Bones.Bones) | ||||
|         { | ||||
|             var targetBone = Bones.FirstOrDefault(b => b.name == bone.Name); | ||||
|             if (targetBone == null) continue; | ||||
|  | ||||
|             bone.Transform.ApplyTo(targetBone.transform); | ||||
|         } | ||||
|  | ||||
|         foreach(var morph in frameData.Morphs) | ||||
|         { | ||||
|             var renderer = Morphs.Keys.FirstOrDefault(k => k.name == morph.Key); | ||||
|             if (renderer == null) continue; | ||||
|  | ||||
|             foreach(var value in morph.Value) | ||||
|             { | ||||
|                 var helper = Morphs[renderer].FirstOrDefault(h => h.Name == value.Name); | ||||
|                 if (helper == null) continue; | ||||
|                 helper.Value = value.Value; | ||||
|                 helper.UpdateMorph(value.Strength); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         SetKeyframe(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
|  | ||||
| using System.Collections.Generic; | ||||
| using System.ComponentModel; | ||||
| using System.Linq; | ||||
| using UnityEngine; | ||||
|  | ||||
| public class DanMachiCharacterKeyframeData : KeyframeData | ||||
| { | ||||
|     public BoneList Bones = new BoneList(); | ||||
|     public Dictionary<string, List<MorphHelper>> Morphs = new Dictionary<string, List<MorphHelper>>(); | ||||
|  | ||||
|     public DanMachiCharacterKeyframeData() { } | ||||
|  | ||||
|     public DanMachiCharacterKeyframeData(DanMachiCharacterContainer container) | ||||
|     { | ||||
|         this.Root = new SerializableTransform(container.transform); | ||||
|         this.Bones = new BoneList() { Name = "", Bones = container.Bones.Select(b => new SerializableBone(b)).ToArray() }; | ||||
|         this.Morphs = container.Morphs.ToDictionary(m => m.Key.name, m => m.Value); | ||||
|     } | ||||
|  | ||||
|     public override KeyframeData Clone() | ||||
|     { | ||||
|         var keyframe = new DanMachiCharacterKeyframeData(); | ||||
|         keyframe.Root = new SerializableTransform(this.Root); | ||||
|         keyframe.Bones = new BoneList() { Name = Bones.Name, Bones = Bones.Bones.Select(b=> new SerializableBone(b)).ToArray() }; | ||||
|         keyframe.Morphs = Morphs.ToDictionary(m => m.Key, m => m.Value.Select(v=>new MorphHelper(v.ParentName, v.Name, v.Strength, v.Value)).ToList()); | ||||
|         return keyframe; | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: c58ee12edd81a8d43a9107bc7906a17b | ||||
| guid: d096ac3a0685dd54a836bc35192a0522 | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
| @@ -0,0 +1,12 @@ | ||||
|  | ||||
| public class DanMachiCharacterSerializable : ObjectContainerSerializable | ||||
| { | ||||
|     public string AssetName; | ||||
|  | ||||
|     public DanMachiCharacterSerializable() { } | ||||
|  | ||||
|     public DanMachiCharacterSerializable(DanMachiCharacterContainer container) : base(container) | ||||
|     { | ||||
|         AssetName = container.Data.AssetName; | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: 6ce5c34b04160214b935e3dcefed9ffc | ||||
| guid: 90e549cfb34f0cc47ac51d28cf4a6d9a | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
| @@ -1,42 +0,0 @@ | ||||
| public class DanMachiObjectContainer : ObjectContainer | ||||
| { | ||||
|     protected static DanMachiModelViewerMain Main => DanMachiModelViewerMain.Instance; | ||||
|  | ||||
|     protected override void Start() | ||||
|     { | ||||
|         if (DoNotSave) return; | ||||
|  | ||||
|         if(Frames.Count == 0) | ||||
|         { | ||||
|             SetKeyframe(); | ||||
|         } | ||||
|  | ||||
|         DanMachiModelViewerMain.RegisterObject(this); | ||||
|         var selector = UITimelineObjectEntry.Create(this); | ||||
|         InstantiatedObjects.Add(selector.gameObject); | ||||
|  | ||||
|         ModelViewerMain.GetInstance<DanMachiModelViewerMain>().SelectObject(this); | ||||
|     } | ||||
|  | ||||
|     public override void Select() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public override void Deselect() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     protected override void OnDestroy() | ||||
|     { | ||||
|         if(_applicationQuitting) return; | ||||
|  | ||||
|         if (Main.SelectedObject == this) | ||||
|         { | ||||
|             Main.SelectObject(null); | ||||
|         } | ||||
|  | ||||
|         ModelViewerMain.UnregisterObject(this); | ||||
|  | ||||
|         base.OnDestroy(); | ||||
|     } | ||||
| } | ||||
| @@ -29,8 +29,8 @@ public class DanMachiAssetLibrary : AssetLibrary | ||||
|         //    ParseList(str); | ||||
|         //}); | ||||
|  | ||||
|         string catalogPath      = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "Low\\aiming\\DanChro\\com.unity.addressables\\catalog_0.0.0.json"; | ||||
|         string localFilesPath   = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "Low\\Unity\\aiming_DanChro\\"; | ||||
|         string catalogPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "Low\\aiming\\DanChro\\com.unity.addressables\\catalog_0.0.0.json"; | ||||
|         LocalFilesPath = ModelViewerSettings.Get("AssetsPath", new ModelViewerSettings.Setting(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "Low\\Unity\\aiming_DanChro\\", ModelViewerSettings.SettingType.FolderPath)); | ||||
|  | ||||
|         yield return LoadAddressableCatalog(catalogPath); | ||||
|  | ||||
| @@ -49,13 +49,13 @@ public class DanMachiAssetLibrary : AssetLibrary | ||||
|                 if (entry.Contains("_anim_")) | ||||
|                 { | ||||
|                     AnimationAssets.Add(entry); | ||||
|                     var chara = new CharacterAsset(entry, localFilesPath + GetResourcePath(entry, out _)); | ||||
|                     var chara = new CharacterAsset(entry, GetResourcePath(entry, out _)); | ||||
|                     Animations.Add(chara); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     CharacterAssets.Add(entry); | ||||
|                     var chara = new CharacterAsset(entry, localFilesPath + GetResourcePath(entry, out _)); | ||||
|                     var chara = new CharacterAsset(entry, GetResourcePath(entry, out _)); | ||||
|                     Characters.Add(chara); | ||||
|                 } | ||||
|             } | ||||
| @@ -82,7 +82,7 @@ public class DanMachiAssetLibrary : AssetLibrary | ||||
|         //    Characters.Add(chara); | ||||
|         //} | ||||
|  | ||||
|         DanMachiModelViewerInterface.Instance.CharacterSelection.SetData(Characters); | ||||
|         DanMachiInterface.Instance.CharacterSelection.SetData(Characters); | ||||
|  | ||||
|         yield break; | ||||
|     } | ||||
|   | ||||
							
								
								
									
										6
									
								
								Assets/DanMachi/Scripts/DanMachiInterface.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Assets/DanMachi/Scripts/DanMachiInterface.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| public class DanMachiInterface : ModelViewerInterface | ||||
| { | ||||
|     public static DanMachiInterface Instance => GetInstance<DanMachiInterface>(); | ||||
|  | ||||
|     public CharacterDropdown CharacterSelection; | ||||
| } | ||||
							
								
								
									
										42
									
								
								Assets/DanMachi/Scripts/DanMachiMain.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								Assets/DanMachi/Scripts/DanMachiMain.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| using System.Collections; | ||||
| using System.Linq; | ||||
| using UnityEngine; | ||||
|  | ||||
| [RequireComponent(typeof(DanMachiAssetLibrary), typeof(DanMachiModelBuilder), typeof(DanMachiInterface))] | ||||
| public class DanMachiMain : ModelViewerMain | ||||
| { | ||||
|     public static DanMachiMain Instance => GetInstance<DanMachiMain>(); | ||||
|  | ||||
|     protected DanMachiAssetLibrary _assets => DanMachiAssetLibrary.Instance; | ||||
|     protected DanMachiModelBuilder _modelBuilder => DanMachiModelBuilder.Instance; | ||||
|  | ||||
|     protected override void Awake() | ||||
|     { | ||||
|         CurrentScene = SceneContainer.Create<SceneContainer>(this); | ||||
|         base.Awake(); | ||||
|     } | ||||
|  | ||||
|     private IEnumerator Start() | ||||
|     { | ||||
|         Application.targetFrameRate = 30; | ||||
|         Error.Log(Color.green, "Viewer version: " + Application.version); | ||||
|  | ||||
|         float warningTimer = 0; | ||||
|         while (DanMachiAssetLibrary.Instance == null || DanMachiModelBuilder.Instance == null || DanMachiInterface.Instance == null || SharedResources.Instance == null) | ||||
|         { | ||||
|             warningTimer += Time.deltaTime; | ||||
|             if(warningTimer > 2) | ||||
|             { | ||||
|                 warningTimer = 0; | ||||
|                 string report = $"AssetLibrary: {DanMachiAssetLibrary.Instance != null}\nModelBuilder: {DanMachiModelBuilder.Instance != null}\nInterface: {DanMachiInterface.Instance != null}\nResources: {SharedResources.Instance != null}"; | ||||
|                 Error.Log(report, Color.red); | ||||
|             } | ||||
|             yield return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void Update() | ||||
|     { | ||||
|         //AutoSaveUpdate(); | ||||
|     } | ||||
| } | ||||
| @@ -8,28 +8,65 @@ public class DanMachiModelBuilder : ModelBuilder | ||||
| { | ||||
|     public static DanMachiModelBuilder Instance => GetInstance<DanMachiModelBuilder>(); | ||||
|  | ||||
|     public override IEnumerator SpawnAsset(Enum assetType, string assetPath, Action<ObjectContainer> callback = null) | ||||
|     public override IEnumerator SpawnSerializedCoroutine(ObjectContainerSerializable oc, Action<ObjectContainer> callback = null) | ||||
|     { | ||||
|         yield return base.SpawnSerializedCoroutine(oc); | ||||
|  | ||||
|         switch (oc) | ||||
|         { | ||||
|             case DanMachiCharacterSerializable character: | ||||
|                 { | ||||
|                     var chara = SpawnAsset(AssetTypes.Character, character.AssetName); | ||||
|                     chara.DeserializeFrames(character); | ||||
|                     break; | ||||
|                 } | ||||
|             default: | ||||
|                 { | ||||
|                     Error.Log(Color.red, "Data not recognized: " + oc.Filename + " " + oc.GUID); | ||||
|                     break; | ||||
|                 } | ||||
|         } | ||||
|         yield break; | ||||
|     } | ||||
|  | ||||
|     public override ObjectContainer SpawnAsset(Enum assetType, string assetPath) | ||||
|     { | ||||
|         base.SpawnAsset(assetType, assetPath); | ||||
|  | ||||
|         switch (assetType) | ||||
|         { | ||||
|             case AssetTypes.Unknown: | ||||
|                 throw new NotImplementedException(); | ||||
|             case AssetTypes.Character: | ||||
|                 var asset = DanMachiAssetLibrary.Instance.Characters.First(c=>c.AssetName == assetPath); | ||||
|                 callback?.Invoke(SpawnCharacter(asset)); | ||||
|                 break; | ||||
|                 return SpawnCharacter(asset); | ||||
|             default: | ||||
|                 throw new NotImplementedException(); | ||||
|         } | ||||
|         yield break; | ||||
|     } | ||||
|  | ||||
|     public DanMachiCharacterContainer SpawnCharacter(CharacterAsset asset) | ||||
|     private DanMachiCharacterContainer SpawnCharacter(CharacterAsset asset) | ||||
|     { | ||||
|         var container = ObjectContainer.Create<DanMachiCharacterContainer>("Character"); | ||||
|         var handle = UIHandle.CreateAsChild<UIHandleMain>(container.transform).Init(container); | ||||
|         container.Build(asset); | ||||
|         container.PlayAnimation(container.Animations[0]); | ||||
|  | ||||
|         var animationSets = DanMachiAssetLibrary.Instance.Animations.Where(a => a.Category == asset.Category && a.Id == asset.Id); | ||||
|         var defaultAnimSet = animationSets.FirstOrDefault(a => a.Costume == "common"); | ||||
|         defaultAnimSet ??= animationSets.FirstOrDefault(); | ||||
|         if (defaultAnimSet != null) | ||||
|         { | ||||
|             var animSetDropdown = container.CharacterPanel.AnimationSetDropdown; | ||||
|             var option = animSetDropdown.options.FindIndex(d => d.text == defaultAnimSet.Costume); | ||||
|             if (option != -1) | ||||
|             { | ||||
|                 animSetDropdown.value = option; | ||||
|                 container.CharacterPanel.AnimationDropdown.value = 1; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         DanMachiMain.Instance.SelectObject(container); | ||||
|  | ||||
|         return container; | ||||
|     } | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| using System.Collections.Generic; | ||||
| using TMPro; | ||||
|  | ||||
| public class DanMachiModelViewerInterface : ModelViewerInterface | ||||
| { | ||||
|     public static DanMachiModelViewerInterface Instance => GetInstance<DanMachiModelViewerInterface>(); | ||||
|  | ||||
|     public CharacterDropdown CharacterSelection; | ||||
|     public UIToolbar SelectedObjectToolbar; | ||||
| } | ||||
| @@ -1,89 +0,0 @@ | ||||
| using System.Collections; | ||||
| using System.Linq; | ||||
| using UnityEngine; | ||||
|  | ||||
| [RequireComponent(typeof(DanMachiAssetLibrary), typeof(DanMachiModelBuilder), typeof(DanMachiModelViewerInterface))] | ||||
| public class DanMachiModelViewerMain : ModelViewerMain | ||||
| { | ||||
|     public static DanMachiModelViewerMain Instance => GetInstance<DanMachiModelViewerMain>(); | ||||
|  | ||||
|     protected DanMachiAssetLibrary _assets => DanMachiAssetLibrary.Instance; | ||||
|     protected DanMachiModelBuilder _modelBuilder => DanMachiModelBuilder.Instance; | ||||
|  | ||||
|     protected override void Awake() | ||||
|     { | ||||
|         CurrentScene = SceneContainer.Create<DanMachiSceneContainer>(this); | ||||
|         base.Awake(); | ||||
|     } | ||||
|  | ||||
|     private IEnumerator Start() | ||||
|     { | ||||
|         Application.targetFrameRate = 30; | ||||
|         Error.Log(Color.green, "Viewer version: " + Application.version); | ||||
|  | ||||
|         float warningTimer = 0; | ||||
|         while (DanMachiAssetLibrary.Instance == null || DanMachiModelBuilder.Instance == null || DanMachiModelViewerInterface.Instance == null || SharedResources.Instance == null) | ||||
|         { | ||||
|             warningTimer += Time.deltaTime; | ||||
|             if(warningTimer > 2) | ||||
|             { | ||||
|                 warningTimer = 0; | ||||
|                 string report = $"AssetLibrary: {DanMachiAssetLibrary.Instance != null}\nModelBuilder: {DanMachiModelBuilder.Instance != null}\nInterface: {DanMachiModelViewerInterface.Instance != null}\nResources: {SharedResources.Instance != null}"; | ||||
|                 Error.Log(report, Color.red); | ||||
|             } | ||||
|             yield return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void Update() | ||||
|     { | ||||
|         //AutoSaveUpdate(); | ||||
|     } | ||||
|  | ||||
|     public static void RegisterObject(DanMachiObjectContainer container) | ||||
|     { | ||||
|         Instance.CurrentScene.AllObjects.Add(container); | ||||
|     } | ||||
|  | ||||
|     public static void UnregisterObject(DanMachiObjectContainer container) | ||||
|     { | ||||
|         Instance.CurrentScene.AllObjects.Remove(container); | ||||
|     } | ||||
|  | ||||
|     public static void DisposeOf(GameObject go) | ||||
|     { | ||||
|         if (go == null) return; | ||||
|         var rends = go.GetComponentsInChildren<Renderer>(); | ||||
|         foreach (var rend in rends) | ||||
|         { | ||||
|             for (int i = rend.materials.Length - 1; i >= 0; i--) | ||||
|             { | ||||
|                 Destroy(rend.materials[i]); | ||||
|             } | ||||
|         } | ||||
|         Destroy(go); | ||||
|         UnityEngine.Resources.UnloadUnusedAssets(); | ||||
|         System.GC.Collect(); | ||||
|     } | ||||
|  | ||||
|     public IEnumerator LoadScene(DanMachiSceneSerializable bc) | ||||
|     { | ||||
|         EmptyScene<DanMachiSceneContainer>(); | ||||
|  | ||||
|         foreach (var c in bc.Objects) | ||||
|         { | ||||
|             if (c.GUID == "cameraOrbit") | ||||
|             { | ||||
|                 MainCameraOrbit.DeserializeFrames(c); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 yield return _modelBuilder.SpawnSerialized(c); | ||||
|             } | ||||
|         } | ||||
|         bc.Timeline.Deserialize(TimelineController.Instance); | ||||
|         CurrentScene.Frames = bc.Frames.Select(f => new FrameContent(f)).ToList(); | ||||
|         yield return 0; | ||||
|         TimelineController.SetCurrentFrame(TimelineController.Instance.CurrentFrame); | ||||
|     } | ||||
| } | ||||
| @@ -1,49 +0,0 @@ | ||||
| using UnityEngine; | ||||
|  | ||||
| public class DanMachiSceneContainer : SceneContainer | ||||
| { | ||||
|     public override KeyframeData SerializeFrame() | ||||
|     { | ||||
|         return new KeyframeData(); | ||||
|     } | ||||
|  | ||||
|     public override ObjectContainerSerializable Serialize() | ||||
|     { | ||||
|         return new SceneSerializable(this); | ||||
|     } | ||||
|  | ||||
|     public override void Lerp(KeyframeData frame1, KeyframeData frame2, float amount) | ||||
|     { | ||||
|         var frame = (frame1 as KeyframeData).Lerp(frame2, amount) as KeyframeData; | ||||
|     } | ||||
|  | ||||
|     protected override void OnDestroy() | ||||
|     { | ||||
|         if (_applicationQuitting) return; | ||||
|  | ||||
|         for (int i = AllObjects.Count - 1; i >= 0; i--) | ||||
|         { | ||||
|             var obj = AllObjects[i]; | ||||
|             if (obj.GetDataType() == DataType.Camera) | ||||
|             { | ||||
|                 Debug.Log("Destroying cam"); | ||||
|                 obj.Frames.Clear(); | ||||
|                 obj.SetDefaultFrame(); | ||||
|                 continue; | ||||
|             } | ||||
|             Destroy(obj.gameObject); | ||||
|         } | ||||
|  | ||||
|         base.OnDestroy(); | ||||
|     } | ||||
|  | ||||
|     public override void Select() | ||||
|     { | ||||
|         //Settings.gameObject.SetActive(true); | ||||
|     } | ||||
|  | ||||
|     public override void Deselect() | ||||
|     { | ||||
|         //Settings.gameObject.SetActive(false); | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +0,0 @@ | ||||
| using System; | ||||
|  | ||||
| [Serializable] | ||||
| public class DanMachiSceneSerializable : SceneSerializable | ||||
| { | ||||
| } | ||||
| @@ -1,21 +1,8 @@ | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using UnityEngine; | ||||
|  | ||||
| namespace Unity.Animations.SpringBones | ||||
| { | ||||
|     public class SpringBone : MonoBehaviour | ||||
|     { | ||||
|         // Start is called before the first frame update | ||||
|         void Start() | ||||
|         { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // Update is called once per frame | ||||
|         void Update() | ||||
|         { | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,8 @@ | ||||
| using UnityEngine; | ||||
|  | ||||
| namespace Unity.Animations.SpringBones | ||||
| { | ||||
|     public class SpringCapsuleCollider : MonoBehaviour | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: c04af4c8b1b74df4783e6f4815bd909f | ||||
| guid: 572171c99ddfc0542b942432884ec564 | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
							
								
								
									
										8
									
								
								Assets/DanMachi/Scripts/SpringBone/SpringManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Assets/DanMachi/Scripts/SpringBone/SpringManager.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| using UnityEngine; | ||||
|  | ||||
| namespace Unity.Animations.SpringBones | ||||
| { | ||||
|     public class SpringManager : MonoBehaviour | ||||
|     { | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								Assets/DanMachi/Scripts/SpringBone/SpringManager.cs.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Assets/DanMachi/Scripts/SpringBone/SpringManager.cs.meta
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: eebc1635655c1984b999d5430c8d3ce0 | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
|   defaultReferences: [] | ||||
|   executionOrder: 0 | ||||
|   icon: {instanceID: 0} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
| @@ -0,0 +1,8 @@ | ||||
| using UnityEngine; | ||||
|  | ||||
| namespace Unity.Animations.SpringBones | ||||
| { | ||||
|     public class SpringSphereCollider : MonoBehaviour | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| fileFormatVersion: 2 | ||||
| guid: a181323294f10e14faef8a3238a3bf5f | ||||
| MonoImporter: | ||||
|   externalObjects: {} | ||||
|   serializedVersion: 2 | ||||
|   defaultReferences: [] | ||||
|   executionOrder: 0 | ||||
|   icon: {instanceID: 0} | ||||
|   userData:  | ||||
|   assetBundleName:  | ||||
|   assetBundleVariant:  | ||||
| @@ -60,32 +60,33 @@ public class CharacterDropdown : MonoBehaviour | ||||
|  | ||||
|         UnityAction<int> groupCallback = (index) => | ||||
|         { | ||||
|             if (index == 0) return; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 SetDropdownData(1, null); | ||||
|                 Despawn(); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             var category = GetOption(0); | ||||
|             SetDropdownData(1, characters.Where(c => c.Category == category).Select(c => c.Id).Distinct().ToList(), true, true); | ||||
|             //SetDropdownData(2, new List<string>(), true, true); | ||||
|         }; | ||||
|  | ||||
|         UnityAction<int> charaCallback = (index) => | ||||
|         { | ||||
|             if (index == 0) return; | ||||
|             if (index == 0) | ||||
|             { | ||||
|                 Despawn(); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             var category = GetOption(0); | ||||
|             var id = GetOption(1); | ||||
|             var costumes = characters.Where(c => c.Category == category && c.Id == id); | ||||
|             var costume = costumes.FirstOrDefault(c => c.Costume == "common"); | ||||
|             costume ??= costumes.First(); | ||||
|             DanMachiModelBuilder.Instance.SpawnCharacter(costume); | ||||
|             //SetDropdownData(2, characters.Where(c => c.Category == category && c.Id == id).Select(c => c.Costume).ToList(), true, true); | ||||
|             DanMachiModelBuilder.Instance.SpawnAsset(AssetTypes.Character, costume.AssetName); | ||||
|         }; | ||||
|  | ||||
|         //UnityAction<int> costumeCallback = (index) => | ||||
|         //{ | ||||
|         //    var chara = DanMachiAssetLibrary.Instance.GetCharacter(GetOption(0), GetOption(1), GetOption(2)); | ||||
|         //    StartCoroutine(DanMachiModelBuilder.Instance.SpawnAsset(AssetTypes.Character, chara)); | ||||
|         //}; | ||||
|  | ||||
|         SetCallbacks(new List<UnityAction<int>>() | ||||
|         { | ||||
|             groupCallback, | ||||
| @@ -113,7 +114,7 @@ public class CharacterDropdown : MonoBehaviour | ||||
|         { | ||||
|             Debug.LogError("Delete Current"); | ||||
|         } | ||||
|         StartCoroutine(ModelBuilder.GetInstance().SpawnAsset(AssetTypes.Character, MainDropdown.options[selection].text)); | ||||
|         StartCoroutine(ModelBuilder.GetInstance().SpawnAssetCoroutine(AssetTypes.Character, MainDropdown.options[selection].text)); | ||||
|     } | ||||
|  | ||||
|     public void SetDropdownData(string label, List<string> options, bool nullValue = false, bool sortValues = false) | ||||
| @@ -122,12 +123,6 @@ public class CharacterDropdown : MonoBehaviour | ||||
|         SetDropdownData(depth, options, nullValue, sortValues); | ||||
|     } | ||||
|  | ||||
|     public string GetOption(int depth) | ||||
|     { | ||||
|         if (Dropdowns[depth].value == 0) return null; | ||||
|         return Dropdowns[depth].options[Dropdowns[depth].value].text; | ||||
|     } | ||||
|  | ||||
|     public void SetDropdownData(int depth, List<string> options, bool nullValue = false, bool sortValues = false) | ||||
|     { | ||||
|         if (depth >= Dropdowns.Count || depth < 0) | ||||
| @@ -137,4 +132,42 @@ public class CharacterDropdown : MonoBehaviour | ||||
|         } | ||||
|         ModelViewerInterface.SetDropdownData(Dropdowns[depth], options, nullValue, sortValues); | ||||
|     } | ||||
|  | ||||
|     public void SelectDropdownData(int depth, string valueText, bool notify) | ||||
|     { | ||||
|         var dropdown = Dropdowns[depth]; | ||||
|         var value = dropdown.options.FindIndex(d=>d.text == valueText); | ||||
|         SelectDropdownData(depth, value, notify); | ||||
|     } | ||||
|  | ||||
|     public void SelectDropdownData(int depth, int value, bool notify) | ||||
|     { | ||||
|         if (value == -1) return; | ||||
|  | ||||
|         var dropdown = Dropdowns[depth]; | ||||
|  | ||||
|         if (notify) | ||||
|         { | ||||
|             dropdown.value = value; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             dropdown.SetValueWithoutNotify(value); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public string GetOption(int depth) | ||||
|     { | ||||
|         if (Dropdowns[depth].value == 0) return null; | ||||
|         return Dropdowns[depth].options[Dropdowns[depth].value].text; | ||||
|     } | ||||
|  | ||||
|     private void Despawn() | ||||
|     { | ||||
|         var selected = ModelViewerMain.GetInstance().SelectedObject; | ||||
|         if (selected != null) | ||||
|         { | ||||
|             selected.Destroy(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,9 +28,10 @@ public class CharacterPanel : MonoBehaviour | ||||
|     { | ||||
|         var pose = _selectedChara.SerializeFrame(); | ||||
|         var data = _selectedChara.Data; | ||||
|         var newData = DanMachiAssetLibrary.Instance.Characters.First(c => c.Category == data.Category && c.Id == data.Id && c.Costume == CostumeDropdown.options[value].text); | ||||
|         var chara = DanMachiModelBuilder.Instance.SpawnCharacter(newData); | ||||
|         chara.PastePose(pose, PoseLoadOptions.All()); | ||||
|         _selectedChara.Rebuild(DanMachiAssetLibrary.Instance.Characters.First(c => c.Category == data.Category && c.Id == data.Id && c.Costume == CostumeDropdown.options[value].text)); | ||||
|         //var newData = DanMachiAssetLibrary.Instance.Characters.First(c => c.Category == data.Category && c.Id == data.Id && c.Costume == CostumeDropdown.options[value].text); | ||||
|         //var chara = DanMachiModelBuilder.Instance.SpawnAsset(AssetTypes.Character, newData.AssetName); | ||||
|         _selectedChara.PastePose(pose, PoseLoadOptions.All()); | ||||
|     } | ||||
|  | ||||
|     public void SelectAnimationSet(int value) | ||||
| @@ -38,6 +39,7 @@ public class CharacterPanel : MonoBehaviour | ||||
|         if(value == 0) | ||||
|         { | ||||
|             AnimationDropdown.SetOptions(null); | ||||
|             _selectedChara.PlayAnimation((AnimationClip)null); | ||||
|             return; | ||||
|         } | ||||
|         var data = _selectedChara.Data; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user