FateViewer/Assets/Scripts/FateModelBuilder.cs

459 lines
18 KiB
C#

using System.Collections;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class FateModelBuilder : MonoBehaviour
{
public Material ParticleMaterial;
public static FateModelBuilder Instance;
public bool LoadingInProgress = false;
public AnimatorOverrideController AnimatorController;
private void Awake()
{
Instance = this;
}
public IEnumerator ReplaceServant(string id)
{
if (LoadingInProgress)
{
Error.Log(Color.red, "Loading already in progress!");
yield break;
}
if (FateViewerMain.SelectedServant != null)
{
FateViewerMain.SelectedServant.DeleteModel();
}
yield return LoadServant(id);
}
public IEnumerator LoadServant(string id)
{
if (LoadingInProgress) yield break;
LoadingInProgress = true;
var Servants = FateViewerMain.Instance.Servants;
int idNum = int.Parse(id);
var urlBase = $"{FateViewerMain.AAContent}Servants/{idNum}";
var costume = Servants.GetAllCostumes().FirstOrDefault(s => s.battleCharaId == idNum);
if (costume != null)
{
var servant = Servants.Entries.First(s => s.costumes.Contains(costume));
var lcButt = UIController.Instance.LoadedCharaButton;
lcButt.GetComponentInChildren<TMPro.TextMeshProUGUI>().text = servant.name + " - AA database";
lcButt.GetComponentInChildren<Button>().onClick.RemoveAllListeners();
lcButt.GetComponentInChildren<Button>().onClick.AddListener(() => UIController.Instance.OpenUrl("https://apps.atlasacademy.io/db/JP/servant/" + servant.collectionNo));
}
AssetBundle assetBundle = null;
string url = $"{urlBase}/{idNum}";
yield return FateAssetManager.DownloadBundle(url, (cb) =>
{
assetBundle = cb;
});
if (assetBundle == null)
{
Error.Log(Color.red, "Loading assetbundle failed!");
LoadingInProgress = false;
yield break;
}
StartCoroutine(BuildModel(assetBundle, urlBase));
}
public void ReplaceTexture()
{
StartCoroutine(ReplaceTexture1());
}
private IEnumerator ReplaceTexture1()
{
if (!FateViewerMain.SelectedServant)
{
Error.Log(Color.red, "No servant loaded!");
UIController.Instance.ReactivateTextureLoad();
yield break;
}
var uploader = WebGLUpDownExamples._webGLUpload;
var newMat = new Material(Shader.Find("Legacy Shaders/Diffuse"));
//var targetMaterial = Materials.FirstOrDefault(m=>m.mainTexture.name )
uploader.UploadTexture(WebGLUpload.ImageFormat.png, 0, true, newMat);
do
{
yield return new WaitForEndOfFrame();
}
while (!uploader.TextureReady);
uploader.TextureReady = false;
Debug.Log($"file {newMat.mainTexture.name} loaded");
foreach (var mat in FateViewerMain.SelectedServant.Materials)
{
if (mat.mainTexture.name == newMat.mainTexture.name)
{
mat.mainTexture = newMat.mainTexture;
}
}
Destroy(newMat);
UIController.Instance.ReactivateTextureLoad();
}
public IEnumerator BuildModel(AssetBundle assetBundle, string modelUrl)
{
if (assetBundle == null)
{
Error.Log(Color.red, "Asset load fail");
Debug.LogError("Asset load fail");
LoadingInProgress = false;
assetBundle.Unload(true);
yield break;
}
FateServantContainer servant = new GameObject().AddComponent<FateServantContainer>();
servant.name = assetBundle.name;
foreach (var asset in assetBundle.LoadAllAssets())
{
if (asset == null) { continue; }
else if (asset.GetType() == typeof(GameObject))
{
if((asset as GameObject).name == "chr")
{
servant.BodyMain = asset as GameObject;
}
}
else if (asset.GetType() == typeof(Texture2D))
{
Texture2D tex = asset as Texture2D;
servant.Textures.Add(tex);
}
else if (asset.GetType() == typeof(Material))
{
servant.Materials.Add(asset as Material);
}
else if (asset.GetType() == typeof(TextAsset))
{
}
else if (asset.GetType() == typeof(AnimationClip))
{
}
else
{
//Error.Log(Color.yellow, asset.GetType().ToString());
//Debug.LogWarning(asset.GetType());
}
}
UIController.Instance.CutoffSlider?.onValueChanged.RemoveAllListeners();
foreach (Material mat in servant.Materials)
{
if (mat.shader.name.Contains("Particle"))
{
mat.shader = Shader.Find("Particles/Standard Unlit");
var tex = mat.mainTexture;
var color = mat.color;
mat.CopyPropertiesFromMaterial(ParticleMaterial);
mat.mainTexture = tex;
mat.color = color;
}
else
{
mat.shader = Shader.Find("FateShader3Compatible");
if (mat.mainTexture != null)
{
var texture = servant.Textures.FirstOrDefault(t => t.name == mat.mainTexture.name);
if (texture != null)
{
mat.SetTexture("_MainTex", texture);
}
else
{
Error.Log(Color.red, $"Texture {mat.mainTexture.name} not found");
}
var alpha = servant.Textures.FirstOrDefault(t => t.name == mat.mainTexture.name + "a" || t.name == mat.mainTexture.name + "_alpha");
if (alpha)
{
mat.SetTexture("_Alpha", alpha);
}
}
Material temp = mat;
mat.SetFloat("_Cutoff", 0.91f);
UIController.Instance.CutoffSlider?.onValueChanged.AddListener((value) => { temp.SetFloat("_Cutoff", value / 100);});
}
}
if(servant.BodyMain == null)
{
Error.Log(Color.red, "Servant body was not loaded");
assetBundle.Unload(true);
LoadingInProgress = false;
yield break;
}
servant.BodyMain = Instantiate(servant.BodyMain, servant.transform);
servant.InstantiatedObjects.Add(servant.BodyMain);
var simpleAnimation = servant.GetComponentInChildren<SimpleAnimation>();
simpleAnimation.enabled = false;
servant.AnimationClips.AddRange(simpleAnimation.GetStates());
servant.Animator = servant.BodyMain.GetComponentInChildren<Animator>();
if (servant.Animator)
{
servant.OverrideController = new AnimatorOverrideController(AnimatorController);
servant.OverrideController["clip"] = null;
servant.Animator.speed = 0;
servant.Animator.runtimeAnimatorController = servant.OverrideController;
servant.Animator.Play(null);
}
GameObject MeshToggle = Resources.Load("MeshToggle") as GameObject;
var meshes = servant.Meshes = servant.BodyMain.GetComponentsInChildren<Renderer>().ToList();
for (int i = 0; i < meshes.Count; i++)
{
int meshId = i;
GameObject go = Instantiate(MeshToggle, UIController.Instance.MeshesListContent);
servant.InstantiatedObjects.Add(go);
go.GetComponentInChildren<TMPro.TextMeshProUGUI>().text = meshes[i].name;
if (meshes[i].enabled)
{
string[] splitName = meshes[i].name.Split('_');
if (splitName.Length >= 3)
{
//Debug.LogWarning(meshes[i].name);
string partName = splitName[0];
var sameParts = meshes.Where(r => r.name.Split('_').Length >= 3).Where(r => r.name.Split('_')[0] == partName);
var bestPart = sameParts.OrderBy(r => r.name.Split('_')[2]).Reverse().Take(1);
//Debug.LogWarning(sameParts.Count());
foreach (var part in sameParts.Except(bestPart))
{
part.enabled = false;
}
}
}
go.GetComponentInChildren<Toggle>().isOn = meshes[i].enabled;
go.GetComponentInChildren<Toggle>().onValueChanged.AddListener((value) => meshes[meshId].enabled = value);
}
FateViewerMain.Instance.SpawnedServants.Add(servant);
FateViewerMain.SelectedServant = servant;
UIController.Instance.SetBodyAnimationDropdownData(servant.AnimationClips.Select(a => a.name).ToList());
var animId = UIController.Instance.BodyAnimationDropdown.options.IndexOf(UIController.Instance.BodyAnimationDropdown.options.FirstOrDefault(a => a.text == "Default"));
UIController.Instance.BodyAnimationDropdown.SetValueWithoutNotify(animId);
servant.PlayAnimation("Default");
assetBundle.Unload(false);
CenterCamera();
LoadingInProgress = false;
}
public IEnumerator BuildNP(AssetBundle assetBundle)
{
if (assetBundle == null)
{
Error.Log(Color.red, "Asset load fail");
Debug.LogError("Asset load fail");
LoadingInProgress = false;
assetBundle.Unload(true);
yield break;
}
FateServantContainer servant = new GameObject().AddComponent<FateServantContainer>();
servant.name = assetBundle.name;
foreach (var asset in assetBundle.LoadAllAssets())
{
if (asset == null) { continue; }
else if (asset.GetType() == typeof(GameObject))
{
if (asset.name.StartsWith("chr_"))
{
servant.BodyMain = asset as GameObject;
}
else if (asset.name.StartsWith("model_"))
{
Instantiate(asset, servant.transform);
}
}
else if (asset.GetType() == typeof(Texture2D))
{
Texture2D tex = asset as Texture2D;
servant.Textures.Add(tex);
}
else if (asset.GetType() == typeof(Material))
{
servant.Materials.Add(asset as Material);
}
else if (asset.GetType() == typeof(TextAsset))
{
}
else if (asset.GetType() == typeof(AnimationClip))
{
}
else
{
Error.Log(Color.yellow, asset.GetType().ToString());
Debug.LogWarning(asset.GetType());
}
}
UIController.Instance.CutoffSlider?.onValueChanged.RemoveAllListeners();
foreach (Material mat in servant.Materials)
{
if (mat.shader.name.Contains("Particle"))
{
mat.shader = Shader.Find("Particles/Standard Unlit");
var tex = mat.mainTexture;
var color = mat.color;
mat.CopyPropertiesFromMaterial(ParticleMaterial);
mat.mainTexture = tex;
mat.color = color;
}
else
{
mat.shader = Shader.Find("FateShader3Compatible");
if (mat.mainTexture != null)
{
var texture = servant.Textures.FirstOrDefault(t => t.name == mat.mainTexture.name);
if (texture != null)
{
mat.SetTexture("_MainTex", texture);
}
else
{
Error.Log(Color.red, $"Texture {mat.mainTexture.name} not found");
}
var alpha = servant.Textures.FirstOrDefault(t => t.name == mat.mainTexture.name + "a" || t.name == mat.mainTexture.name + "_alpha");
if (alpha)
{
mat.SetTexture("_Alpha", alpha);
}
}
Material temp = mat;
mat.SetFloat("_Cutoff", 0.91f);
UIController.Instance.CutoffSlider?.onValueChanged.AddListener((value) => { temp.SetFloat("_Cutoff", value / 100); });
}
}
if (servant.BodyMain == null)
{
Error.Log(Color.red, "Servant body was not loaded");
assetBundle.Unload(true);
LoadingInProgress = false;
yield break;
}
servant.BodyMain = Instantiate(servant.BodyMain, servant.transform);
servant.InstantiatedObjects.Add(servant.BodyMain);
servant.BodyMain.SetActive(true);
var simpleAnimation = servant.GetComponentInChildren<SimpleAnimation>();
simpleAnimation.enabled = false;
servant.AnimationClips.AddRange(simpleAnimation.GetStates());
servant.Animator = servant.BodyMain.GetComponentInChildren<Animator>();
if (servant.Animator)
{
servant.OverrideController = new AnimatorOverrideController(AnimatorController);
servant.OverrideController["clip"] = null;
servant.Animator.speed = 0;
servant.Animator.runtimeAnimatorController = servant.OverrideController;
servant.Animator.Play(null);
}
//GameObject MeshToggle = Resources.Load("MeshToggle") as GameObject;
//var meshes = servant.Meshes = servant.BodyMain.GetComponentsInChildren<Renderer>().ToList();
//for (int i = 0; i < meshes.Count; i++)
//{
// int meshId = i;
// GameObject go = Instantiate(MeshToggle, UIController.Instance.MeshesListContent);
// servant.InstantiatedObjects.Add(go);
// go.GetComponentInChildren<TMPro.TextMeshProUGUI>().text = meshes[i].name;
// if (meshes[i].enabled)
// {
// string[] splitName = meshes[i].name.Split('_');
// if (splitName.Length >= 3)
// {
// string partName = splitName[0];
// var sameParts = meshes.Where(r => r.name.Split('_').Length >= 3).Where(r => r.name.Split('_')[0] == partName);
// var bestPart = sameParts.OrderBy(r => r.name.Split('_')[2]).Reverse().Take(1);
// foreach (var part in sameParts.Except(bestPart))
// {
// part.enabled = false;
// }
// }
// }
// go.GetComponentInChildren<Toggle>().isOn = meshes[i].enabled;
// go.GetComponentInChildren<Toggle>().onValueChanged.AddListener((value) => meshes[meshId].enabled = value);
//}
FateViewerMain.Instance.SpawnedServants.Add(servant);
FateViewerMain.SelectedServant = servant;
UIController.Instance.SetBodyAnimationDropdownData(servant.AnimationClips.Select(a => a.name).ToList());
var animId = 0;
UIController.Instance.BodyAnimationDropdown.SetValueWithoutNotify(animId);
servant.PlayAnimation("Default");
assetBundle.Unload(false);
CenterCamera();
LoadingInProgress = false;
}
public void CenterCamera()
{
/*
foreach (Transform t in MainBone)
{
AnimBounds.Encapsulate(new Bounds(t.transform.position, Vector3.one * 1.5f));
}
Bounds AnimBounds = CharaModel.GetComponentInChildren<SkinnedMeshRenderer>().bounds; //CharaModel.GetComponentInChildren<SkinnedMeshRenderer>().localBounds;
foreach (var renderer in CharaModel.GetComponentsInChildren<SkinnedMeshRenderer>())
{
AnimBounds.Encapsulate(renderer.bounds);
}
Camera.main.transform.position = new Vector3(-5, AnimBounds.center.y, 0);
Camera.main.transform.eulerAngles = new Vector3(0, 90, 0);
var orbit = GameObject.FindObjectOfType<CameraOrbit>();
var max = Mathf.Max(AnimBounds.size.x, AnimBounds.size.y, AnimBounds.size.z);
orbit.camZoom = max / 2;
orbit.camZoomMax = max > 15 ? max : 15;
orbit.camZoomMin = 0.2f;
*/
var orbit = GameObject.FindObjectOfType<CameraOrbit>();
orbit.camZoom = 1.5f;
orbit.camZoomMax = 500;
orbit.camZoomMin = 0.2f;
Camera.main.transform.eulerAngles = new Vector3(0, 90, 0);
Camera.main.transform.position = new Vector3(-5, 1, 0);
}
//public IEnumerator CreateRuntimeMask()
//{
// //GameObject activeGameObject = CharaModel;
// //AvatarMask avatarMask = new AvatarMask();
// //avatarMask.AddTransformPath(activeGameObject.transform);
// //var layers = OriginalController.layers;
// //layers[1].avatarMask = avatarMask;
// //OriginalController.layers = layers;
// //Animator.runtimeAnimatorController = OriginalController;
// //for (int i = 0; i < avatarMask.transformCount; i++)
// //{
// // bool value = avatarMask.GetTransformPath(i).Contains("joint_eye") || avatarMask.GetTransformPath(i).Contains("joint_mouth");
// // avatarMask.SetTransformActive(i, value);
// //}
// //OverrideController = new AnimatorOverrideController(Animator.runtimeAnimatorController);
// //Animator.runtimeAnimatorController = OverrideController;
// yield return PlayAnimation("Default");
// yield return PlayAnimationLayer2("Default");
//}
}