Files
UmaViewer/Assets/Scripts/UmaViewerBuilder.cs
T

988 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using CriWareFormats;
using Gallop;
using NAudio.Wave;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using UmaMusumeAudio;
using UnityEngine;
using UnityEngine.SceneManagement;
using Debug = UnityEngine.Debug;
using Random = UnityEngine.Random;
public class UmaViewerBuilder : MonoBehaviour
{
public static UmaViewerBuilder Instance;
public static UmaViewerMain Main => UmaViewerMain.Instance;
UmaViewerUI UI => UmaViewerUI.Instance;
public List<AssetBundle> Loaded;
public List<Shader> ShaderList = new List<Shader>();
public Material TransMaterialCharas;
public Material TransMaterialProps;
public UmaContainerCharacter CurrentUMAContainer;
public UmaContainer CurrentOtherContainer;
public UmaHeadData CurrentHead;
public List<AudioSource> CurrentAudioSources = new List<AudioSource>();
public List<UmaLyricsData> CurrentLyrics = new List<UmaLyricsData>();
public AnimatorOverrideController OverrideController;
public AnimatorOverrideController FaceOverrideController;
public AnimatorOverrideController CameraOverrideController;
public Animator AnimationCameraAnimator;
public Camera AnimationCamera;
public GameObject LiveControllerPrefab;
private bool ShadersLoaded = false;
private void Awake()
{
Instance = this;
}
public IEnumerator LoadUma(CharaEntry chara, string costumeId, bool mini)
{
int id = chara.Id;
var umaContainer = new GameObject($"Chara_{id}_{costumeId}").AddComponent<UmaContainerCharacter>();
umaContainer.CharaEntry = chara;
CurrentUMAContainer = umaContainer;
if (mini)
{
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(chara);
LoadMiniUma(umaContainer, chara, costumeId);
}
else if (chara.IsMob)
{
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(chara);
LoadMobUma(umaContainer, chara, costumeId, loadMotion: true);
}
else if (UI.isHeadFix && CurrentHead != null && CurrentHead.chara.IsMob)
{
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(CurrentHead.chara);
LoadMobUma(umaContainer, CurrentHead.chara, costumeId, chara.Id, true);
}
else
{
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(chara);
LoadNormalUma(umaContainer, chara, costumeId, true);
}
yield break;
}
public void LoadLiveUma(List<LiveCharacterSelect> characters)
{
UmaAssetManager.UnloadAllBundle();
for (int i = 0; i < characters.Count; i++)
{
if (characters[i].CharaEntry.Name != "")
{
var umaContainer = new GameObject($"Chara_{characters[i].CharaEntry.Id}_{characters[i].CostumeId}").AddComponent<UmaContainerCharacter>();
if (characters[i].CharaEntry.IsMob)
{
umaContainer.IsLive = true;
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(characters[i].CharaEntry);
umaContainer.transform.parent = Gallop.Live.Director.instance.charaObjs[i];
umaContainer.transform.localPosition = new Vector3();
LoadMobUma(umaContainer, characters[i].CharaEntry, characters[i].CostumeId);
}
else
{
umaContainer.IsLive = true;
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(characters[i].CharaEntry);
umaContainer.transform.parent = Gallop.Live.Director.instance.charaObjs[i];
umaContainer.transform.localPosition = new Vector3();
LoadNormalUma(umaContainer, characters[i].CharaEntry, characters[i].CostumeId);
}
Gallop.Live.Director.instance.CharaContainerScript.Add(umaContainer);
}
}
}
private void LoadNormalUma(UmaContainerCharacter umaContainer, CharaEntry chara, string costumeId, bool loadMotion = false)
{
int id = chara.Id;
DataRow charaData = umaContainer.CharaData;
bool genericCostume = umaContainer.IsGeneric = costumeId.Length >= 4;
string skin, height, socks, bust, sex, shape, costumeIdShort = "";
skin = charaData["skin"].ToString();
height = charaData["height"].ToString();
socks = charaData["socks"].ToString();
bust = charaData["bust"].ToString();
sex = charaData["sex"].ToString();
shape = charaData["shape"].ToString();
UmaDatabaseEntry asset = null;
if (genericCostume)
{
costumeIdShort = costumeId.Remove(costumeId.LastIndexOf('_'));
umaContainer.VarCostumeIdShort = costumeIdShort;
umaContainer.VarCostumeIdLong = costumeId;
umaContainer.VarBust = bust;
umaContainer.VarSkin = skin;
umaContainer.VarSocks = socks;
umaContainer.VarHeight = height;
// Pattern for generic body type is as follows:
//
// (costume id)_(body_type_sub)_(body_setting)_(height)_(shape)_(bust)
//
// body_type_sub is used for variants like the summer/winter uniform or the swimsuit/towel
// body_setting is used for subvariants of each variant like the big belly version of the uniform, and the genders for the tracksuits
//
// Some models will naturally be missing due to how this system is designed.
string body = UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/pfb_bdy{costumeId}_{height}_{shape}_{bust}";
UmaViewerMain.Instance.AbList.TryGetValue(body, out asset);
}
else UmaViewerMain.Instance.AbList.TryGetValue(UmaDatabaseController.BodyPath + $"bdy{id}_{costumeId}/pfb_bdy{id}_{costumeId}", out asset);
if (asset == null)
{
Debug.LogError("No body, can't load!");
return;
}
else if (genericCostume)
{
string texPattern1 = "", texPattern2 = "", texPattern3 = "", texPattern4 = "", texPattern5 = "";
switch (costumeId.Split('_')[0])
{
case "0001":
texPattern1 = $"tex_bdy{costumeIdShort}_00_{skin}_{bust}_0{socks}";
texPattern2 = $"tex_bdy{costumeIdShort}_00_0_{bust}";
texPattern3 = $"tex_bdy{costumeIdShort}_zekken";
texPattern4 = $"tex_bdy{costumeIdShort}_00_waku";
texPattern5 = $"tex_bdy{costumeIdShort}_num";
break;
case "0003":
texPattern1 = $"tex_bdy{costumeIdShort}_00_{skin}_{bust}";
texPattern2 = $"tex_bdy{costumeIdShort}_00_0_{bust}";
break;
case "0006": //last var is color?
texPattern1 = $"tex_bdy{costumeId}_{skin}_{bust}_0{0}";
texPattern2 = $"tex_bdy{costumeId}_0_{bust}_00_";
break;
default:
texPattern1 = $"tex_bdy{costumeId}_{skin}_{bust}";
texPattern2 = $"tex_bdy{costumeId}_0_{bust}";
break;
}
Debug.Log(texPattern1 + " " + texPattern2);
//Load Body Textures
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith(UmaDatabaseController.BodyPath)
&& (a.Name.Contains(texPattern1)
|| a.Name.Contains(texPattern2)
|| (string.IsNullOrEmpty(texPattern3) ? false : a.Name.Contains(texPattern3))
|| (string.IsNullOrEmpty(texPattern4) ? false : a.Name.Contains(texPattern4))
|| (string.IsNullOrEmpty(texPattern5) ? false : a.Name.Contains(texPattern5)))))
{
umaContainer.LoadTextures(asset1);
}
//Load Body
umaContainer.LoadBody(asset);
//Load Physics
if (Main.AbList.TryGetValue(UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/clothes/pfb_bdy{costumeIdShort}_cloth00", out _))
{
var asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/clothes/pfb_bdy{costumeIdShort}_cloth00"];
umaContainer.LoadPhysics(asset1);
asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/clothes/pfb_bdy{costumeIdShort}_bust{bust}_cloth00"];
umaContainer.LoadPhysics(asset1);
}
}
else
{
umaContainer.LoadBody(asset);
//Load Physics
var asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{id}_{costumeId}/clothes/pfb_bdy{id}_{costumeId}_cloth00"];
umaContainer.LoadPhysics(asset1);
asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{id}_{costumeId}/clothes/pfb_bdy{id}_{costumeId}_bust_cloth00"];
umaContainer.LoadPhysics(asset1);
}
// Record Head Data
int head_id;
string head_costumeId;
int tailId = Convert.ToInt32(charaData["tail_model_id"]);
if (UI.isHeadFix && CurrentHead != null)
{
head_id = CurrentHead.id;
head_costumeId = CurrentHead.costumeId;
tailId = CurrentHead.tailId;
}
else
{
head_id = id;
head_costumeId = costumeId;
CurrentHead = new UmaHeadData
{
id = id,
costumeId = costumeId,
tailId = tailId,
chara = chara
};
}
string head = UmaDatabaseController.HeadPath + $"chr{head_id}_{head_costumeId}/pfb_chr{head_id}_{head_costumeId}";
asset = null;
Main.AbList.TryGetValue(head, out asset);
bool isDefaultHead = false;
//Some costumes don't have custom heads
if (head_costumeId != "00" && asset == null)
{
asset = Main.AbList[UmaDatabaseController.HeadPath + $"chr{head_id}_00/pfb_chr{head_id}_00"];
isDefaultHead = true;
}
if (asset != null)
{
//Load Hair Textures
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"{UmaDatabaseController.HeadPath}chr{head_id}_{head_costumeId}/textures")))
{
umaContainer.LoadTextures(asset1);
}
//Load Head
umaContainer.LoadHead(asset);
//Load Physics
if (isDefaultHead)
{
var asset1 = Main.AbList[UmaDatabaseController.HeadPath + $"chr{id}_00/clothes/pfb_chr{id}_00_cloth00"];
umaContainer.LoadPhysics(asset1);
}
else
{
var asset1 = Main.AbList[UmaDatabaseController.HeadPath + $"chr{head_id}_{head_costumeId}/clothes/pfb_chr{head_id}_{head_costumeId}_cloth00"];
umaContainer.LoadPhysics(asset1);
}
}
if (tailId != 0)
{
string tailName = $"tail{tailId.ToString().PadLeft(4, '0')}_00";
string tailPath = $"3d/chara/tail/{tailName}/";
string tailPfb = tailPath + $"pfb_{tailName}";
asset = null;
Main.AbList.TryGetValue(tailPfb, out asset);
if (asset != null)
{
foreach (var asset2 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"{tailPath}textures/tex_{tailName}_{head_id}") || a.Name.StartsWith($"{tailPath}textures/tex_{tailName}_0000")))
{
umaContainer.LoadTextures(asset2);
}
umaContainer.LoadTail(asset);
//Load Physics
var asset1 = Main.AbList[$"{tailPath}clothes/pfb_{tailName}_cloth00"];
umaContainer.LoadPhysics(asset1);
}
else
{
Debug.Log("no tail");
}
}
umaContainer.LoadPhysics();
umaContainer.SetDynamicBoneEnable(UI.DynamicBoneEnable);
umaContainer.LoadFaceMorph(id, costumeId);
umaContainer.TearControllers.ForEach(a => a.SetDir(a.CurrentDir));
umaContainer.HeadBone = (GameObject)umaContainer.Body.GetComponent<AssetHolder>()._assetTable["head"];
umaContainer.EyeHeight = umaContainer.Head.GetComponent<AssetHolder>()._assetTableValue["head_center_offset_y"];
umaContainer.MergeModel();
umaContainer.SetHeight(-1);
umaContainer.Initialize(!UI.isTPose);
umaContainer.Position = umaContainer.transform.Find("Position");
if (!UI.isTPose && loadMotion)
{
if (Main.AbList.TryGetValue($"3d/motion/event/body/chara/chr{id}_00/anm_eve_chr{id}_00_idle01_loop", out UmaDatabaseEntry entry))
{
umaContainer.LoadAnimation(entry);
}
}
}
private void LoadMobUma(UmaContainerCharacter umaContainer, CharaEntry chara, string costumeId, int bodyid = -1, bool loadMotion = false)
{
int id = chara.Id;
umaContainer.IsMob = chara.IsMob;
umaContainer.MobDressColor = UmaDatabaseController.ReadMobDressColor(umaContainer.CharaData["dress_color_id"].ToString());
umaContainer.MobHeadColor = UmaDatabaseController.ReadMobHairColor(umaContainer.CharaData["chara_hair_color"].ToString());
DataRow charaData = umaContainer.CharaData;
bool genericCostume = umaContainer.IsGeneric = costumeId.Length >= 4;
string skin, height, socks, bust, sex, shape, costumeIdShort = "";
string faceid, hairid, personality;
faceid = charaData["chara_face_model"].ToString();
hairid = charaData["chara_hair_model"].ToString();
personality = charaData["default_personality"].ToString();
skin = charaData["chara_skin_color"].ToString();
height = "0";
socks = charaData["socks"].ToString();
bust = charaData["chara_bust_size"].ToString();
sex = charaData["sex"].ToString();
shape = "0";
UmaDatabaseEntry asset = null;
if (genericCostume)
{
costumeIdShort = costumeId.Remove(costumeId.LastIndexOf('_'));
umaContainer.VarCostumeIdShort = costumeIdShort;
umaContainer.VarCostumeIdLong = costumeId;
umaContainer.VarBust = bust;
umaContainer.VarSkin = skin;
umaContainer.VarSocks = socks;
umaContainer.VarHeight = height;
// Pattern for generic body type is as follows:
//
// (costume id)_(body_type_sub)_(body_setting)_(height)_(shape)_(bust)
//
// body_type_sub is used for variants like the summer/winter uniform or the swimsuit/towel
// body_setting is used for subvariants of each variant like the big belly version of the uniform, and the genders for the tracksuits
//
// Some models will naturally be missing due to how this system is designed.
string body = "";
body = UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/pfb_bdy{costumeId}_{height}_{shape}_{bust}";
Debug.Log("Looking for " + body);
Main.AbList.TryGetValue(body, out asset);
}
else Main.AbList.TryGetValue($"{UmaDatabaseController.BodyPath}bdy{bodyid}_{costumeId}/pfb_bdy{bodyid}_{costumeId}", out asset);
if (asset == null)
{
Debug.LogError("No body, can't load!");
return;
}
else if (genericCostume)
{
string texPattern1 = "", texPattern2 = "", texPattern3 = "", texPattern4 = "", texPattern5 = "";
switch (costumeId.Split('_')[0])
{
case "0001":
texPattern1 = $"tex_bdy{costumeIdShort}_00_{skin}_{bust}_0{socks}";
texPattern2 = $"tex_bdy{costumeIdShort}_00_0_{bust}";
texPattern3 = $"tex_bdy{costumeIdShort}_zekken";
texPattern4 = $"tex_bdy{costumeIdShort}_00_waku";
texPattern5 = $"tex_bdy{costumeIdShort}_num";
break;
case "0003":
texPattern1 = $"tex_bdy{costumeIdShort}_00_{skin}_{bust}";
texPattern2 = $"tex_bdy{costumeIdShort}_00_0_{bust}";
break;
case "0006": //last var is color?
texPattern1 = $"tex_bdy{costumeId}_{skin}_{bust}_0{0}";
texPattern2 = $"tex_bdy{costumeId}_0_{bust}_00_";
break;
default:
texPattern1 = $"tex_bdy{costumeId}_{skin}_{bust}";
texPattern2 = $"tex_bdy{costumeId}_0_{bust}";
break;
}
Debug.Log(texPattern1 + " " + texPattern2);
//Load Body Textures
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith(UmaDatabaseController.BodyPath)
&& (a.Name.Contains(texPattern1)
|| a.Name.Contains(texPattern2)
|| (string.IsNullOrEmpty(texPattern3) ? false : a.Name.Contains(texPattern3))
|| (string.IsNullOrEmpty(texPattern4) ? false : a.Name.Contains(texPattern4))
|| (string.IsNullOrEmpty(texPattern5) ? false : a.Name.Contains(texPattern5)))))
{
umaContainer.LoadTextures(asset1);
}
//Load Body
umaContainer.LoadBody(asset);
//Load Physics
if (Main.AbList.TryGetValue(UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/clothes/pfb_bdy{costumeIdShort}_cloth00", out _))
{
var asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/clothes/pfb_bdy{costumeIdShort}_cloth00"];
umaContainer.LoadPhysics(asset1);
asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{costumeIdShort}/clothes/pfb_bdy{costumeIdShort}_bust{bust}_cloth00"];
umaContainer.LoadPhysics(asset1);
}
}
else
{
umaContainer.LoadBody(asset);
//Load Physics
var asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{bodyid}_{costumeId}/clothes/pfb_bdy{bodyid}_{costumeId}_cloth00"];
umaContainer.LoadPhysics(asset1);
asset1 = Main.AbList[UmaDatabaseController.BodyPath + $"bdy{bodyid}_{costumeId}/clothes/pfb_bdy{bodyid}_{costumeId}_bust_cloth00"];
umaContainer.LoadPhysics(asset1);
}
// Record Head Data
int head_id = 1;
string head_costumeId = "00";
int tailId = 1;
CurrentHead = new UmaHeadData
{
id = id,
costumeId = costumeId,
tailId = tailId,
chara = chara
};
var head_s = head_id.ToString().PadLeft(4, '0');
string head = UmaDatabaseController.HeadPath + $"chr{head_s}_{head_costumeId}/pfb_chr{head_s}_{head_costumeId}_face{faceid.PadLeft(3, '0')}";
string hair = UmaDatabaseController.HeadPath + $"chr{head_s}_{head_costumeId}/pfb_chr{head_s}_{head_costumeId}_hair{hairid.PadLeft(3, '0')}";
Main.AbList.TryGetValue(head, out asset);
Main.AbList.TryGetValue(hair, out UmaDatabaseEntry hairasset);
bool isDefaultHead = true;
if (asset != null && hairasset != null)
{
//Load Face And Hair Textures
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"{UmaDatabaseController.HeadPath}chr{head_s}_{head_costumeId}/textures")))
{
if (asset1.Name.Contains($"tex_chr{head_s}_{head_costumeId}_face{faceid.PadLeft(3, '0')}_0")
|| asset1.Name.Contains($"tex_chr{head_s}_{head_costumeId}_face{faceid.PadLeft(3, '0')}_{skin}"))
{
umaContainer.LoadTextures(asset1);
}
if (asset1.Name.Contains($"tex_chr{head_s}_{head_costumeId}_hair{hairid.PadLeft(3, '0')}"))
{
umaContainer.LoadTextures(asset1);
}
}
//Load face
umaContainer.LoadHead(asset);
//Load hair
umaContainer.LoadHair(hairasset);
umaContainer.MergeHairModel();
//Load Physics
if (isDefaultHead)
{
if (Main.AbList.TryGetValue($"{UmaDatabaseController.HeadPath}chr{head_s}_00/clothes/pfb_chr{head_s}_00_hair{hairid.PadLeft(3, '0')}_cloth00", out UmaDatabaseEntry asset1))
{
umaContainer.LoadPhysics(asset1);
}
}
}
if (tailId != 0)
{
string tailName = $"tail{tailId.ToString().PadLeft(4, '0')}_00";
string tailPath = $"3d/chara/tail/{tailName}/";
string tailPfb = tailPath + $"pfb_{tailName}";
asset = UmaViewerMain.Instance.AbChara.FirstOrDefault(a => a.Name == tailPfb);
if (asset != null)
{
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"{tailPath}textures/tex_{tailName}_{head_s}") || a.Name.StartsWith($"{tailPath}textures/tex_{tailName}_0000")))
{
umaContainer.LoadTextures(asset1);
}
umaContainer.LoadTail(asset);
//Load Physics
if (Main.AbList.TryGetValue($"{tailPath}clothes/pfb_{tailName}_cloth00", out UmaDatabaseEntry asset2))
{
umaContainer.LoadPhysics(asset2);
}
}
else
{
Debug.Log("no tail");
}
}
umaContainer.LoadPhysics(); //Need to load physics before loading FacialMorph
umaContainer.SetDynamicBoneEnable(UI.DynamicBoneEnable);
//Load FacialMorph
umaContainer.LoadFaceMorph(id, costumeId);
umaContainer.TearControllers.ForEach(a => a.SetDir(a.CurrentDir));
umaContainer.HeadBone = (GameObject)umaContainer.Body.GetComponent<AssetHolder>()._assetTable["head"];
umaContainer.EyeHeight = umaContainer.Head.GetComponent<AssetHolder>()._assetTableValue["head_center_offset_y"];
umaContainer.MergeModel();
umaContainer.SetHeight(-1);
umaContainer.Initialize(!UI.isTPose);
umaContainer.Position = umaContainer.transform.Find("Position");
if (!UI.isTPose && loadMotion)
{
if (Main.AbList.TryGetValue($"3d/motion/event/body/type00/anm_eve_type00_homestand{personality.PadLeft(2, '0')}_loop", out UmaDatabaseEntry entry))
{
umaContainer.LoadAnimation(entry);
}
}
}
private void LoadMiniUma(UmaContainerCharacter umaContainer, CharaEntry chara, string costumeId)
{
int id = chara.Id;
DataRow charaData = umaContainer.CharaData;
umaContainer.IsMini = true;
bool isGeneric = umaContainer.IsGeneric = costumeId.Length >= 4;
string skin = charaData["skin"].ToString(),
height = charaData["height"].ToString(),
socks = charaData["socks"].ToString(),
bust = charaData["bust"].ToString(),
sex = charaData["sex"].ToString(),
costumeIdShort = "";
bool customHead = true;
UmaDatabaseEntry asset = null;
if (isGeneric)
{
costumeIdShort = costumeId.Remove(costumeId.LastIndexOf('_'));
string body = $"3d/chara/mini/body/mbdy{costumeIdShort}/pfb_mbdy{costumeId}_0";
Main.AbList.TryGetValue(body,out asset);
}
else Main.AbList.TryGetValue($"3d/chara/mini/body/mbdy{id}_{costumeId}/pfb_mbdy{id}_{costumeId}",out asset);
if (asset == null)
{
Debug.LogError("No body, can't load!");
return;
}
else if (isGeneric)
{
string texPattern1 = "";
switch (costumeId.Split('_')[0])
{
case "0003":
texPattern1 = $"tex_mbdy{costumeIdShort}_00_{skin}_{0}";
break;
default:
texPattern1 = $"tex_mbdy{costumeId}_{skin}_{0}";
break;
}
//Load Body Textures
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith("3d/chara/mini/body/") && a.Name.Contains(texPattern1)))
{
umaContainer.LoadTextures(asset1);
}
//Load Body
umaContainer.LoadBody(asset);
}
else
umaContainer.LoadBody(asset);
string hair = $"3d/chara/mini/head/mchr{id}_{costumeId}/pfb_mchr{id}_{costumeId}_hair";
Main.AbList.TryGetValue(hair, out asset);
if (costumeId != "00" && asset == null)
{
customHead = false;
Main.AbList.TryGetValue($"3d/chara/mini/head/mchr{id}_00/pfb_mchr{id}_00_hair", out asset);
}
if (asset != null)
{
//Load Hair Textures
if (customHead)
{
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"3d/chara/mini/head/mchr{id}_{costumeId}/textures")))
{
umaContainer.LoadTextures(asset1);
}
}
else
{
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"3d/chara/mini/head/mchr{id}_00/textures")))
{
umaContainer.LoadTextures(asset1);
}
}
//Load Hair
umaContainer.LoadHead(asset);
}
string head = $"3d/chara/mini/head/mchr0001_00/pfb_mchr0001_00_face0";
Main.AbList.TryGetValue(head,out asset);
if (asset != null)
{
//Load Head Textures
foreach (var asset1 in UmaViewerMain.Instance.AbChara.Where(a => a.Name.StartsWith($"3d/chara/mini/head/mchr0001_00/textures/tex_mchr0001_00_face0_{skin}")))
{
umaContainer.LoadTextures(asset1);
}
//Load Head
umaContainer.LoadHead(asset);
}
umaContainer.MergeModel();
var matList = new List<MeshRenderer>(umaContainer.GetComponentsInChildren<MeshRenderer>());
var eyemat = matList.FirstOrDefault(a => a.gameObject.name.Equals("M_Eye"));
var mouthmat = matList.FirstOrDefault(a => a.gameObject.name.Equals("M_Mouth"));
var eyebrowLmat = matList.FirstOrDefault(a => a.gameObject.name.Equals("M_Mayu_L"));
var eyebrowRmat = matList.FirstOrDefault(a => a.gameObject.name.Equals("M_Mayu_R"));
UI.LoadFacialPanelsMini(eyemat.material, eyebrowLmat.material, eyebrowRmat.material, mouthmat.material);
if(Main.AbList.TryGetValue($"3d/motion/mini/event/body/chara/chr{id}_00/anm_min_eve_chr{id}_00_idle01_loop",out asset))
{
umaContainer.LoadAnimation(asset);
}
}
public void LoadProp(UmaDatabaseEntry entry)
{
UnloadProp();
UmaAssetManager.UnloadAllBundle();
var prop = new GameObject(Path.GetFileName(entry.Name)).AddComponent<UmaContainerProp>();
prop.LoadProp(entry);
CurrentOtherContainer = prop;
}
public void LoadLive(LiveEntry live, List<LiveCharacterSelect> characters)
{
UmaSceneController.LoadScene("LiveScene",
delegate ()
{
GameObject MainLive = Instantiate(LiveControllerPrefab);
Gallop.Live.Director mController = MainLive.GetComponentInChildren<Gallop.Live.Director>();
mController.live = live;
mController.IsRecordVMD = UI.isRecordVMD;
List<GameObject> transferObjs = new List<GameObject>() {
MainLive,
GameObject.Find("ViewerMain"),
GameObject.Find("Directional Light"),
GameObject.Find("GlobalShaderController"),
GameObject.Find("AudioManager")
};
// Move the GameObject (you attach this in the Inspector) to the newly loaded Scene
transferObjs.ForEach(o => SceneManager.MoveGameObjectToScene(o, SceneManager.GetSceneByName("LiveScene")));
mController.Initialize();
characters.ForEach(a =>
{
if (a.CharaEntry == null || a.CostumeId == "")
{
a.CharaEntry = Main.Characters[Random.Range(0, Main.Characters.Count/2)];
a.CostumeId = "0002_00_00";
}
});//fill empty
LoadLiveUma(characters);
},
delegate ()
{
Gallop.Live.Director.instance.InitializeUI();
Gallop.Live.Director.instance.InitializeTimeline(characters, UI.LiveMode);
Gallop.Live.Director.instance.InitializeMusic(live.MusicId, characters);
Gallop.Live.Director.instance.Play();
LiveViewerUI.Instance.RecordingUI.SetActive(Gallop.Live.Director.instance.IsRecordVMD);
}
);
}
//Use decrypt function
public void LoadLiveSound(int songid, UmaDatabaseEntry SongAwb, bool needLyrics = true)
{
//load character voice
if (SongAwb != null)
{
PlaySound(SongAwb);
}
//load BG
string nameVar = $"snd_bgm_live_{songid}_oke";
UmaDatabaseEntry BGawb = Main.AbSounds.FirstOrDefault(a => a.Name.Contains(nameVar) && a.Name.EndsWith("awb"));
if (BGawb != null)
{
var BGclip = LoadAudio(BGawb);
if (BGclip.Count > 0)
{
AddAudioSource(BGclip[0]);
}
}
if (needLyrics)
{
LoadLiveLyrics(songid);
}
}
public void PlaySound(UmaDatabaseEntry SongAwb, int subindex = -1)
{
if (CurrentAudioSources.Count > 0)
{
var tmp = CurrentAudioSources[0];
CurrentAudioSources.Clear();
Destroy(tmp.gameObject);
UI.ResetAudioPlayer();
}
if (subindex == -1)
{
foreach (AudioClip clip in LoadAudio(SongAwb))
{
AddAudioSource(clip);
}
}
else
{
AddAudioSource(LoadAudio(SongAwb)[subindex]);
}
}
private void AddAudioSource(AudioClip clip)
{
AudioSource source;
if (CurrentAudioSources.Count > 0)
{
source = CurrentAudioSources[0].gameObject.AddComponent<AudioSource>();
}
else
{
source = new GameObject("SoundController").AddComponent<AudioSource>();
}
CurrentAudioSources.Add(source);
source.clip = clip;
source.Play();
}
public static List<AudioClip> LoadAudio(UmaDatabaseEntry awb)
{
List<AudioClip> clips = new List<AudioClip>();
string awbPath = awb.FilePath;
if (!File.Exists(awbPath)) return clips;
FileStream awbFile = File.OpenRead(awbPath);
AwbReader awbReader = new AwbReader(awbFile);
foreach (Wave wave in awbReader.Waves)
{
var stream = new UmaWaveStream(awbReader, wave.WaveId);
var sampleProvider = stream.ToSampleProvider();
int channels = stream.WaveFormat.Channels;
int bytesPerSample = stream.WaveFormat.BitsPerSample / 8;
int sampleRate = stream.WaveFormat.SampleRate;
AudioClip clip = AudioClip.Create(
Path.GetFileNameWithoutExtension(awb.Name) + "_" + wave.WaveId.ToString(),
(int)(stream.Length / channels / bytesPerSample),
channels,
sampleRate,
true,
data => sampleProvider.Read(data, 0, data.Length),
position => stream.Position = position * channels * bytesPerSample);
clips.Add(clip);
}
return clips;
}
public void LoadLiveLyrics(int songid)
{
if (CurrentLyrics.Count > 0) CurrentLyrics.Clear();
string lyricsVar = $"live/musicscores/m{songid}/m{songid}_lyrics";
UmaDatabaseEntry lyricsAsset = Main.AbList[lyricsVar];
AssetBundle bundle = UmaAssetManager.LoadAssetBundle(lyricsAsset);
TextAsset asset = bundle.LoadAsset<TextAsset>(Path.GetFileNameWithoutExtension(lyricsVar));
string[] lines = asset.text.Split("\n"[0]);
for (int i = 1; i < lines.Length; i++)
{
string[] words = lines[i].Split(',');
if (words.Length > 0)
{
try
{
UmaLyricsData lyricsData = new UmaLyricsData()
{
time = float.Parse(words[0]) / 1000,
text = (words.Length > 1) ? words[1].Replace("[COMMA]", ",") : ""
};
CurrentLyrics.Add(lyricsData);
}
catch { }
}
}
}
public void LoadAssetPath(string path, Transform SetParent)
{
Instantiate(UmaViewerMain.Instance.AbList[path].Get<GameObject>(), SetParent);
}
public void SetPreviewCamera(AnimationClip clip)
{
if (clip)
{
if (!AnimationCameraAnimator.runtimeAnimatorController)
{
AnimationCameraAnimator.runtimeAnimatorController = Instantiate(CameraOverrideController);
}
(AnimationCameraAnimator.runtimeAnimatorController as AnimatorOverrideController)["clip_1"] = clip;
AnimationCamera.enabled = true;
AnimationCameraAnimator.Play("motion_1", 0, 0);
CurrentUMAContainer?.SetHeight(0);
}
else
{
AnimationCamera.enabled = false;
CurrentUMAContainer?.SetHeight(-1);
}
}
public Sprite LoadCharaIcon(string id)
{
string value = $"chara/chr{id}/chr_icon_{id}";
if (UmaViewerMain.Instance.AbList.TryGetValue(value, out UmaDatabaseEntry entry))
{
AssetBundle assetBundle = UmaAssetManager.LoadAssetBundle(entry, true);
if (assetBundle.Contains($"chr_icon_{id}"))
{
Texture2D texture = (Texture2D)assetBundle.LoadAsset($"chr_icon_{id}");
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
assetBundle.Unload(false);
return sprite;
}
}
return null;
}
public Sprite LoadMobCharaIcon(string id)
{
string value = $"mob/mob_chr_icon_{id}_000001_01";
if (UmaViewerMain.Instance.AbList.TryGetValue(value, out UmaDatabaseEntry entry))
{
string path = entry.FilePath;
AssetBundle assetBundle = UmaAssetManager.LoadAssetBundle(entry, true);
if (assetBundle.Contains($"mob_chr_icon_{id}_000001_01"))
{
Texture2D texture = (Texture2D)assetBundle.LoadAsset($"mob_chr_icon_{id}_000001_01");
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
assetBundle.Unload(false);
return sprite;
}
}
return null;
}
public Sprite LoadSprite(UmaDatabaseEntry item)
{
AssetBundle assetBundle = UmaAssetManager.LoadAssetBundle(item, true);
Texture2D texture = (Texture2D)assetBundle.LoadAsset(assetBundle.GetAllAssetNames()[0]);
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
assetBundle.Unload(false);
return sprite;
}
public Sprite LoadLiveIcon(int musicid)
{
string value = $"live/jacket/jacket_icon_l_{musicid}";
if (UmaViewerMain.Instance.AbList.TryGetValue(value, out UmaDatabaseEntry entry))
{
AssetBundle assetBundle = UmaAssetManager.LoadAssetBundle(entry, true);
if (assetBundle.Contains($"jacket_icon_l_{musicid}"))
{
Texture2D texture = (Texture2D)assetBundle.LoadAsset($"jacket_icon_l_{musicid}");
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
assetBundle.Unload(false);
return sprite;
}
}
return null;
}
public void UnloadProp()
{
if (CurrentOtherContainer != null)
{
Destroy(CurrentOtherContainer.gameObject);
}
}
public void UnloadUma()
{
if (CurrentUMAContainer != null)
{
//It seems that OnDestroy will executed after new model loaded, which cause new FacialPanels empty...
UmaViewerUI.Instance.currentFaceDrivenKeyTarget = null;
UmaViewerUI.Instance.LoadEmotionPanels(null);
UmaViewerUI.Instance.LoadFacialPanels(null);
if (UmaViewerUI.Instance.MaterialsList)
foreach (Transform t in UmaViewerUI.Instance.MaterialsList.content)
{
Destroy(t.gameObject);
}
if (CurrentUMAContainer.transform.parent && CurrentUMAContainer.transform.parent.name.Contains("Root"))
{
Destroy(CurrentUMAContainer.transform.parent.gameObject);
}
else
{
Destroy(CurrentUMAContainer.gameObject);
}
}
}
public void ClearMorphs()
{
var umaContainer = CurrentUMAContainer;
if (umaContainer != null && umaContainer.FaceDrivenKeyTarget != null)
{
foreach (var container in UI.EmotionList.GetComponentsInChildren<UmaUIContainer>())
{
if (container.Slider != null)
container.Slider.value = 0;
}
foreach (var container in UI.FacialList.GetComponentsInChildren<UmaUIContainer>())
{
if (container.Slider != null)
container.Slider.SetValueWithoutNotify(0);
}
if (umaContainer.FaceDrivenKeyTarget)
{
umaContainer.FaceDrivenKeyTarget.ClearAllWeights();
umaContainer.FaceDrivenKeyTarget.ChangeMorph();
}
}
}
public void UnloadAllBundle() => UmaAssetManager.UnloadAllBundle(true);
private void FixedUpdate()
{
if (AnimationCamera && AnimationCamera.enabled == true)
{
var fov = AnimationCamera.gameObject.transform.parent.transform.localScale.x;
AnimationCamera.fieldOfView = fov;
}
}
}