├── HCharaSwitcher.sln ├── README.md ├── HS2_HCharaSwitcher ├── Properties │ └── AssemblyInfo.cs ├── Hooks.cs ├── HS2_HCharaSwitcher.csproj ├── HS2_HCharaSwitcher.cs └── Tools.cs └── LICENSE /HCharaSwitcher.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HS2_HCharaSwitcher", "HS2_HCharaSwitcher\HS2_HCharaSwitcher.csproj", "{FBE56F47-6D8B-4D0A-BF72-97A461D0CA29}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {FBE56F47-6D8B-4D0A-BF72-97A461D0CA29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {FBE56F47-6D8B-4D0A-BF72-97A461D0CA29}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {FBE56F47-6D8B-4D0A-BF72-97A461D0CA29}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {FBE56F47-6D8B-4D0A-BF72-97A461D0CA29}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | EndGlobal 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HCharaSwitcher 2 | 3 | This plugin allows you to change character cards during H scene. 4 | 5 | # DO NOT REUPLOAD WITHOUT PERMISSION | 未经许可请勿转载 6 | 7 | **Features:** 8 | * Integrated into the game UI 9 | * Change cards for male, female H members 10 | * Ability to swap cards of characters in 3P HScenes 11 | * Changes personality, voice, BGM, ABMX, Overlays, other data according to the character card 12 | * Preserve weakness state checkbox 13 | * VR Compatibility 14 | 15 | **Usage:** 16 | * Open the coordinate card UI and a new window which allows you to change cards should open 17 | * Select a character in the top character picker 18 | * Click "Switch" 19 | 20 | **Download:** 21 | * Get the latest release for your game from https://github.com/Mantas-2155X/HCharaSwitcher/releases 22 | 23 | **Installation:** 24 | * Unzip `GAME_HCharaSwitcher.zip` into your game directory. 25 | * You should see `GAME_HCharaSwitcher.dll` in `BepInEx/Plugins/2155X/`. 26 | 27 | **Notes:** 28 | * If you wish to use hs2plug with this, tell the creator Katarsys to fix his plugin. 29 | * Needs https://github.com/BepInEx/BepInEx for the plugin. 30 | -------------------------------------------------------------------------------- /HS2_HCharaSwitcher/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("HS2_HCharaSwitcher")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Mantas-2155X aka 2155X")] 11 | [assembly: AssemblyProduct("HS2_HCharaSwitcher")] 12 | [assembly: AssemblyCopyright("Mantas-2155X aka 2155X Copyright © 2020")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("FBE56F47-6D8B-4D0A-BF72-97A461D0CA29")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion(HS2_HCharaSwitcher.HS2_HCharaSwitcher.VERSION)] 35 | [assembly: AssemblyFileVersion(HS2_HCharaSwitcher.HS2_HCharaSwitcher.VERSION)] -------------------------------------------------------------------------------- /HS2_HCharaSwitcher/Hooks.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using AIChara; 4 | using HarmonyLib; 5 | using Manager; 6 | using UnityEngine; 7 | using UnityEngine.UI; 8 | 9 | namespace HS2_HCharaSwitcher 10 | { 11 | public static class Hooks 12 | { 13 | [HarmonyPostfix, HarmonyPatch(typeof(HScene), "SetStartAnimationInfo")] 14 | public static void HScene_SetStartAnimationInfo_Patch(HScene __instance, HSceneManager ___hSceneManager, HSceneSprite ___sprite, ChaControl[] ___chaMales, ChaControl[] ___chaFemales) 15 | { 16 | HS2_HCharaSwitcher.hScene = __instance; 17 | HS2_HCharaSwitcher.hSprite = ___sprite; 18 | HS2_HCharaSwitcher.hFlagCtrl = HS2_HCharaSwitcher.hScene.ctrlFlag; 19 | HS2_HCharaSwitcher.hSceneManager = ___hSceneManager; 20 | 21 | HS2_HCharaSwitcher.chaMales = ___chaMales; 22 | HS2_HCharaSwitcher.chaFemales = ___chaFemales; 23 | 24 | HS2_HCharaSwitcher.htrav = Traverse.Create(HS2_HCharaSwitcher.hScene); 25 | 26 | Tools.isSelectedFemale = true; 27 | 28 | Tools.CreateUI(); 29 | } 30 | 31 | [HarmonyPostfix, HarmonyPatch(typeof(HSceneSprite), "OnClickCloth")] 32 | public static void HSceneSprite_OnClickCloth_Patch(int mode) 33 | { 34 | if (HS2_HCharaSwitcher.hSprite.objClothPanel.alpha > 0.99f) 35 | Tools.TogglePanel(mode == 2); 36 | else 37 | Tools.TogglePanel(true); 38 | } 39 | 40 | [HarmonyPostfix, HarmonyPatch(typeof(HSceneSprite), "ClothPanelClose")] 41 | public static void HSceneSprite_ClothPanelClose_Patch() => Tools.TogglePanel(false); 42 | 43 | public static void HSceneSpriteChaChoice_Init_ChangeSelection(HSceneSpriteChaChoice __instance, int val) 44 | { 45 | var oldIsSelectedFemale = Tools.isSelectedFemale; 46 | 47 | var list = new List(); 48 | list.AddRange(from chaControl in __instance.Females where chaControl != null && chaControl.fileParam != null select chaControl); 49 | list.AddRange(from chaControl in __instance.Males where chaControl != null && chaControl.fileParam != null select chaControl); 50 | 51 | Tools.isSelectedFemale = list[val].sex == 1; 52 | 53 | if(oldIsSelectedFemale != Tools.isSelectedFemale) 54 | { 55 | foreach (var comp in Object.FindObjectsOfType()) 56 | { 57 | if(comp == null) 58 | continue; 59 | 60 | var trav = Traverse.Create(comp); 61 | 62 | trav.Property("_SelectedID").SetValue(-1); 63 | trav.Field("SelectedLabel").GetValue().text = ""; 64 | trav.Field("filename").SetValue(""); 65 | trav.Field("CardImage").GetValue().texture = trav.Field("CardImageDef").GetValue(); 66 | } 67 | } 68 | 69 | Tools.PopulateList(); 70 | Tools.SetupSwitch(); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /HS2_HCharaSwitcher/HS2_HCharaSwitcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FBE56F47-6D8B-4D0A-BF72-97A461D0CA29} 8 | Library 9 | Properties 10 | HS2_HCharaSwitcher 11 | HS2_HCharaSwitcher 12 | v4.7 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | none 28 | true 29 | ../_bin/HS2/BepInEx/plugins/2155X/ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\..\..\libs\GitHub\BepInEx\latest\BepInEx\core\0Harmony.dll 37 | False 38 | 39 | 40 | ..\..\..\libs\Game\HS2\Assembly-CSharp.dll 41 | False 42 | 43 | 44 | ..\..\..\libs\GitHub\BepInEx\latest\BepInEx\core\BepInEx.dll 45 | False 46 | 47 | 48 | ..\..\..\libs\GitHub\BepInEx\latest\BepInEx\core\BepInEx.Harmony.dll 49 | False 50 | 51 | 52 | ..\..\..\libs\Game\HS2\IL.dll 53 | False 54 | 55 | 56 | 57 | 58 | 59 | 60 | ..\..\..\libs\Game\HS2\UnityEngine.dll 61 | False 62 | 63 | 64 | ..\..\..\libs\Game\HS2\UnityEngine.AnimationModule.dll 65 | False 66 | 67 | 68 | ..\..\..\libs\Game\HS2\UnityEngine.AudioModule.dll 69 | False 70 | 71 | 72 | ..\..\..\libs\Game\HS2\UnityEngine.CoreModule.dll 73 | False 74 | 75 | 76 | ..\..\..\libs\Game\HS2\UnityEngine.UI.dll 77 | False 78 | 79 | 80 | ..\..\..\libs\Game\HS2\UnityEngine.UIModule.dll 81 | False 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /HS2_HCharaSwitcher/HS2_HCharaSwitcher.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | using HarmonyLib; 5 | 6 | using BepInEx; 7 | 8 | using AIChara; 9 | using Manager; 10 | using Illusion.Game; 11 | 12 | namespace HS2_HCharaSwitcher 13 | { 14 | [BepInProcess("HoneySelect2")] 15 | [BepInProcess("HoneySelect2VR")] 16 | [BepInPlugin(nameof(HS2_HCharaSwitcher), nameof(HS2_HCharaSwitcher), VERSION)] 17 | public class HS2_HCharaSwitcher : BaseUnityPlugin 18 | { 19 | public const string VERSION = "1.2.1"; 20 | 21 | public static HS2_HCharaSwitcher instance; 22 | 23 | public static HScene hScene; 24 | public static HSceneSprite hSprite; 25 | public static HSceneFlagCtrl hFlagCtrl; 26 | public static HSceneManager hSceneManager; 27 | 28 | public static ChaControl[] chaMales; 29 | public static ChaControl[] chaFemales; 30 | 31 | public static Traverse htrav; 32 | 33 | public static bool canSwitch; 34 | 35 | private void Awake() 36 | { 37 | instance = this; 38 | 39 | Tools.isSelectedFemale = true; 40 | 41 | var harmony = Harmony.CreateAndPatchAll(typeof(Hooks)); 42 | 43 | var iteratorMethod = AccessTools.Method(typeof(HSceneSpriteChaChoice), "b__17_0"); 44 | var postfix = new HarmonyMethod(typeof(Hooks), nameof(Hooks.HSceneSpriteChaChoice_Init_ChangeSelection)); 45 | harmony.Patch(iteratorMethod, null, postfix); 46 | } 47 | 48 | public static void ChangeCharacter(string card, int id) 49 | { 50 | if (!canSwitch || !ProcBase.endInit || htrav.Field("nowChangeAnim").GetValue() || hFlagCtrl.nowOrgasm) 51 | return; 52 | 53 | switch (id) 54 | { 55 | case 0: 56 | case 1: 57 | var charaF = chaFemales[id]; 58 | if (charaF == null) 59 | return; 60 | 61 | instance.StartCoroutine(ChangeCharacterF(charaF, card, id)); 62 | break; 63 | case 2: 64 | case 3: 65 | var charaM = chaMales[id - 2]; 66 | if (charaM == null) 67 | return; 68 | 69 | instance.StartCoroutine(ChangeCharacterM(charaM, card, id - 2)); 70 | break; 71 | } 72 | } 73 | 74 | public static IEnumerator SwapCharacters(bool swapFemales) 75 | { 76 | if (!canSwitch || !ProcBase.endInit || htrav.Field("nowChangeAnim").GetValue() || hFlagCtrl.nowOrgasm) 77 | yield break; 78 | 79 | if (swapFemales && chaFemales[0] != null && chaFemales[1] != null && chaFemales[0].visibleAll && chaFemales[1].visibleAll) 80 | { 81 | var firstCard = chaFemales[0].chaFile.charaFileName; 82 | var secondCard = chaFemales[1].chaFile.charaFileName; 83 | 84 | yield return ChangeCharacterF(chaFemales[0], secondCard, 0); 85 | yield return ChangeCharacterF(chaFemales[1], firstCard, 1); 86 | } 87 | else if (!swapFemales && chaMales[0] != null && chaMales[1] != null && chaMales[0].visibleAll && chaMales[1].visibleAll) 88 | { 89 | var firstCard = chaMales[0].chaFile.charaFileName; 90 | var secondCard = chaMales[1].chaFile.charaFileName; 91 | 92 | yield return ChangeCharacterM(chaMales[0], secondCard, 0); 93 | yield return ChangeCharacterM(chaMales[1], firstCard, 1); 94 | } 95 | } 96 | 97 | private static IEnumerator ChangeCharacterF(ChaControl chara, string card, int id) 98 | { 99 | canSwitch = false; 100 | 101 | var visible = chara.visibleAll; 102 | 103 | // card, outfit, reload 104 | if (!chara.chaFile.LoadCharaFile(card, chara.sex)) 105 | { 106 | canSwitch = true; 107 | yield break; 108 | } 109 | 110 | chara.ChangeNowCoordinate(); 111 | chara.Reload(); 112 | 113 | hSceneManager.females[id] = chara; 114 | hSceneManager.Personality[id] = chara.chaFile.parameter2.personality; 115 | 116 | chara.visibleAll = visible; 117 | 118 | // States & Rootmotion 119 | hSceneManager.SetFemaleState(id == 0 ? new[] {chaFemales[0], null} : new[] {null, chaFemales[1]}); 120 | 121 | if (id == 0) 122 | { 123 | switch (hSceneManager.FemaleState[0]) 124 | { 125 | case ChaFileDefine.State.Broken: 126 | hFlagCtrl.isFaintness = true; 127 | hFlagCtrl.FaintnessType = 1; 128 | hFlagCtrl.isFaintnessVoice = true; 129 | break; 130 | case ChaFileDefine.State.Aversion: 131 | hSceneManager.isForce = true; 132 | break; 133 | } 134 | 135 | hScene.RootmotionOffsetF = new [] 136 | { 137 | new RootmotionOffset(), 138 | hScene.RootmotionOffsetF[1] 139 | }; 140 | 141 | hScene.RootmotionOffsetF[0].Chara = chaFemales[0]; 142 | } 143 | else 144 | { 145 | switch (hSceneManager.FemaleState[1]) 146 | { 147 | case ChaFileDefine.State.Broken: 148 | hFlagCtrl.FaintnessType = hFlagCtrl.FaintnessType == 1 ? 0 : 2; 149 | break; 150 | case ChaFileDefine.State.Aversion: 151 | hSceneManager.isForceSecond = true; 152 | break; 153 | } 154 | 155 | hScene.RootmotionOffsetF = new [] 156 | { 157 | hScene.RootmotionOffsetF[0], 158 | new RootmotionOffset() 159 | }; 160 | 161 | hScene.RootmotionOffsetF[1].Chara = chaFemales[1]; 162 | } 163 | 164 | // Hitobjects, collisions 165 | if (chara.objTop != null) 166 | { 167 | chara.LoadHitObject(); 168 | hScene.ctrlFemaleCollisionCtrls[id].Init(chara, chara.objHitHead, chara.objHitBody); 169 | } 170 | 171 | // BGM 172 | if (id == 0) 173 | { 174 | var fileGameInfo = hSceneManager.females[0].fileGameInfo2; 175 | 176 | if (hSceneManager.females[0].chaID != -1 && fileGameInfo != null) 177 | Utils.Sound.Play(new Utils.Sound.SettingBGM(BGM.state_normal + (int)fileGameInfo.nowDrawState)); 178 | else if (hSceneManager.females[0].chaID == -1) 179 | Utils.Sound.Play(new Utils.Sound.SettingBGM(BGM.fur)); 180 | } 181 | 182 | // missing shapes stuff L428 - L441 183 | 184 | // More hitobjects 185 | hScene.ctrlHitObjectFemales[id] = new HitObjectCtrl(); 186 | if (chaFemales[id].objBodyBone != null) 187 | { 188 | hScene.ctrlHitObjectFemales[id].id = id; 189 | instance.StartCoroutine(hScene.ctrlHitObjectFemales[id].HitObjInit(1, chaFemales[id].objBodyBone, chaFemales[id])); 190 | } 191 | 192 | // missing shapes stuff L467 - L476 193 | 194 | // FeelHit gauge 195 | if (id == 0) 196 | { 197 | htrav.Field("ctrlFeelHit").Method("FeelHitInit", hSceneManager.Personality[0]).GetValue(); 198 | htrav.Field("ctrlFeelHit").Method("SetFeelCha", chaFemales[0]).GetValue(); 199 | } 200 | 201 | // yures and dynamics 202 | var yures = htrav.Field("ctrlYures").GetValue(); 203 | if (yures != null) 204 | { 205 | yures[id].Init(); 206 | yures[id].SetChaControl(chaFemales[id]); 207 | yures[id].femaleID = id; 208 | } 209 | 210 | if(id == 0) 211 | hScene.ctrlAuto.Load(hSceneManager.strAssetLeaveItToYouFolder, hSceneManager.Personality[0]); 212 | 213 | var dynamics = htrav.Field("ctrlDynamics").GetValue(); 214 | dynamics?[id].Init(chaFemales[id]); 215 | 216 | // Voice stuff 217 | instance.StartCoroutine(id == 1 218 | ? hScene.ctrlVoice.Init(hSceneManager.females[0].fileParam2.personality, 219 | hSceneManager.females[0].fileParam2.voicePitch, hSceneManager.females[0], 220 | hSceneManager.females[1].fileParam2.personality, hSceneManager.females[1].fileParam2.voicePitch, 221 | hSceneManager.females[1]) 222 | : hScene.ctrlVoice.Init(hSceneManager.females[0].fileParam2.personality, 223 | hSceneManager.females[0].fileParam2.voicePitch, hSceneManager.females[0])); 224 | 225 | // More voice stuff 226 | var animatorStateInfo = chaFemales[id].getAnimatorStateInfo(0); 227 | hScene.ctrlVoice.BreathProc(animatorStateInfo, chaFemales[id], id, id == 0 && hFlagCtrl.voice.sleep); 228 | 229 | // Reload UI stuff 230 | hSprite.Setting(chaFemales, chaMales); 231 | Tools.SetupChaChoice(hSprite.charaChoice); 232 | 233 | // ProcBases setparams 234 | var proc = htrav.Field("lstProc").GetValue>(); 235 | var mode = htrav.Field("mode").GetValue(); 236 | var modeCtrl = htrav.Field("modeCtrl").GetValue(); 237 | 238 | var trav = Traverse.Create(proc[mode]); 239 | trav.Field("feelHit").SetValue(htrav.Field("ctrlFeelHit").GetValue()); 240 | trav.Field("chaFemales").SetValue(chaFemales); 241 | trav.Field("ctrlYures").SetValue(yures); 242 | 243 | if (mode != -1 && modeCtrl != -1 && ProcBase.endInit) 244 | proc[mode].setAnimationParamater(); 245 | 246 | yield return 0; 247 | yield return 0; 248 | 249 | // Refreshen from weakness 250 | if (Tools.wakeToggle.isOn && hFlagCtrl.isFaintness) 251 | { 252 | hFlagCtrl.click = HSceneFlagCtrl.ClickKind.RecoverFaintness; 253 | 254 | yield return 0; 255 | yield return 0; 256 | } 257 | 258 | // Reload animation. The copy is unavoidable because there's an equals check for new animation 259 | hSprite.ChangeStart = true; 260 | hFlagCtrl.selectAnimationListInfo = Tools.CopyAnimationInfo(hFlagCtrl.nowAnimationInfo); 261 | 262 | yield return 0; 263 | 264 | canSwitch = true; 265 | } 266 | 267 | private static IEnumerator ChangeCharacterM(ChaControl chara, string card, int id) 268 | { 269 | canSwitch = false; 270 | 271 | var visible = chara.visibleAll; 272 | 273 | // card, outfit, reload 274 | if (!chara.chaFile.LoadCharaFile(card, chara.sex)) 275 | { 276 | canSwitch = true; 277 | yield break; 278 | } 279 | 280 | chara.ChangeNowCoordinate(); 281 | chara.Reload(); 282 | 283 | if (id == 0) 284 | { 285 | chara.isPlayer = true; 286 | hSceneManager.player = chara; 287 | } 288 | 289 | chara.visibleAll = visible; 290 | 291 | chara.LoadHitObject(); 292 | hScene.ctrlMaleCollisionCtrls[id].Init(chaFemales[0], chaMales[id].objHitHead, chaMales[id].objHitBody); 293 | 294 | yield return hScene.ctrlHitObjectMales[id].HitObjInit(0, chaMales[id].objBodyBone, chaMales[id]); 295 | 296 | hScene.ctrlLookAts[id].DankonInit(chaMales[id], chaFemales); 297 | 298 | var yure = htrav.Field("ctrlYureMale").GetValue()[id]; 299 | 300 | yure.Init(); 301 | yure.chaMale = chaMales[id]; 302 | yure.MaleID = id; 303 | 304 | if (chaMales[id] != null && chaMales[id].objBodyBone != null) 305 | { 306 | hScene.ctrlEyeNeckMale[id].Init(chaMales[id], id); 307 | hScene.ctrlEyeNeckMale[id].SetPartner(chaFemales[0].objBodyBone, (chaFemales[1] != null) ? chaFemales[1].objBodyBone : null, (chaMales[id == 0 ? 1 : 0] != null) ? chaMales[id == 0 ? 1 : 0].objBodyBone : null); 308 | } 309 | 310 | hSprite.Setting(chaFemales, chaMales); 311 | Tools.SetupChaChoice(hSprite.charaChoice); 312 | 313 | yield return 0; 314 | 315 | // Reload animation. The copy is unavoidable because there's an equals check for new animation 316 | hSprite.ChangeStart = true; 317 | hFlagCtrl.selectAnimationListInfo = Tools.CopyAnimationInfo(hFlagCtrl.nowAnimationInfo); 318 | 319 | yield return 0; 320 | 321 | canSwitch = true; 322 | } 323 | } 324 | } -------------------------------------------------------------------------------- /HS2_HCharaSwitcher/Tools.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Collections.Generic; 3 | 4 | using HarmonyLib; 5 | 6 | using Manager; 7 | using CharaCustom; 8 | 9 | using UnityEngine; 10 | using UnityEngine.UI; 11 | 12 | namespace HS2_HCharaSwitcher 13 | { 14 | public static class Tools 15 | { 16 | private static HSceneSpriteCoordinatesCard comp; 17 | private static CanvasGroup canvas; 18 | private static Traverse ctrav; 19 | 20 | private static Button applyBtn; 21 | 22 | public static Toggle wakeToggle; 23 | 24 | public static bool isSelectedFemale; 25 | 26 | public static void CreateUI() 27 | { 28 | var UI = GameObject.Find(Application.productName == "HoneySelect2VR" ? "UI/Panel" : "UI"); 29 | if (UI == null) 30 | return; 31 | 32 | var orig = UI.transform.Find("ClothPanel/CoordinatesCard"); 33 | if (orig == null) 34 | return; 35 | 36 | var copy = Object.Instantiate(orig, orig.transform.parent); 37 | 38 | comp = copy.gameObject.GetComponent(); 39 | if (comp == null) 40 | return; 41 | 42 | ctrav = Traverse.Create(comp); 43 | 44 | copy.name = "CharacterCard"; 45 | 46 | var oldPos = copy.localPosition; 47 | copy.localPosition = new Vector3(oldPos.x, -350, oldPos.z); 48 | 49 | canvas = copy.gameObject.GetComponent(); 50 | 51 | var undo = UI.transform.Find("ClothPanel/CharacterCard/CardImageBG/BeforeCoode"); 52 | if (undo == null) 53 | return; 54 | 55 | Object.Destroy(undo.gameObject); 56 | 57 | var content = UI.transform.Find("ClothPanel/CharacterCard/CoodenatePanel/Scroll View/Viewport/Content"); 58 | if (content == null) 59 | return; 60 | 61 | var children = (from Transform child in content where child != null select child.gameObject).ToList(); 62 | children.ForEach(Object.Destroy); 63 | 64 | var image = UI.transform.Find("ClothPanel/CharacterCard/CoodenatePanel/Image"); 65 | if (image == null) 66 | return; 67 | 68 | var imgcopy = Object.Instantiate(image, image.transform.parent.parent); 69 | imgcopy.name = "Separator"; 70 | imgcopy.localPosition = new Vector3(202, 5, 0); 71 | imgcopy.localScale = new Vector3(2, 1, 1); 72 | 73 | var apply = UI.transform.Find("ClothPanel/CharacterCard/CoodenatePanel/DecideCoode"); 74 | if (apply == null) 75 | return; 76 | 77 | var coodPanel = apply.parent; 78 | 79 | var text = apply.gameObject.GetComponentInChildren(); 80 | if (text == null) 81 | return; 82 | 83 | text.text = "Switch"; 84 | 85 | applyBtn = apply.gameObject.GetComponent