// **************************************************************************************** // PresetPrepare Plugin by dynms1337 // Licensed under CC BY // **************************************************************************************** using System; using UnityEngine; using System.Collections.Generic; using SimpleJSON; using System.Linq; using MacGruber; using MVR.FileManagementSecure; using UnityEngine.UI; namespace dynms1337 { public partial class CharacterFusioner : MVRScript { public const string STR_characters = "characters"; public const string STR_baseCharacter = "baseCharacter"; public const string DIR_APPEARANCES = dUtil.DIR_APPEARANCES; public CharacterProfile baseCharacter; public List characters = new List(); public List allCharacters { get { return new List() { baseCharacter }.Concat(characters).ToList(); } } protected List uiElementCharacter = new List(); protected List uiWeightSliders = new List(); UIDynamicLabelInput appNameInput; JSONStorableBool showThumbnail; private void Init_Character() { // ------------------ UI RightSide ------------------ bool isRightsideCharactersUI = true; dUtil.CreateText(this, $"Additional Characteres", "\nAdditional Characteres", rightSide: isRightsideCharactersUI); Utils.SetupButton(this, "Add Appearance...", callback: () => { SuperController.singleton.GetMediaPathDialog(callback: AddCharacter, filter: "vap", suggestedFolder: DIR_APPEARANCES, fullComputerBrowse: true, showDirs: true, showKeepOpt: false, fileRemovePrefix: null, hideExtenstion: false, shortCuts: FileManagerSecure.GetShortCutsForDirectory(DIR_APPEARANCES, false, false, true, true)); }, rightSide: isRightsideCharactersUI); dUtil.CreateSpacer(this, rightSide: isRightsideCharactersUI); // Preset Choosers //dUtil.CreateText(this, $"character-editor text", "\nParameters", rightSide: isRightsideCharactersUI); Init_Preset(isRightsideCharactersUI); dUtil.CreateSpacer(this, rightSide: isRightsideCharactersUI); showThumbnail = dUtil.CreateToggle(this, $"Show Thumbnail", true, rightSide: isRightsideCharactersUI, callback: b => repaint_Characters()); dUtil.CreateSpacer(this, rightSide: isRightsideCharactersUI); // ------------------ UI LeftSide ------------------ // base character bool isRightsideBase = false; valBaseText = dUtil.CreateText(this, $"Base - Text", baseCharaText("Value@PluginLoaded"), rightSide: isRightsideBase); var uiBaseWeight = dUtil.CreateSlider(this, $"Base weight", 0f, 0f, 1f, constrain: true, interactable: false, rightSide: isRightsideBase); valBaseWeight = slider2float(uiBaseWeight); Utils.SetupButton(this, "Set Base Appearance...", callback: () => { SuperController.singleton.GetMediaPathDialog(callback: SetBaseCharacter, filter: "vap", suggestedFolder: DIR_APPEARANCES, fullComputerBrowse: true, showDirs: true, showKeepOpt: false, fileRemovePrefix: null, hideExtenstion: false, shortCuts: FileManagerSecure.GetShortCutsForDirectory(DIR_APPEARANCES, false, false, true, true)); }, rightSide: isRightsideBase); } public void RandomizeAll() { uiWeightSliders.ForEach(s => slider2float(s).val = UnityEngine.Random.Range(0f, 1f)); var rand = new System.Random(); presetChooserDic.ToList().ForEach(kvp => { var chooser = kvp.Key; if (kvp.Value.val) chooser.val = chooser.choices.ElementAt(rand.Next(chooser.choices.Count())); }); } public void ResetToBaseCharacter() { uiWeightSliders.ForEach(s => slider2float(s).val = 0f); presetChooserDic.ToList().ForEach(kvp => { var chooser = kvp.Key; if (kvp.Value.val) chooser.val = baseCharacter.name; }); } void SetBaseCharacter(string vapPath) { float weight = baseCharacter.weight; baseCharacter = CharacterProfile.createBaseCharacter(this, vapPath); baseCharacter.weight = weight; ResetMorphs(); repaint(); } string baseCharaText(string name) { return $"Base Character : \n{name}"; } void AddCharacter(string vapPath) { var chara = CharacterProfile.createAdditionalCharacter(this, vapPath); if (characters.Select(c => c.name == chara.name).Any(b => b)) { dUtil.error($"AddCharacter > Cannot add Characters with duplicate names : {chara.name}"); return; } characters.Add(chara); update_Preset(); ResetMorphs(); repaint(); } void RemoveCharacter(CharacterProfile chara) { characters.Remove(chara); update_Preset(); ResetMorphs(); repaint(); } Dictionary weightValDict = new Dictionary(); private void repaint_Characters() { dUtil.RemoveUIElements(this, uiElementCharacter); uiWeightSliders.Clear(); uiElementCharacter.Clear(); bool isRightsideMorphUI = true; foreach (var chara in characters) { //uiElementCharacter.Add(dUtil.CreateText(this, $"{chara.name} - Text", $"\n{chara.name}", rightSide: isRightsideMorphUI)); // Add Thumbnail if (showThumbnail.val) { int width = 400; int height = 400; var goPrefab = new GameObject($"thumb-{chara.name}"); goPrefab.SetActive(false); RectTransform rt = goPrefab.AddComponent(); rt.anchorMax = new Vector2(0, 1); rt.anchorMin = new Vector2(0, 1); rt.offsetMax = new Vector2(535, -500); rt.offsetMin = new Vector2(10, -600); LayoutElement le = goPrefab.AddComponent(); //le.flexibleWidth = 1; le.minHeight = height; le.minWidth = width; le.preferredHeight = height; le.preferredWidth = width; var t = this.CreateUIElement(goPrefab.transform, isRightsideMorphUI); uiElementCharacter.Add(t.gameObject); Image image = t.gameObject.AddComponent(); image.type = Image.Type.Simple; // FIXED: Use the stored appearancePath to preserve subdirectory structure dUtil.LoadTexture(dUtil.get_thumbnailPath(chara.appearancePath, "jpg"), callback: qi => { var tex = dUtil.ResizeTexture(qi.tex, width, height); image.sprite = Sprite.Create(tex, new Rect(0, 0, width, height), Vector2.zero); }); } JSONStorableFloat jsf = null; weightValDict.TryGetValue(chara.name, out jsf); var slider = dUtil.CreateSlider(this, $"{chara.name} - Weight", chara.weight, 0f, 1f, constrain: true, interactable: true, rightSide: isRightsideMorphUI, registerStorableIfCreate: true, callback: f => { chara.weight = f; isUpdateMorph = true; }, jsf:jsf); weightValDict[chara.name] = slider2float(slider); uiElementCharacter.Add(slider); uiWeightSliders.Add(slider); uiElementCharacter.Add(dUtil.CreateButton(this, "Remove", Color.red, rightSide: isRightsideMorphUI, callback: () => { RemoveCharacter(chara); })); uiElementCharacter.Add(dUtil.CreateSpacer(this, rightSide: isRightsideMorphUI)); } } private void Start_Character() { // base character var _morphs = new Dictionary(); getActiveMorphs().ForEach(m => _morphs[m.displayName] = m.morphValue); // create dictionary without displayName duplicate error. baseCharacter = CharacterProfile.createBaseCharacter(this); update_Preset(); } } }