├── native_patcher ├── patcher.def └── native_patcher.vcxproj.filters ├── Libs ├── Obi.dll ├── KK_FinalIK.dll └── UnityEngine.UnityWebRequestAudioModule.dll ├── Images ├── cursor.png ├── icon_call.png ├── icon_hand.png ├── icon_play.png ├── icon_warp.png ├── icon_call_xz.png ├── icon_gripmove.png ├── icon_hand_1.png ├── icon_hand_2.png ├── icon_school.png ├── icon_school_1.png ├── icon_school_2.png ├── icon_settings.png ├── logo-github.gif └── credits.txt ├── doc └── img │ ├── icon_hand.png │ ├── icon_menu.png │ ├── icon_warp.png │ └── icon_school.png ├── Shared ├── Fixes │ ├── Mirror │ │ ├── mirror-shader │ │ └── Manager.cs │ ├── BepInExVrLogBackend.cs │ ├── UnityPatches.cs │ └── Util.cs ├── Obsolete │ ├── Fixes │ │ ├── topmostguishader │ │ ├── OpenVRHelperTempfixHook.cs │ │ ├── BepInExVrLogBackend.cs │ │ ├── topmostgui.shader │ │ ├── ReduceAssetUnloads.cs │ │ └── TopmostToolIcons.cs │ └── Controls │ │ ├── BetterWarpTool.cs │ │ ├── ToolUtil.cs │ │ └── BetterMenuTool.cs ├── Features │ ├── SFX │ │ ├── Slap │ │ │ └── Skin │ │ │ │ ├── Rough │ │ │ │ ├── Slaps A1.ogg │ │ │ │ ├── Slaps A2.ogg │ │ │ │ ├── Slaps B1.ogg │ │ │ │ ├── Slaps B4.ogg │ │ │ │ ├── sv_se_h_40.ogg │ │ │ │ ├── sv_se_h_41.ogg │ │ │ │ ├── sv_se_h_42.ogg │ │ │ │ ├── sv_se_h_43.ogg │ │ │ │ ├── sv_se_h_44.ogg │ │ │ │ ├── MeidosSlap00.ogg │ │ │ │ └── MeidosSlap01.ogg │ │ │ │ └── Soft │ │ │ │ ├── Slaps A2.ogg │ │ │ │ ├── sv_se_h_40.ogg │ │ │ │ ├── sv_se_h_42.ogg │ │ │ │ └── sv_se_h_43.ogg │ │ ├── Tap │ │ │ ├── Cloth │ │ │ │ ├── Rough │ │ │ │ │ └── PAT DOWN COAT_1.ogg │ │ │ │ └── Soft │ │ │ │ │ └── SUFFLE AND TAPPING 47.ogg │ │ │ └── Skin │ │ │ │ ├── Soft │ │ │ │ ├── SUFFLE AND TAPPING 35.ogg │ │ │ │ ├── SUFFLE AND TAPPING 4.ogg │ │ │ │ ├── SUFFLE AND TAPPING 49.ogg │ │ │ │ ├── SUFFLE AND TAPPING 63.ogg │ │ │ │ ├── SUFFLE AND TAPPING 8.ogg │ │ │ │ ├── SUFFLE AND TAPPING 114.ogg │ │ │ │ ├── SUFFLE AND TAPPING 115.ogg │ │ │ │ ├── SUFFLE AND TAPPING 118.ogg │ │ │ │ ├── SUFFLE AND TAPPING 5_1.ogg │ │ │ │ └── SUFFLE AND TAPPING 118_1.ogg │ │ │ │ └── Rough │ │ │ │ ├── SUFFLE AND TAPPING 59.ogg │ │ │ │ └── SUFFLE AND TAPPING 114_1.ogg │ │ └── Traverse │ │ │ └── Skin │ │ │ └── Soft │ │ │ └── SUFFLE AND TAPPING 5_1.ogg │ ├── Voice │ │ └── VoiceBundles.cs │ └── PrivacyScreen.cs ├── Constants.cs ├── Interpreters │ ├── Scenes │ │ ├── CustomSceneInterpreter.cs │ │ ├── OtherSceneInterpreter.cs │ │ └── SceneInterpreter.cs │ └── Input │ │ └── InputWait.cs ├── IK │ ├── Amplifier.cs │ ├── NoPosBeforeIK.cs │ ├── OffsetEffector.cs │ ├── OffsetManipulator.cs │ ├── LookAt.cs │ ├── VRIKGuide.cs │ ├── BeforeIK.cs │ ├── VRIK.cs │ └── OffsetModifier.cs ├── Grasp │ ├── IK │ │ └── SlapReaction.cs │ ├── Parts │ │ ├── BodyPartHead.cs │ │ ├── VisualObject.cs │ │ └── BendGoal.cs │ ├── Translate │ │ ├── Translate.cs │ │ ├── TranslateCompensate.cs │ │ └── TranslateMove.cs │ └── Helpers │ │ └── BaseHold.cs ├── AssemblyInfo.cs ├── Utils │ ├── Extensions.cs │ ├── WindowTools.cs │ └── DebugHooks.cs ├── Shared.shproj ├── Handlers │ ├── Helpers │ │ ├── SmoothDamp.cs │ │ └── ItemLag.cs │ ├── Handler.cs │ └── ForGrasp │ │ └── HeadPartGuide.cs ├── Settings │ └── KoikContext.cs ├── Camera │ ├── CameraControlControl.cs │ └── EffectorVFX.cs ├── Controls │ ├── KoikMenuTool.cs │ └── Locomotion.cs └── Holders │ └── VRBoop.cs ├── CharaStudioVR ├── Fixes │ ├── topmostguishader │ ├── OpenVRHelperTempfixHook.cs │ ├── topmostgui.shader │ ├── TopmostToolIcons.cs │ ├── LoadFixHook.cs │ └── SaveLoadSceneHook.cs ├── Util │ ├── ColorZOrderShader │ ├── MaterialHelper.cs │ ├── BepInExVrLogBackend.cs │ └── MoveableGUIObject.cs ├── StudioStandingMode.cs ├── Controls │ ├── BetterWarpTool.cs │ ├── ObjMoveHelper.cs │ └── BetterMenuTool.cs ├── Settings │ └── CharaStudioContext.cs ├── packages.config └── Interpreters │ ├── KKSCharaStudioActor.cs │ └── TransientHead.cs ├── .gitmodules ├── SharedGame ├── Interpreters │ ├── Patches │ │ ├── ActionScenePatches.cs │ │ ├── TalkScenePatches.cs │ │ └── GraspPatches.cs │ └── Extras │ │ ├── InterpreterHooks.cs │ │ └── IntegrationMaleBreath.cs ├── Caress │ └── CaressUtil.cs ├── Handlers │ ├── ForScenes │ │ ├── ActionSceneHandler.cs │ │ └── TalkSceneHandler.cs │ └── Helpers │ │ ├── AibuItemMover.cs │ │ └── KissHelper.cs ├── SharedGame.shproj ├── GameStandingMode.cs ├── Features │ └── HideMaleHead.cs └── SharedGame.projitems ├── SharedStudio ├── Interpreters │ └── KoikStudioInterpreter.cs ├── SharedStudio.projitems ├── SharedStudio.shproj ├── Settings │ └── StudioSettings.cs └── StudioStandingMode.cs ├── PatcherLoader ├── packages.config ├── Properties │ └── AssemblyInfo.cs ├── Loader.cs └── PatcherLoader.csproj ├── nuget.config ├── .gitignore ├── KK_VR ├── packages.config └── VRPlugin.cs ├── KK_Studio ├── packages.config └── VRPlugin.cs ├── LICENSE ├── KKS_VR └── packages.config └── release.ps1 /native_patcher/patcher.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | setup_all 3 | -------------------------------------------------------------------------------- /Libs/Obi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Libs/Obi.dll -------------------------------------------------------------------------------- /Images/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/cursor.png -------------------------------------------------------------------------------- /Libs/KK_FinalIK.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Libs/KK_FinalIK.dll -------------------------------------------------------------------------------- /Images/icon_call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_call.png -------------------------------------------------------------------------------- /Images/icon_hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_hand.png -------------------------------------------------------------------------------- /Images/icon_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_play.png -------------------------------------------------------------------------------- /Images/icon_warp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_warp.png -------------------------------------------------------------------------------- /doc/img/icon_hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/doc/img/icon_hand.png -------------------------------------------------------------------------------- /doc/img/icon_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/doc/img/icon_menu.png -------------------------------------------------------------------------------- /doc/img/icon_warp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/doc/img/icon_warp.png -------------------------------------------------------------------------------- /Images/icon_call_xz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_call_xz.png -------------------------------------------------------------------------------- /Images/icon_gripmove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_gripmove.png -------------------------------------------------------------------------------- /Images/icon_hand_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_hand_1.png -------------------------------------------------------------------------------- /Images/icon_hand_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_hand_2.png -------------------------------------------------------------------------------- /Images/icon_school.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_school.png -------------------------------------------------------------------------------- /Images/icon_school_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_school_1.png -------------------------------------------------------------------------------- /Images/icon_school_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_school_2.png -------------------------------------------------------------------------------- /Images/icon_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/icon_settings.png -------------------------------------------------------------------------------- /Images/logo-github.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Images/logo-github.gif -------------------------------------------------------------------------------- /doc/img/icon_school.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/doc/img/icon_school.png -------------------------------------------------------------------------------- /Shared/Fixes/Mirror/mirror-shader: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Fixes/Mirror/mirror-shader -------------------------------------------------------------------------------- /CharaStudioVR/Fixes/topmostguishader: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/CharaStudioVR/Fixes/topmostguishader -------------------------------------------------------------------------------- /CharaStudioVR/Util/ColorZOrderShader: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/CharaStudioVR/Util/ColorZOrderShader -------------------------------------------------------------------------------- /Shared/Obsolete/Fixes/topmostguishader: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Obsolete/Fixes/topmostguishader -------------------------------------------------------------------------------- /Images/credits.txt: -------------------------------------------------------------------------------- 1 | The hand icon is based on https://www.iconsdb.com/black-icons/stop-3-icon.html 2 | Gratefully copied under CC0. 3 | -------------------------------------------------------------------------------- /Libs/UnityEngine.UnityWebRequestAudioModule.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Libs/UnityEngine.UnityWebRequestAudioModule.dll -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/Slaps A1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/Slaps A1.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/Slaps A2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/Slaps A2.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/Slaps B1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/Slaps B1.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/Slaps B4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/Slaps B4.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Soft/Slaps A2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Soft/Slaps A2.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Soft/sv_se_h_40.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Soft/sv_se_h_40.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Soft/sv_se_h_42.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Soft/sv_se_h_42.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Soft/sv_se_h_43.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Soft/sv_se_h_43.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_40.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_40.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_41.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_41.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_42.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_42.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_43.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_43.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_44.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/sv_se_h_44.ogg -------------------------------------------------------------------------------- /Shared/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace KK_VR 2 | { 3 | internal static class Constants 4 | { 5 | public const string Version = "2.6"; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/MeidosSlap00.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/MeidosSlap00.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Slap/Skin/Rough/MeidosSlap01.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Slap/Skin/Rough/MeidosSlap01.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Cloth/Rough/PAT DOWN COAT_1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Cloth/Rough/PAT DOWN COAT_1.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 35.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 35.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 4.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 49.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 49.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 63.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 63.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 8.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 8.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Cloth/Soft/SUFFLE AND TAPPING 47.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Cloth/Soft/SUFFLE AND TAPPING 47.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Rough/SUFFLE AND TAPPING 59.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Rough/SUFFLE AND TAPPING 59.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 114.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 114.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 115.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 115.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 118.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 118.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 5_1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 5_1.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Rough/SUFFLE AND TAPPING 114_1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Rough/SUFFLE AND TAPPING 114_1.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 118_1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Tap/Skin/Soft/SUFFLE AND TAPPING 118_1.ogg -------------------------------------------------------------------------------- /Shared/Features/SFX/Traverse/Skin/Soft/SUFFLE AND TAPPING 5_1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IllusionMods/KKS_VR/HEAD/Shared/Features/SFX/Traverse/Skin/Soft/SUFFLE AND TAPPING 5_1.ogg -------------------------------------------------------------------------------- /Shared/Interpreters/Scenes/CustomSceneInterpreter.cs: -------------------------------------------------------------------------------- 1 | namespace KK_VR.Interpreters 2 | { 3 | internal class CustomSceneInterpreter : SceneInterpreter 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Shared/Interpreters/Scenes/OtherSceneInterpreter.cs: -------------------------------------------------------------------------------- 1 | namespace KK_VR.Interpreters 2 | { 3 | internal class OtherSceneInterpreter : SceneInterpreter 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "VRGIN_OpenXR"] 2 | path = VRGIN_OpenXR 3 | url = https://github.com/ManlyMarco/VRGIN_OpenXR 4 | [submodule "VRGIN"] 5 | path = VRGIN 6 | url = https://github.com/lotsofbearsKoikatsu/VRGIN 7 | -------------------------------------------------------------------------------- /Shared/IK/Amplifier.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using System.Text; 5 | 6 | //namespace KK_VR.IK 7 | //{ 8 | // internal class Amplifier 9 | // { 10 | // } 11 | //} 12 | -------------------------------------------------------------------------------- /Shared/Grasp/IK/SlapReaction.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using System.Text; 5 | 6 | //namespace KK_VR.Grasp 7 | //{ 8 | // internal class SlapReaction 9 | // { 10 | // } 11 | //} 12 | -------------------------------------------------------------------------------- /SharedGame/Interpreters/Patches/ActionScenePatches.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace KK_VR.Patches 7 | { 8 | internal class ActionScenePatches 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SharedStudio/Interpreters/KoikStudioInterpreter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using VRGIN.Core; 5 | 6 | namespace KK_VR.Interpreters 7 | { 8 | internal class KoikStudioInterpreter : GameInterpreter 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PatcherLoader/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Shared/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using KK_VR; 3 | 4 | [assembly: AssemblyTitle(VRPlugin.Name)] 5 | [assembly: AssemblyDescription("Adds VR support. Launch the game with running SteamVR.")] 6 | [assembly: AssemblyCompany("https://gitgoon.dev/IllusionMods/KKS_VR")] 7 | [assembly: AssemblyProduct(VRPlugin.Name)] 8 | [assembly: AssemblyCopyright("Copyright © 2020, 2021")] 9 | [assembly: AssemblyVersion(VRPlugin.Version)] 10 | -------------------------------------------------------------------------------- /Shared/Utils/Extensions.cs: -------------------------------------------------------------------------------- 1 | namespace KK_VR 2 | { 3 | internal static class Extensions 4 | { 5 | /// 6 | /// Remove a prefix from the given string, if it exists. 7 | /// 8 | public static string StripPrefix(string prefix, string str) 9 | { 10 | if (str.StartsWith(prefix)) return str.Substring(prefix.Length); 11 | return null; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SharedGame/Caress/CaressUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using HarmonyLib; 4 | 5 | namespace KK_VR.Caress 6 | { 7 | public class CaressUtil 8 | { 9 | /// 10 | /// Send a synthetic click event to the hand controls. 11 | /// 12 | public static IEnumerator ClickCo() 13 | { 14 | var consumed = false; 15 | HandCtrlHooks.InjectMouseButtonDown(0, () => consumed = true); 16 | while (!consumed) yield return null; 17 | HandCtrlHooks.InjectMouseButtonUp(0); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Shared/Grasp/Parts/BodyPartHead.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using KK_VR.IK; 5 | using static KK_VR.Grasp.GraspController; 6 | using UnityEngine; 7 | 8 | namespace KK_VR.Grasp 9 | { 10 | internal class BodyPartHead : BodyPart 11 | { 12 | internal readonly KK.RootMotion.FinalIK.FBBIKHeadEffector headEffector; 13 | internal BodyPartHead( 14 | PartName _name, 15 | ChaControl _chara, 16 | Transform _afterIK, 17 | Transform _beforeIK) : base(_name, _afterIK, _beforeIK) 18 | { 19 | headEffector = FBBIK.CreateHeadEffector(_chara, anchor); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Shared/IK/NoPosBeforeIK.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using UnityEngine; 5 | 6 | namespace KK_VR.IK 7 | { 8 | /// 9 | /// Component that assumes rotation of the target bone just before IK solver reads it. 10 | /// 11 | [DefaultExecutionOrder(9900)] 12 | internal class NoPosBeforeIK : MonoBehaviour 13 | { 14 | private Transform _bone; 15 | internal void Init(Transform bone) 16 | { 17 | _bone = bone; 18 | } 19 | internal void LateUpdate() 20 | { 21 | if (_bone == null) return; 22 | transform.rotation = _bone.rotation; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.unityproj 11 | *.suo 12 | *.tmp 13 | *.user 14 | *.userprefs 15 | *.pidb 16 | *.booproj 17 | *.svd 18 | 19 | 20 | # Unity3D generated meta files 21 | *.pidb.meta 22 | 23 | # Unity3D Generated File On Crash Reports 24 | sysinfo.txt 25 | 26 | # Builds 27 | *.apk 28 | *.unitypackage 29 | 30 | *.exe 31 | *.suo 32 | */bin 33 | */obj 34 | 35 | # VSfile. 36 | .vs/ 37 | /VRGIN.Template/Libs/*.dll 38 | packages/ 39 | KoikatuVR/Libs 40 | PatcherLoader/Libs 41 | /bin 42 | /PostBuild.bat 43 | /_ReSharper.Caches 44 | /.editorconfig 45 | 46 | # rider 47 | .idea/ -------------------------------------------------------------------------------- /Shared/Grasp/Translate/Translate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using UnityEngine; 5 | 6 | namespace KK_VR.Grasp 7 | { 8 | internal abstract class Translate 9 | { 10 | internal Translate(Action onStep, Action onFinish) 11 | { 12 | _onStep = onStep; 13 | _onFinish = onFinish; 14 | } 15 | 16 | protected float _lerp; 17 | private readonly Action _onStep; 18 | private readonly Action _onFinish; 19 | 20 | internal virtual void DoStep() 21 | { 22 | _lerp += Time.deltaTime; 23 | _onStep?.Invoke(); 24 | 25 | if (_lerp >= 1f) 26 | { 27 | _onFinish?.Invoke(); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SharedGame/Handlers/ForScenes/ActionSceneHandler.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using System.Text; 5 | //using UnityEngine; 6 | //using VRGIN.Controls; 7 | 8 | //namespace KK_VR.Handlers 9 | //{ 10 | // // No real use for this one unless we'll get VRIK with custom animController. 11 | // // LF animation retargeting. 12 | // internal class ActionSceneHandler : MonoBehaviour 13 | // { 14 | // private Controller _controller; 15 | // private void Awake() 16 | // { 17 | // _controller = GetComponent(); 18 | // } 19 | // internal float GetStickRotation() 20 | // { 21 | // var xy = _controller.Input.GetAxis(); 22 | // return Mathf.Atan2(xy.y, xy.x) * Mathf.Rad2Deg + 90f; 23 | // } 24 | 25 | // } 26 | //} 27 | -------------------------------------------------------------------------------- /SharedGame/Interpreters/Extras/InterpreterHooks.cs: -------------------------------------------------------------------------------- 1 | using KKAPI.MainGame; 2 | using KK_VR.Interpreters; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using UnityEngine; 8 | using static Illusion.Component.ShortcutKey; 9 | 10 | namespace KK_VR.Interpreters 11 | { 12 | // Because I'd much rather use neat hooks instead of re-inventing them. 13 | internal class InterpreterHooks : GameCustomFunctionController 14 | { 15 | protected override void OnStartH(MonoBehaviour proc, HFlag hFlag, bool vr) 16 | { 17 | KoikGameInterp.StartScene(KoikGameInterp.SceneType.HScene, proc); 18 | } 19 | protected override void OnEndH(MonoBehaviour proc, HFlag hFlag, bool vr) 20 | { 21 | KoikGameInterp.EndScene(KoikGameInterp.SceneType.HScene); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CharaStudioVR/Fixes/OpenVRHelperTempfixHook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HarmonyLib; 3 | using Unity.XR.OpenVR; 4 | 5 | // Will break haptic feedback in KKS if enabled. 6 | namespace KK_VR.Fixes 7 | { 8 | /// 9 | /// No idea what exactly it does but it doesn't seem to hurt anything. Originally a part of KKS_CharaStudioVR 10 | /// 11 | public static class OpenVRHelperTempfixHook 12 | { 13 | public static void Patch() 14 | { 15 | new Harmony("OpenVRHelperTempfixHook").PatchAll(typeof(OpenVRHelperTempfixHook)); 16 | } 17 | 18 | [HarmonyPrefix] 19 | [HarmonyPatch(typeof(OpenVRHelpers), "IsUsingSteamVRInput", new Type[] { })] 20 | public static bool PreIsUsingSteamVRInput(ref bool __result) 21 | { 22 | __result = true; 23 | return false; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SharedStudio/SharedStudio.projitems: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 9472fde9-73d0-4f62-adc0-8d0828ee2de6 7 | 8 | 9 | KK_VR 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Shared/Interpreters/Scenes/SceneInterpreter.cs: -------------------------------------------------------------------------------- 1 | using KK_VR.Camera; 2 | using UnityEngine.SceneManagement; 3 | 4 | namespace KK_VR.Interpreters 5 | { 6 | /// 7 | /// Scene based actions that don't correlate with the input 8 | /// 9 | abstract class SceneInterpreter 10 | { 11 | internal virtual void OnStart() 12 | { 13 | #if KKS 14 | // KKS swaps VFX all the time gotta keep up, KK doesn't seem like. 15 | EffectorVFX.Refresh(); 16 | #endif 17 | } 18 | internal virtual void OnDisable() 19 | { 20 | 21 | } 22 | internal virtual void OnUpdate() 23 | { 24 | 25 | } 26 | internal virtual void OnLateUpdate() 27 | { 28 | 29 | } 30 | internal virtual void OnSceneLoaded(Scene scene, LoadSceneMode mode) 31 | { 32 | 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Shared/Obsolete/Fixes/OpenVRHelperTempfixHook.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using HarmonyLib; 3 | //using Unity.XR.OpenVR; 4 | 5 | // Will break haptic feedback in KKS if enabled. 6 | //namespace KKS_VR.Fixes 7 | //{ 8 | // /// 9 | // /// No idea what exactly it does but it doesn't seem to hurt anything. Originally a part of KKS_CharaStudioVR 10 | // /// 11 | // public static class OpenVRHelperTempfixHook 12 | // { 13 | // public static void Patch() 14 | // { 15 | // new Harmony("OpenVRHelperTempfixHook").PatchAll(typeof(OpenVRHelperTempfixHook)); 16 | // } 17 | 18 | // [HarmonyPrefix] 19 | // [HarmonyPatch(typeof(OpenVRHelpers), "IsUsingSteamVRInput", new Type[] { })] 20 | // public static bool PreIsUsingSteamVRInput(ref bool __result) 21 | // { 22 | // __result = true; 23 | // return false; 24 | // } 25 | // } 26 | //} 27 | -------------------------------------------------------------------------------- /CharaStudioVR/Util/MaterialHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using KKAPI.Utilities; 3 | using UnityEngine; 4 | 5 | namespace KK_VR.Util 6 | { 7 | internal class MaterialHelper 8 | { 9 | private static Shader _colorZOrderShader; 10 | 11 | public static Shader GetColorZOrderShader() 12 | { 13 | if (_colorZOrderShader == null) 14 | { 15 | try 16 | { 17 | var bundle = AssetBundle.LoadFromMemory(ResourceUtils.GetEmbeddedResource("ColorZOrderShader")); 18 | _colorZOrderShader = bundle.LoadAsset("ColorZOrder"); 19 | bundle.Unload(false); 20 | } 21 | catch (Exception ex) 22 | { 23 | Console.WriteLine(ex.ToString()); 24 | return null; 25 | } 26 | } 27 | 28 | return _colorZOrderShader; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Shared/IK/OffsetEffector.cs: -------------------------------------------------------------------------------- 1 | //using UnityEngine; 2 | //using System.Collections; 3 | //using KK.RootMotion.FinalIK; 4 | //using System.Collections.Generic; 5 | //using KK_VR.Grasp; 6 | //using RootMotion.FinalIK; 7 | 8 | //namespace KK_VR.IK 9 | //{ 10 | 11 | // /// 12 | // /// Custom positionOffset effector for FBBIK. 13 | // /// 14 | // internal class OffsetEffector : MonoBehaviour 15 | // { 16 | // // Main link. 17 | // private KK.RootMotion.FinalIK.IKEffector _effector; 18 | // //private readonly float weight = 1f; 19 | 20 | // internal void Init(KK.RootMotion.FinalIK.IKEffector effector) 21 | // { 22 | // //_ik = ik; 23 | // _effector = effector; 24 | // //_ik.solver.OnPreUpdate += ModifyOffset; 25 | // } 26 | // private void LateUpdate() 27 | // { 28 | // _effector.positionOffset += transform.position - _effector.bone.position; 29 | // } 30 | // } 31 | //} 32 | -------------------------------------------------------------------------------- /Shared/Grasp/Translate/TranslateCompensate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using UnityEngine; 5 | 6 | namespace KK_VR.Grasp 7 | { 8 | internal class TranslateCompensate : Translate 9 | { 10 | internal TranslateCompensate(Action onStep, Action onFinish, Transform shouldMove, Transform shouldStay) 11 | : base(onStep: onStep, onFinish: onFinish) 12 | { 13 | _shouldMove = shouldMove; 14 | _shouldStay = shouldStay; 15 | _oldPos = _shouldStay.position; 16 | } 17 | // Part to compensate movement with. 18 | private readonly Transform _shouldMove; 19 | 20 | // Part that should stay put. 21 | private readonly Transform _shouldStay; 22 | private Vector3 _oldPos; 23 | 24 | internal override void DoStep() 25 | { 26 | base.DoStep(); 27 | _shouldMove.position += _oldPos - _shouldStay.position; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /KK_VR/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /KK_Studio/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Shared/Shared.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 447ca481-4806-48d1-8e95-d545d8294620 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SharedGame/Interpreters/Patches/TalkScenePatches.cs: -------------------------------------------------------------------------------- 1 | #if KK 2 | using HarmonyLib; 3 | using KK_VR.Interpreters; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace KK_VR.Patches 10 | { 11 | [HarmonyPatch] 12 | internal class TalkScenePatches 13 | { 14 | [HarmonyPostfix] 15 | [HarmonyPatch(typeof(TalkScene), nameof(TalkScene.Awake))] 16 | public static void TalkSceneAwakePrefix(TalkScene __instance) 17 | { 18 | // A cheap surefire way to differentiate between TalkScene/ADV. 19 | //VRPlugin.Logger.LogDebug($"TalkScene:Awake:{KoikGame.CurrentScene}"); 20 | if (KoikGameInterp.CurrentScene == KoikGameInterp.SceneType.TalkScene) 21 | { 22 | ((TalkSceneInterp)KoikGameInterp.SceneInterpreter).OverrideAdv(__instance); 23 | } 24 | else 25 | { 26 | KoikGameInterp.StartScene(KoikGameInterp.SceneType.TalkScene, __instance); 27 | } 28 | } 29 | } 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /SharedGame/SharedGame.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0aa55027-91a2-4fc5-b657-8c2a2b96f160 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SharedStudio/SharedStudio.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9472fde9-73d0-4f62-adc0-8d0828ee2de6 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Shared/Grasp/Translate/TranslateMove.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ADV.Commands.Base; 5 | using UnityEngine; 6 | 7 | namespace KK_VR.Grasp 8 | { 9 | internal class TranslateMove : Translate 10 | { 11 | internal TranslateMove(Transform anchor, Action onStep, Action onFinish) 12 | : base(onStep: onStep, onFinish: onFinish) 13 | { 14 | 15 | _anchor = anchor; 16 | _offsetPos = anchor.localPosition; 17 | _offsetRot = anchor.localRotation; 18 | } 19 | 20 | private readonly Transform _anchor; 21 | private readonly Quaternion _offsetRot; 22 | private readonly Vector3 _offsetPos; 23 | 24 | 25 | internal override void DoStep() 26 | { 27 | base.DoStep(); 28 | var step = Mathf.SmoothStep(0f, 1f, _lerp); 29 | _anchor.localPosition = Vector3.Lerp(_offsetPos, Vector3.zero, step); 30 | _anchor.localRotation = Quaternion.Lerp(_offsetRot, Quaternion.identity, step); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Shared/Handlers/Helpers/SmoothDamp.cs: -------------------------------------------------------------------------------- 1 | using ADV.Commands.Base; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using UnityEngine; 7 | 8 | namespace KK_VR.Handlers 9 | { 10 | /// 11 | /// Wrapped Mathf.SmoothDamp for comfy use 12 | /// 13 | internal class SmoothDamp 14 | { 15 | internal SmoothDamp(float smoothTime = 1f, float target = 1f) 16 | { 17 | _smoothTime = smoothTime; 18 | _target = target; 19 | } 20 | private float _current; 21 | private float _currentVelocity; 22 | private readonly float _target; 23 | private readonly float _smoothTime; 24 | internal float Current => _current; 25 | internal float Increase() 26 | { 27 | return _current = Mathf.SmoothDamp(_current, _target, ref _currentVelocity, _smoothTime); 28 | } 29 | internal float Decrease() 30 | { 31 | return _current = Mathf.SmoothDamp(_current, 0f, ref _currentVelocity, _smoothTime); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SharedGame/Handlers/Helpers/AibuItemMover.cs: -------------------------------------------------------------------------------- 1 | using KK_VR.Interpreters; 2 | using static HandCtrl; 3 | using UnityEngine; 4 | 5 | namespace KK_VR.Handlers 6 | { 7 | /// 8 | /// Feeds ~controller position to the hFlag.xy field 9 | /// 10 | internal class AibuItemMover 11 | { 12 | internal AibuItemMover(AibuColliderKind touch, Transform anchor) 13 | { 14 | _itemId = (int)touch - 2; 15 | _anchor = anchor; 16 | _lastPos = anchor.position; 17 | _item = HSceneInterp.handCtrl.useAreaItems[_itemId].obj.transform; 18 | } 19 | private readonly int _itemId; 20 | private readonly Transform _item; 21 | private readonly Transform _anchor; 22 | private Vector3 _lastPos; 23 | 24 | 25 | internal void Move() 26 | { 27 | var vec = (Vector2)_item.InverseTransformVector(_lastPos - _anchor.position); 28 | vec.y = 0f - vec.y; 29 | HSceneInterp.hFlag.xy[_itemId] += vec * 10f; 30 | _lastPos = _anchor.position; 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SharedStudio/Settings/StudioSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using BepInEx.Configuration; 5 | using VRGIN.Core; 6 | 7 | namespace KK_VR.Settings 8 | { 9 | public class StudioSettings 10 | { 11 | private const string SectionGeneral = "General"; 12 | 13 | public static ConfigEntry NearClipPlane { get; private set; } 14 | 15 | 16 | 17 | public static VRSettings Create(ConfigFile config) 18 | { 19 | var settings = new VRSettings(); 20 | 21 | var ipdScale = config.Bind(SectionGeneral, "IPD Scale", 0.9f, 22 | new ConfigDescription( 23 | "Scale of the camera. The lesser the bigger the world around appears", 24 | new AcceptableValueRange(0.25f, 4f))); 25 | Tie(ipdScale, v => settings.IPDScale = v); 26 | 27 | return settings; 28 | } 29 | 30 | private static void Tie(ConfigEntry entry, Action set) 31 | { 32 | set(entry.Value); 33 | entry.SettingChanged += (_, _1) => set(entry.Value); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /native_patcher/native_patcher.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Source Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /SharedStudio/StudioStandingMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using KK_VR.Controls; 5 | using KK_VR.Features; 6 | using KK_VR.Settings; 7 | using UnityEngine.XR; 8 | using VRGIN.Controls; 9 | using VRGIN.Modes; 10 | 11 | namespace KK_VR 12 | { 13 | internal class StudioStandingMode : StandingMode 14 | { 15 | public override IEnumerable Tools { get; } = new[] 16 | { 17 | typeof(Controls.GameplayTool) 18 | }; 19 | 20 | protected override IEnumerable CreateShortcuts() 21 | { 22 | // Disable all VRGIN shortcuts. We'll define necessary shortcuts 23 | // (if any) by ourselves. 24 | return Enumerable.Empty(); 25 | } 26 | protected override Controller CreateLeftController() 27 | { 28 | var controller = base.CreateLeftController(); 29 | controller.ToolIndex = 0; 30 | return controller; 31 | } 32 | 33 | protected override Controller CreateRightController() 34 | { 35 | var controller = base.CreateRightController(); 36 | controller.ToolIndex = 0; 37 | return controller; 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CharaStudioVR/StudioStandingMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using KK_VR.Controls; 4 | using KK_VR.Features; 5 | using KK_VR.Settings; 6 | using UnityEngine.XR; 7 | using VRGIN.Controls; 8 | using VRGIN.Modes; 9 | 10 | namespace KK_VR 11 | { 12 | internal class StudioStandingMode : StandingMode 13 | { 14 | public override IEnumerable Tools { get; } = new[] 15 | { 16 | typeof(BetterMenuTool), 17 | typeof(BetterWarpTool), 18 | typeof(GripMoveStudioNEOV2Tool) 19 | }; 20 | 21 | protected override Controller CreateLeftController() 22 | { 23 | var controller = base.CreateLeftController(); 24 | AddComponents(controller, EyeSide.Left); 25 | return controller; 26 | } 27 | 28 | protected override Controller CreateRightController() 29 | { 30 | var controller = base.CreateRightController(); 31 | AddComponents(controller, EyeSide.Right); 32 | return controller; 33 | } 34 | 35 | private static void AddComponents(Controller controller, EyeSide controllerSide) 36 | { 37 | if (StudioSettings.EnableBoop.Value) 38 | VRBoopStudio.Initialize(controller, controllerSide); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Shared/Fixes/Mirror/Manager.cs: -------------------------------------------------------------------------------- 1 | using KKAPI.Utilities; 2 | using UnityEngine; 3 | using VRGIN.Core; 4 | using Object = UnityEngine.Object; 5 | 6 | namespace KK_VR.Fixes.Mirror 7 | { 8 | /// 9 | /// Mirrors in the base game look very weird in VR. This object 10 | /// replaces components and materials to fix this issue. 11 | /// 12 | internal class Manager 13 | { 14 | private Material _material; 15 | 16 | public void Fix(MirrorReflection refl) 17 | { 18 | if (refl.GetComponent() != null) return; 19 | var mirror = refl.gameObject; 20 | Object.Destroy(refl); 21 | mirror.AddComponent(); 22 | mirror.GetComponent().material = Material(); 23 | } 24 | 25 | private Material Material() 26 | { 27 | if (_material == null) 28 | { 29 | var bundle = ResourceUtils.GetEmbeddedResource("mirror-shader"); 30 | if (bundle == null) VRLog.Error("Failed to load shader bundle"); 31 | var shader = VRGIN.Helpers.UnityHelper.LoadFromAssetBundle(bundle, "Assets/MirrorReflection.shader"); 32 | if (shader == null) VRLog.Error("Failed to load shader"); 33 | _material = new Material(shader); 34 | } 35 | 36 | return _material; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PatcherLoader/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PatcherLoader")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PatcherLoader")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("7b4a46e3-629c-46cc-adf4-8fe8fced992d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Shared/Fixes/BepInExVrLogBackend.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using BepInEx.Logging; 3 | using VRGIN.Core; 4 | 5 | namespace KK_VR.Fixes 6 | { 7 | public class BepInExVrLogBackend : ILoggerBackend 8 | { 9 | private static ManualLogSource _logger; 10 | 11 | public static void ApplyYourself() 12 | { 13 | _logger = BepInEx.Logging.Logger.CreateLogSource("VRLog"); 14 | 15 | VRLog.Backend = new BepInExVrLogBackend(); 16 | } 17 | 18 | public void Log(string text, object[] args, VRLog.LogMode severity) 19 | { 20 | var logText = args == null ? text : string.Format(text, args); 21 | _logger.Log(ConvertToBepinLogLevel(severity), Format(logText)); 22 | } 23 | 24 | private static string Format(string text) 25 | { 26 | var frame = new StackTrace(4).GetFrame(0); 27 | return string.Format("[{0:0000}] [{2}.{3}] {1}", UnityEngine.Time.realtimeSinceStartup, text, frame.GetMethod().DeclaringType?.Name ?? "???", frame.GetMethod().Name); 28 | } 29 | 30 | private static LogLevel ConvertToBepinLogLevel(VRLog.LogMode severity) 31 | { 32 | return severity switch 33 | { 34 | VRLog.LogMode.Debug => LogLevel.Debug, 35 | VRLog.LogMode.Info => LogLevel.Info, 36 | VRLog.LogMode.Warning => LogLevel.Warning, 37 | VRLog.LogMode.Error => LogLevel.Error, 38 | _ => LogLevel.Message 39 | }; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CharaStudioVR/Util/BepInExVrLogBackend.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using BepInEx.Logging; 3 | using VRGIN.Core; 4 | 5 | namespace KK_VR.Util 6 | { 7 | public class BepInExVrLogBackend : ILoggerBackend 8 | { 9 | private static ManualLogSource _logger; 10 | 11 | public static void ApplyYourself() 12 | { 13 | _logger = BepInEx.Logging.Logger.CreateLogSource("VRLog"); 14 | 15 | VRLog.Backend = new BepInExVrLogBackend(); 16 | } 17 | 18 | public void Log(string text, object[] args, VRLog.LogMode severity) 19 | { 20 | var logText = args == null ? text : string.Format(text, args); 21 | _logger.Log(ConvertToBepinLogLevel(severity), Format(logText)); 22 | } 23 | 24 | private static string Format(string text) 25 | { 26 | var frame = new StackTrace(4).GetFrame(0); 27 | return string.Format("[{0:0000}] [{2}.{3}] {1}", UnityEngine.Time.realtimeSinceStartup, text, frame.GetMethod().DeclaringType?.Name ?? "???", frame.GetMethod().Name); 28 | } 29 | 30 | private static LogLevel ConvertToBepinLogLevel(VRLog.LogMode severity) 31 | { 32 | return severity switch 33 | { 34 | VRLog.LogMode.Debug => LogLevel.Debug, 35 | VRLog.LogMode.Info => LogLevel.Info, 36 | VRLog.LogMode.Warning => LogLevel.Warning, 37 | VRLog.LogMode.Error => LogLevel.Error, 38 | _ => LogLevel.Message 39 | }; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Shared/Obsolete/Fixes/BepInExVrLogBackend.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using BepInEx.Logging; 3 | using VRGIN.Core; 4 | 5 | namespace KKS_VR.Fixes 6 | { 7 | public class BepInExVrLogBackend : ILoggerBackend 8 | { 9 | private static ManualLogSource _logger; 10 | 11 | public static void ApplyYourself() 12 | { 13 | _logger = BepInEx.Logging.Logger.CreateLogSource("VRLog"); 14 | 15 | VRLog.Backend = new BepInExVrLogBackend(); 16 | } 17 | 18 | public void Log(string text, object[] args, VRLog.LogMode severity) 19 | { 20 | var logText = args == null ? text : string.Format(text, args); 21 | _logger.Log(ConvertToBepinLogLevel(severity), Format(logText)); 22 | } 23 | 24 | private static string Format(string text) 25 | { 26 | var frame = new StackTrace(4).GetFrame(0); 27 | return string.Format("[{0:0000}] [{2}.{3}] {1}", UnityEngine.Time.realtimeSinceStartup, text, frame.GetMethod().DeclaringType?.Name ?? "???", frame.GetMethod().Name); 28 | } 29 | 30 | private static LogLevel ConvertToBepinLogLevel(VRLog.LogMode severity) 31 | { 32 | return severity switch 33 | { 34 | VRLog.LogMode.Debug => LogLevel.Debug, 35 | VRLog.LogMode.Info => LogLevel.Info, 36 | VRLog.LogMode.Warning => LogLevel.Warning, 37 | VRLog.LogMode.Error => LogLevel.Error, 38 | _ => LogLevel.Message 39 | }; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Shared/Interpreters/Input/InputWait.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using static VRGIN.Controls.Controller; 3 | using Valve.VR; 4 | 5 | namespace KK_VR.Interpreters 6 | { 7 | internal readonly struct InputWait 8 | { 9 | internal InputWait(int _index, TrackpadDirection _direction, bool _manipulateSpeed, float _duration) 10 | { 11 | index = _index; 12 | direction = _direction; 13 | manipulateSpeed = _manipulateSpeed; 14 | 15 | duration = _duration; 16 | timestamp = Time.time; 17 | finish = Time.time + _duration; 18 | } 19 | internal InputWait(int _index, TrackpadDirection _direction, float _duration) 20 | { 21 | index = _index; 22 | direction = _direction; 23 | 24 | duration = _duration; 25 | timestamp = Time.time; 26 | finish = Time.time + _duration; 27 | } 28 | internal InputWait(int _index, EVRButtonId _button, float _duration) 29 | { 30 | index = _index; 31 | button = _button; 32 | 33 | duration = _duration; 34 | timestamp = Time.time; 35 | finish = Time.time + _duration; 36 | } 37 | internal readonly int index; 38 | internal readonly TrackpadDirection direction; 39 | internal readonly EVRButtonId button; 40 | internal readonly bool manipulateSpeed; 41 | internal readonly float timestamp; 42 | internal readonly float duration; 43 | internal readonly float finish; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SharedGame/Interpreters/Extras/IntegrationMaleBreath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text; 5 | using HarmonyLib; 6 | using static KK_VR.Fixes.Util; 7 | 8 | namespace KK_VR 9 | { 10 | internal static class IntegrationMaleBreath 11 | { 12 | internal static bool IsActive => _active; 13 | private static bool _active; 14 | 15 | /// 16 | /// Provides whatever personality was set in the config for male voice, so we can use it for male reaction. 17 | /// 18 | internal static Func GetMaleBreathPersonality; 19 | 20 | /// 21 | /// Synchronizes state of the plugin when PoV is used. 22 | /// 23 | internal static Action OnPov; 24 | 25 | 26 | internal static void Init() 27 | { 28 | var type = AccessTools.TypeByName("KK_MaleBreath.MaleBreath"); 29 | if (type != null) 30 | { 31 | if (GetMethod(type, "GetPlayerPersonality", out var getPlayerPersonality)) 32 | { 33 | GetMaleBreathPersonality = AccessTools.MethodDelegate>(getPlayerPersonality); 34 | } 35 | 36 | if (GetMethod(type, "OnPov", out var onPov)) 37 | { 38 | OnPov = AccessTools.MethodDelegate>(onPov); 39 | } 40 | _active = GetMaleBreathPersonality != null && OnPov != null; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SharedGame/Interpreters/Patches/GraspPatches.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using KK_VR.Grasp; 3 | 4 | namespace KK_VR.Patches 5 | { 6 | [HarmonyPatch] 7 | internal class GraspPatches 8 | { 9 | [HarmonyPrefix] 10 | [HarmonyPatch(typeof(MotionIK), nameof(MotionIK.Calc))] 11 | public static void MotionIKCalcPrefix(string stateName, MotionIK __instance) 12 | { 13 | GraspHelper.SetDefaultState(__instance.info, stateName); 14 | 15 | } 16 | [HarmonyPostfix] 17 | [HarmonyPatch(typeof(MotionIK), nameof(MotionIK.Calc))] 18 | public static void MotionIKCalcPostfix(MotionIK __instance) 19 | { 20 | GraspHelper.SetWorkingState(__instance.info); 21 | } 22 | 23 | 24 | //[HarmonyPrefix] 25 | //[HarmonyPatch(typeof(HitReaction), nameof(HitReaction.HitsEffector))] 26 | //public static void HitsEffectorPrefix(int _nid, ref Vector3[] forces, HitReaction __instance) 27 | //{ 28 | // var chara = __instance.ik.GetComponentInParent(); 29 | // for (var i = 0; i < forces.Length; i++) 30 | // { 31 | // forces[i] = GraspController.Instance.HitReactionWorkaround( 32 | // forces[i], 33 | // chara, 34 | // __instance.effectorHit[_nid].effectorHitPoints[i].effectorLinks[0].effector); 35 | // } 36 | // foreach (var force in forces) 37 | // { 38 | // //VRPlugin.Logger.LogDebug($"{force}"); 39 | // } 40 | //} 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Shared/Features/Voice/VoiceBundles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace KK_VR.Features 7 | { 8 | public static class VoiceBundles 9 | { 10 | 11 | // Look up maleBreath, i do it way more eloquently there. 12 | 13 | // ** is a Stand-in for personality Id. 14 | // ^ is a Stand-in for experience level. 15 | public static List Shorts = 16 | [ 17 | "h/h_ko_**_0^_005_00", 18 | "h/h_ko_**_0^_005_01", 19 | "h/h_ko_**_0^_005_02", 20 | "h/h_ko_**_0^_005_03", 21 | "h/h_ko_**_0^_005_04", 22 | "h/h_ko_**_0^_005_05", 23 | "h/h_ko_**_0^_005_06", 24 | "h/h_ko_**_0^_005_07", 25 | "h/h_ko_**_0^_005_08", 26 | "h/h_ko_**_0^_005_09", 27 | "h/h_ko_**_0^_006_00", 28 | "h/h_ko_**_0^_006_01", 29 | "h/h_ko_**_0^_006_02", 30 | "h/h_ko_**_0^_006_03", 31 | "h/h_ko_**_0^_006_04", 32 | "h/h_ko_**_0^_006_05", 33 | "h/h_ko_**_0^_006_06", 34 | "h/h_ko_**_0^_006_07", 35 | "h/h_ko_**_0^_006_08", 36 | "h/h_ko_**_0^_006_09", 37 | ]; 38 | 39 | public static List Laughs = 40 | [ 41 | "adv/com_ev_**_464_00", 42 | "adv/com_ev_**_464_01", 43 | //"adv/com_ev_**_464_02", 44 | "adv/com_ev_**_465_00", 45 | "adv/com_ev_**_465_01", 46 | "adv/com_ev_**_465_02", 47 | //"adm/adm_**_tanon_02" 48 | ]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SharedGame/GameStandingMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using KK_VR.Features; 5 | using KK_VR.Settings; 6 | using VRGIN.Controls; 7 | using VRGIN.Modes; 8 | 9 | namespace KK_VR 10 | { 11 | /// 12 | /// Initialize controllers and custom tools 13 | /// 14 | internal class GameStandingMode : StandingMode 15 | { 16 | public override IEnumerable Tools { get; } = 17 | [ 18 | typeof(Controls.GameplayTool) 19 | ]; 20 | 21 | protected override IEnumerable CreateShortcuts() 22 | { 23 | // Disable all VRGIN shortcuts. We'll define necessary shortcuts 24 | // (if any) by ourselves. 25 | return Enumerable.Empty(); 26 | } 27 | 28 | protected override Controller CreateLeftController() 29 | { 30 | var controller = base.CreateLeftController(); 31 | controller.ToolIndex = 0; 32 | return controller; 33 | } 34 | 35 | protected override Controller CreateRightController() 36 | { 37 | var controller = base.CreateRightController(); 38 | controller.ToolIndex = 0; 39 | return controller; 40 | } 41 | 42 | protected override void SyncCameras() 43 | { 44 | // Do nothing. CameraControlControl and friends take care of this. 45 | } 46 | 47 | protected override void InitializeScreenCapture() 48 | { 49 | // Don't enable CapturePanorama because it looks broken (throws an 50 | // exception). 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CharaStudioVR/Controls/BetterWarpTool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using HarmonyLib; 4 | using Valve.VR; 5 | using VRGIN.Controls; 6 | using VRGIN.Controls.Tools; 7 | 8 | 9 | // MainGame doesn't have warp tool no more. 10 | namespace KK_VR.Controls 11 | { 12 | /// 13 | /// WarpTool version that cancels teleporting when user tries grab moving 14 | /// 15 | /// 16 | internal class BetterWarpTool : WarpTool 17 | { 18 | protected override void OnUpdate() 19 | { 20 | // If current state is moving/rotating the teleport target, cancel it so that grab moving 21 | // can be done (by default it's stuck in teleport mode until you switch tools) 22 | if (Controller.GetPressDown(EVRButtonId.k_EButton_Grip)) 23 | { 24 | var tv = Traverse.Create(this); 25 | var state = tv.Field("State"); 26 | var stateVal = state.GetValue(); 27 | if (stateVal == 1 || stateVal == 2) 28 | { 29 | state.SetValue(0); 30 | tv.Method("SetVisibility", new[] { typeof(bool) }).GetValue(false); 31 | } 32 | } 33 | 34 | base.OnUpdate(); 35 | } 36 | 37 | //public override List GetHelpTexts() 38 | //{ 39 | // return new List(new[] 40 | // { 41 | // ToolUtil.HelpTrackpadCenter(Owner, "Press to teleport"), 42 | // ToolUtil.HelpGrip(Owner, "Hold to move"), 43 | // }.Where(x => x != null)); 44 | //} 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Shared/Obsolete/Controls/BetterWarpTool.cs: -------------------------------------------------------------------------------- 1 | //using System.Collections.Generic; 2 | //using System.Linq; 3 | //using HarmonyLib; 4 | //using Valve.VR; 5 | //using VRGIN.Controls; 6 | //using VRGIN.Controls.Tools; 7 | 8 | 9 | // Warp tool is gone. 10 | //namespace KKS_VR.Controls 11 | //{ 12 | // /// 13 | // /// WarpTool version that cancels teleporting when user tries grab moving 14 | // /// 15 | // /// 16 | // internal class BetterWarpTool : WarpTool 17 | // { 18 | // protected override void OnUpdate() 19 | // { 20 | // // If current state is moving/rotating the teleport target, cancel it so that grab moving 21 | // // can be done (by default it's stuck in teleport mode until you switch tools) 22 | // if (Controller.GetPressDown(EVRButtonId.k_EButton_Grip)) 23 | // { 24 | // var tv = Traverse.Create(this); 25 | // var state = tv.Field("State"); 26 | // var stateVal = state.GetValue(); 27 | // if (stateVal == 1 || stateVal == 2) 28 | // { 29 | // state.SetValue(0); 30 | // tv.Method("SetVisibility", new[] { typeof(bool) }).GetValue(false); 31 | // } 32 | // } 33 | 34 | // base.OnUpdate(); 35 | // } 36 | 37 | // public override List GetHelpTexts() 38 | // { 39 | // return new List(new[] 40 | // { 41 | // ToolUtil.HelpTrackpadCenter(Owner, "Press to teleport"), 42 | // ToolUtil.HelpGrip(Owner, "Hold to move"), 43 | // }.Where(x => x != null)); 44 | // } 45 | // } 46 | //} 47 | -------------------------------------------------------------------------------- /Shared/IK/OffsetManipulator.cs: -------------------------------------------------------------------------------- 1 | using KK_VR.Grasp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using UnityEngine; 7 | 8 | namespace KK_VR.IK 9 | { 10 | // Simplified version from FinalIK scripts 11 | internal abstract class OffsetManipulator : OffsetModifier 12 | { 13 | protected class EffectorLink 14 | { 15 | internal EffectorLink(KK.RootMotion.FinalIK.IKEffector _effector, Vector3 _offset, float _weight) 16 | { 17 | effector = _effector; 18 | defaultWeight = _weight; 19 | weight = _weight; 20 | offset = _offset; 21 | } 22 | internal readonly KK.RootMotion.FinalIK.IKEffector effector; 23 | internal readonly Vector3 offset; 24 | internal readonly float defaultWeight; 25 | internal float weight; 26 | internal void MultiplyWeight(float multiplier) => weight = Mathf.Clamp01(weight * multiplier); 27 | } 28 | protected readonly List _linkList = []; 29 | 30 | protected void OnInit(KK.RootMotion.FinalIK.FullBodyBipedIK ik) 31 | { 32 | _ik = ik; 33 | _ik.solver.OnPreUpdate += ModifyOffset; 34 | } 35 | internal void Add(BodyPart bodyPart, float weight) 36 | { 37 | _linkList.Add(new EffectorLink(bodyPart.effector, this.transform.InverseTransformPoint(bodyPart.anchor.position), weight)); 38 | } 39 | protected override void OnModifyOffset() 40 | { 41 | foreach (var link in _linkList) 42 | { 43 | link.effector.positionOffset += (transform.TransformPoint(link.offset) - (link.effector.bone.position + link.effector.positionOffset)) * link.weight; 44 | } 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Shared/IK/LookAt.cs: -------------------------------------------------------------------------------- 1 | using KK.RootMotion.FinalIK; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using UnityEngine; 7 | using VRGIN.Core; 8 | 9 | namespace KK_VR.IK 10 | { 11 | // Requires proper implementation with added scripts to manage it in SensibleH (WIP). 12 | internal class LookAt 13 | { 14 | internal static LookAtController SetupLookAtIK(ChaControl chara) 15 | { 16 | return null; 17 | var fbbik = chara.objAnim.GetComponent(); 18 | if (fbbik == null) return null; 19 | var lookAt = chara.objAnim.AddComponent(); 20 | Transform[] spine = 21 | [ 22 | fbbik.references.spine[0], 23 | fbbik.references.spine[1], 24 | fbbik.references.spine[1].Find("cf_j_spine03"), 25 | fbbik.references.spine[2] 26 | ]; 27 | lookAt.solver.SetChain(spine, fbbik.references.head, null, fbbik.references.root); 28 | lookAt.solver.bodyWeight = 0.6f; 29 | lookAt.solver.headWeight = 0.8f; 30 | var lookAtController = chara.objAnim.AddComponent(); 31 | lookAtController.ik = lookAt; 32 | lookAtController.weightSmoothTime = 1f; 33 | lookAtController.targetSwitchSmoothTime = 1f; 34 | lookAtController.maxRadiansDelta = 0.25f; 35 | lookAtController.maxMagnitudeDelta = 0.25f; 36 | lookAtController.slerpSpeed = 1f; 37 | lookAtController.maxRootAngle = 180f; 38 | 39 | //lookController.target = VR.Camera.Head; 40 | //_spine03 = fbbik.references.spine[1].Find("cf_j_spine03"); 41 | lookAtController.target = VR.Camera.Head; //hFlag.ctrlCamera.transform; 42 | return lookAtController; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Shared/Fixes/UnityPatches.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using UnityEngine; 3 | using UnityEngine.UI; 4 | 5 | // Collection of patches to Unity. 6 | 7 | namespace KK_VR.Fixes 8 | { 9 | /// 10 | /// GraphicRaycaster.sortOrderPriority and GraphicRaycaster.renderOrderPriority 11 | /// respect the render/sort order of the canvas only when the render mode 12 | /// is set to ScreenSpaceOverlay. This causes incorrect UI item to receive 13 | /// clicks (#40). 14 | /// 15 | /// This class defines patches to ensure that these properties remain 16 | /// referenced after the canvas is modified to render to the VRGIN GUI 17 | /// camera. 18 | /// 19 | [HarmonyPatch(typeof(GraphicRaycaster))] 20 | internal class GraphicRaycasterPatches 21 | { 22 | [HarmonyPatch(nameof(GraphicRaycaster.sortOrderPriority), MethodType.Getter)] 23 | [HarmonyPostfix] 24 | private static void PostGetSortOrderPriority(GraphicRaycaster __instance, ref Canvas ___m_Canvas, ref int __result) 25 | { 26 | ___m_Canvas = ___m_Canvas ?? __instance.GetComponent(); 27 | if (___m_Canvas.worldCamera == _vrGuiCamera) __result = ___m_Canvas.sortingOrder; 28 | } 29 | 30 | [HarmonyPatch(nameof(GraphicRaycaster.renderOrderPriority), MethodType.Getter)] 31 | [HarmonyPostfix] 32 | private static void PostGetRenderOrderPriority(GraphicRaycaster __instance, ref Canvas ___m_Canvas, ref int __result) 33 | { 34 | ___m_Canvas = ___m_Canvas ?? __instance.GetComponent(); 35 | if (___m_Canvas.worldCamera == _vrGuiCamera) __result = ___m_Canvas.rootCanvas.renderOrder; 36 | } 37 | 38 | public static void Initialize() 39 | { 40 | _vrGuiCamera = GameObject.Find("VRGIN_GUICamera")?.GetComponent(); 41 | } 42 | 43 | private static UnityEngine.Camera _vrGuiCamera; 44 | 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Shared/Features/PrivacyScreen.cs: -------------------------------------------------------------------------------- 1 | using KK_VR.Settings; 2 | using UnityEngine; 3 | using UnityEngine.UI; 4 | using VRGIN.Core; 5 | using Object = UnityEngine.Object; 6 | 7 | namespace KK_VR.Features 8 | { 9 | /// 10 | /// Class that allows the user to hide contents of the desktop mirror screen. 11 | /// 12 | internal class PrivacyScreen 13 | { 14 | private static Canvas _blocker; 15 | 16 | internal static void UpdatePrivacyScreen() 17 | { 18 | if (KoikSettings.PrivacyScreen.Value) 19 | Create(); 20 | else 21 | Destroy(); 22 | } 23 | 24 | private static void Create() 25 | { 26 | if (_blocker != null) return; 27 | 28 | var blocker = new GameObject("PrivacyScreen").AddComponent(); 29 | blocker.transform.SetParent(VR.Camera.transform, false); 30 | blocker.renderMode = RenderMode.ScreenSpaceOverlay; 31 | // We can't go all the way to 32767 because many of the game's canvases 32 | // try to go one above all other canvas' sorting orders, causing 33 | // an unwanted wrap-around behaviour. 34 | blocker.sortingOrder = 30000; 35 | var panel = new GameObject("Panel").AddComponent(); 36 | panel.transform.SetParent(blocker.transform, false); 37 | panel.color = Color.black; 38 | panel.rectTransform.sizeDelta = new Vector2(Screen.width, Screen.height); 39 | _blocker = blocker; 40 | } 41 | 42 | private static void Destroy() 43 | { 44 | if (_blocker != null) 45 | { 46 | Object.Destroy(_blocker.gameObject); 47 | _blocker = null; 48 | } 49 | } 50 | 51 | public static bool IsOwnedCanvas(Canvas other) 52 | { 53 | return _blocker != null && _blocker == other; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Shared/IK/VRIKGuide.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using System.Text; 5 | //using UnityEngine; 6 | //using VRGIN.Controls; 7 | 8 | //namespace KK_VR.Features 9 | //{ 10 | // // Component to atleast somehow walk in VRIK. 11 | // // Proper setup would require retargeting bunch of animations on KK body rig, 12 | // // and that would require someone who knows their way around the blender. 13 | // // Based on FinalIK demo. 14 | // internal class VRIKGuide : MonoBehaviour 15 | // { 16 | // private Animator _animator; 17 | // private Controller _controller; 18 | // private Transform _root; 19 | // private bool _run; 20 | // private float _speed; 21 | // private float _angleVel; 22 | // private float _speedVel; 23 | // private float _accelerationTime = 0.2f; 24 | 25 | // internal void StartMovement() 26 | // { 27 | 28 | // } 29 | // internal void OnTrigger(bool press) 30 | // { 31 | 32 | // } 33 | // //private float GetStickAngle() 34 | // //{ 35 | // // return 36 | // //} 37 | 38 | // private void UpdatePosition() 39 | // { 40 | 41 | // var xy = _controller.Input.GetAxis(); 42 | // var deg = Mathf.Atan2(xy.y, xy.x) * Mathf.Rad2Deg + 90f; 43 | // Move(xy.magnitude); 44 | // } 45 | // private void Rotate() 46 | // { 47 | // // Base current rotation on Head.forward + angle from joystick. 48 | // //var angle = 49 | 50 | // } 51 | // private void Move(float distance) 52 | // { 53 | // _speed = Mathf.SmoothDamp(_speed, _run ? 1f : 0.5f, ref _speedVel, _accelerationTime); 54 | // distance *= _speed; 55 | 56 | // _animator.SetFloat("Locomotion", distance); 57 | 58 | // _root.position += Time.deltaTime * distance * _root.forward; 59 | // } 60 | // } 61 | //} 62 | -------------------------------------------------------------------------------- /CharaStudioVR/Fixes/topmostgui.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/Sprite Outline" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Texture", 2D) = "white" {} 6 | } 7 | 8 | Subshader 9 | { 10 | Tags{ "RenderType" = "TransparentCutout" "Queue" = "Transparent+0" "IsEmissive" = "true" } 11 | Pass 12 | { 13 | ZTest Always Cull Off ZWrite Off 14 | Fog { Mode off } 15 | CGPROGRAM 16 | #pragma target 3.0 17 | #pragma vertex vert 18 | #pragma fragment frag 19 | 20 | #include "UnityCG.cginc" 21 | 22 | sampler2D _MainTex; 23 | float4 _MainTex_ST; 24 | float4 _MainTex_TexelSize; 25 | 26 | struct appdata 27 | { 28 | float4 vertex : POSITION; 29 | float2 uv : TEXCOORD0; 30 | }; 31 | 32 | struct v2f 33 | { 34 | float2 uv : TEXCOORD0; 35 | float4 vertex : SV_POSITION; 36 | }; 37 | v2f vert (appdata v) 38 | { 39 | v2f o; 40 | o.vertex = UnityObjectToClipPos(v.vertex); 41 | o.uv = TRANSFORM_TEX(v.uv, _MainTex); 42 | return o; 43 | } 44 | 45 | #define _f 12.2f; 46 | 47 | fixed4 frag (v2f i) : SV_Target 48 | { 49 | fixed4 col = tex2D(_MainTex, i.uv); 50 | 51 | float2 texel = _MainTex_TexelSize * _f; 52 | fixed leftPixel = tex2D(_MainTex, i.uv + float2(-texel.x, 0)).a; 53 | fixed upPixel = tex2D(_MainTex, i.uv + float2(0, texel.y)).a; 54 | fixed rightPixel = tex2D(_MainTex, i.uv + float2(texel.x, 0)).a; 55 | fixed bottomPixel = tex2D(_MainTex, i.uv + float2(0, -texel.y)).a; 56 | 57 | fixed sum = leftPixel + upPixel + rightPixel + bottomPixel; 58 | fixed outline = step(1, sum) * step(sum, 4); 59 | clip(outline + col.a - 0.5); 60 | return lerp(fixed4(0,0,0,1), col, col.a); 61 | } 62 | 63 | ENDCG 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Shared/Obsolete/Fixes/topmostgui.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/Sprite Outline" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Texture", 2D) = "white" {} 6 | } 7 | 8 | Subshader 9 | { 10 | Tags{ "RenderType" = "TransparentCutout" "Queue" = "Transparent+0" "IsEmissive" = "true" } 11 | Pass 12 | { 13 | ZTest Always Cull Off ZWrite Off 14 | Fog { Mode off } 15 | CGPROGRAM 16 | #pragma target 3.0 17 | #pragma vertex vert 18 | #pragma fragment frag 19 | 20 | #include "UnityCG.cginc" 21 | 22 | sampler2D _MainTex; 23 | float4 _MainTex_ST; 24 | float4 _MainTex_TexelSize; 25 | 26 | struct appdata 27 | { 28 | float4 vertex : POSITION; 29 | float2 uv : TEXCOORD0; 30 | }; 31 | 32 | struct v2f 33 | { 34 | float2 uv : TEXCOORD0; 35 | float4 vertex : SV_POSITION; 36 | }; 37 | v2f vert (appdata v) 38 | { 39 | v2f o; 40 | o.vertex = UnityObjectToClipPos(v.vertex); 41 | o.uv = TRANSFORM_TEX(v.uv, _MainTex); 42 | return o; 43 | } 44 | 45 | #define _f 12.2f; 46 | 47 | fixed4 frag (v2f i) : SV_Target 48 | { 49 | fixed4 col = tex2D(_MainTex, i.uv); 50 | 51 | float2 texel = _MainTex_TexelSize * _f; 52 | fixed leftPixel = tex2D(_MainTex, i.uv + float2(-texel.x, 0)).a; 53 | fixed upPixel = tex2D(_MainTex, i.uv + float2(0, texel.y)).a; 54 | fixed rightPixel = tex2D(_MainTex, i.uv + float2(texel.x, 0)).a; 55 | fixed bottomPixel = tex2D(_MainTex, i.uv + float2(0, -texel.y)).a; 56 | 57 | fixed sum = leftPixel + upPixel + rightPixel + bottomPixel; 58 | fixed outline = step(1, sum) * step(sum, 4); 59 | clip(outline + col.a - 0.5); 60 | return lerp(fixed4(0,0,0,1), col, col.a); 61 | } 62 | 63 | ENDCG 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /CharaStudioVR/Fixes/TopmostToolIcons.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HarmonyLib; 3 | using KKAPI.Utilities; 4 | using UnityEngine; 5 | using VRGIN.Controls; 6 | using VRGIN.Core; 7 | 8 | 9 | // Only single tool left, no icons needed. 10 | namespace KK_VR.Fixes 11 | { 12 | /// 13 | /// Fix custom tool icons not being on top of the black circle 14 | /// 15 | public class TopmostToolIcons 16 | { 17 | public static void Patch() 18 | { 19 | new Harmony("TopmostToolIconsHook").PatchAll(typeof(TopmostToolIcons)); 20 | } 21 | 22 | private static Shader _guiShader; 23 | 24 | public static Shader GetGuiShader() 25 | { 26 | if (_guiShader == null) 27 | { 28 | var bundle = AssetBundle.LoadFromMemory(ResourceUtils.GetEmbeddedResource("topmostguishader")); 29 | _guiShader = bundle.LoadAsset("topmostgui"); 30 | if (_guiShader == null) throw new ArgumentNullException(nameof(_guiShader)); 31 | //_guiShader = new Material(guiShader); 32 | bundle.Unload(false); 33 | } 34 | 35 | return _guiShader; 36 | } 37 | 38 | [HarmonyPostfix] 39 | [HarmonyPatch(typeof(Controller), "OnUpdate")] 40 | private static void ToolIconFixHook(Controller __instance) 41 | { 42 | var tools = __instance.Tools; 43 | var any = 0; 44 | 45 | foreach (var tool in tools) 46 | { 47 | var canvasRenderer = tool.Icon?.GetComponent(); 48 | if (canvasRenderer == null) return; 49 | 50 | var orig = canvasRenderer.GetMaterial(); 51 | if (orig == null || orig.shader == _guiShader) continue; 52 | 53 | any++; 54 | 55 | var copy = new Material(GetGuiShader()); 56 | canvasRenderer.SetMaterial(copy, 0); 57 | } 58 | 59 | if (any == 0) return; 60 | 61 | Canvas.ForceUpdateCanvases(); 62 | 63 | VRLog.Debug($"Replaced materials on {any} tool icon renderers"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Shared/Obsolete/Fixes/ReduceAssetUnloads.cs: -------------------------------------------------------------------------------- 1 | //using System.Collections.Generic; 2 | //using System.Reflection; 3 | //using System.Reflection.Emit; 4 | //using HarmonyLib; 5 | //using KKAPI.Utilities; 6 | //using UnityEngine; 7 | //using VRGIN.Core; 8 | 9 | //namespace KK_VR.Fixes 10 | //{ 11 | // /// 12 | 13 | // ///Guess it was moved to and conflicts with the IllusionFix nowadays, as UniRx freaks out all the time because of this. 14 | 15 | // /// Avoid triggering resource unload when loading UI-only scenes. 16 | // /// todo move into illusionfixes? 17 | // /// 18 | // [HarmonyPatch] 19 | // public class ReduceAssetUnloads 20 | // { 21 | // private static IEnumerable TargetMethods() 22 | // { 23 | // yield return CoroutineUtils.GetMoveNext(AccessTools.Method(typeof(Manager.Scene), nameof(Manager.Scene.LoadStart))); 24 | // } 25 | 26 | // private static AsyncOperation MaybeUnloadUnusedAssets() 27 | // { 28 | //#if KK 29 | // if (Manager.Scene.Instance.IsFadeNow) 30 | //#else 31 | // if (Manager.Scene.IsFadeNow) 32 | //#endif 33 | // { 34 | // return Resources.UnloadUnusedAssets(); 35 | // } 36 | // else 37 | // { 38 | // VRLog.Info("Skipping unload"); 39 | // return null; 40 | // } 41 | // } 42 | // private static IEnumerable Transpiler(IEnumerable insts, MethodBase __originalMethod) 43 | // { 44 | // foreach (var inst in insts) 45 | // if (inst.opcode == OpCodes.Call && 46 | // inst.operand is MethodInfo method && 47 | // method.Name == "UnloadUnusedAssets") 48 | // { 49 | // yield return CodeInstruction.Call(() => MaybeUnloadUnusedAssets()); 50 | // //VRPlugin.Logger.LogDebug("Patched UnloadUnusedAssets in " + __originalMethod.GetFullName()); 51 | // } 52 | // else 53 | // { 54 | // yield return inst; 55 | // } 56 | // } 57 | // } 58 | //} 59 | -------------------------------------------------------------------------------- /Shared/Utils/WindowTools.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace KK_VR 7 | { 8 | internal static class WindowTools 9 | { 10 | private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); 11 | 12 | [DllImport("user32.dll")] 13 | private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); 14 | 15 | [DllImport("user32.dll", SetLastError = true)] 16 | private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 17 | 18 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 19 | private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 20 | 21 | [DllImport("User32.dll")] 22 | private static extern int SetForegroundWindow(IntPtr hWnd); 23 | 24 | private const string GET_CLASS_NAME_MAGIC = "UnityWndClass"; 25 | 26 | private static IntPtr WindowHandle = IntPtr.Zero; 27 | 28 | private static void GetWindowHandle() 29 | { 30 | var pid = Process.GetCurrentProcess().Id; 31 | EnumWindows((w, param) => 32 | { 33 | if (w == IntPtr.Zero) return true; 34 | if (GetWindowThreadProcessId(w, out uint lpdwProcessId) == 0) return true; 35 | if (lpdwProcessId != pid) return true; 36 | var cn = new StringBuilder(256); 37 | if (GetClassName(w, cn, cn.Capacity) == 0) return true; 38 | if (cn.ToString() != GET_CLASS_NAME_MAGIC) return true; 39 | WindowHandle = w; 40 | return false; 41 | }, IntPtr.Zero); 42 | 43 | if (WindowHandle == IntPtr.Zero) 44 | Console.WriteLine("Could not find Unity window handle"); 45 | else 46 | Console.WriteLine("Found Unity window handle ptr=" + WindowHandle); 47 | } 48 | 49 | public static void BringWindowToFront() 50 | { 51 | if (WindowHandle == IntPtr.Zero) GetWindowHandle(); 52 | SetForegroundWindow(WindowHandle); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SharedGame/Handlers/Helpers/KissHelper.cs: -------------------------------------------------------------------------------- 1 | using KK_VR.Interpreters; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using UnityEngine; 7 | using VRGIN.Core; 8 | using Random = UnityEngine.Random; 9 | 10 | namespace KK_VR.Handlers 11 | { 12 | /// 13 | /// Starts proactive kiss 14 | /// 15 | internal class KissHelper 16 | { 17 | private float _kissAttemptTimestamp; 18 | private float _kissAttemptChance; 19 | private Transform _eyes; 20 | private Transform _shoulders; 21 | 22 | internal KissHelper(Transform eyes, Transform shoulders) 23 | { 24 | _eyes = eyes; 25 | _shoulders = shoulders; 26 | var heroine = HSceneInterp.hFlag.lstHeroine[0]; 27 | _kissAttemptChance = 0.1f + ((int)heroine.HExperience - 1) * 0.15f + (heroine.weakPoint == 0 ? 0.1f : 0f); 28 | } 29 | internal void AttemptProactiveKiss() 30 | { 31 | if (_kissAttemptTimestamp < Time.time) 32 | { 33 | //VRPlugin.Logger.LogDebug($"AttemptProactiveKiss:chance - {_kissAttemptChance}"); 34 | var headPos = VR.Camera.Head.position; 35 | if (Random.value < _kissAttemptChance 36 | && !HSceneInterp.IsVoiceActive 37 | && HSceneInterp.IsIdleOutside(HSceneInterp.hFlag.nowAnimStateName) 38 | && Mathf.Abs(Mathf.DeltaAngle(_shoulders.eulerAngles.y, _eyes.eulerAngles.y)) < 30f 39 | && Vector3.Distance(_eyes.position, headPos) < 0.55f 40 | && Vector3.Angle(headPos - _eyes.position, _eyes.forward) < 30f) 41 | { 42 | //_kissAttempt = true; 43 | //_kissDistance = 0.4f; 44 | HSceneInterp.LeanToKiss(); 45 | SetAttemptTimestamp(2f + Random.value * 2f); 46 | } 47 | else 48 | { 49 | SetAttemptTimestamp(); 50 | } 51 | } 52 | } 53 | private void SetAttemptTimestamp(float modifier = 1f) 54 | { 55 | _kissAttemptTimestamp = Time.time + (20f * modifier); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Shared/Obsolete/Fixes/TopmostToolIcons.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using HarmonyLib; 3 | //using KKAPI.Utilities; 4 | //using UnityEngine; 5 | //using VRGIN.Controls; 6 | //using VRGIN.Core; 7 | 8 | 9 | // Only single tool left, no icons needed. 10 | //namespace KKS_VR.Fixes 11 | //{ 12 | // /// 13 | // /// Fix custom tool icons not being on top of the black circle 14 | // /// 15 | // public class TopmostToolIcons 16 | // { 17 | // public static void Patch() 18 | // { 19 | // new Harmony("TopmostToolIconsHook").PatchAll(typeof(TopmostToolIcons)); 20 | // } 21 | 22 | // private static Shader _guiShader; 23 | 24 | // public static Shader GetGuiShader() 25 | // { 26 | // if (_guiShader == null) 27 | // { 28 | // var bundle = AssetBundle.LoadFromMemory(ResourceUtils.GetEmbeddedResource("topmostguishader")); 29 | // _guiShader = bundle.LoadAsset("topmostgui"); 30 | // if (_guiShader == null) throw new ArgumentNullException(nameof(_guiShader)); 31 | // //_guiShader = new Material(guiShader); 32 | // bundle.Unload(false); 33 | // } 34 | 35 | // return _guiShader; 36 | // } 37 | 38 | // [HarmonyPostfix] 39 | // [HarmonyPatch(typeof(Controller), "OnUpdate")] 40 | // private static void ToolIconFixHook(Controller __instance) 41 | // { 42 | // var tools = __instance.Tools; 43 | // var any = 0; 44 | 45 | // foreach (var tool in tools) 46 | // { 47 | // var canvasRenderer = tool.Icon?.GetComponent(); 48 | // if (canvasRenderer == null) return; 49 | 50 | // var orig = canvasRenderer.GetMaterial(); 51 | // if (orig == null || orig.shader == _guiShader) continue; 52 | 53 | // any++; 54 | 55 | // var copy = new Material(GetGuiShader()); 56 | // canvasRenderer.SetMaterial(copy, 0); 57 | // } 58 | 59 | // if (any == 0) return; 60 | 61 | // Canvas.ForceUpdateCanvases(); 62 | 63 | // VRLog.Debug($"Replaced materials on {any} tool icon renderers"); 64 | // } 65 | // } 66 | //} 67 | -------------------------------------------------------------------------------- /Shared/Fixes/Util.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using KK_VR.Handlers; 3 | using KK_VR.Holders; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using UnityEngine; 10 | 11 | namespace KK_VR.Fixes 12 | { 13 | public static class Util 14 | { 15 | public static Vector3 Divide(Vector3 a, Vector3 b) => new(a.x / b.x, a.y / b.y, a.z / b.z); 16 | public static GameObject CreatePrimitive(PrimitiveType primitive, Vector3 size, Transform parent, Color color, float alpha, bool removeCollider = true) 17 | { 18 | return CreatePrimitive(primitive, size, parent, new Color(color.r, color.g, color.b, alpha), removeCollider); 19 | } 20 | public static GameObject CreatePrimitive(PrimitiveType primitive, Vector3 size, Transform parent, Color color, bool removeCollider = true) 21 | { 22 | var sphere = GameObject.CreatePrimitive(primitive); 23 | if (removeCollider) 24 | { 25 | GameObject.Destroy(sphere.GetComponent()); 26 | } 27 | var renderer = sphere.GetComponent(); 28 | renderer.material = Holder.Material; 29 | renderer.material.color = color; 30 | if (parent != null) 31 | sphere.transform.SetParent(parent, false); 32 | sphere.transform.localScale = size; 33 | return sphere; 34 | } 35 | public static float SignedAngle(Vector3 from, Vector3 to, Vector3 axis) 36 | { 37 | float unsignedAngle = Vector3.Angle(from, to); 38 | 39 | float cross_x = from.y * to.z - from.z * to.y; 40 | float cross_y = from.z * to.x - from.x * to.z; 41 | float cross_z = from.x * to.y - from.y * to.x; 42 | float sign = Mathf.Sign(axis.x * cross_x + axis.y * cross_y + axis.z * cross_z); 43 | return unsignedAngle * sign; 44 | } 45 | /// True if found, false if not(null) 46 | internal static bool GetMethod(Type type, string methodName, out MethodInfo method) 47 | { 48 | method = AccessTools.FirstMethod(type, m => m.Name.Equals(methodName)); 49 | return method != null; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Shared/Grasp/Parts/VisualObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using static KK_VR.Grasp.GraspController; 3 | using UnityEngine; 4 | using KK_VR.Interpreters; 5 | using KK_VR.Settings; 6 | 7 | namespace KK_VR.Grasp 8 | { 9 | /// 10 | /// Visual cue of a character's body part to help during IK manipulation. 11 | /// 12 | internal class VisualObject 13 | { 14 | internal readonly GameObject gameObject; 15 | private readonly Renderer _renderer; 16 | private bool _enable = KoikSettings.IKShowGuideObjects.Value; 17 | private readonly static List _colors = 18 | [ 19 | new(1f, 0f, 0f, 0.2f), // Red 20 | new(0f, 1f, 0f, 0.2f), // Green 21 | new(0f, 0f, 1f, 0.2f), // Blue 22 | new(1f, 1f, 1f, 0.2f) // Gray 23 | ]; 24 | internal VisualObject(BodyPart bodyPart) 25 | { 26 | gameObject = KK_VR.Fixes.Util.CreatePrimitive( 27 | PrimitiveType.Sphere, 28 | GetGuideObjectSize(bodyPart.name), 29 | bodyPart.afterIK, 30 | _colors[3], 31 | removeCollider: false); 32 | gameObject.name = "ik_vl_" + bodyPart.GetLowerCaseName(); 33 | _renderer = gameObject.GetComponent(); 34 | _renderer.enabled = false; 35 | } 36 | internal void Show() => _renderer.enabled = _enable && true; 37 | internal void Hide() => _renderer.enabled = false; 38 | internal void SetState(bool state) 39 | { 40 | _enable = state; 41 | if (state) 42 | { 43 | Show(); 44 | } 45 | else 46 | { 47 | Hide(); 48 | } 49 | } 50 | internal void SetColor(bool active) 51 | { 52 | _renderer.material.color = active ? _colors[1] : _colors[3]; 53 | } 54 | private Vector3 GetGuideObjectSize(PartName partName) 55 | { 56 | return partName switch 57 | { 58 | PartName.ShoulderL or PartName.ShoulderR => new Vector3(0.14f, 0.14f, 0.14f), 59 | PartName.HandL or PartName.HandR => new Vector3(0.11f, 0.11f, 0.11f), 60 | _ => new Vector3(0.2f, 0.2f, 0.2f), 61 | }; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /CharaStudioVR/Fixes/LoadFixHook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BepInEx.Logging; 3 | using HarmonyLib; 4 | using KK_VR.Interpreters; 5 | using Studio; 6 | using VRGIN.Core; 7 | 8 | namespace KK_VR.Fixes 9 | { 10 | public static class LoadFixHook 11 | { 12 | //public static bool forceSetStandingMode; 13 | //private static bool standingMode; 14 | 15 | public static void InstallHook() 16 | { 17 | new Harmony("HS2VRStudioNEOV2VR.LoadFixHook").PatchAll(typeof(LoadFixHook)); 18 | } 19 | 20 | [HarmonyPrefix] 21 | [HarmonyPatch(typeof(SceneLoadScene), "OnClickLoad", new Type[] { })] 22 | public static bool LoadScenePreHook(Studio.Studio __instance) 23 | { 24 | try 25 | { 26 | VRPlugin.Logger.Log(LogLevel.Debug, "Start Scene Loading."); 27 | if (VRManager.Instance.Mode is StudioStandingMode) ((KKSCharaStudioInterpreter)VR.Manager.Interpreter).ForceResetVRMode(); 28 | } 29 | catch (Exception obj) 30 | { 31 | VRLog.Error(obj); 32 | } 33 | 34 | return true; 35 | } 36 | 37 | //[HarmonyPrefix] 38 | //[HarmonyPatch(typeof(Scene), "UnloadBaseScene", new Type[] { })] 39 | //public static void UnloadBaseScenePreHook() 40 | //{ 41 | // try 42 | // { 43 | // KKSCharaStudioVRPlugin.PluginLogger.Log(LogLevel.Debug, "Start Scene or Map Unloading."); 44 | // if (VRManager.Instance.Mode is GenericStandingMode) 45 | // standingMode = true; 46 | // else 47 | // standingMode = false; 48 | // } 49 | // catch (Exception obj) 50 | // { 51 | // VRLog.Error(obj); 52 | // } 53 | //} 54 | 55 | // todo invalid patch target 56 | //[HarmonyPostfix] 57 | //[HarmonyPatch(typeof(Map), nameof(Map.OnLoadAfter), new Type[] { typeof(string) })] 58 | //public static void OnLoadAfter(Map __instance, string levelName) 59 | //{ 60 | // if (standingMode) 61 | // { 62 | // KKSCharaStudioVRPlugin.PluginLogger.Log(LogLevel.Debug, "Start Scene or Map Unloading."); 63 | // (VR.Manager.Interpreter as KKSCharaStudioInterpreter).ForceResetVRMode(); 64 | // } 65 | //} 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /CharaStudioVR/Settings/CharaStudioContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | using UnityEngine; 4 | using VRGIN.Core; 5 | using VRGIN.Visuals; 6 | 7 | namespace KK_VR.Settings 8 | { 9 | [XmlRoot("Context")] 10 | public class CharaStudioContext : IVRManagerContext 11 | { 12 | private readonly DefaultMaterialPalette _Materials; 13 | private readonly VRSettings _Settings; 14 | [XmlIgnore] public IMaterialPalette Materials => _Materials; 15 | [XmlIgnore] public VRSettings Settings => _Settings; 16 | 17 | public bool ConfineMouse { get; set; } 18 | public bool EnforceDefaultGUIMaterials { get; set; } 19 | public bool GUIAlternativeSortingMode { get; set; } 20 | public float GuiFarClipPlane { get; set; } 21 | public string GuiLayer { get; set; } 22 | public float GuiNearClipPlane { get; set; } 23 | public int IgnoreMask { get; set; } 24 | public string InvisibleLayer { get; set; } 25 | public Color PrimaryColor { get; set; } 26 | public bool SimulateCursor { get; set; } 27 | public string UILayer { get; set; } 28 | public int UILayerMask { get; set; } 29 | public float UnitToMeter { get; set; } 30 | public float NearClipPlane { get; set; } 31 | public GUIType PreferredGUI { get; set; } 32 | public string Version { get; set; } 33 | public float MaxFarClipPlane { get; set; } 34 | public int GuiMaterialRenderQueue { get; set; } 35 | Type IVRManagerContext.VoiceCommandType { get; } 36 | public bool ForceIMGUIOnScreen { get; set; } 37 | 38 | public CharaStudioContext(VRSettings settings) 39 | { 40 | _Materials = new DefaultMaterialPalette(); 41 | _Settings = settings; 42 | ConfineMouse = true; 43 | EnforceDefaultGUIMaterials = false; 44 | GUIAlternativeSortingMode = false; 45 | GuiLayer = "Default"; 46 | GuiFarClipPlane = 1000f; 47 | GuiNearClipPlane = -1000f; 48 | IgnoreMask = 0; 49 | InvisibleLayer = "Ignore Raycast"; 50 | PrimaryColor = Color.cyan; 51 | SimulateCursor = true; 52 | UILayer = "UI"; 53 | UILayerMask = LayerMask.GetMask(UILayer); 54 | UnitToMeter = 1f; 55 | NearClipPlane = 0.001f; 56 | PreferredGUI = GUIType.uGUI; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Shared/Handlers/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace KK_VR.Handlers 5 | { 6 | /// 7 | /// Component responsible for the management of functions associated with colliders 8 | /// 9 | internal class Handler : MonoBehaviour 10 | { 11 | protected virtual Tracker Tracker { get; set; } 12 | /// 13 | /// True if something is being tracked. Track for recently blacklisted items continues, but new ones don't get added. 14 | /// 15 | internal virtual bool IsBusy => Tracker.IsBusy; 16 | /// 17 | /// Can be true only after 'UpdateNoBlacks()' if every item in track is blacklisted. 18 | /// 19 | internal bool InBlack => Tracker.colliderInfo == null; 20 | internal Transform GetTrackTransform => Tracker.colliderInfo.collider.transform; 21 | internal ChaControl GetChara => Tracker.colliderInfo.chara; 22 | 23 | 24 | protected virtual void OnDisable() 25 | { 26 | Tracker.ClearTracker(); 27 | } 28 | 29 | protected virtual void OnTriggerEnter(Collider other) 30 | { 31 | Tracker.AddCollider(other); 32 | } 33 | 34 | protected virtual void OnTriggerExit(Collider other) 35 | { 36 | Tracker.RemoveCollider(other); 37 | } 38 | internal void ClearBlacks() 39 | { 40 | Tracker.RemoveBlacks(); 41 | } 42 | /// 43 | /// Null-ghost panacea. No clue what they are. 44 | /// 45 | internal void ClearTracker() 46 | { 47 | Tracker.ClearTracker(); 48 | } 49 | internal void UpdateTrackerNoBlacks() 50 | { 51 | Tracker.SetInfoBlackListByID(); 52 | } 53 | /// 54 | /// Option to use provided blackList instead of setup blackDic 55 | /// 56 | internal void UpdateTrackerNoBlacks(List blackList) 57 | { 58 | Tracker.SetInfoBlackListByType(blackList); 59 | } 60 | /// 61 | /// Pick the most interesting bodyPart from the current track. 62 | /// 63 | internal void UpdateTracker(ChaControl tryToAvoid = null) 64 | { 65 | Tracker.SetSuggestedInfo(tryToAvoid); 66 | #if DEBUG 67 | Tracker.DebugShowActive(); 68 | #endif 69 | } 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /Shared/Grasp/Helpers/BaseHold.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using UnityEngine; 5 | using VRGIN.Core; 6 | 7 | namespace KK_VR.Grasp 8 | { 9 | /// 10 | /// Holds/manipulates whole character 11 | /// 12 | internal class BaseHold 13 | { 14 | internal BaseHold(BodyPart _bodyPart, Transform _objAnim, Transform _attachPoint) 15 | { 16 | bodyPart = _bodyPart; 17 | objAnim = _objAnim; 18 | attachPoint = _attachPoint; 19 | offsetPos = _attachPoint.InverseTransformDirection(_objAnim.transform.position - _attachPoint.position); 20 | offsetRot = Quaternion.Inverse(_attachPoint.rotation) * _objAnim.transform.rotation; 21 | } 22 | private readonly BodyPart bodyPart; 23 | private readonly Transform objAnim; 24 | private readonly Transform attachPoint; 25 | private Quaternion offsetRot; 26 | private Vector3 offsetPos; 27 | private int scrollDir; 28 | private bool scrollInc; 29 | 30 | private readonly Quaternion _left = Quaternion.Euler(0f, 1f, 0f); 31 | private readonly Quaternion _right = Quaternion.Euler(0f, -1f, 0f); 32 | 33 | internal void Execute() 34 | { 35 | if (scrollDir != 0) 36 | { 37 | if (scrollDir == 1) 38 | { 39 | DoBaseHoldVerticalScroll(scrollInc); 40 | } 41 | else 42 | { 43 | DoBaseHoldHorizontalScroll(scrollInc); 44 | } 45 | } 46 | objAnim.transform.SetPositionAndRotation( 47 | attachPoint.position + attachPoint.TransformDirection(offsetPos), 48 | attachPoint.rotation * offsetRot 49 | ); 50 | } 51 | 52 | internal void StartBaseHoldScroll(int direction, bool increase) 53 | { 54 | scrollDir = direction; 55 | scrollInc = increase; 56 | } 57 | 58 | internal void StopBaseHoldScroll() 59 | { 60 | scrollDir = 0; 61 | } 62 | 63 | private void DoBaseHoldVerticalScroll(bool increase) 64 | { 65 | offsetPos += VR.Camera.Head.forward * (Time.deltaTime * (increase ? 10f : -10f)); 66 | } 67 | 68 | 69 | private void DoBaseHoldHorizontalScroll(bool left) 70 | { 71 | offsetRot *= (left ? _left : _right); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Shared/Settings/KoikContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml.Serialization; 6 | using UnityEngine; 7 | using VRGIN.Controls.Speech; 8 | using VRGIN.Core; 9 | using VRGIN.Helpers; 10 | using VRGIN.Visuals; 11 | 12 | namespace KK_VR.Settings 13 | { 14 | [XmlRoot("Context")] 15 | public class KoikContext : IVRManagerContext 16 | { 17 | private DefaultMaterialPalette _Materials; 18 | 19 | private VRSettings _Settings; 20 | 21 | [XmlIgnore] public IMaterialPalette Materials => _Materials; 22 | 23 | [XmlIgnore] public VRSettings Settings => _Settings; 24 | 25 | public bool ConfineMouse { get; set; } 26 | 27 | public bool EnforceDefaultGUIMaterials { get; set; } 28 | 29 | public bool GUIAlternativeSortingMode { get; set; } 30 | 31 | public float GuiFarClipPlane { get; set; } 32 | 33 | public string GuiLayer { get; set; } 34 | 35 | public float GuiNearClipPlane { get; set; } 36 | 37 | public int IgnoreMask { get; set; } 38 | 39 | public string InvisibleLayer { get; set; } 40 | 41 | public Color PrimaryColor { get; set; } 42 | 43 | public bool SimulateCursor { get; set; } 44 | 45 | public string UILayer { get; set; } 46 | 47 | public int UILayerMask { get; set; } 48 | 49 | public float UnitToMeter { get; set; } 50 | 51 | public float NearClipPlane { get; set; } 52 | 53 | public GUIType PreferredGUI { get; set; } 54 | 55 | public string Version { get; set; } 56 | 57 | public float MaxFarClipPlane { get; set; } 58 | 59 | public int GuiMaterialRenderQueue { get; set; } 60 | 61 | Type IVRManagerContext.VoiceCommandType { get; } 62 | 63 | public bool ForceIMGUIOnScreen { get; set; } 64 | 65 | 66 | public KoikContext(VRSettings settings) 67 | { 68 | _Materials = new DefaultMaterialPalette(); 69 | _Settings = settings; 70 | ConfineMouse = true; 71 | EnforceDefaultGUIMaterials = false; 72 | GUIAlternativeSortingMode = false; 73 | GuiLayer = "Default"; 74 | GuiFarClipPlane = 1000f; 75 | GuiNearClipPlane = -1000f; 76 | IgnoreMask = 0; 77 | InvisibleLayer = "Ignore Raycast"; 78 | PrimaryColor = Color.cyan; 79 | SimulateCursor = true; 80 | UILayer = "UI"; 81 | UILayerMask = LayerMask.GetMask(UILayer); 82 | UnitToMeter = 1f; 83 | NearClipPlane = 0.001f; 84 | PreferredGUI = GUIType.uGUI; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Shared/Camera/CameraControlControl.cs: -------------------------------------------------------------------------------- 1 | using VRGIN.Core; 2 | 3 | namespace KK_VR.Camera 4 | { 5 | /// 6 | /// CameraControlControl disables a CameraControl_Ver2 object and 7 | /// do its work instead. It's meant to be attached to a GameObject 8 | /// to which a CameraControl_Ver2 is already attached. 9 | /// 10 | /// The CameraControl_Ver2 implments a camera that can be rotated, 11 | /// zoomed and moved with a mouse, and is used in H scenes and in Maker. 12 | /// It's also responsible for "map masking", a feature that hides 13 | /// walls that blocks the view of the character. 14 | /// 15 | /// In VR, these features are not only unnecessary but are harmful, 16 | /// because the control features fight with Unity's attempt to 17 | /// set the camera position, and map masking causes random parts 18 | /// of walls to dissappear. 19 | /// 20 | /// For this reason we want to disable almost all of its 21 | /// functionalities, except that we want to keep its ability to unlock 22 | /// cursor. We also ensure that the controlled camera always has the same 23 | /// transform as the VR camera, so that (1) characters can correctly look 24 | /// at the camera, and (2) the directional light, which is a child of the 25 | /// main camera, has the right orientation. 26 | /// 27 | internal class CameraControlControl : ProtectedBehaviour 28 | { 29 | private CameraControl_Ver2 _control; 30 | 31 | protected override void OnStart() 32 | { 33 | _control = GetComponent(); 34 | if (_control == null) 35 | { 36 | VRLog.Error("CameraControlControl: CameraControl_Ver2 was not found"); 37 | } 38 | 39 | if (_control.enabled) 40 | _control.enabled = false; 41 | else 42 | VRLog.Warn("control is already disabled"); 43 | } 44 | 45 | protected override void OnUpdate() 46 | { 47 | var head = VR.Camera.Head; 48 | transform.SetPositionAndRotation(head.position, head.rotation); 49 | // One of the default macros from GameObjectList enables the camera 50 | // control. We make sure that it remains desabled. 51 | if (_control != null) 52 | { 53 | _control.enabled = false; 54 | } 55 | } 56 | 57 | protected override void OnLateUpdate() 58 | { 59 | if (_control.isCursorLock && Singleton.IsInstance()) 60 | { 61 | Singleton.Instance.SetCursorLock(false); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Shared/IK/BeforeIK.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace KK_VR.IK 4 | { 5 | /// 6 | /// Component that assumes orientation of the target bone just before IK solver reads it. 7 | /// 8 | [DefaultExecutionOrder(9900)] 9 | public class BeforeIK : MonoBehaviour 10 | { 11 | private Transform _bone; 12 | /// 13 | /// Creates new GameObject with this component, initiates it 14 | /// and attaches to "cf_t_root" bone of particular chara. 15 | /// 16 | internal static Transform CreateObj(string name, ChaControl chara, Transform targetBone) 17 | { 18 | 19 | var beforeIKObj = new GameObject("ik_b4_" + name).transform; 20 | beforeIKObj.SetPositionAndRotation(targetBone.position, targetBone.rotation); 21 | beforeIKObj.parent = chara.transform.Find("BodyTop/p_cf_body_bone/cf_t_root"); 22 | beforeIKObj.gameObject.AddComponent().Init(targetBone); 23 | return beforeIKObj; 24 | } 25 | internal static Transform CreateObj(string name, ChaControl chara, Transform targetBone, Transform targetRotation) 26 | { 27 | 28 | var beforeIKObj = new GameObject("ik_b4_" + name).transform; 29 | beforeIKObj.SetPositionAndRotation(targetBone.position, targetBone.rotation); 30 | beforeIKObj.parent = chara.transform.Find("BodyTop/p_cf_body_bone/cf_t_root"); 31 | beforeIKObj.gameObject.AddComponent().Init(targetBone); 32 | return beforeIKObj; 33 | } 34 | //private Vector3 _offsetPos; 35 | 36 | // Default quaternion isn't identity. 37 | //private Quaternion _offsetRot = Quaternion.identity; 38 | public void Init(Transform bone) 39 | { 40 | _bone = bone; 41 | } 42 | //public void SetOffsets(Vector3 offsetPosition, Quaternion offsetRotation) 43 | //{ 44 | // _offsetPos = offsetPosition; 45 | // _offsetRot = offsetRotation; 46 | //} 47 | //public void SetDebug(float x, float y, float z) 48 | //{ 49 | // _offsetRot = Quaternion.Euler(x, y, z); 50 | //} 51 | //public void Retarget(Transform bone) => _bone = bone; 52 | 53 | //public void UpdateTransform() 54 | //{ 55 | // if (_bone == null || _chara == null) return; 56 | // transform.SetPositionAndRotation(_bone.TransformPoint(_offsetPos), _bone.rotation * _offsetRot); 57 | //} 58 | public void LateUpdate() 59 | { 60 | if (_bone == null) return; 61 | transform.SetPositionAndRotation(_bone.position, _bone.rotation); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /KKS_VR/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SharedGame/Features/HideMaleHead.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using VRGIN.Core; 3 | 4 | namespace KK_VR.Features 5 | { 6 | /// 7 | /// A component to be attached to every male character. 8 | /// 9 | internal class HideMaleHead : ProtectedBehaviour 10 | { 11 | public static bool ForceHideHead { get; set; } 12 | public static bool ForceShowHead { get; set; } 13 | 14 | private ChaControl _control; 15 | 16 | protected override void OnAwake() 17 | { 18 | _control = GetComponent(); 19 | } 20 | 21 | protected override void OnLateUpdate() 22 | { 23 | // Hide the head if the VR camera is inside it. 24 | // This also essentially negates the effect of scenairo-controlled 25 | // head hiding, which is found in some ADV scenes. 26 | if (ForceShowHead) 27 | { 28 | _control.fileStatus.visibleHeadAlways = true; 29 | return; 30 | } 31 | var head = _control.objHead?.transform; 32 | if (_control.objTop?.activeSelf == true && head != null) 33 | { 34 | var wasVisible = _control.fileStatus.visibleHeadAlways; 35 | var vrEye = VR.Camera.transform; 36 | var headCenter = head.TransformPoint(0, 0.12f, -0.04f); 37 | var sqrDistance = (vrEye.position - headCenter).sqrMagnitude; 38 | var visible = !ForceHideHead && 0.0361f < sqrDistance; // 19 centimeters 39 | _control.fileStatus.visibleHeadAlways = visible; 40 | if (wasVisible && !visible) 41 | { 42 | // The VR camera may have just teleported into the head. In 43 | // this case, it's important that the head disappears with 44 | // 0 frame delay, so we proactively deactive it here. 45 | _control.objHead.SetActive(false); 46 | foreach (var hair in _control.objHair) 47 | { 48 | hair.SetActive(false); 49 | } 50 | } 51 | } 52 | else 53 | { 54 | _control.fileStatus.visibleHeadAlways = true; 55 | } 56 | } 57 | } 58 | 59 | [HarmonyPatch(typeof(ChaControl))] 60 | internal class HideMaleHeadPatches 61 | { 62 | [HarmonyPatch(nameof(ChaControl.Initialize))] 63 | [HarmonyPostfix] 64 | static void PostInitialize(ChaControl __instance) 65 | { 66 | if (__instance.sex == 0 && !__instance.transform.parent.name.Equals("HScene")) 67 | { 68 | // In H we do this more lazily/appropriately through POV. 69 | __instance.GetOrAddComponent(); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Shared/Obsolete/Controls/ToolUtil.cs: -------------------------------------------------------------------------------- 1 | //using System.Linq; 2 | //using UnityEngine; 3 | //using VRGIN.Controls; 4 | //using VRGIN.Core; 5 | 6 | 7 | // Descriptions are gone. 8 | //namespace KKS_VR.Controls 9 | //{ 10 | // internal class ToolUtil 11 | // { 12 | // public static HelpText HelpTrigger(Controller controller, string description) 13 | // { 14 | // return MakeHelpText(controller, description, new Vector3(0.06f, -0.04f, -0.05f), Vector3.zero, "trigger"); 15 | // } 16 | 17 | // public static HelpText HelpGrip(Controller controller, string description) 18 | // { 19 | // return MakeHelpText(controller, description, new Vector3(-0.06f, 0, -0.05f), Vector3.zero, "lgrip", "handgrip"); 20 | // } 21 | 22 | // public static HelpText HelpTrackpadCenter(Controller controller, string description) 23 | // { 24 | // return MakeHelpText(controller, description, new Vector3(0, 0.06f, 0.02f), Vector3.zero, "trackpad", "thumbstick"); 25 | // } 26 | 27 | // public static HelpText HelpTrackpadLeft(Controller controller, string description) 28 | // { 29 | // return MakeHelpText(controller, description, new Vector3(-0.05f, 0.04f, 0), new Vector3(-0.01f, 0, 0), "trackpad", "thumbstick"); 30 | // } 31 | 32 | // public static HelpText HelpTrackpadRight(Controller controller, string description) 33 | // { 34 | // return MakeHelpText(controller, description, new Vector3(0.05f, 0.04f, 0), new Vector3(0.01f, 0, 0), "trackpad", "thumbstick"); 35 | // } 36 | 37 | // public static HelpText HelpTrackpadUp(Controller controller, string description) 38 | // { 39 | // return MakeHelpText(controller, description, new Vector3(0, 0.04f, 0.07f), new Vector3(0, 0, 0.01f), "trackpad", "thumbstick"); 40 | // } 41 | 42 | // public static HelpText HelpTrackpadDown(Controller controller, string description) 43 | // { 44 | // return MakeHelpText(controller, description, new Vector3(0, 0.04f, -0.05f), new Vector3(0, 0, -0.01f), "trackpad", "thumbstick"); 45 | // } 46 | 47 | 48 | // public static HelpText MakeHelpText( 49 | // Controller controller, 50 | // string description, 51 | // Vector3 textOffset, 52 | // Vector3 lineOffset, 53 | // params string[] attachNames) 54 | // { 55 | // var attach = attachNames 56 | // .Select(name => controller.FindAttachPosition(name)) 57 | // .Where(x => x != null) 58 | // .FirstOrDefault(); 59 | // if (attach == null) 60 | // { 61 | // VRLog.Warn($"HelpText: attach point not found for {attachNames}"); 62 | // return null; 63 | // } 64 | 65 | // return HelpText.Create(description, attach, textOffset, lineOffset); 66 | // } 67 | // } 68 | //} 69 | -------------------------------------------------------------------------------- /PatcherLoader/Loader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using System.Runtime.InteropServices; 5 | using System.Reflection; 6 | using Mono.Cecil; 7 | using BepInEx; 8 | using BepInEx.Logging; 9 | using System.Diagnostics; 10 | using System.Linq; 11 | 12 | namespace PatcherLoader 13 | { 14 | /// 15 | /// This "patcher" doesn't patch any .NET assemblies. It just loads and 16 | /// executes a native DLL, which applies some patches to in-memory native 17 | /// code. 18 | /// 19 | /// This needs to be implemented as a preloading-time patcher rather than 20 | /// a regular plugin because the latter doesn't run early enough in the 21 | /// startup sequence of the game. 22 | /// 23 | public static class Loader 24 | { 25 | public static IEnumerable TargetDLLs => GetDLLs(); 26 | 27 | public static void Patch(AssemblyDefinition assembly) 28 | { 29 | } 30 | 31 | private readonly static ManualLogSource logger 32 | = Logger.CreateLogSource("KK_MainGameVR_Patcher"); 33 | 34 | private delegate void SetupAll(); 35 | 36 | private static IEnumerable GetDLLs() 37 | { 38 | var processName = Paths.ProcessName; 39 | if ((processName != "Koikatu" && processName != "Koikatsu Party") 40 | || (!Environment.CommandLine.Contains("--vr") 41 | && !Process.GetProcesses().Where(p => p != null && p.ProcessName == "vrcompositor").Any())) 42 | { 43 | yield break; 44 | } 45 | 46 | var patcherPath = Path.Combine( 47 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 48 | "native_patcher.dll"); 49 | 50 | logger.LogInfo($"Loading {patcherPath}"); 51 | 52 | var hModule = NativeMethods.LoadLibraryW(patcherPath); 53 | if (hModule == IntPtr.Zero) 54 | { 55 | logger.LogError($"Failed to load native DLL. Error code: {Marshal.GetLastWin32Error()}"); 56 | yield break; 57 | } 58 | var funPtr = NativeMethods.GetProcAddress(hModule, "setup_all"); 59 | if (funPtr == IntPtr.Zero) 60 | { 61 | logger.LogError($"GetProcAddress failed: {Marshal.GetLastWin32Error()}"); 62 | yield break; 63 | } 64 | var setupAll = (SetupAll)Marshal.GetDelegateForFunctionPointer(funPtr, typeof(SetupAll)); 65 | setupAll(); 66 | 67 | yield break; 68 | } 69 | } 70 | 71 | internal static class NativeMethods 72 | { 73 | [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] 74 | public static extern IntPtr LoadLibraryW(string name); 75 | 76 | [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)] 77 | public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Shared/Controls/KoikMenuTool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using VRGIN.Controls; 6 | using UnityEngine; 7 | using static Illusion.Utils; 8 | using VRGIN.Visuals; 9 | using VRGIN.Core; 10 | using KK_VR.Interpreters; 11 | using KK_VR.Settings; 12 | 13 | namespace KK_VR.Controls 14 | { 15 | internal class KoikMenuTool 16 | { 17 | internal bool IsAttached => _attached; 18 | private bool _attached; 19 | private static GUIQuad _gui; 20 | internal KoikMenuTool(Controller controller) 21 | { 22 | if (!_gui 23 | && ((KoikSettings.MainHand.Value == KoikSettings.Handedness.Left && controller == VR.Mode.Left) 24 | || (KoikSettings.MainHand.Value == KoikSettings.Handedness.Right && controller == VR.Mode.Right))) 25 | { 26 | _gui = GUIQuad.Create(); 27 | _gui.transform.parent = controller.transform; 28 | _gui.transform.localScale = Vector3.one * 0.3f; 29 | _gui.transform.localPosition = new Vector3(0, 0.05f, -0.06f); 30 | _gui.transform.localRotation = Quaternion.Euler(90, 0, 0); 31 | _gui.IsOwned = true; 32 | _gui.gameObject.SetActive(true); 33 | _attached = true; 34 | } 35 | } 36 | internal static void ToggleState() 37 | { 38 | _gui.gameObject.SetActive(!_gui.gameObject.activeSelf); 39 | } 40 | //internal void TakeGUI(GUIQuad quad) 41 | //{ 42 | // if (quad && !Gui && !quad.IsOwned) 43 | // { 44 | // Gui = quad; 45 | // //Gui.transform.parent = transform; 46 | // Gui.transform.SetParent(transform, worldPositionStays: true); 47 | 48 | // quad.IsOwned = true; 49 | // } 50 | // VRLog.Debug($"TakeGui:{Gui}:{quad.IsOwned}"); 51 | //} 52 | 53 | internal static void TakeGui() 54 | { 55 | if (_gui != null && !_gui.transform.parent.name.Contains("Controller") && _gui.transform.parent != VR.Camera.Origin) 56 | { 57 | var head = VR.Camera.Head; 58 | var origin = VR.Camera.Origin; 59 | 60 | _gui.transform.SetParent(origin, worldPositionStays: true); 61 | 62 | // If no menu in proximity after the scene load. (was abandoned beforehand) 63 | if (Vector3.Distance(_gui.transform.position, head.position) > 3f) 64 | { 65 | _gui.transform.SetPositionAndRotation( 66 | head.position + (origin.rotation * Quaternion.Euler(0f, 60f, 0f)) * head.forward, 67 | head.rotation * Quaternion.Euler(0f, 90f, 0f) 68 | ); 69 | } 70 | } 71 | } 72 | 73 | internal void AbandonGUI() 74 | { 75 | if (_attached) 76 | { 77 | //timeAbandoned = Time.unscaledTime; 78 | _gui.IsOwned = false; 79 | _gui.transform.SetParent(VR.Camera.Origin, true); 80 | _attached = false; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /CharaStudioVR/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Shared/Controls/Locomotion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using KK_VR.Handlers; 5 | using KK_VR.Settings; 6 | using UnityEngine; 7 | using VRGIN.Controls; 8 | using VRGIN.Core; 9 | 10 | namespace KK_VR.Controls 11 | { 12 | // Can be rough after awhile, as the locomotion is very smooth. 13 | // Kinda? the same idea like in Blade and Sorcery game, move and/or rotate in the direction of thumbstick. 14 | internal class Locomotion 15 | { 16 | internal Locomotion(Controller controller) 17 | { 18 | _controller = controller; 19 | } 20 | private readonly Controller _controller; 21 | private float _current; 22 | private float _currentDelta; 23 | private float _currentVelocity; 24 | private Quaternion _currentRot; 25 | private Vector2 _nonZeroVec; 26 | private float _distance; 27 | internal Vector2 GetAxis 28 | { 29 | get 30 | { 31 | var axis = _controller.Input.GetAxis(); 32 | _distance = axis.magnitude; 33 | 34 | // Keep old non zero axis to deaccelerate smoothly after ending; 35 | if (_distance != 0f) 36 | { 37 | _nonZeroVec = axis; 38 | } 39 | return _nonZeroVec; 40 | } 41 | } 42 | private Vector3 GetVec => _currentDelta * (_currentRot * Vector3.forward); 43 | private Quaternion GetRot 44 | { 45 | get 46 | { 47 | var originRot = VR.Camera.Origin.rotation; 48 | var targetRot = originRot * (Quaternion.Inverse(originRot) * _currentRot); 49 | var angle = Quaternion.Angle(originRot, targetRot); 50 | 51 | return angle > 5f ? Quaternion.RotateTowards(originRot, targetRot, _currentDelta * angle) : VR.Camera.Origin.rotation; 52 | } 53 | } 54 | 55 | private bool Update() 56 | { 57 | var axis = GetAxis; 58 | var target = _distance < 0.2f ? 0f : 1f; 59 | var smoothTime = target == 0f ? 0.25f : 1f; 60 | 61 | _current = Mathf.SmoothDamp(_current, target, ref _currentVelocity, smoothTime); 62 | 63 | if (_current > 0.001f) 64 | { 65 | var angle = Mathf.Atan2(axis.y, axis.x) * Mathf.Rad2Deg; 66 | 67 | // No clue why flip is required. 68 | angle = 0f - (angle - 90f); 69 | 70 | _currentDelta = _current * Time.deltaTime; 71 | _currentRot = Quaternion.Euler(0f, angle + _controller.transform.rotation.eulerAngles.y, 0f); 72 | 73 | return true; 74 | } 75 | return false; 76 | } 77 | internal bool MoveRotate(Vector3 deltaPos) 78 | { 79 | if (Update()) 80 | { 81 | var origin = VR.Camera.Origin; 82 | origin.SetPositionAndRotation(origin.position + deltaPos + GetVec, GetRot); 83 | return true; 84 | } 85 | return false; 86 | } 87 | internal bool Move(Vector3 deltaPos) 88 | { 89 | if (Update()) 90 | { 91 | VR.Camera.Origin.position += deltaPos + GetVec; 92 | return true; 93 | } 94 | return false; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Shared/Handlers/ForGrasp/HeadPartGuide.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using static KK_VR.Grasp.GraspController; 3 | using KK_VR.Holders; 4 | using KK_VR.Grasp; 5 | using KK_VR.Settings; 6 | 7 | namespace KK_VR.Handlers 8 | { 9 | internal class HeadPartGuide : PartGuide 10 | { 11 | 12 | protected override BodyPart BodyPart 13 | { 14 | get => _bodyPart; 15 | set => _bodyPart = value is BodyPartHead head ? head : null; 16 | } 17 | private BodyPartHead _bodyPart; 18 | internal override void Follow(Transform target, HandHolder hand) 19 | { 20 | if (KoikSettings.IKHeadEffector.Value == KoikSettings.HeadEffector.Disabled) 21 | { 22 | return; 23 | } 24 | else if (_bodyPart.headEffector.enabled == false) 25 | { 26 | _bodyPart.headEffector.enabled = true; 27 | } 28 | _hand = hand; 29 | _attach = false; 30 | _follow = true; 31 | _target = target; 32 | 33 | //if (KoikGame.Settings.ShowGuideObjects) _bodyPart.visual.Show(); 34 | 35 | _bodyPart.ResetState(); 36 | _bodyPart.AddState(State.Active | State.Grasped); 37 | 38 | _offsetRot = Quaternion.Inverse(target.rotation) * _anchor.rotation; 39 | _offsetPos = target.InverseTransformPoint(_anchor.position); 40 | 41 | Tracker.SetBlacklistDic(hand.Grasp.GetBlacklistDic); 42 | ClearBlacks(); 43 | _bodyPart.visual.SetColor(IsBusy); 44 | _wasBusy = false; 45 | } 46 | internal override void Stay() 47 | { 48 | _hand = null; 49 | _follow = false; 50 | _attach = false; 51 | //_anchor.parent = _bodyPart.beforeIK; 52 | //SetBodyPartCollidersToTrigger(false); 53 | } 54 | 55 | //internal override void Sleep(bool instant) 56 | //{ 57 | // _hand = null; 58 | // _follow = false; 59 | // _attach = false; 60 | // //gameObject.SetActive(false); 61 | // //transform.localScale = _origScale; 62 | // SetBodyPartCollidersToTrigger(false); 63 | //} 64 | 65 | internal override void Attach(Transform target) 66 | { 67 | _hand = null; 68 | _attach = true; 69 | _target = target; 70 | 71 | _offsetRot = Quaternion.Inverse(_target.rotation) * _anchor.rotation; 72 | _offsetPos = _target.InverseTransformPoint(_anchor.position); 73 | //transform.parent = _objAnim; 74 | } 75 | protected override void Disable() 76 | { 77 | base.Disable(); 78 | if (KoikSettings.IKHeadEffector.Value != KoikSettings.HeadEffector.Always) 79 | { 80 | _bodyPart.headEffector.enabled = false; 81 | } 82 | } 83 | 84 | private void Update() 85 | { 86 | if (_follow) 87 | { 88 | _anchor.SetPositionAndRotation( 89 | _target.TransformPoint(_offsetPos), 90 | _target.rotation * _offsetRot 91 | ); 92 | } 93 | else 94 | { 95 | _translate?.DoStep(); 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /CharaStudioVR/Interpreters/KKSCharaStudioActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using KK_VR.Settings; 4 | using UnityEngine; 5 | using VRGIN.Core; 6 | using VRGIN.Helpers; 7 | 8 | namespace KK_VR.Interpreters 9 | { 10 | public class KKSCharaStudioActor : DefaultActorBehaviour 11 | { 12 | private LookTargetController _TargetController; 13 | public TransientHead Head { get; private set; } 14 | public override Transform Eyes => Head.Eyes; 15 | 16 | public override bool HasHead 17 | { 18 | get => Head.Visible; 19 | set => Head.Visible = value; 20 | } 21 | 22 | public bool IsFemale => Actor.sex == 1; 23 | 24 | protected override void Initialize(ChaControl actor) 25 | { 26 | base.Initialize(actor); 27 | Head = actor.gameObject.AddComponent(); 28 | } 29 | 30 | protected override void OnStart() 31 | { 32 | base.OnStart(); 33 | _TargetController = LookTargetController.AttachTo(this, gameObject); 34 | } 35 | 36 | protected override void OnLateUpdate() 37 | { 38 | base.OnLateUpdate(); 39 | var eyeLookCtrl = Actor.eyeLookCtrl; 40 | var neckLookCtrl = Actor.neckLookCtrl; 41 | var transform = UnityEngine.Camera.main.transform; 42 | if ((bool)transform) 43 | { 44 | if ((bool)eyeLookCtrl && eyeLookCtrl.target == transform) eyeLookCtrl.target = _TargetController.Target; 45 | if ((bool)neckLookCtrl && neckLookCtrl.target == transform) neckLookCtrl.target = _TargetController.Target; 46 | } 47 | 48 | if (!(Actor.asVoice != null)) return; 49 | try 50 | { 51 | var asVoice = Actor.asVoice; 52 | asVoice.gameObject.transform.position = Actor.objHeadBone.transform.position; 53 | var minVoiceDistance = StudioSettings.MinVoiceDistance.Value; 54 | var maxVoiceDistance = StudioSettings.MaxVoiceDistance.Value; 55 | if (asVoice.minDistance != minVoiceDistance || asVoice.maxDistance != maxVoiceDistance) 56 | { 57 | VRLog.Debug( 58 | $"Modify audio parameter {asVoice.name}: ({asVoice.minDistance}, {asVoice.maxDistance}, {asVoice.rolloffMode}) -> ({minVoiceDistance}, {maxVoiceDistance}, {AudioRolloffMode.Logarithmic})"); 59 | asVoice.minDistance = minVoiceDistance; 60 | asVoice.maxDistance = maxVoiceDistance; 61 | asVoice.rolloffMode = AudioRolloffMode.Logarithmic; 62 | } 63 | } 64 | catch (Exception e) 65 | { 66 | VRLog.Error(e); 67 | } 68 | } 69 | 70 | internal void OnVRModeChanged(bool newMode) 71 | { 72 | if (!(_TargetController != null) || newMode) return; 73 | 74 | var eyeLookCtrl = Actor.eyeLookCtrl; 75 | var neckLookCtrl = Actor.neckLookCtrl; 76 | var transform = UnityEngine.Camera.main.transform; 77 | if ((bool)transform) 78 | { 79 | if ((bool)eyeLookCtrl && eyeLookCtrl.target == _TargetController.Target) eyeLookCtrl.target = transform; 80 | if ((bool)neckLookCtrl && neckLookCtrl.target == _TargetController.Target) neckLookCtrl.target = transform; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /release.ps1: -------------------------------------------------------------------------------- 1 | if ($PSScriptRoot -match '.+?\\bin\\?') { 2 | $dir = $PSScriptRoot + "\" 3 | } 4 | else { 5 | $dir = $PSScriptRoot + "\bin\" 6 | } 7 | 8 | $out = $dir + "\out" 9 | Remove-Item -Force -Path ($out) -Recurse -ErrorAction SilentlyContinue 10 | 11 | # KK ------------------------------------- 12 | Write-Output ("# Creating KK release #") 13 | 14 | New-Item -ItemType Directory -Force -Path ($out + "\BepInEx\plugins\KK_MainGameVR\Images") | Out-Null 15 | New-Item -ItemType Directory -Force -Path ($out + "\BepInEx\patchers\KK_MainGameVR_Patcher") | Out-Null 16 | New-Item -ItemType Directory -Force -Path ($out + "\Koikatu_Data") | Out-Null 17 | 18 | Copy-Item -Path ($dir + "\KK\*") -Destination ($out + "\BepInEx\plugins\KK_MainGameVR") -ErrorAction Stop -Force | Out-Null 19 | # Copy-Item copies empty directories and I don't see any way to tell it to only copy files 20 | Remove-Item -Path ($out + "\BepInEx\plugins\KK_MainGameVR\Data") -Force 21 | Remove-Item -Path ($out + "\BepInEx\plugins\KK_MainGameVR\Patcher") -Force 22 | Remove-Item -Path ($out + "\BepInEx\plugins\KK_MainGameVR\Plugins") -Force 23 | 24 | Copy-Item -Path ($dir + "\KK\Patcher\*") -Destination ($out + "\BepInEx\patchers\KK_MainGameVR_Patcher") | Out-Null 25 | Copy-Item -Path ($dir + "\KK\Images\*") -Destination ($out + "\BepInEx\plugins\KK_MainGameVR\Images\") -Force | Out-Null 26 | Copy-Item -Path ($dir + "\KK\Data\*") -Destination ($out + "\Koikatu_Data") -Recurse | Out-Null 27 | 28 | $ver = "v" + (Get-ChildItem -Path ($dir + "\KK\KoikatuVR.dll") -Force -ErrorAction Stop)[0].VersionInfo.FileVersion.ToString() -replace "([\d+\.]+?\d+)[\.0]*$", '${1}' 29 | Write-Output ("Version " + $ver) 30 | Compress-Archive -Path ($out + "\*") -Force -CompressionLevel "Optimal" -DestinationPath ($dir +"KK_VR_" + $ver + ".zip") 31 | 32 | # KK Party 33 | Write-Output ("Also creating KK Party release") 34 | 35 | Rename-Item ($out + "\Koikatu_Data") -NewName "Koikatsu Party_Data" 36 | Compress-Archive -Path ($out + "\*") -Force -CompressionLevel "Optimal" -DestinationPath ($dir +"KKParty_VR_" + $ver + ".zip") 37 | 38 | Remove-Item -Force -Path ($out) -Recurse -ErrorAction Inquire 39 | 40 | # KKS ------------------------------------ 41 | Write-Output ("# Creating KKS release #") 42 | 43 | New-Item -ItemType Directory -Force -Path ($out + "\BepInEx\plugins\KKS_VR\Images") | Out-Null 44 | New-Item -ItemType Directory -Force -Path ($out + "\CharaStudio_Data") | Out-Null 45 | New-Item -ItemType Directory -Force -Path ($out + "\KoikatsuSunshine_Data") | Out-Null 46 | 47 | Copy-Item -Path ($dir + "\KKS\*") -Destination ($out + "\BepInEx\plugins\KKS_VR") -Force -ErrorAction Stop | Out-Null 48 | # Copy-Item copies empty directories and I don't see any way to tell it to only copy files 49 | Remove-Item -Path ($out + "\BepInEx\plugins\KKS_VR\Libs") -Force 50 | 51 | Copy-Item -Path ($dir + "\KKS\Images\*") -Destination ($out + "\BepInEx\plugins\KKS_VR\Images\") -Force | Out-Null 52 | Copy-Item -Path ($dir + "\KKS\Libs\_Data\*") -Destination ($out + "\CharaStudio_Data") -Recurse | Out-Null 53 | Copy-Item -Path ($dir + "\KKS\Libs\_Data\*") -Destination ($out + "\KoikatsuSunshine_Data") -Recurse | Out-Null 54 | 55 | $ver = "v" + (Get-ChildItem -Path ($dir + "\KKS\KKS_MainGameVR.dll") -Force -ErrorAction Stop)[0].VersionInfo.FileVersion.ToString() -replace "([\d+\.]+?\d+)[\.0]*$", '${1}' 56 | Write-Output ("Version " + $ver) 57 | Compress-Archive -Path ($out + "\*") -Force -CompressionLevel "Optimal" -DestinationPath ($dir +"KKS_VR_" + $ver + ".zip") 58 | 59 | Remove-Item -Force -Path ($out) -Recurse -ErrorAction SilentlyContinue 60 | -------------------------------------------------------------------------------- /CharaStudioVR/Controls/ObjMoveHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Studio; 3 | using UnityEngine; 4 | 5 | namespace KK_VR.Controls 6 | { 7 | internal class ObjMoveHelper 8 | { 9 | public Vector3 moveAlongBasePos; 10 | 11 | public void SetBasePos(Vector3 basePos) 12 | { 13 | moveAlongBasePos = basePos; 14 | } 15 | 16 | public ObjectCtrlInfo GetFirstObject() 17 | { 18 | var instance = Singleton.Instance; 19 | if (instance != null) 20 | { 21 | var selectObjectCtrl = instance.treeNodeCtrl.selectObjectCtrl; 22 | if (selectObjectCtrl != null && selectObjectCtrl.Length != 0) 23 | return selectObjectCtrl[0]; 24 | } 25 | 26 | return null; 27 | } 28 | 29 | public void MoveAllCharaAndItemsHere(Vector3 newPos, bool keepY = true) 30 | { 31 | var instance = Singleton.Instance; 32 | if (instance == null) return; 33 | 34 | var vector = newPos - moveAlongBasePos; 35 | if (keepY) vector.y = 0f; 36 | 37 | var list = new List(); 38 | var selectObjectCtrl = instance.treeNodeCtrl.selectObjectCtrl; 39 | for (var i = 0; i < selectObjectCtrl.Length; i++) 40 | { 41 | var guideObject = selectObjectCtrl[i].guideObject; 42 | if (guideObject != null) 43 | { 44 | var localPosition = guideObject.transformTarget.localPosition; 45 | guideObject.transformTarget.position = guideObject.transformTarget.position + vector; 46 | guideObject.changeAmount.pos = guideObject.transformTarget.localPosition; 47 | if (guideObject.enablePos) 48 | { 49 | var item = new GuideCommand.EqualsInfo 50 | { 51 | dicKey = guideObject.dicKey, 52 | oldValue = localPosition, 53 | newValue = guideObject.changeAmount.pos 54 | }; 55 | list.Add(item); 56 | } 57 | } 58 | 59 | Singleton.Instance.Push(new GuideCommand.MoveEqualsCommand(list.ToArray())); 60 | } 61 | } 62 | 63 | public void MoveObject(ObjectCtrlInfo oci, Vector3 newPos, bool keepY) 64 | { 65 | if (keepY) 66 | newPos.y = oci.guideObject.transformTarget.position.y; 67 | 68 | var guideObject = oci.guideObject; 69 | if (guideObject != null) 70 | { 71 | var localPosition = guideObject.transformTarget.localPosition; 72 | guideObject.transformTarget.position = newPos; 73 | guideObject.changeAmount.pos = guideObject.transformTarget.localPosition; 74 | if (guideObject.enablePos) 75 | { 76 | var equalsInfo = new GuideCommand.EqualsInfo 77 | { 78 | dicKey = guideObject.dicKey, 79 | oldValue = localPosition, 80 | newValue = guideObject.changeAmount.pos 81 | }; 82 | Singleton.Instance.Push(new GuideCommand.MoveEqualsCommand(new GuideCommand.EqualsInfo[1] { equalsInfo })); 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /KK_Studio/VRPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using BepInEx; 8 | using BepInEx.Logging; 9 | using HarmonyLib; 10 | using KK_VR.Features; 11 | using KK_VR.Fixes; 12 | using KK_VR.Settings; 13 | using KKAPI; 14 | using KKAPI.MainGame; 15 | using UnityEngine; 16 | using VRGIN.Core; 17 | using VRGIN.Helpers; 18 | 19 | namespace KK_VR 20 | { 21 | [BepInPlugin(GUID, Name, Version)] 22 | [BepInProcess(KoikatuAPI.StudioProcessName)] 23 | [BepInDependency(KoikatuAPI.GUID, KoikatuAPI.VersionConst)] 24 | public class VRPlugin : BaseUnityPlugin 25 | { 26 | public const string GUID = "kk.vr.studio"; 27 | public const string Name = "StudioVR"; 28 | public const string Version = Constants.Version; 29 | 30 | internal static new ManualLogSource Logger; 31 | 32 | private void Awake() 33 | { 34 | Logger = base.Logger; 35 | 36 | var settings = StudioSettings.Create(Config); 37 | 38 | if (Environment.CommandLine.Contains("--vr") || SteamVRDetector.IsRunning) 39 | { 40 | BepInExVrLogBackend.ApplyYourself(); 41 | StartCoroutine(LoadDevice(settings)); 42 | } 43 | CrossFader.Initialize(Config, enabled); 44 | } 45 | 46 | private IEnumerator LoadDevice(VRSettings settings) 47 | { 48 | //yield return new WaitUntil(() => Manager.Scene. initialized); 49 | //yield return new WaitUntil(() => Manager.Scene.initialized && Manager.Scene.LoadSceneName == "Title"); 50 | var openVR = "OpenVR"; 51 | if (UnityEngine.VR.VRSettings.loadedDeviceName != openVR) 52 | { 53 | UnityEngine.VR.VRSettings.LoadDeviceByName(openVR); 54 | yield return null; 55 | } 56 | UnityEngine.VR.VRSettings.enabled = true; 57 | while (UnityEngine.VR.VRSettings.loadedDeviceName != openVR) 58 | { 59 | yield return null; 60 | } 61 | while (true) 62 | { 63 | var rect = VRGIN.Native.WindowManager.GetClientRect(); 64 | if (rect.Right - rect.Left > 0) 65 | { 66 | break; 67 | } 68 | //VRLog.Info("waiting for the window rect to be non-empty"); 69 | yield return null; 70 | } 71 | 72 | new Harmony(GUID).PatchAll(typeof(VRPlugin).Assembly); 73 | VRManager.Create(new KoikContext(settings)); 74 | 75 | VR.Manager.SetMode(); 76 | 77 | VRFade.Create(); 78 | GraphicRaycasterPatches.Initialize(); 79 | 80 | // It's been reported in #28 that the game window defocues when 81 | // the game is under heavy load. We disable window ghosting in 82 | // an attempt to counter this. 83 | NativeMethods.DisableProcessWindowsGhosting(); 84 | 85 | //if (SettingsManager.EnableBoop.Value) 86 | //{ 87 | // VRBoop.Initialize(); 88 | //} 89 | Logger.LogInfo("Finished loading into VR mode!"); 90 | } 91 | 92 | private static class NativeMethods 93 | { 94 | [DllImport("user32.dll")] 95 | public static extern void DisableProcessWindowsGhosting(); 96 | } 97 | 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Shared/Utils/DebugHooks.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Collection of patches that are to be enabled only during development. 4 | 5 | namespace KK_VR 6 | { 7 | #if false 8 | /// Report every time TransformDebug.targetTransform is rotated. 9 | [HarmonyPatch] 10 | class TransformPatches 11 | { 12 | static IEnumerable TargetMethods() 13 | { 14 | yield return AccessTools.PropertySetter(typeof(Transform), "rotation"); 15 | yield return AccessTools.PropertySetter(typeof(Transform), "localRotation"); 16 | yield return AccessTools.PropertySetter(typeof(Transform), "eulerAngles"); 17 | yield return AccessTools.Method(typeof(Transform), "SetPositionAndRotation"); 18 | yield return AccessTools.Method(typeof(Transform), "Rotate", new[] { typeof(Vector3), typeof(Space) }); 19 | yield return AccessTools.Method(typeof(Transform), "Rotate", new[] { typeof(float), typeof(float), typeof(float), typeof(Space) }); 20 | yield return AccessTools.Method(typeof(Transform), "Rotate", new[] { typeof(Vector3), typeof(float), typeof(Space) }); 21 | yield return AccessTools.Method(typeof(Transform), "RotateAround", new[] { typeof(Vector3), typeof(Vector3), typeof(float) }); 22 | yield return AccessTools.Method(typeof(Transform), "LookAt", new[] { typeof(Transform), typeof(Vector3) }); 23 | yield return AccessTools.Method(typeof(Transform), "LookAt", new[] { typeof(Vector3), typeof(Vector3) }); 24 | yield break; 25 | } 26 | 27 | static void Prefix(Transform __instance) 28 | { 29 | if (__instance == TransformDebug.targetTransform) 30 | { 31 | VRLog.Info("Someone is modifying the target transform!"); 32 | VRLog.Info(new StackTrace(false)); 33 | } 34 | } 35 | } 36 | 37 | // Dump human-readable ADV scenarios under the "scenario_dump/" folder. 38 | [HarmonyPatch(typeof(AssetBundleManager))] 39 | class AssetBundleManagerPatches 40 | { 41 | [HarmonyPatch("LoadAsset", new[] { typeof(string), typeof(string), typeof(Type), typeof(string) })] 42 | [HarmonyPostfix] 43 | static void PostLoadAsset(string assetBundleName, string assetName, Type type, AssetBundleLoadAssetOperation __result) 44 | { 45 | if (type == typeof(ADV.ScenarioData)) 46 | { 47 | try 48 | { 49 | var scenarioData = __result.GetAsset(); 50 | Directory.CreateDirectory("scenario_dump"); 51 | StreamWriter writer = new StreamWriter($"scenario_dump/{assetBundleName.Replace('/', '_')}-{assetName.Replace('/', '_')}.txt"); 52 | foreach (var param in scenarioData.list) 53 | { 54 | writer.WriteLine($"{(param.Multi ? "M" : " ")} {param.Command} {string.Join(", ", param.Args)}"); 55 | } 56 | writer.Close(); 57 | } 58 | catch(Exception e) 59 | { 60 | VRLog.Error(e); 61 | } 62 | } 63 | } 64 | } 65 | 66 | // Log every time a scenario command is executed. 67 | [HarmonyPatch(typeof(ADV.CommandList))] 68 | class CommandListPatches 69 | { 70 | [HarmonyPatch("Add", new[] { typeof(ADV.ScenarioData.Param), typeof(int) })] 71 | [HarmonyPrefix] 72 | static void PreAdd(ADV.ScenarioData.Param item) 73 | { 74 | VRLog.Info($"{(item.Multi ? "M" : " ")} {item.Command} {string.Join(", ", item.Args)}"); 75 | } 76 | } 77 | #endif 78 | } 79 | -------------------------------------------------------------------------------- /SharedGame/SharedGame.projitems: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 0aa55027-91a2-4fc5-b657-8c2a2b96f160 7 | 8 | 9 | KK_VR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /KK_VR/VRPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Runtime.InteropServices; 4 | using BepInEx; 5 | using BepInEx.Logging; 6 | using HarmonyLib; 7 | using KKAPI; 8 | using KKAPI.MainGame; 9 | using KK_VR.Features; 10 | using KK_VR.Fixes; 11 | using KK_VR.Interpreters; 12 | using KK_VR.Settings; 13 | using UnityEngine; 14 | using VRGIN.Core; 15 | using VRGIN.Helpers; 16 | using VRGIN.Controls.Handlers; 17 | using KK_VR.Camera; 18 | 19 | namespace KK_VR 20 | { 21 | [BepInPlugin(GUID, Name, Version)] 22 | [BepInProcess(KoikatuAPI.GameProcessName)] 23 | [BepInProcess(KoikatuAPI.GameProcessNameSteam)] 24 | [BepInDependency(KoikatuAPI.GUID, KoikatuAPI.VersionConst)] 25 | [BepInIncompatibility("bero.crossfadervr")] 26 | public class VRPlugin : BaseUnityPlugin 27 | { 28 | public const string GUID = "kk.vr.game"; 29 | public const string Name = "MainGameVR"; 30 | public const string Version = Constants.Version; 31 | 32 | internal static new ManualLogSource Logger; 33 | 34 | private void Awake() 35 | { 36 | Logger = base.Logger; 37 | 38 | var settings = new GameSettings().Create(Config); 39 | 40 | if (Environment.CommandLine.Contains("--vr") || SteamVRDetector.IsRunning) 41 | { 42 | BepInExVrLogBackend.ApplyYourself(); 43 | StartCoroutine(LoadDevice(settings)); 44 | } 45 | CrossFader.Initialize(Config, enabled); 46 | } 47 | 48 | private const string DeviceOpenVR = "OpenVR"; 49 | private IEnumerator LoadDevice(VRSettings settings) 50 | { 51 | //yield return new WaitUntil(() => Manager.Scene. initialized); 52 | //yield return new WaitUntil(() => Manager.Scene.initialized && Manager.Scene.LoadSceneName == "Title"); 53 | 54 | if (UnityEngine.VR.VRSettings.loadedDeviceName != DeviceOpenVR) 55 | { 56 | UnityEngine.VR.VRSettings.LoadDeviceByName(DeviceOpenVR); 57 | yield return null; 58 | } 59 | UnityEngine.VR.VRSettings.enabled = true; 60 | while (UnityEngine.VR.VRSettings.loadedDeviceName != DeviceOpenVR) 61 | { 62 | yield return null; 63 | } 64 | while (true) 65 | { 66 | var rect = VRGIN.Native.WindowManager.GetClientRect(); 67 | if (rect.Right - rect.Left > 0) 68 | { 69 | break; 70 | } 71 | //VRLog.Info("waiting for the window rect to be non-empty"); 72 | yield return null; 73 | } 74 | 75 | new Harmony(GUID).PatchAll(typeof(VRPlugin).Assembly); 76 | VRManager.Create(new KoikContext(settings)); 77 | 78 | VR.Manager.SetMode(); 79 | 80 | VRFade.Create(); 81 | GraphicRaycasterPatches.Initialize(); 82 | NativeMethods.DisableProcessWindowsGhosting(); 83 | 84 | 85 | GameAPI.RegisterExtraBehaviour(GUID); 86 | 87 | Logger.LogInfo("Finished loading into VR mode!"); 88 | } 89 | 90 | 91 | 92 | 93 | private static class NativeMethods 94 | { 95 | // It's been reported in #28 that the game window defocues when 96 | // the game is under heavy load. We disable window ghosting in 97 | // an attempt to counter this. 98 | [DllImport("user32.dll")] 99 | public static extern void DisableProcessWindowsGhosting(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /CharaStudioVR/Controls/BetterMenuTool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | using Valve.VR; 6 | using VRGIN.Controls; 7 | using VRGIN.Controls.Tools; 8 | using VRGIN.Core; 9 | using VRGIN.Visuals; 10 | using Object = UnityEngine.Object; 11 | 12 | 13 | namespace KK_VR.Controls 14 | { 15 | /// 16 | /// MenuTool that supports right clicks by pressing the trackpad 17 | /// 18 | internal class BetterMenuTool : MenuTool 19 | { 20 | //public override List GetHelpTexts() 21 | //{ 22 | // return new List(new[] 23 | // { 24 | // ToolUtil.HelpTrackpadCenter(Owner, "Press to Right Click"), 25 | // ToolUtil.HelpTrackpadUp(Owner, "Slide to Move Cursor"), 26 | // ToolUtil.HelpTrigger(Owner, "Left Click"), 27 | // ToolUtil.HelpGrip(Owner, "Take/release screen") 28 | // }.Where(x => x != null)); 29 | //} 30 | 31 | #region Override base functionality to add right clicks 32 | 33 | private float pressDownTime; 34 | private Vector2 touchDownPosition; 35 | private double _DeltaX; 36 | private double _DeltaY; 37 | 38 | protected override void OnUpdate() 39 | { 40 | //base.OnUpdate(); 41 | var controller = Controller; 42 | 43 | if (controller.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) 44 | { 45 | VR.Input.Mouse.RightButtonDown(); 46 | pressDownTime = Time.unscaledTime; 47 | } 48 | if (controller.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger)) 49 | { 50 | VR.Input.Mouse.LeftButtonDown(); 51 | pressDownTime = Time.unscaledTime; 52 | } 53 | 54 | if (controller.GetPressUp(EVRButtonId.k_EButton_Grip)) 55 | { 56 | if ((bool)(Object)Gui) 57 | AbandonGUI(); 58 | else 59 | TakeGUI(GUIQuadRegistry.Quads.FirstOrDefault(q => !q.IsOwned)); 60 | } 61 | if (controller.GetTouchDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) 62 | { 63 | touchDownPosition = controller.GetAxis(); 64 | //this.touchDownMousePosition = MouseOperations.GetClientCursorPosition(); 65 | } 66 | if (controller.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad) && Time.unscaledTime - pressDownTime > 0.3f) 67 | { 68 | var axis = controller.GetAxis(); 69 | var vector2 = axis - (VR.HMD == HMDType.Oculus ? Vector2.zero : touchDownPosition); 70 | var num = VR.HMD == HMDType.Oculus ? Time.unscaledDeltaTime * 5f : 1f; 71 | _DeltaX += vector2.x * (double)VRGUI.Width * 0.1 * num; 72 | _DeltaY += -(double)vector2.y * VRGUI.Height * 0.2 * num; 73 | var pixelDeltaX = _DeltaX > 0.0 ? (int)Math.Floor(_DeltaX) : (int)Math.Ceiling(_DeltaX); 74 | var pixelDeltaY = _DeltaY > 0.0 ? (int)Math.Floor(_DeltaY) : (int)Math.Ceiling(_DeltaY); 75 | _DeltaX -= pixelDeltaX; 76 | _DeltaY -= pixelDeltaY; 77 | VR.Input.Mouse.MoveMouseBy(pixelDeltaX, pixelDeltaY); 78 | touchDownPosition = axis; 79 | } 80 | 81 | if (controller.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) 82 | { 83 | VR.Input.Mouse.RightButtonUp(); 84 | pressDownTime = 0.0f; 85 | } 86 | if (controller.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) 87 | { 88 | VR.Input.Mouse.LeftButtonUp(); 89 | pressDownTime = 0.0f; 90 | } 91 | } 92 | 93 | #endregion 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Shared/Handlers/Helpers/ItemLag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | using VRGIN.Core; 7 | 8 | namespace KK_VR.Handlers 9 | { 10 | /// 11 | /// Stabilizes orientation of a model representing the controller 12 | /// 13 | internal class ItemLag 14 | { 15 | private readonly Transform _transform; 16 | private readonly Quaternion[] _prevRotations; 17 | private readonly Vector3[] _prevPositions; 18 | 19 | //private readonly int _frameFloor; 20 | //private readonly int _frameCeiling; 21 | private readonly float[] _frameCoefs; 22 | 23 | private int _frameIndex; 24 | private readonly int _frameCurAmount; 25 | private readonly float _frameCurAmountCoef; 26 | 27 | internal ItemLag(Transform transform, int frameAvg) 28 | { 29 | _transform = transform; 30 | _frameCurAmount = frameAvg; 31 | _frameCurAmountCoef = 1f / frameAvg; 32 | //_frameFloor = frameAvg - 5; 33 | //_frameCeiling = frameAvg + 5; 34 | _prevRotations = new Quaternion[frameAvg]; 35 | _prevPositions = new Vector3[frameAvg]; 36 | _frameCoefs = new float[frameAvg]; 37 | 38 | // Coefficients can be customized to change rotation follow type, even non-linear should look good. 39 | for (var i = 0; i < frameAvg; i++) 40 | { 41 | _frameCoefs[i] = 1f / (i + 2f); 42 | } 43 | var pos = _transform.position; 44 | var rot = _transform.rotation; 45 | for (var i = 0; i < _frameCurAmount; i++) 46 | { 47 | _prevRotations[i] = rot; 48 | _prevPositions[i] = pos; 49 | } 50 | } 51 | 52 | internal void SetPositionAndRotation(Vector3 position, Quaternion rotation) 53 | { 54 | _prevRotations[_frameIndex] = rotation; 55 | _prevPositions[_frameIndex] = position; 56 | //} 57 | _frameIndex++; 58 | if (_frameIndex == _frameCurAmount) _frameIndex = 0; 59 | UpdatePositionAndRotation(); 60 | } 61 | 62 | private void UpdatePositionAndRotation() 63 | { 64 | // The most stale frame is grabbed on init part. 65 | var count = _frameCurAmount - 1; 66 | 67 | // The most stale rotation. Doesn't get touched in the loop. 68 | var avgRot = _prevRotations[_frameIndex]; 69 | // Position that won't get touched in the loop. Don't care about the order, we use average. 70 | var avgPos = _prevPositions[count]; 71 | 72 | var j = _frameIndex; 73 | for (var i = 0; i < count; i++) 74 | { 75 | if (++j == _frameCurAmount) j = 0; 76 | avgRot = Quaternion.Lerp(avgRot, _prevRotations[j], _frameCoefs[i]); 77 | avgPos += _prevPositions[i]; 78 | } 79 | 80 | avgPos *= _frameCurAmountCoef; 81 | _transform.SetPositionAndRotation(avgPos, avgRot); 82 | } 83 | internal void SetPosition(Vector3 position) 84 | { 85 | _prevPositions[_frameIndex] = position; 86 | _frameIndex++; 87 | if (_frameIndex == _frameCurAmount) _frameIndex = 0; 88 | UpdatePosition(); 89 | } 90 | private void UpdatePosition() 91 | { 92 | var avgPos = _prevPositions[0]; 93 | for (var i = 1; i < _frameCurAmount; i++) 94 | { 95 | avgPos += _prevPositions[i]; 96 | } 97 | _transform.position = avgPos * _frameCurAmountCoef; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /PatcherLoader/PatcherLoader.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D} 8 | Library 9 | Properties 10 | PatcherLoader 11 | PatcherLoader 12 | v3.5 13 | 512 14 | true 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | ..\bin\KK\Patcher\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | true 27 | 28 | 29 | pdbonly 30 | true 31 | ..\bin\KK\Patcher\ 32 | TRACE 33 | prompt 34 | 4 35 | true 36 | 37 | 38 | 39 | ..\packages\IllusionLibs.BepInEx.Harmony.2.9.0\lib\net35\0Harmony.dll 40 | False 41 | 42 | 43 | ..\packages\IllusionLibs.BepInEx.5.4.22\lib\net35\BepInEx.dll 44 | False 45 | 46 | 47 | ..\packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.dll 48 | False 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Shared/Obsolete/Controls/BetterMenuTool.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using UnityEngine; 5 | //using Valve.VR; 6 | //using VRGIN.Controls; 7 | //using VRGIN.Controls.Tools; 8 | //using VRGIN.Core; 9 | //using VRGIN.Visuals; 10 | //using Object = UnityEngine.Object; 11 | 12 | 13 | // Was of no use at the time, currently no clue tbh. 14 | //namespace KKS_VR.Controls 15 | //{ 16 | // /// 17 | // /// MenuTool that supports right clicks by pressing the trackpad 18 | // /// 19 | // internal class BetterMenuTool : MenuTool 20 | // { 21 | // public override List GetHelpTexts() 22 | // { 23 | // return new List(new[] 24 | // { 25 | // ToolUtil.HelpTrackpadCenter(Owner, "Press to Right Click"), 26 | // ToolUtil.HelpTrackpadUp(Owner, "Slide to Move Cursor"), 27 | // ToolUtil.HelpTrigger(Owner, "Left Click"), 28 | // ToolUtil.HelpGrip(Owner, "Take/release screen") 29 | // }.Where(x => x != null)); 30 | // } 31 | 32 | // #region Override base functionality to add right clicks 33 | 34 | // private float pressDownTime; 35 | // private Vector2 touchDownPosition; 36 | // private double _DeltaX; 37 | // private double _DeltaY; 38 | 39 | // protected override void OnUpdate() 40 | // { 41 | // //base.OnUpdate(); 42 | // var controller = Controller; 43 | 44 | // if (controller.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) 45 | // { 46 | // VR.Input.Mouse.RightButtonDown(); 47 | // pressDownTime = Time.unscaledTime; 48 | // } 49 | // if (controller.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger)) 50 | // { 51 | // VR.Input.Mouse.LeftButtonDown(); 52 | // pressDownTime = Time.unscaledTime; 53 | // } 54 | 55 | // if (controller.GetPressUp(EVRButtonId.k_EButton_Grip)) 56 | // { 57 | // if ((bool)(Object)Gui) 58 | // AbandonGUI(); 59 | // else 60 | // TakeGUI(GUIQuadRegistry.Quads.FirstOrDefault(q => !q.IsOwned)); 61 | // } 62 | // if (controller.GetTouchDown(EVRButtonId.k_EButton_SteamVR_Touchpad)) 63 | // { 64 | // touchDownPosition = controller.GetAxis(); 65 | // //this.touchDownMousePosition = MouseOperations.GetClientCursorPosition(); 66 | // } 67 | // if (controller.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad) && Time.unscaledTime - pressDownTime > 0.3f) 68 | // { 69 | // var axis = controller.GetAxis(); 70 | // var vector2 = axis - (VR.HMD == HMDType.Oculus ? Vector2.zero : touchDownPosition); 71 | // var num = VR.HMD == HMDType.Oculus ? Time.unscaledDeltaTime * 5f : 1f; 72 | // _DeltaX += vector2.x * (double)VRGUI.Width * 0.1 * num; 73 | // _DeltaY += -(double)vector2.y * VRGUI.Height * 0.2 * num; 74 | // var pixelDeltaX = _DeltaX > 0.0 ? (int)Math.Floor(_DeltaX) : (int)Math.Ceiling(_DeltaX); 75 | // var pixelDeltaY = _DeltaY > 0.0 ? (int)Math.Floor(_DeltaY) : (int)Math.Ceiling(_DeltaY); 76 | // _DeltaX -= pixelDeltaX; 77 | // _DeltaY -= pixelDeltaY; 78 | // VR.Input.Mouse.MoveMouseBy(pixelDeltaX, pixelDeltaY); 79 | // touchDownPosition = axis; 80 | // } 81 | 82 | // if (controller.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad)) 83 | // { 84 | // VR.Input.Mouse.RightButtonUp(); 85 | // pressDownTime = 0.0f; 86 | // } 87 | // if (controller.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) 88 | // { 89 | // VR.Input.Mouse.LeftButtonUp(); 90 | // pressDownTime = 0.0f; 91 | // } 92 | // } 93 | 94 | // #endregion 95 | // } 96 | //} 97 | -------------------------------------------------------------------------------- /SharedGame/Handlers/ForScenes/TalkSceneHandler.cs: -------------------------------------------------------------------------------- 1 | using VRGIN.Helpers; 2 | using UnityEngine; 3 | using KK_VR.Interpreters; 4 | using KK_VR.Settings; 5 | using KK_VR.Features; 6 | using static HandCtrl; 7 | using KK_VR.Grasp; 8 | 9 | namespace KK_VR.Handlers 10 | { 11 | class TalkSceneHandler : ItemHandler 12 | { 13 | internal bool DoUndress(bool decrease, out ChaControl chara) 14 | { 15 | if (Undresser.Undress(_tracker.colliderInfo.behavior.part, chara = _tracker.colliderInfo.chara, decrease)) 16 | { 17 | //HandNoises.PlaySfx(_index, 1f, HandNoises.Sfx.Undress, HandNoises.Surface.Cloth); 18 | _controller.StartRumble(new RumbleImpulse(1000)); 19 | return true; 20 | } 21 | return false; 22 | } 23 | 24 | protected override void DoReaction(float velocity) 25 | { 26 | var chara = _tracker.colliderInfo.chara; 27 | if (!IsReactionEligible(chara)) return; 28 | 29 | var touch = _tracker.colliderInfo.behavior.touch; 30 | if (TalkSceneInterp.talkScene != null 31 | && touch != AibuColliderKind.none 32 | && chara == TalkSceneInterp.talkScene.targetHeroine.chaCtrl 33 | && !CrossFader.AdvHooks.Reaction 34 | // Add familiarity here too ? prob 35 | && (velocity > 1f || UnityEngine.Random.value < 0.3f) 36 | && (GraspHelper.Instance == null || !GraspHelper.Instance.IsGraspActive(chara))) 37 | { 38 | TalkSceneInterp.talkScene.TouchFunc(TouchReaction(touch), Vector3.zero); 39 | } 40 | else if (velocity > 1f || _tracker.reactionType == Tracker.ReactionType.HitReaction) 41 | { 42 | if (GraspHelper.Instance != null && !GraspHelper.Instance.IsGraspActive(chara) && UnityEngine.Random.value < GameSettings.TouchReaction.Value) 43 | { 44 | GraspHelper.Instance.TouchReaction(chara, _hand.Anchor.position, _tracker.colliderInfo.behavior.part); 45 | } 46 | else 47 | { 48 | TalkSceneInterp.HitReactionPlay(_tracker.colliderInfo.behavior.react, chara); 49 | } 50 | } 51 | else if (_tracker.reactionType == Tracker.ReactionType.Short) 52 | { 53 | Features.LoadGameVoice.PlayVoice(Features.LoadGameVoice.VoiceType.Short, chara, voiceWait: UnityEngine.Random.value < 0.5f); 54 | } 55 | else if (_tracker.reactionType == Tracker.ReactionType.Laugh) 56 | { 57 | Features.LoadGameVoice.PlayVoice(Features.LoadGameVoice.VoiceType.Laugh, chara, voiceWait: UnityEngine.Random.value < 0.5f); 58 | } 59 | _controller.StartRumble(new RumbleImpulse(1000)); 60 | 61 | } 62 | public bool TriggerPress() 63 | { 64 | var chara = _tracker.colliderInfo.chara; 65 | var touch = _tracker.colliderInfo.behavior.touch; 66 | if (TalkSceneInterp.talkScene != null 67 | && touch != AibuColliderKind.none 68 | && chara == TalkSceneInterp.talkScene.targetHeroine.chaCtrl 69 | && !CrossFader.AdvHooks.Reaction) 70 | { 71 | TalkSceneInterp.talkScene.TouchFunc(TouchReaction(touch), Vector3.zero); 72 | return true; 73 | } 74 | return false; 75 | } 76 | public void TriggerRelease() 77 | { 78 | 79 | } 80 | private string TouchReaction(AibuColliderKind colliderKind) 81 | { 82 | return colliderKind switch 83 | { 84 | AibuColliderKind.mouth => "Cheek", 85 | AibuColliderKind.muneL => "MuneL", 86 | AibuColliderKind.muneR => "MuneR", 87 | AibuColliderKind.reac_head => "Head", 88 | AibuColliderKind.reac_armL => "HandL", 89 | AibuColliderKind.reac_armR => "HandR", 90 | _ => null 91 | 92 | }; 93 | } 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /CharaStudioVR/Fixes/SaveLoadSceneHook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using BepInEx.Logging; 4 | using HarmonyLib; 5 | using KK_VR.Controls; 6 | using Manager; 7 | using Studio; 8 | using UnityEngine; 9 | using VRGIN.Core; 10 | 11 | namespace KK_VR.Fixes 12 | { 13 | public static class SaveLoadSceneHook 14 | { 15 | private static UnityEngine.Camera[] backupRenderCam; 16 | 17 | private static Sprite sceneLoadScene_spriteLoad; 18 | 19 | public static void InstallHook() 20 | { 21 | VRPlugin.Logger.Log(LogLevel.Info, "Install SaveLoadSceneHook"); 22 | new Harmony("KKSCharaStudioVR.SaveLoadSceneHook").PatchAll(typeof(SaveLoadSceneHook)); 23 | } 24 | 25 | [HarmonyPrefix] 26 | [HarmonyPatch(typeof(Studio.Studio), "SaveScene", new Type[] { })] 27 | public static bool SaveScenePreHook(Studio.Studio __instance, ref UnityEngine.Camera[] __state) 28 | { 29 | VRPlugin.Logger.Log(LogLevel.Debug, "Update Camera position and rotation for Scene Capture and last Camera data."); 30 | try 31 | { 32 | VRCameraMoveHelper.Instance.CurrentToCameraCtrl(); 33 | var field = typeof(Studio.GameScreenShot).GetField("renderCam", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 34 | var obj = field.GetValue(Singleton.Instance.gameScreenShot) as UnityEngine.Camera[]; 35 | VRPlugin.Logger.Log(LogLevel.Debug, "Backup Screenshot render cam."); 36 | backupRenderCam = obj; 37 | var value = new UnityEngine.Camera[1] { VR.Camera.SteamCam.camera }; 38 | __state = backupRenderCam; 39 | field.SetValue(Singleton.Instance.gameScreenShot, value); 40 | } 41 | catch (Exception obj2) 42 | { 43 | VRLog.Error("Error in SaveScenePreHook. Force continue."); 44 | VRLog.Error(obj2); 45 | } 46 | 47 | return true; 48 | } 49 | 50 | [HarmonyPostfix] 51 | [HarmonyPatch(typeof(Studio.Studio), "SaveScene", new Type[] { })] 52 | public static void SaveScenePostHook(Studio.Studio __instance, UnityEngine.Camera[] __state) 53 | { 54 | VRPlugin.Logger.Log(LogLevel.Debug, "Restore backup render cam."); 55 | try 56 | { 57 | typeof(Studio.GameScreenShot).GetField("renderCam", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) 58 | .SetValue(Singleton.Instance.gameScreenShot, __state); 59 | } 60 | catch (Exception obj) 61 | { 62 | VRLog.Error("Error in SaveScenePostHook. Force continue."); 63 | VRLog.Error(obj); 64 | } 65 | } 66 | 67 | [HarmonyPrefix] 68 | [HarmonyPatch(typeof(SceneLoadScene), "OnClickLoad", new Type[] { })] 69 | public static void SceneLoadSceneOnClickLoadPreHook(SceneLoadScene __instance) 70 | { 71 | try 72 | { 73 | sceneLoadScene_spriteLoad = typeof(SceneLoadScene).GetField("spriteLoad", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance) as Sprite; 74 | } 75 | catch (Exception obj) 76 | { 77 | VRLog.Error(obj); 78 | } 79 | } 80 | 81 | [HarmonyPostfix] 82 | [HarmonyPatch(typeof(Scene), "LoadReserve", new Type[] 83 | { 84 | typeof(Scene.Data), 85 | typeof(bool) 86 | })] 87 | public static void LoadScenePostHook(Scene.Data data, bool isLoadingImageDraw) 88 | { 89 | try 90 | { 91 | if (data.levelName == "StudioNotification" && data.isAdd && NotificationScene.spriteMessage == sceneLoadScene_spriteLoad) 92 | VRCameraMoveHelper.Instance.MoveToCurrent(); 93 | } 94 | catch (Exception obj) 95 | { 96 | VRLog.Error(obj); 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Shared/Grasp/Parts/BendGoal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Illusion.Component.Correct; 5 | using KK_VR.Interpreters; 6 | using UnityEngine; 7 | 8 | namespace KK_VR.Grasp 9 | { 10 | internal class BendGoal : MonoBehaviour 11 | { 12 | internal bool IsBusy => transform.localPosition != Vector3.zero; 13 | 14 | private KK.RootMotion.FinalIK.IKConstraintBend _bendConstraint; 15 | private Translate _translate; 16 | private Transform _origGoal; 17 | private Transform _target; 18 | private Vector3 _offsetPos; 19 | private bool _follow; 20 | 21 | internal bool IsClose(Vector3 position) 22 | { 23 | return Vector3.Distance(_bendConstraint.bone2.transform.position, position) < 0.1f; 24 | } 25 | 26 | internal static BendGoal Create(BodyPart bodyPart) 27 | { 28 | var gameObject = new GameObject("BendGoal_" + bodyPart.GetLowerCaseName()); 29 | gameObject.transform.SetParent(bodyPart.chain.bendConstraint.bendGoal, false); 30 | var goal = gameObject.AddComponent(); 31 | var baseData = bodyPart.chain.bendConstraint.bendGoal.GetComponent(); 32 | // Male doesn't have bendGoals by default outside of H. 33 | if (KoikGameInterp.CurrentScene != KoikGameInterp.SceneType.HScene && baseData.bone == null) 34 | { 35 | baseData.bone = bodyPart.chain.bendConstraint.bone2; 36 | } 37 | goal.Init(bodyPart); 38 | return goal; 39 | } 40 | 41 | 42 | private void Init(BodyPart bodyPart) 43 | { 44 | _bendConstraint = bodyPart.chain.bendConstraint; 45 | _origGoal = _bendConstraint.bendGoal; 46 | _bendConstraint.bendGoal = this.transform; 47 | } 48 | 49 | private void OnDestroy() 50 | { 51 | if (_bendConstraint != null && _origGoal != null) 52 | { 53 | _bendConstraint.bendGoal = _origGoal; 54 | } 55 | } 56 | 57 | internal void Sleep(bool instant = false) 58 | { 59 | if (instant || !IsBusy) 60 | { 61 | Disable(); 62 | } 63 | else 64 | { 65 | _translate = new TranslateMove(transform, null, Disable); 66 | } 67 | } 68 | 69 | internal void Follow(Transform target) 70 | { 71 | if (target != null) 72 | { 73 | if (_bendConstraint.weight != 1f) 74 | { 75 | _translate = new TranslateCompensate( 76 | // This weight doesn't have Clamp01 by default. 77 | () => _bendConstraint.weight = Mathf.Clamp01(_bendConstraint.weight + Time.deltaTime), 78 | () => Follow(target), 79 | transform, 80 | _bendConstraint.bone2); 81 | } 82 | else 83 | { 84 | _follow = true; 85 | _target = target; 86 | _translate = null; 87 | _offsetPos = target.InverseTransformPoint(transform.position); 88 | } 89 | } 90 | } 91 | 92 | internal void Stay() 93 | { 94 | _follow = false; 95 | _translate = null; 96 | } 97 | 98 | private void Disable() 99 | { 100 | transform.localPosition = Vector3.zero; 101 | transform.localRotation = Quaternion.identity; 102 | 103 | _follow = false; 104 | _translate = null; 105 | } 106 | 107 | private void LateUpdate() 108 | { 109 | if (_translate != null) 110 | { 111 | _translate.DoStep(); 112 | } 113 | else if (_follow) 114 | { 115 | transform.SetPositionAndRotation(_target.TransformPoint(_offsetPos), _target.rotation); 116 | } 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /CharaStudioVR/Interpreters/TransientHead.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | using VRGIN.Core; 6 | using VRGIN.Helpers; 7 | 8 | namespace KK_VR.Interpreters 9 | { 10 | public class TransientHead : ProtectedBehaviour 11 | { 12 | private readonly List rendererList = new List(); 13 | private bool hidden; 14 | private Transform root; 15 | private Renderer[] m_tongues; 16 | private ChaControl avatar; 17 | private Transform headTransform; 18 | private Transform eyesTransform; 19 | public Transform Eyes => eyesTransform; 20 | 21 | public bool Visible 22 | { 23 | get => !hidden; 24 | set 25 | { 26 | VRLog.Info(value ? "Show head" : "Hide head"); 27 | SetVisibility(value); 28 | } 29 | } 30 | 31 | protected override void OnAwake() 32 | { 33 | base.OnAwake(); 34 | avatar = GetComponent(); 35 | Reinitialize(); 36 | } 37 | 38 | public void Reinitialize() 39 | { 40 | headTransform = GetHead(avatar); 41 | eyesTransform = GetEyes(avatar); 42 | root = avatar.objRoot.transform; 43 | var array = m_tongues = (from renderer in root.GetComponentsInChildren() 44 | where renderer.name.ToLower().StartsWith("cm_o_tang") || renderer.name == "cf_o_tang" 45 | select renderer 46 | into tongue 47 | where tongue.enabled 48 | select tongue).ToArray(); 49 | } 50 | 51 | public static Transform GetHead(ChaControl human) 52 | { 53 | return human.objHead.GetComponentsInParent().First((Transform t) => t.name.StartsWith("c") && t.name.ToLower().Contains("j_head")); 54 | } 55 | 56 | public static Transform GetEyes(ChaControl human) 57 | { 58 | var transform = human.objHeadBone.transform.Descendants().FirstOrDefault((Transform t) => t.name.StartsWith("c") && t.name.ToLower().EndsWith("j_faceup_tz")); 59 | if (!transform) 60 | { 61 | VRLog.Info("Creating eyes"); 62 | transform = new GameObject("cf_j_faceup_tz").transform; 63 | transform.SetParent(GetHead(human), false); 64 | transform.transform.localPosition = new Vector3(0f, 0.07f, 0.05f); 65 | } 66 | else 67 | { 68 | VRLog.Info("found eyes"); 69 | } 70 | 71 | return transform; 72 | } 73 | 74 | private void SetVisibility(bool visible) 75 | { 76 | if (visible) 77 | { 78 | if (hidden) 79 | { 80 | foreach (var renderer3 in rendererList) 81 | if ((bool)renderer3) 82 | renderer3.enabled = true; 83 | var tongues = m_tongues; 84 | foreach (var renderer2 in tongues) 85 | if ((bool)renderer2) 86 | renderer2.enabled = true; 87 | } 88 | } 89 | else if (!hidden) 90 | { 91 | var tongues = m_tongues = (from renderer in root.GetComponentsInChildren() 92 | where renderer.name.StartsWith("cm_o_tang") || renderer.name == "cf_o_tang" 93 | select renderer 94 | into tongue 95 | where tongue.enabled 96 | select tongue).ToArray(); 97 | rendererList.Clear(); 98 | 99 | foreach (var item in from renderer in headTransform.GetComponentsInChildren() 100 | where renderer.enabled 101 | select renderer) 102 | { 103 | rendererList.Add(item); 104 | item.enabled = false; 105 | } 106 | 107 | tongues = m_tongues; 108 | for (var i = 0; i < tongues.Length; i++) 109 | tongues[i].enabled = false; 110 | } 111 | 112 | hidden = !visible; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /CharaStudioVR/Util/MoveableGUIObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Studio; 4 | using UnityEngine; 5 | using VRGIN.Core; 6 | 7 | namespace KK_VR.Util 8 | { 9 | public class MoveableGUIObject : MonoBehaviour 10 | { 11 | public List> onMoveLister = new List>(); 12 | public List> onReleasedLister = new List>(); 13 | public GuideObject guideObject; 14 | public GuideScale guideScale; 15 | public ObjectCtrlInfo objectCtrlInfo; 16 | public Vector3 oldPos; 17 | public Vector3 oldRot; 18 | public Vector3 oldScale; 19 | public bool isMoveObj; 20 | private Renderer renderer; 21 | public Renderer visibleReference; 22 | 23 | private void Start() 24 | { 25 | renderer = GetComponent(); 26 | } 27 | 28 | public void OnMoveStart() 29 | { 30 | if (guideObject != null) 31 | { 32 | oldPos = guideObject.changeAmount.pos; 33 | oldRot = guideObject.changeAmount.rot; 34 | oldScale = guideObject.changeAmount.scale; 35 | } 36 | } 37 | 38 | public void OnMoved() 39 | { 40 | foreach (var item in onMoveLister) 41 | try 42 | { 43 | item(this); 44 | } 45 | catch (Exception e) 46 | { 47 | VRLog.Error(e); 48 | } 49 | } 50 | 51 | public void OnReleased() 52 | { 53 | if (guideObject != null) 54 | { 55 | if (guideScale == null) 56 | { 57 | if (guideObject.enablePos) 58 | { 59 | var equalsInfo = new GuideCommand.EqualsInfo 60 | { 61 | dicKey = guideObject.dicKey, 62 | oldValue = oldPos, 63 | newValue = guideObject.changeAmount.pos 64 | }; 65 | Singleton.Instance.Push(new GuideCommand.MoveEqualsCommand(new GuideCommand.EqualsInfo[1] { equalsInfo })); 66 | } 67 | 68 | if (guideObject.enableRot) 69 | { 70 | var equalsInfo2 = new GuideCommand.EqualsInfo 71 | { 72 | dicKey = guideObject.dicKey, 73 | oldValue = oldRot, 74 | newValue = guideObject.changeAmount.rot 75 | }; 76 | Singleton.Instance.Push(new GuideCommand.RotationEqualsCommand(new GuideCommand.EqualsInfo[1] { equalsInfo2 })); 77 | } 78 | } 79 | else if (guideObject.enableScale) 80 | { 81 | var changeAmountInfo = new GuideCommand.EqualsInfo[1] 82 | { 83 | new GuideCommand.EqualsInfo 84 | { 85 | dicKey = guideObject.dicKey, 86 | oldValue = oldScale, 87 | newValue = guideObject.changeAmount.scale 88 | } 89 | }; 90 | Singleton.Instance.Push(new GuideCommand.ScaleEqualsCommand(changeAmountInfo)); 91 | } 92 | } 93 | 94 | foreach (var item in onReleasedLister) 95 | try 96 | { 97 | item(this); 98 | } 99 | catch (Exception e) 100 | { 101 | VRLog.Error(e); 102 | } 103 | } 104 | 105 | private void Update() 106 | { 107 | if (isMoveObj) transform.localScale = Vector3.one * 0.1f * Studio.Studio.optionSystem.manipulateSize; 108 | if (guideScale != null) transform.localScale = Vector3.one * 0.05f * Studio.Studio.optionSystem.manipulateSize; 109 | if (visibleReference != null && renderer != null) renderer.gameObject.layer = visibleReference.gameObject.layer; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Shared/IK/VRIK.cs: -------------------------------------------------------------------------------- 1 | //using KK.RootMotion.FinalIK; 2 | //using KK_VR.Fixes; 3 | //using KK_VR.Handlers; 4 | //using KK_VR.Holders; 5 | //using System; 6 | //using System.Collections.Generic; 7 | //using System.Linq; 8 | //using System.Text; 9 | //using UnityEngine; 10 | //using VRGIN.Core; 11 | 12 | //namespace KK_VR.Features 13 | //{ 14 | // public class VRIK 15 | // { 16 | // public static VRIK Instance => _instance ?? new(); 17 | // private static VRIK _instance; 18 | 19 | 20 | // public void TestRun(ChaControl chara) 21 | // { 22 | // PrepareVRIK(chara); 23 | // } 24 | 25 | // private KK.RootMotion.FinalIK.VRIK PrepareVRIK(ChaControl chara) 26 | // { 27 | // var ik = chara.animBody.GetComponent(); 28 | // if (ik == null) return null; 29 | // ik.enabled = false; 30 | // var refs = ik.references; 31 | // var vrik = chara.animBody.gameObject.AddComponent(); 32 | // var vRef = vrik.references; 33 | 34 | // vRef.root = refs.root; 35 | // vRef.pelvis = refs.pelvis; 36 | // vRef.spine = refs.spine[1]; // cf_j_spine02 37 | // vRef.chest = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_spine01/cf_j_spine02/cf_j_spine03"); 38 | // vRef.neck = refs.spine[2]; 39 | // vRef.head = refs.head; 40 | 41 | // vRef.leftShoulder = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_spine01/cf_j_spine02/cf_j_spine03/cf_d_shoulder_L/cf_j_shoulder_L"); 42 | // vRef.leftUpperArm = refs.leftUpperArm; 43 | // vRef.leftForearm = refs.leftForearm; 44 | // vRef.leftHand = refs.leftHand; 45 | 46 | // vRef.rightShoulder = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_spine01/cf_j_spine02/cf_j_spine03/cf_d_shoulder_R/cf_j_shoulder_R"); 47 | // vRef.rightUpperArm = refs.rightUpperArm; 48 | // vRef.rightForearm = refs.rightForearm; 49 | // vRef.rightHand = refs.rightHand; 50 | 51 | // vRef.leftThigh = refs.leftThigh; 52 | // vRef.leftCalf = refs.leftCalf; 53 | // vRef.leftFoot = refs.leftFoot; 54 | // vRef.leftToes = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_waist01/cf_j_waist02/cf_j_thigh00_L/cf_j_leg01_L/cf_j_leg03_L/cf_j_foot_L/cf_j_toes_L"); 55 | 56 | // vRef.rightThigh = refs.rightThigh; 57 | // vRef.rightCalf = refs.rightCalf; 58 | // vRef.rightFoot = refs.rightFoot; 59 | // vRef.rightToes = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_waist01/cf_j_waist02/cf_j_thigh00_R/cf_j_leg01_R/cf_j_leg03_R/cf_j_foot_R/cf_j_toes_R"); 60 | // return vrik; 61 | // } 62 | 63 | // private readonly Vector3[] _handPosOffset = 64 | // [ 65 | // new(0f, 0f, -0.1f), 66 | // new(0f, 0f, -0.1f) 67 | // ]; 68 | // private readonly Quaternion[] _handRotOffset = 69 | // [ 70 | // Quaternion.Euler(-30f, 90f, 0f), 71 | // Quaternion.Euler(-30f, -90f, 0f), 72 | // ]; 73 | // private void SyncWithRig(KK.RootMotion.FinalIK.VRIK vrik) 74 | // { 75 | // var hands = HandHolder.GetHands; 76 | // vrik.solver.leftArm.target = AddHandOffset(0, hands[0].Anchor); 77 | // vrik.solver.rightArm.target = AddHandOffset(1, hands[1].Anchor); 78 | // var headTarget = new GameObject("headTarget").transform; 79 | // headTarget.SetParent(VR.Camera.Head, false); 80 | // headTarget.localPosition = Vector3.zero; 81 | // headTarget.localRotation = Quaternion.identity; 82 | // vrik.solver.spine.headTarget = headTarget; 83 | 84 | // Util.CreatePrimitive(PrimitiveType.Sphere, new Vector3(0.05f, 0.05f, 0.05f), VR.Mode.Left.transform, Color.yellow, 0.5f); 85 | // Util.CreatePrimitive(PrimitiveType.Sphere, new Vector3(0.05f, 0.05f, 0.05f), VR.Mode.Right.transform, Color.yellow, 0.5f); 86 | // } 87 | 88 | // private Transform AddHandOffset(int index, Transform parent) 89 | // { 90 | // var gameObject = new GameObject("VRIK_hand_anchor"); 91 | // gameObject.transform.SetParent(parent, false); 92 | // // For some reason when we deal with VRGIN objects, orientation can get weird out of nowhere. 93 | // gameObject.transform.localPosition = _handPosOffset[index]; 94 | // gameObject.transform.localRotation = _handRotOffset[index]; 95 | // return gameObject.transform; 96 | // } 97 | // } 98 | //} 99 | -------------------------------------------------------------------------------- /Shared/IK/OffsetModifier.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using KK.RootMotion.FinalIK; 4 | using RootMotion.FinalIK; 5 | 6 | namespace KK_VR.IK 7 | { 8 | // Simplified version from FinalIK scripts 9 | /// 10 | /// Base class for all FBBIK effector positionOffset modifiers. Works with animatePhysics, safe delegates, offset limits. 11 | /// 12 | public abstract class OffsetModifier : MonoBehaviour 13 | { 14 | 15 | ///// 16 | ///// Limiting effector position offsets 17 | ///// 18 | //[System.Serializable] 19 | //public class OffsetLimits 20 | //{ 21 | // public KK.RootMotion.FinalIK.FullBodyBipedEffector effector; 22 | // /// 23 | // /// Spring force, if zero then this is a hard limit, if not, offset can exceed the limit. 24 | // /// 25 | // public float spring = 0f; 26 | // /// 27 | // /// Axes to limit the offset on 28 | // /// 29 | // public bool x, y, z; 30 | // /// 31 | // /// Limits 32 | // /// 33 | // public float minX, maxX, minY, maxY, minZ, maxZ; 34 | 35 | // // Apply the limit to the effector 36 | // public void Apply(KK.RootMotion.FinalIK.IKEffector e, Quaternion rootRotation) 37 | // { 38 | // Vector3 offset = Quaternion.Inverse(rootRotation) * e.positionOffset; 39 | 40 | // if (spring <= 0f) 41 | // { 42 | // // Hard limits 43 | // if (x) offset.x = Mathf.Clamp(offset.x, minX, maxX); 44 | // if (y) offset.y = Mathf.Clamp(offset.y, minY, maxY); 45 | // if (z) offset.z = Mathf.Clamp(offset.z, minZ, maxZ); 46 | // } 47 | // else 48 | // { 49 | // // Soft limits 50 | // if (x) offset.x = SpringAxis(offset.x, minX, maxX); 51 | // if (y) offset.y = SpringAxis(offset.y, minY, maxY); 52 | // if (z) offset.z = SpringAxis(offset.z, minZ, maxZ); 53 | // } 54 | 55 | // // Apply to the effector 56 | // e.positionOffset = rootRotation * offset; 57 | // } 58 | 59 | // // Just math for limiting floats 60 | // private float SpringAxis(float value, float min, float max) 61 | // { 62 | // if (value > min && value < max) return value; 63 | // if (value < min) return Spring(value, min, true); 64 | // return Spring(value, max, false); 65 | // } 66 | 67 | // // Spring math 68 | // private float Spring(float value, float limit, bool negative) 69 | // { 70 | // float illegal = value - limit; 71 | // float s = illegal * spring; 72 | 73 | // if (negative) return value + Mathf.Clamp(-s, 0, -illegal); 74 | // return value - Mathf.Clamp(s, 0, illegal); 75 | // } 76 | //} 77 | 78 | protected private KK.RootMotion.FinalIK.FullBodyBipedIK _ik; 79 | 80 | // not using Time.deltaTime or Time.fixedDeltaTime here, because we don't know if animatePhysics is true or not on the character, so we have to keep track of time ourselves. 81 | //protected float deltaTime { get { return Time.time - lastTime; } } 82 | //protected float deltaTime { get { return Time.deltaTime; } } 83 | protected abstract void OnModifyOffset(); 84 | 85 | //protected float lastTime; 86 | 87 | 88 | // The main function that checks for all conditions and calls OnModifyOffset if they are met 89 | protected void ModifyOffset() 90 | { 91 | if (gameObject.activeSelf) 92 | { 93 | OnModifyOffset(); 94 | } 95 | //if (weight <= 0f) return; 96 | //if (ik == null) return; 97 | //weight = Mathf.Clamp01(weight); 98 | //if (deltaTime <= 0f) return; 99 | 100 | 101 | //lastTime = Time.time; 102 | } 103 | 104 | //protected void ApplyLimits(OffsetLimits[] limits) 105 | //{ 106 | // // Apply the OffsetLimits 107 | // foreach (var limit in limits) 108 | // { 109 | // limit.Apply(ik.solver.GetEffector(limit.effector), transform.rotation); 110 | // } 111 | //} 112 | 113 | // Remove the delegate when destroyed 114 | 115 | 116 | protected virtual void OnDestroy() 117 | { 118 | if (_ik != null) _ik.solver.OnPreUpdate -= ModifyOffset; 119 | } 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /Shared/Holders/VRBoop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using HarmonyLib; 4 | using UnityEngine; 5 | using VRGIN.Core; 6 | using VRGIN.Controls; 7 | using System.Linq; 8 | using System.Collections; 9 | 10 | namespace KK_VR.Features 11 | { 12 | /// 13 | /// Adds colliders to the controllers so you can boop things 14 | /// Based on a feature in KK_VREnhancement by thojmr 15 | /// https://github.com/thojmr/KK_VREnhancement/blob/5e46bc9a89bf2517c5482bc9df097c7f0274730f/KK_VREnhancement/VRController.Collider.cs 16 | /// 17 | public static class VRBoop 18 | { 19 | private readonly static List _activeDBC = []; 20 | public static void Initialize() 21 | { 22 | // Hooks in here don't get patched by the whole assembly PatchAll since the class has no HarmonyPatch attribute 23 | Harmony.CreateAndPatchAll(typeof(VRBoop), typeof(VRBoop).FullName); 24 | } 25 | public static void AddDB(DynamicBoneCollider DBCollider) 26 | { 27 | _activeDBC.Add(DBCollider); 28 | } 29 | public static void RefreshDynamicBones(IEnumerable charas) 30 | { 31 | // Hooks don't give us BetterPenetration dynamic bones. 32 | foreach (var chara in charas) 33 | { 34 | var dbList = chara.GetComponentsInChildren(); 35 | foreach (var db in dbList) 36 | { 37 | AttachControllerColliders(db); 38 | } 39 | var dbList01 = chara.GetComponentsInChildren(); 40 | foreach (var db in dbList01) 41 | { 42 | AttachControllerColliders(db); 43 | } 44 | var dbList02 = chara.GetComponentsInChildren(); 45 | foreach (var db in dbList02) 46 | { 47 | AttachControllerColliders(db); 48 | } 49 | } 50 | } 51 | [HarmonyPostfix] 52 | [HarmonyWrapSafe] 53 | [HarmonyPatch(typeof(DynamicBone), nameof(DynamicBone.SetupParticles))] 54 | [HarmonyPatch(typeof(DynamicBone_Ver01), nameof(DynamicBone_Ver01.SetupParticles))] 55 | [HarmonyPatch(typeof(DynamicBone_Ver02), nameof(DynamicBone_Ver02.SetupParticles))] 56 | private static void OnDynamicBoneInit(MonoBehaviour __instance) 57 | { 58 | AttachControllerColliders(__instance); 59 | } 60 | 61 | [HarmonyPrefix] 62 | [HarmonyWrapSafe] 63 | [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.LoadCharaFbxDataAsync))] 64 | // [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.LoadCharaFbxDataNoAsync))] // unnecessary, the collider array is reset before the SetupParticles hook 65 | private static void OnClothesChanged(ref Action actObj) 66 | { 67 | // This action is called with the loaded object after the colliders on it are set up 68 | // This needs to be done despite the SetupParticles hook because LoadCharaFbxData resets the collider list 69 | actObj += newObj => 70 | { 71 | if (newObj == null) return; 72 | foreach (var newBone in newObj.GetComponentsInChildren()) 73 | { 74 | var colliders = newBone.m_Colliders; 75 | if (colliders != null) 76 | AddColliders(colliders); 77 | } 78 | }; 79 | } 80 | 81 | private static void AttachControllerColliders(MonoBehaviour dynamicBone) 82 | { 83 | var colliderList = GetColliderList(dynamicBone); 84 | if (colliderList != null) 85 | { 86 | AddColliders(colliderList); 87 | } 88 | } 89 | private static void AddColliders(List colliderList) 90 | { 91 | foreach (var dbc in _activeDBC) 92 | { 93 | if (!colliderList.Contains(dbc)) 94 | { 95 | colliderList.Add(dbc); 96 | } 97 | } 98 | } 99 | 100 | private static List GetColliderList(MonoBehaviour dynamicBone) 101 | { 102 | return dynamicBone switch 103 | { 104 | DynamicBone d => d.m_Colliders, 105 | DynamicBone_Ver01 d => d.m_Colliders, 106 | DynamicBone_Ver02 d => d.Colliders, 107 | null => throw new ArgumentNullException(nameof(dynamicBone)), 108 | _ => throw new ArgumentException(@"Not a DynamicBone - " + dynamicBone.GetType(), nameof(dynamicBone)), 109 | }; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Shared/Camera/EffectorVFX.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityStandardAssets.ImageEffects; 4 | using VRGIN.Core; 5 | 6 | namespace KK_VR.Camera 7 | { 8 | /// 9 | /// A component to be attached to the VR camera. Ensures that it has the 10 | /// same set of camera effects enabled as the game camera. 11 | /// 12 | class EffectorVFX : ProtectedBehaviour 13 | { 14 | protected override void OnUpdate() 15 | { 16 | var blueprint = VR.Camera.Blueprint; 17 | if (blueprint && _source != blueprint) 18 | { 19 | _source = blueprint; 20 | HandleNewGameCamera(blueprint); 21 | } 22 | } 23 | 24 | protected override void OnLateUpdate() 25 | { 26 | _fog.UpdateEnabled(); 27 | _amplifyColor.UpdateEnabled(); 28 | if (_amplifyColor.mirror && _amplifyColor.source) 29 | { 30 | // NightDarkener tweaks exposure. 31 | _amplifyColor.mirror.Exposure = _amplifyColor.source.Exposure; 32 | } 33 | _amplifyOcclusion.UpdateEnabled(); 34 | _bloom.UpdateEnabled(); 35 | _sunShafts.UpdateEnabled(); 36 | if (_sunShafts.mirror && _sunShafts.source && _sunShafts.mirror.enabled) 37 | { 38 | _sunShafts.mirror.sunColor = _sunShafts.source.sunColor; 39 | _sunShafts.mirror.sunTransform = _sunShafts.source.sunTransform; 40 | 41 | TweakSunShaftSettings(_sunShafts.mirror); 42 | } 43 | _vignette.UpdateEnabled(); 44 | _blur.UpdateEnabled(); 45 | if (_blur.mirror && _blur.source && _blur.mirror.enabled) 46 | { 47 | _blur.mirror.iterations = _blur.source.iterations; 48 | } 49 | _sepia.UpdateEnabled(); 50 | _flareLayer.UpdateEnabled(); 51 | } 52 | 53 | Mirrored _fog; 54 | Mirrored _amplifyColor; 55 | Mirrored _amplifyOcclusion; 56 | Mirrored _bloom; 57 | Mirrored _sunShafts; 58 | Mirrored _vignette; 59 | // Depth-of-field effect doesn't really make sense in VR, where the 60 | // player is free to look at whatever they want. 61 | //Mirrored _dof; 62 | Mirrored _blur; 63 | // Crossfade with a still image won't work well in VR. 64 | //Mirrored _crossFade; 65 | Mirrored _sepia; 66 | Mirrored _flareLayer; 67 | 68 | UnityEngine.Camera _source; 69 | 70 | private void HandleNewGameCamera(UnityEngine.Camera gameCamera) 71 | { 72 | void Copy(ref Mirrored m) where 73 | T : Behaviour 74 | { 75 | if (m.mirror != null) 76 | { 77 | Destroy(m.mirror); 78 | } 79 | m.source = gameCamera.GetComponent(); 80 | if (m.source == null) 81 | { 82 | m.mirror = null; 83 | } 84 | else 85 | { 86 | m.mirror = VRGIN.Helpers.UnityHelper.CopyComponent(m.source, gameObject); 87 | } 88 | } 89 | 90 | Copy(ref _fog); 91 | Copy(ref _amplifyColor); 92 | Copy(ref _amplifyOcclusion); 93 | Copy(ref _bloom); 94 | Copy(ref _sunShafts); 95 | Copy(ref _vignette); 96 | Copy(ref _blur); 97 | Copy(ref _sepia); 98 | Copy(ref _flareLayer); 99 | } 100 | 101 | /// 102 | /// Make sun shafts less obnoxious in VR 103 | /// 104 | private static void TweakSunShaftSettings(SunShafts sunShafts) 105 | { 106 | sunShafts.sunThreshold = new Color(0.74f, 0.74f, 0.74f, 0); 107 | sunShafts.maxRadius = 0.2f; 108 | sunShafts.radialBlurIterations = 3; 109 | sunShafts.sunShaftBlurRadius = 3; 110 | sunShafts.sunShaftIntensity = 0.6f; 111 | } 112 | 113 | /// 114 | /// Keep up with constant VFX updates 115 | /// 116 | internal static void Refresh() 117 | { 118 | var effector = VR.Camera.GetComponent(); 119 | if (effector != null && VR.Camera.Blueprint != null) 120 | { 121 | effector.HandleNewGameCamera(VR.Camera.Blueprint); 122 | } 123 | } 124 | 125 | 126 | struct Mirrored 127 | where T : Behaviour 128 | { 129 | public T mirror; 130 | public T source; 131 | 132 | public void UpdateEnabled() 133 | { 134 | if (mirror != null) 135 | { 136 | mirror.enabled = (source && source.enabled); 137 | } 138 | } 139 | } 140 | } 141 | } 142 | --------------------------------------------------------------------------------