using Gallop; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; public class UmaViewerUI : MonoBehaviour { public static UmaViewerUI Instance; private UmaViewerMain Main => UmaViewerMain.Instance; private UmaViewerBuilder Builder => UmaViewerBuilder.Instance; public CanvasScaler canvasScaler; [Header("normal models")] public ScrollRect CharactersList; public ScrollRect MobCharactersList; public PageManager MobCharactersPageCtrl; public ScrollRect CostumeList; public ScrollRect HeadCostumeList; public ScrollRect MobCostumeList; public ScrollRect AnimationSetList; public ScrollRect AnimationList; public PageManager AnimationPageCtrl; [Header("mini models")] public ScrollRect MiniCharactersList; public ScrollRect MiniCostumeList; public ScrollRect MiniAnimationSetList; public ScrollRect MiniAnimationList; public PageManager MiniAnimationPageCtrl; [Header("other")] public ScrollRect PropList; public PageManager PropPageCtrl; public ScrollRect SceneList; public PageManager ScenePageCtrl; public ScrollRect MessageScrollRect; public TextMeshProUGUI MessageText; public PoseManager PoseManager; public HandleManager HandleManager; [Header("lists")] public ScrollRect EmotionList; public Transform FacialList; public ScrollRect EarList; public ScrollRect EyeBrowList; public ScrollRect EyeList; public ScrollRect MouthList; public ScrollRect OtherList; public ScrollRect LiveList; public ScrollRect LiveSoundList; public ScrollRect LiveCharaSoundList; public ScrollRect NormalSoundList; public ScrollRect NormalSubSoundList; public PageManager NormalSoundCtrl; [Header("pose mode")] public Transform HandlesPanel; [Header("live settings")] public Sprite CharaIconDefault; public Sprite CostumeIconDefault; public LiveCharacterSelect CurrentSeletChara; public GameObject LiveSelectPrefab; public GameObject LiveSelectPannel; public GameObject SelectCharacterPannel; public ScrollRect LiveSelectList; public Image LiveSelectImage; public Text LiveSelectInfoText; private LiveEntry currentLive; [Header("settings")] public UISettingsCamera CameraSettings; public UISettingsModel ModelSettings; public UISettingsSound AudioSettings; public UISettingsAnimation AnimationSettings; public UISettingsScreenshot ScreenshotSettings; public UISettingsAssets AssetSettings; public UISettingsOther OtherSettings; public List TogglablePanels = new List(); public List TogglableFacials = new List(); [Header("prefabs")] public GameObject UmaContainerPrefab; public GameObject UmaContainerCostumePrefab; public GameObject UmaContainerLivePrefab; public GameObject UmaContainerSliderPrefab; public UmaUIContainer UmaContainerTogglePrefab; public Color UIColor1, UIColor2; public string CurrentHeadCostumeId = string.Empty; [Header("Live")] public bool LiveTime = false; public bool isRecordVMD; public bool isRequireStage = true; public Dropdown LiveRecoedToggle; public int LiveMode = 1; public FaceDrivenKeyTarget currentFaceDrivenKeyTarget; private void Awake() { Instance = this; } private void Start() { OtherSettings.ApplySettings(); CameraSettings.AAModeDropdown.SetValueWithoutNotify(Config.Instance.AntiAliasing); AssetSettings.LoadedAssetsClear(); UmaAssetManager.OnLoadedBundleUpdate += AssetSettings.LoadedAssetsAdd; UmaAssetManager.OnLoadedBundleRemove += AssetSettings.LoadedAssetsRemove; UmaAssetManager.OnLoadedBundleClear += AssetSettings.LoadedAssetsClear; PoseManager.LoadLocalPoseFiles(); #if UNITY_ANDROID && !UNITY_EDITOR canvasScaler.referenceResolution = new Vector2(1280, 720); #endif StartCoroutine(ApplyGraphicsSettings()); } private void OnDestroy() { UmaAssetManager.OnLoadedBundleUpdate -= AssetSettings.LoadedAssetsAdd; UmaAssetManager.OnLoadedBundleRemove -= AssetSettings.LoadedAssetsRemove; UmaAssetManager.OnLoadedBundleClear -= AssetSettings.LoadedAssetsClear; } private void Update() { if (Builder.CurrentAudioSources.Count > 0 && Builder.CurrentAudioSources[0]) { AudioSource MianSource = Builder.CurrentAudioSources[0]; if (MianSource.clip) { AudioSettings.UpdateTrack(MianSource); } } var umaContainer = Builder.CurrentUMAContainer; if (umaContainer != null && umaContainer.OverrideController != null) { AnimationSettings.UpdateAnimationInfo(umaContainer); } } /// Some settings may not be saved when set in Start() public IEnumerator ApplyGraphicsSettings() { yield return 0; CameraSettings.ChangeAntiAliasing(Config.Instance.AntiAliasing); GraphicsSettings.renderPipelineAsset = Config.Instance.Region == Region.Global ? null : UmaViewerMain.Instance.DefaultRenderPipeline; } public void HighlightChildImage(Transform mainObject, UmaUIContainer child) { foreach (var t in mainObject.GetComponentsInChildren()) { if (t.transform.parent != mainObject) continue; t.ToggleImage.enabled = (t == child); } } public void LoadModelPanels() { var containerG = Instantiate(UmaContainerPrefab, AnimationSetList.content).GetComponent(); containerG.Name = containerG.name = "Generic"; containerG.Button.onClick.AddListener(() => { HighlightChildImage(AnimationSetList.content, containerG); ListAnimations(-1, false); }); var containerT = Instantiate(UmaContainerPrefab, AnimationSetList.content).GetComponent(); containerT.Name = containerT.name = "Tail"; containerT.Button.onClick.AddListener(() => { HighlightChildImage(AnimationSetList.content, containerT); ListAnimations(-2, false); }); var containerE = Instantiate(UmaContainerPrefab, AnimationSetList.content).GetComponent(); containerE.Name = containerE.name = "Ear"; containerE.Button.onClick.AddListener(() => { HighlightChildImage(AnimationSetList.content, containerE); ListAnimations(-3, false); }); foreach (var chara in Main.Characters.OrderBy(c => c.Id)) { var charaInstance = chara; var container3 = Instantiate(UmaContainerPrefab, CharactersList.content).GetComponent(); container3.Name = container3.name = chara.Id + " " + chara.GetName(); container3.Button.onClick.AddListener(() => { HighlightChildImage(CharactersList.content, container3); ListCostumes(charaInstance, false); }); if (chara.Icon) { container3.Image.sprite = (chara.Icon == null ? CharaIconDefault : chara.Icon); container3.Image.enabled = true; } var container4 = Instantiate(UmaContainerPrefab, AnimationSetList.content).GetComponent(); container4.Name = container4.name = chara.Id + " " + chara.GetName(); container4.Button.onClick.AddListener(() => { HighlightChildImage(AnimationSetList.content, container4); ListAnimations(charaInstance.Id, false); }); if (chara.Icon) { container4.Image.sprite = (chara.Icon == null ? CharaIconDefault : chara.Icon); container4.Image.enabled = true; } } var pageentrys = new List(); foreach (var chara in Main.MobCharacters.OrderBy(c => c.Id)) { var charaInstance = chara; var pageentry = new PageManager.Entry(); pageentry.Name = chara.GetName(); pageentry.OnClick = (container) => { HighlightChildImage(MobCharactersList.content, container); ListCostumes(charaInstance, false); }; if (chara.Icon) { pageentry.Sprite = chara.Icon; } pageentrys.Add(pageentry); } MobCharactersPageCtrl.Initialize(pageentrys, MobCharactersList); } public void LoadMiniModelPanels() { var container1 = Instantiate(UmaContainerPrefab, MiniAnimationSetList.content).GetComponent(); container1.Name = container1.name = "General"; container1.Button.onClick.AddListener(() => { HighlightChildImage(MiniAnimationSetList.content, container1); ListAnimations(-1, true); }); foreach (var chara in Main.Characters.OrderBy(c => c.Id)) { var charaInstance = chara; var container2 = Instantiate(UmaContainerPrefab, MiniCharactersList.content).GetComponent(); container2.Name = container2.name = chara.Id + " " + chara.GetName(); container2.Button.onClick.AddListener(() => { HighlightChildImage(MiniCharactersList.content, container2); ListCostumes(charaInstance, true); }); if (chara.Icon) { container2.Image.sprite = chara.Icon; container2.Image.enabled = true; } var container3 = Instantiate(UmaContainerPrefab, MiniAnimationSetList.content).GetComponent(); container3.Name = container3.name = chara.Id + " " + chara.GetName(); container3.Button.onClick.AddListener(() => { HighlightChildImage(MiniAnimationSetList.content, container3); ListAnimations(charaInstance.Id, true); }); if (chara.Icon) { container3.Image.sprite = chara.Icon; container3.Image.enabled = true; } } } public void LoadFacialPanels(FaceDrivenKeyTarget target) { currentFaceDrivenKeyTarget = target; if(FacialList) foreach (UmaUIContainer ui in FacialList.GetComponentsInChildren(true)) { Destroy(ui.gameObject); } if (target == null) return; List targetMorph = new List(target.OtherMorphs); Action, ScrollRect> action = (UmaContainerSliderPrefab, target, targetMorph, TargetList) => { foreach (FacialMorph morph in targetMorph) { if (morph is FacialOtherMorph extraMorph) { foreach (var prop in extraMorph.BindProperties) { var container = Instantiate(UmaContainerSliderPrefab, TargetList.content).GetComponent(); container.Name = $"{morph.name}({prop.Type})"; container.Slider.value = prop.Value; switch (prop.Type) { case BindProperty.BindType.Shader: case BindProperty.BindType.Texture: container.Slider.maxValue = 1; container.Slider.minValue = 0; break; case BindProperty.BindType.Select: container.Slider.wholeNumbers = true; container.Slider.maxValue = prop.BindPrefabs.Count - 1; container.Slider.minValue = 0; break; case BindProperty.BindType.EyeSelect: container.Slider.wholeNumbers = true; container.Slider.maxValue = prop.BindPrefabs.Count / 2 - 1; container.Slider.minValue = 0; break; case BindProperty.BindType.Enable: case BindProperty.BindType.TearSelect: case BindProperty.BindType.TearSide: container.Slider.wholeNumbers = true; container.Slider.maxValue = 1; container.Slider.minValue = 0; break; case BindProperty.BindType.TearWeight: container.Slider.maxValue = 1; container.Slider.minValue = 0; break; case BindProperty.BindType.TearSpeed: container.Slider.maxValue = 2; container.Slider.minValue = 0; break; } container.Slider.onValueChanged.AddListener((a) => { target.ChangeMorphWeight(prop, a, morph); }); } } else { var container = Instantiate(UmaContainerSliderPrefab, TargetList.content).GetComponent(); container.Name = $"{morph.name}({morph.tag})"; container.Slider.value = morph.weight; container.Slider.maxValue = 1; container.Slider.minValue = morph.tag.Contains("Range") ? -1 : 0; container.Slider.onValueChanged.AddListener((a) => { target.ChangeMorphWeight(morph, a); }); } } }; action(UmaContainerSliderPrefab, target, target.EarMorphs, EarList); action(UmaContainerSliderPrefab, target, target.EyeBrowMorphs, EyeBrowList); action(UmaContainerSliderPrefab, target, target.EyeMorphs, EyeList); action(UmaContainerSliderPrefab, target, target.MouthMorphs, MouthList); action(UmaContainerSliderPrefab, target, targetMorph, OtherList); } public void LoadFacialPanelsMini(Material Eye, Material MayuL, Material MayuR, Material Mouth) { currentFaceDrivenKeyTarget = null; foreach (UmaUIContainer ui in FacialList.GetComponentsInChildren(true)) { Destroy(ui.gameObject); } var action = new Action((list, name, mat, type) => { if (mat == null) return; var container = Instantiate(UmaContainerSliderPrefab, list.content).GetComponent(); container.Name = name; container.Slider.wholeNumbers = true; container.Slider.value = 0; container.Slider.maxValue = 15; container.Slider.minValue = 0; container.Slider.onValueChanged.AddListener((a) => { var val = Convert.ToInt32(a); if (type == 0) { mat.mainTextureOffset = new Vector2(0.25f * (val % 4), -0.25f * (val / 4)); } else if (type == 1) { var vector = mat.GetVector("_UVOffset"); mat.SetVector("_UVOffset", new Vector4(0.25f * (val % 4), -0.25f * (val / 4), vector.z, vector.w)); } else if (type == 2) { var vector = mat.GetVector("_UVOffset"); mat.SetVector("_UVOffset", new Vector4(vector.x, vector.y, 0.25f * (val % 4), -0.25f * (val / 4))); } }); }); action(EyeList, "Eye_L_Select", Eye, 2); action(EyeList, "Eye_R_Select", Eye, 1); action(MouthList, "Mouth_Select", Mouth, 0); action(EyeBrowList, "Mayu_L_Select", MayuL, 0); action(EyeBrowList, "Mayu_R_Select", MayuR, 0); } public void UpdateFacialPanels() { if (currentFaceDrivenKeyTarget) LoadFacialPanels(currentFaceDrivenKeyTarget); } public void LoadEmotionPanels(FaceEmotionKeyTarget target) { if (EmotionList) foreach (UmaUIContainer ui in EmotionList.content.GetComponentsInChildren()) { Destroy(ui.gameObject); } if (target == null) return; foreach (var emotion in target.FaceEmotionKey) { if (emotion.label == "Base") { continue; } var container = Instantiate(UmaContainerSliderPrefab, EmotionList.content).GetComponent(); container.Name = emotion.label; container.Slider.value = emotion.weight; container.Slider.maxValue = 1; container.Slider.minValue = 0; container.Slider.onValueChanged.AddListener((a) => { target.ChangeEmotionWeight(emotion, a); }); } } public void LoadLivePanels() { Action createContainer = (live, containerPrefab, parent, onClickAction) => { var container = Instantiate(containerPrefab, parent.content).GetComponent(); container.Name = " " + live.MusicId + " " + live.SongName; container.Image.sprite = live.Icon; container.Image.enabled = container.Image.sprite; container.Button.onClick.AddListener(() => { HighlightChildImage(parent.content, container); onClickAction.Invoke(); }); }; foreach (var live in Main.Lives.OrderBy(c => c.MusicId)) { createContainer(live, UmaContainerLivePrefab, LiveList, () => ShowLiveSelectPanel(live)); createContainer(live, UmaContainerLivePrefab, LiveSoundList, () => ListLiveSounds(live.MusicId)); } } public void LoadNormalSoundPanels() { NormalSoundCtrl.Clear(); var pageentrys = new List(); foreach (var entry in Main.AbSounds.Where(a => (!a.Name.Contains("live")) && a.Name.EndsWith("awb"))) { var pageentry = new PageManager.Entry(); pageentry.Name = Path.GetFileNameWithoutExtension(entry.Name); pageentry.OnClick = (container) => { HighlightChildImage(NormalSoundList.content, container); ListNormalSubSounds(entry); }; pageentrys.Add(pageentry); } NormalSoundCtrl.Initialize(pageentrys, NormalSoundList); } public void LoadPropPanel() { var pageentrys = new List(); foreach (var prop in Main.AbList.Where(a => a.Key.Contains("pfb_chr_prop") && !a.Key.Contains("clothes"))) { var pageentry = new PageManager.Entry(); pageentry.Name = Path.GetFileName(prop.Key); pageentry.OnClick = (container) => { HighlightChildImage(PropList.content, container); Builder.LoadProp(prop.Value); }; pageentrys.Add(pageentry); } PropPageCtrl.Initialize(pageentrys, PropList); } public void LoadMapPanel() { var pageentrys = new List(); foreach (var scene in Main.AbList.Where(a => ((a.Key.StartsWith("3d/env") && Path.GetFileName(a.Key).StartsWith("pfb_")) || a.Key.StartsWith("cutt/cutt_son") && Path.GetFileName(a.Key).StartsWith("cutt_son")))) { var pageentry = new PageManager.Entry(); pageentry.Name = Path.GetFileName(scene.Key); pageentry.FontSize = 19; pageentry.OnClick = (container) => { HighlightChildImage(SceneList.content, container); Builder.LoadProp(scene.Value); }; pageentrys.Add(pageentry); } ScenePageCtrl.Initialize(pageentrys, SceneList); } public void PlayLive() { if (currentLive == null) return; PoseManager.SetPoseMode(false); var selectlist = LiveSelectList.content.GetComponentsInChildren(); if (selectlist != null) { LiveTime = true; ModelSettings.SetEyeTrackingEnable(false); Builder.LoadLive(currentLive, new List(selectlist)); LiveSelectPannel.SetActive(false); } } void ShowLiveSelectPanel(LiveEntry entry) { LiveSelectPannel.SetActive(true); Builder.loadLivePreviewSound(entry.MusicId); for (int i = LiveSelectList.content.childCount - 1; i >= 0; i--) { Destroy(LiveSelectList.content.GetChild(i).gameObject); } if(LiveMode == 1) { currentLive = entry; LiveSelectImage.sprite = entry.Icon; LiveSelectInfoText.text = $"{entry.SongName}\nMembers Count: {entry.MemberCount}"; for (int i = 0; i < entry.MemberCount; i++) { var chara = Instantiate(LiveSelectPrefab, LiveSelectList.content).GetComponent(); chara.IndexText.text = (i + 1).ToString(); chara.GetComponent