Files
UmaViewer/Assets/Scripts/UmaViewerBuilder.cs
T
Katboi01 812de090d2 Pose Mode fixes
Eyebrow draw order change
2023-12-30 13:59:43 +01:00

996 lines
39 KiB
C#

using CriWareFormats;
using Gallop;
using NAudio.Wave;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
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;
static UmaViewerMain Main => UmaViewerMain.Instance;
static 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 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>();
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>();
umaContainer.IsLive = true;
umaContainer.CharaData = UmaDatabaseController.ReadCharaData(characters[i].CharaEntry);
var charObjs = Gallop.Live.Director.instance.charaObjs;
umaContainer.transform.parent = charObjs[i];
umaContainer.transform.localPosition = new Vector3();
if (characters[i].CharaEntry.IsMob)
{
LoadMobUma(umaContainer, characters[i].CharaEntry, characters[i].CostumeId);
}
else
{
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;
umaContainer.CharaEntry = chara;
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");
umaContainer.SetupBoneHandles();
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.CharaEntry = chara;
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");
umaContainer.SetupBoneHandles();
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;
umaContainer.CharaEntry = chara;
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);
umaContainer.Position = umaContainer.transform.Find("Position");
umaContainer.SetupBoneHandles();
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);
var Lyrics = LoadLiveLyrics(live.MusicId);
if (Lyrics != null)
{
LiveViewerUI.Instance.CurrentLyrics = Lyrics;
}
},
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 List<UmaLyricsData> 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] : ""
};
CurrentLyrics.Add(lyricsData);
}
catch { }
}
}
return CurrentLyrics;
}
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()
{
PoseManager.SetPoseModeStatic(false);
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;
}
}
}