diff --git a/.gitmodules b/.gitmodules
index c8d1f40..719b751 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "VRGIN_OpenXR"]
path = VRGIN_OpenXR
- url = https://github.com/ManlyMarco/VRGIN_OpenXR
\ No newline at end of file
+ url = https://github.com/ManlyMarco/VRGIN_OpenXR
+[submodule "VRGIN"]
+ path = VRGIN
+ url = https://github.com/lotsofbearsKoikatsu/VRGIN
diff --git a/CharaStudioVR/CharaStudioVR.csproj b/CharaStudioVR/CharaStudioVR.csproj
index f0837b1..0b8142a 100644
--- a/CharaStudioVR/CharaStudioVR.csproj
+++ b/CharaStudioVR/CharaStudioVR.csproj
@@ -24,7 +24,7 @@
prompt
4
true
- 8
+ Preview
embedded
@@ -36,6 +36,7 @@
true
8
true
+ Preview
@@ -66,6 +67,12 @@
..\packages\ExtensibleSaveFormat.KoikatsuSunshine.16.8.1\lib\net46\KKS_ExtensibleSaveFormat.dll
False
+
+ ..\..\KK_SensibleH\Libs\KK_FinalIK.dll
+
+
+ ..\Libs\Obi.dll
+
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.CoreModule.2019.4.9\lib\net46\Sirenix.Serialization.dll
False
@@ -184,6 +191,11 @@
+
+
+
+
+
@@ -204,6 +216,8 @@
+
+
diff --git a/Shared/Controls/BetterMenuTool.cs b/CharaStudioVR/Controls/BetterMenuTool.cs
similarity index 86%
rename from Shared/Controls/BetterMenuTool.cs
rename to CharaStudioVR/Controls/BetterMenuTool.cs
index 21047bb..107859b 100644
--- a/Shared/Controls/BetterMenuTool.cs
+++ b/CharaStudioVR/Controls/BetterMenuTool.cs
@@ -9,23 +9,24 @@
using VRGIN.Visuals;
using Object = UnityEngine.Object;
-namespace KKS_VR.Controls
+
+namespace KK_VR.Controls
{
///
/// MenuTool that supports right clicks by pressing the trackpad
///
internal class BetterMenuTool : MenuTool
{
- public override List GetHelpTexts()
- {
- return new List(new[]
- {
- ToolUtil.HelpTrackpadCenter(Owner, "Press to Right Click"),
- ToolUtil.HelpTrackpadUp(Owner, "Slide to Move Cursor"),
- ToolUtil.HelpTrigger(Owner, "Left Click"),
- ToolUtil.HelpGrip(Owner, "Take/release screen")
- }.Where(x => x != null));
- }
+ //public override List GetHelpTexts()
+ //{
+ // return new List(new[]
+ // {
+ // ToolUtil.HelpTrackpadCenter(Owner, "Press to Right Click"),
+ // ToolUtil.HelpTrackpadUp(Owner, "Slide to Move Cursor"),
+ // ToolUtil.HelpTrigger(Owner, "Left Click"),
+ // ToolUtil.HelpGrip(Owner, "Take/release screen")
+ // }.Where(x => x != null));
+ //}
#region Override base functionality to add right clicks
diff --git a/Shared/Controls/BetterWarpTool.cs b/CharaStudioVR/Controls/BetterWarpTool.cs
similarity index 74%
rename from Shared/Controls/BetterWarpTool.cs
rename to CharaStudioVR/Controls/BetterWarpTool.cs
index 9dc8f2e..93e6680 100644
--- a/Shared/Controls/BetterWarpTool.cs
+++ b/CharaStudioVR/Controls/BetterWarpTool.cs
@@ -5,7 +5,9 @@
using VRGIN.Controls;
using VRGIN.Controls.Tools;
-namespace KKS_VR.Controls
+
+// MainGame doesn't have warp tool no more.
+namespace KK_VR.Controls
{
///
/// WarpTool version that cancels teleporting when user tries grab moving
@@ -32,13 +34,13 @@ protected override void OnUpdate()
base.OnUpdate();
}
- public override List GetHelpTexts()
- {
- return new List(new[]
- {
- ToolUtil.HelpTrackpadCenter(Owner, "Press to teleport"),
- ToolUtil.HelpGrip(Owner, "Hold to move"),
- }.Where(x => x != null));
- }
+ //public override List GetHelpTexts()
+ //{
+ // return new List(new[]
+ // {
+ // ToolUtil.HelpTrackpadCenter(Owner, "Press to teleport"),
+ // ToolUtil.HelpGrip(Owner, "Hold to move"),
+ // }.Where(x => x != null));
+ //}
}
}
diff --git a/CharaStudioVR/Controls/GripMenuHandler.cs b/CharaStudioVR/Controls/GripMenuHandler.cs
index 190e0b0..03be0d3 100644
--- a/CharaStudioVR/Controls/GripMenuHandler.cs
+++ b/CharaStudioVR/Controls/GripMenuHandler.cs
@@ -1,5 +1,5 @@
using System.Linq;
-using KKS_VR.Settings;
+using KK_VR.Settings;
using UnityEngine;
using Valve.VR;
using VRGIN.Controls;
@@ -7,7 +7,7 @@
using VRGIN.Native;
using VRGIN.Visuals;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
public class GripMenuHandler : ProtectedBehaviour
{
diff --git a/CharaStudioVR/Controls/GripMoveStudioNEOV2Tool.cs b/CharaStudioVR/Controls/GripMoveStudioNEOV2Tool.cs
index 5f54aaa..582c6da 100644
--- a/CharaStudioVR/Controls/GripMoveStudioNEOV2Tool.cs
+++ b/CharaStudioVR/Controls/GripMoveStudioNEOV2Tool.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using KKS_VR.Settings;
-using KKS_VR.Util;
+using KK_VR.Settings;
+using KK_VR.Util;
using Studio;
using UnityEngine;
using UnityEngine.Rendering;
@@ -15,7 +15,7 @@
using VRGIN.Helpers;
using VRGIN.Visuals;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
internal class GripMoveStudioNEOV2Tool : Tool
{
@@ -89,7 +89,7 @@ private void CreatePointer()
}
}
- protected override void OnDestroy()
+ private void OnDestroy()
{
if (marker != null) Destroy(marker);
if (mirror1 != null) Destroy(mirror1);
diff --git a/CharaStudioVR/Controls/IKTool.cs b/CharaStudioVR/Controls/IKTool.cs
index 25ffbf3..ad69e0d 100644
--- a/CharaStudioVR/Controls/IKTool.cs
+++ b/CharaStudioVR/Controls/IKTool.cs
@@ -1,12 +1,12 @@
using System;
using System.Collections;
-using KKS_VR.Util;
+using KK_VR.Util;
using Studio;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
public class IKTool : MonoBehaviour
{
diff --git a/CharaStudioVR/Controls/ObjMoveHelper.cs b/CharaStudioVR/Controls/ObjMoveHelper.cs
index 0e1a4ae..fac9529 100644
--- a/CharaStudioVR/Controls/ObjMoveHelper.cs
+++ b/CharaStudioVR/Controls/ObjMoveHelper.cs
@@ -2,7 +2,7 @@
using Studio;
using UnityEngine;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
internal class ObjMoveHelper
{
diff --git a/CharaStudioVR/Controls/VRCameraMoveHelper.cs b/CharaStudioVR/Controls/VRCameraMoveHelper.cs
index 23097dd..0fe9d1c 100644
--- a/CharaStudioVR/Controls/VRCameraMoveHelper.cs
+++ b/CharaStudioVR/Controls/VRCameraMoveHelper.cs
@@ -5,7 +5,7 @@
using UnityEngine.UI;
using VRGIN.Core;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
public class VRCameraMoveHelper : MonoBehaviour
{
diff --git a/CharaStudioVR/Controls/VRItemObjMoveHelper.cs b/CharaStudioVR/Controls/VRItemObjMoveHelper.cs
index 95b73d7..e139b8c 100644
--- a/CharaStudioVR/Controls/VRItemObjMoveHelper.cs
+++ b/CharaStudioVR/Controls/VRItemObjMoveHelper.cs
@@ -8,7 +8,7 @@
using VRGIN.Core;
using VRGIN.Helpers;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
public class VRItemObjMoveHelper : MonoBehaviour
{
diff --git a/CharaStudioVR/Features/VRBoop.cs b/CharaStudioVR/Features/VRBoop.cs
new file mode 100644
index 0000000..904b64f
--- /dev/null
+++ b/CharaStudioVR/Features/VRBoop.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+using HarmonyLib;
+using UnityEngine;
+using UnityEngine.XR;
+using VRGIN.Controls;
+
+// MainGame uses a bit different implementation.
+namespace KK_VR.Features
+{
+ ///
+ /// Adds colliders to the controllers so you can boop things
+ /// Based on a feature in KK_VREnhancement by thojmr
+ /// https://github.com/thojmr/KK_VREnhancement/blob/5e46bc9a89bf2517c5482bc9df097c7f0274730f/KK_VREnhancement/VRController.Collider.cs
+ ///
+ public static class VRBoopStudio
+ {
+ internal const string LeftColliderName = "Left_Boop_Collider";
+ internal const string RightColliderName = "Right_Boop_Collider";
+
+ private static DynamicBoneCollider _leftCollider;
+ private static DynamicBoneCollider _rightCollider;
+
+ public static void Initialize(Controller controller, EyeSide controllerSide)
+ {
+ // Hooks in here don't get patched by the whole assembly PatchAll since the class has no HarmonyPatch attribute
+ Harmony.CreateAndPatchAll(typeof(VRBoop), typeof(VRBoop).FullName);
+
+ switch (controllerSide)
+ {
+ case EyeSide.Left:
+ _leftCollider = GetOrAttachCollider(controller.gameObject, LeftColliderName);
+ break;
+ case EyeSide.Right:
+ _rightCollider = GetOrAttachCollider(controller.gameObject, RightColliderName);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(controllerSide), controllerSide, null);
+ }
+ }
+
+ [HarmonyPostfix]
+ [HarmonyWrapSafe]
+ [HarmonyPatch(typeof(DynamicBone), nameof(DynamicBone.SetupParticles))]
+ [HarmonyPatch(typeof(DynamicBone_Ver01), nameof(DynamicBone_Ver01.SetupParticles))]
+ [HarmonyPatch(typeof(DynamicBone_Ver02), nameof(DynamicBone_Ver02.SetupParticles))]
+ private static void OnDynamicBoneInit(MonoBehaviour __instance)
+ {
+ AttachControllerColliders(__instance);
+ }
+
+ [HarmonyPrefix]
+ [HarmonyWrapSafe]
+ [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.LoadCharaFbxDataAsync))]
+ // [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.LoadCharaFbxDataNoAsync))] // unnecessary, the collider array is reset before the SetupParticles hook
+ private static void OnClothesChanged(ref Action actObj)
+ {
+ // This action is called with the loaded object after the colliders on it are set up
+ // This needs to be done despite the SetupParticles hook because LoadCharaFbxData resets the collider list
+ actObj += newObj =>
+ {
+ if (newObj == null) return;
+ foreach (var newBone in newObj.GetComponentsInChildren())
+ {
+ var colliders = newBone.m_Colliders;
+ if (colliders != null)
+ AttachControllerColliders(colliders);
+ }
+ };
+ }
+
+ private static void AttachControllerColliders(MonoBehaviour dynamicBone)
+ {
+ var colliderList = GetColliderList(dynamicBone);
+ if (colliderList == null) return;
+ AttachControllerColliders(colliderList);
+ }
+
+ private static void AttachControllerColliders(List colliderList)
+ {
+ if (colliderList == null) throw new ArgumentNullException(nameof(colliderList));
+
+ if (_leftCollider && !colliderList.Contains(_leftCollider))
+ colliderList.Add(_leftCollider);
+ if (_rightCollider && !colliderList.Contains(_rightCollider))
+ colliderList.Add(_rightCollider);
+ }
+
+ private static List GetColliderList(MonoBehaviour dynamicBone)
+ {
+ return dynamicBone switch
+ {
+ DynamicBone d => d.m_Colliders,
+ DynamicBone_Ver01 d => d.m_Colliders,
+ DynamicBone_Ver02 d => d.Colliders,
+ null => throw new ArgumentNullException(nameof(dynamicBone)),
+ _ => throw new ArgumentException(@"Not a DynamicBone - " + dynamicBone.GetType(), nameof(dynamicBone)),
+ };
+ }
+
+ private static DynamicBoneCollider GetOrAttachCollider(GameObject controllerGameObject, string colliderName)
+ {
+ if (controllerGameObject == null) throw new ArgumentNullException(nameof(controllerGameObject));
+ if (colliderName == null) throw new ArgumentNullException(nameof(colliderName));
+
+ //Check for existing DB collider that may have been attached earlier
+ var existingCollider = controllerGameObject.GetComponentInChildren();
+ if (existingCollider == null)
+ {
+ //Add a DB collider to the controller
+ return AddDbCollider(controllerGameObject, colliderName);
+ }
+
+ return existingCollider;
+ }
+
+ private static DynamicBoneCollider AddDbCollider(GameObject controllerGameObject, string colliderName,
+ float colliderRadius = 0.05f, float collierHeight = 0f, Vector3 colliderCenter = new Vector3(), DynamicBoneCollider.Direction colliderDirection = default)
+ {
+ //Build the dynamic bone collider
+ var colliderObject = new GameObject(colliderName);
+ var collider = colliderObject.AddComponent();
+ collider.m_Radius = colliderRadius;
+ collider.m_Height = collierHeight;
+ collider.m_Center = colliderCenter;
+ collider.m_Direction = colliderDirection;
+ colliderObject.transform.SetParent(controllerGameObject.transform, false);
+ return collider;
+ }
+ }
+}
diff --git a/CharaStudioVR/Fixes/LoadFixHook.cs b/CharaStudioVR/Fixes/LoadFixHook.cs
index a92aeb4..0cf2fe1 100644
--- a/CharaStudioVR/Fixes/LoadFixHook.cs
+++ b/CharaStudioVR/Fixes/LoadFixHook.cs
@@ -1,11 +1,11 @@
using System;
using BepInEx.Logging;
using HarmonyLib;
-using KKS_VR.Interpreters;
+using KK_VR.Interpreters;
using Studio;
using VRGIN.Core;
-namespace KKS_VR.Fixes
+namespace KK_VR.Fixes
{
public static class LoadFixHook
{
diff --git a/Shared/Fixes/OpenVRHelperTempfixHook.cs b/CharaStudioVR/Fixes/OpenVRHelperTempfixHook.cs
similarity index 90%
rename from Shared/Fixes/OpenVRHelperTempfixHook.cs
rename to CharaStudioVR/Fixes/OpenVRHelperTempfixHook.cs
index 772824a..3b3eb3b 100644
--- a/Shared/Fixes/OpenVRHelperTempfixHook.cs
+++ b/CharaStudioVR/Fixes/OpenVRHelperTempfixHook.cs
@@ -2,7 +2,8 @@
using HarmonyLib;
using Unity.XR.OpenVR;
-namespace KKS_VR.Fixes
+// Will break haptic feedback in KKS if enabled.
+namespace KK_VR.Fixes
{
///
/// No idea what exactly it does but it doesn't seem to hurt anything. Originally a part of KKS_CharaStudioVR
diff --git a/CharaStudioVR/Fixes/SaveLoadSceneHook.cs b/CharaStudioVR/Fixes/SaveLoadSceneHook.cs
index 89b02c6..e547c5d 100644
--- a/CharaStudioVR/Fixes/SaveLoadSceneHook.cs
+++ b/CharaStudioVR/Fixes/SaveLoadSceneHook.cs
@@ -2,17 +2,17 @@
using System.Reflection;
using BepInEx.Logging;
using HarmonyLib;
-using KKS_VR.Controls;
+using KK_VR.Controls;
using Manager;
using Studio;
using UnityEngine;
using VRGIN.Core;
-namespace KKS_VR.Fixes
+namespace KK_VR.Fixes
{
public static class SaveLoadSceneHook
{
- private static Camera[] backupRenderCam;
+ private static UnityEngine.Camera[] backupRenderCam;
private static Sprite sceneLoadScene_spriteLoad;
@@ -24,17 +24,17 @@ public static void InstallHook()
[HarmonyPrefix]
[HarmonyPatch(typeof(Studio.Studio), "SaveScene", new Type[] { })]
- public static bool SaveScenePreHook(Studio.Studio __instance, ref Camera[] __state)
+ public static bool SaveScenePreHook(Studio.Studio __instance, ref UnityEngine.Camera[] __state)
{
VRPlugin.Logger.Log(LogLevel.Debug, "Update Camera position and rotation for Scene Capture and last Camera data.");
try
{
VRCameraMoveHelper.Instance.CurrentToCameraCtrl();
var field = typeof(Studio.GameScreenShot).GetField("renderCam", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- var obj = field.GetValue(Singleton.Instance.gameScreenShot) as Camera[];
+ var obj = field.GetValue(Singleton.Instance.gameScreenShot) as UnityEngine.Camera[];
VRPlugin.Logger.Log(LogLevel.Debug, "Backup Screenshot render cam.");
backupRenderCam = obj;
- var value = new Camera[1] { VR.Camera.SteamCam.camera };
+ var value = new UnityEngine.Camera[1] { VR.Camera.SteamCam.camera };
__state = backupRenderCam;
field.SetValue(Singleton.Instance.gameScreenShot, value);
}
@@ -49,7 +49,7 @@ public static bool SaveScenePreHook(Studio.Studio __instance, ref Camera[] __sta
[HarmonyPostfix]
[HarmonyPatch(typeof(Studio.Studio), "SaveScene", new Type[] { })]
- public static void SaveScenePostHook(Studio.Studio __instance, Camera[] __state)
+ public static void SaveScenePostHook(Studio.Studio __instance, UnityEngine.Camera[] __state)
{
VRPlugin.Logger.Log(LogLevel.Debug, "Restore backup render cam.");
try
diff --git a/Shared/Fixes/TopmostToolIcons.cs b/CharaStudioVR/Fixes/TopmostToolIcons.cs
similarity index 96%
rename from Shared/Fixes/TopmostToolIcons.cs
rename to CharaStudioVR/Fixes/TopmostToolIcons.cs
index 4992548..5829107 100644
--- a/Shared/Fixes/TopmostToolIcons.cs
+++ b/CharaStudioVR/Fixes/TopmostToolIcons.cs
@@ -5,7 +5,9 @@
using VRGIN.Controls;
using VRGIN.Core;
-namespace KKS_VR.Fixes
+
+// Only single tool left, no icons needed.
+namespace KK_VR.Fixes
{
///
/// Fix custom tool icons not being on top of the black circle
diff --git a/Shared/Fixes/topmostgui.shader b/CharaStudioVR/Fixes/topmostgui.shader
similarity index 100%
rename from Shared/Fixes/topmostgui.shader
rename to CharaStudioVR/Fixes/topmostgui.shader
diff --git a/Shared/Fixes/topmostguishader b/CharaStudioVR/Fixes/topmostguishader
similarity index 100%
rename from Shared/Fixes/topmostguishader
rename to CharaStudioVR/Fixes/topmostguishader
diff --git a/CharaStudioVR/Interpreters/KKSCharaStudioActor.cs b/CharaStudioVR/Interpreters/KKSCharaStudioActor.cs
index 20c2133..a9068dd 100644
--- a/CharaStudioVR/Interpreters/KKSCharaStudioActor.cs
+++ b/CharaStudioVR/Interpreters/KKSCharaStudioActor.cs
@@ -1,11 +1,11 @@
using System;
using System.Configuration;
-using KKS_VR.Settings;
+using KK_VR.Settings;
using UnityEngine;
using VRGIN.Core;
using VRGIN.Helpers;
-namespace KKS_VR.Interpreters
+namespace KK_VR.Interpreters
{
public class KKSCharaStudioActor : DefaultActorBehaviour
{
@@ -38,7 +38,7 @@ protected override void OnLateUpdate()
base.OnLateUpdate();
var eyeLookCtrl = Actor.eyeLookCtrl;
var neckLookCtrl = Actor.neckLookCtrl;
- var transform = Camera.main.transform;
+ var transform = UnityEngine.Camera.main.transform;
if ((bool)transform)
{
if ((bool)eyeLookCtrl && eyeLookCtrl.target == transform) eyeLookCtrl.target = _TargetController.Target;
@@ -73,7 +73,7 @@ internal void OnVRModeChanged(bool newMode)
var eyeLookCtrl = Actor.eyeLookCtrl;
var neckLookCtrl = Actor.neckLookCtrl;
- var transform = Camera.main.transform;
+ var transform = UnityEngine.Camera.main.transform;
if ((bool)transform)
{
if ((bool)eyeLookCtrl && eyeLookCtrl.target == _TargetController.Target) eyeLookCtrl.target = transform;
diff --git a/CharaStudioVR/Interpreters/KKSCharaStudioInterpreter.cs b/CharaStudioVR/Interpreters/KKSCharaStudioInterpreter.cs
index 803f5bb..53953e6 100644
--- a/CharaStudioVR/Interpreters/KKSCharaStudioInterpreter.cs
+++ b/CharaStudioVR/Interpreters/KKSCharaStudioInterpreter.cs
@@ -9,7 +9,7 @@
using UnityEngine.SceneManagement;
using VRGIN.Core;
-namespace KKS_VR.Interpreters
+namespace KK_VR.Interpreters
{
internal class KKSCharaStudioInterpreter : GameInterpreter
{
@@ -35,7 +35,7 @@ protected override void OnStart()
FixMenuCanvasLayers();
}
- public override Camera FindCamera()
+ public override UnityEngine.Camera FindCamera()
{
return null;
}
@@ -82,7 +82,7 @@ private void SyncVRCameraSkybox()
private void UpdateMainCameraCullingMask()
{
- var component = VR.Camera.SteamCam.GetComponent();
+ var component = VR.Camera.SteamCam.GetComponent();
var list = new List();
var obj = new List { "Studio/Col", "Studio/Select" };
diff --git a/CharaStudioVR/Interpreters/TransientHead.cs b/CharaStudioVR/Interpreters/TransientHead.cs
index 512d6a1..20846f6 100644
--- a/CharaStudioVR/Interpreters/TransientHead.cs
+++ b/CharaStudioVR/Interpreters/TransientHead.cs
@@ -5,7 +5,7 @@
using VRGIN.Core;
using VRGIN.Helpers;
-namespace KKS_VR.Interpreters
+namespace KK_VR.Interpreters
{
public class TransientHead : ProtectedBehaviour
{
diff --git a/CharaStudioVR/Settings/CharaStudioContext.cs b/CharaStudioVR/Settings/CharaStudioContext.cs
index cd60c6c..4040c12 100644
--- a/CharaStudioVR/Settings/CharaStudioContext.cs
+++ b/CharaStudioVR/Settings/CharaStudioContext.cs
@@ -4,7 +4,7 @@
using VRGIN.Core;
using VRGIN.Visuals;
-namespace KKS_VR.Settings
+namespace KK_VR.Settings
{
[XmlRoot("Context")]
public class CharaStudioContext : IVRManagerContext
diff --git a/CharaStudioVR/Settings/StudioSettings.cs b/CharaStudioVR/Settings/StudioSettings.cs
index 090eb0b..a9e1c02 100644
--- a/CharaStudioVR/Settings/StudioSettings.cs
+++ b/CharaStudioVR/Settings/StudioSettings.cs
@@ -3,7 +3,7 @@
using KKAPI.Utilities;
using VRGIN.Core;
-namespace KKS_VR.Settings
+namespace KK_VR.Settings
{
public static class StudioSettings
{
diff --git a/CharaStudioVR/StudioStandingMode.cs b/CharaStudioVR/StudioStandingMode.cs
index e02edcf..1edc6a3 100644
--- a/CharaStudioVR/StudioStandingMode.cs
+++ b/CharaStudioVR/StudioStandingMode.cs
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
-using KKS_VR.Controls;
-using KKS_VR.Features;
-using KKS_VR.Settings;
+using KK_VR.Controls;
+using KK_VR.Features;
+using KK_VR.Settings;
using UnityEngine.XR;
using VRGIN.Controls;
using VRGIN.Modes;
-namespace KKS_VR
+namespace KK_VR
{
internal class StudioStandingMode : StandingMode
{
@@ -35,7 +35,7 @@ protected override Controller CreateRightController()
private static void AddComponents(Controller controller, EyeSide controllerSide)
{
if (StudioSettings.EnableBoop.Value)
- VRBoop.Initialize(controller, controllerSide);
+ VRBoopStudio.Initialize(controller, controllerSide);
}
}
}
diff --git a/CharaStudioVR/Util/MaterialHelper.cs b/CharaStudioVR/Util/MaterialHelper.cs
index 10bcfae..8620c2e 100644
--- a/CharaStudioVR/Util/MaterialHelper.cs
+++ b/CharaStudioVR/Util/MaterialHelper.cs
@@ -2,7 +2,7 @@
using KKAPI.Utilities;
using UnityEngine;
-namespace KKS_VR.Util
+namespace KK_VR.Util
{
internal class MaterialHelper
{
diff --git a/CharaStudioVR/Util/MoveableGUIObject.cs b/CharaStudioVR/Util/MoveableGUIObject.cs
index c9c4526..9dec632 100644
--- a/CharaStudioVR/Util/MoveableGUIObject.cs
+++ b/CharaStudioVR/Util/MoveableGUIObject.cs
@@ -4,7 +4,7 @@
using UnityEngine;
using VRGIN.Core;
-namespace KKS_VR.Util
+namespace KK_VR.Util
{
public class MoveableGUIObject : MonoBehaviour
{
diff --git a/CharaStudioVR/VRPlugin.cs b/CharaStudioVR/VRPlugin.cs
index 555bba7..60e5557 100644
--- a/CharaStudioVR/VRPlugin.cs
+++ b/CharaStudioVR/VRPlugin.cs
@@ -3,18 +3,19 @@
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Logging;
+using KK_VR;
using KKAPI;
-using KKS_VR.Controls;
-using KKS_VR.Fixes;
-using KKS_VR.Interpreters;
-using KKS_VR.Settings;
+using KK_VR.Controls;
+using KK_VR.Fixes;
+using KK_VR.Interpreters;
+using KK_VR.Settings;
using Unity.XR.OpenVR;
using UnityEngine;
using UnityEngine.SceneManagement;
using Valve.VR;
using VRGIN.Core;
-namespace KKS_VR
+namespace KK_VR
{
///
/// Studio code was forked from KKS_CharaStudioVR at https://vr-erogamer.com/archives/1065
@@ -136,7 +137,7 @@ private IEnumerator LoadDevice(VRSettings settings)
private void UpdateNearClipPlane()
{
- VR.Camera.GetComponent().nearClipPlane = StudioSettings.NearClipPlane.Value;
+ VR.Camera.GetComponent().nearClipPlane = StudioSettings.NearClipPlane.Value;
}
private static class NativeMethods
diff --git a/KKS_VR.sln b/KKS_VR.sln
index 192b54d..c60b1c3 100644
--- a/KKS_VR.sln
+++ b/KKS_VR.sln
@@ -3,67 +3,134 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33424.131
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MainGameVR", "MainGameVR\MainGameVR.csproj", "{1F634B93-F4C6-45E9-894D-2F3556A74D67}"
- ProjectSection(ProjectDependencies) = postProject
- {4B6E4305-C95A-4274-94A6-B04A1B01989D} = {4B6E4305-C95A-4274-94A6-B04A1B01989D}
- EndProjectSection
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CharaStudioVR", "CharaStudioVR\CharaStudioVR.csproj", "{07ECD6A8-61D0-4409-A009-C138E76DFA1F}"
ProjectSection(ProjectDependencies) = postProject
{4B6E4305-C95A-4274-94A6-B04A1B01989D} = {4B6E4305-C95A-4274-94A6-B04A1B01989D}
EndProjectSection
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Shared", "Shared\Shared.shproj", "{C21C1A1B-5045-4BBE-818B-8574756D1F34}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Submodules", "Submodules", "{CAEA7F44-149D-486A-8791-77C3C44ED139}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VRGIN_OpenXR", "VRGIN_OpenXR\VRGIN_OpenXR.csproj", "{4B6E4305-C95A-4274-94A6-B04A1B01989D}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KK_VR", "KK_VR\KK_VR.csproj", "{ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KKS_VR", "KKS_VR\KKS_VR.csproj", "{1F36AB35-19D3-4553-A166-AF8DFCA39D50}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Shared", "Shared\Shared.shproj", "{447CA481-4806-48D1-8E95-D545D8294620}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VRGIN", "VRGIN\VRGIN\VRGIN.csproj", "{22788A2C-7695-4A6A-A9F0-115AB9A05FD4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PatcherLoader", "PatcherLoader\PatcherLoader.csproj", "{7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "native_patcher", "native_patcher\native_patcher.vcxproj", "{30177590-0ADF-4817-9D9B-804C7C4C749A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Debug|x64.ActiveCfg = Debug|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Debug|x64.Build.0 = Debug|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Release|Any CPU.Build.0 = Release|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Release|x64.ActiveCfg = Release|Any CPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}.Release|x64.Build.0 = Release|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Debug|x64.ActiveCfg = Debug|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Debug|x64.Build.0 = Debug|Any CPU
+ {07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Debug|x86.ActiveCfg = Debug|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Release|Any CPU.Build.0 = Release|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Release|x64.ActiveCfg = Release|Any CPU
{07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Release|x64.Build.0 = Release|Any CPU
+ {07ECD6A8-61D0-4409-A009-C138E76DFA1F}.Release|x86.ActiveCfg = Release|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Debug|x64.ActiveCfg = Debug|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Debug|x64.Build.0 = Debug|Any CPU
+ {4B6E4305-C95A-4274-94A6-B04A1B01989D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4B6E4305-C95A-4274-94A6-B04A1B01989D}.Debug|x86.Build.0 = Debug|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Release|Any CPU.Build.0 = Release|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Release|x64.ActiveCfg = Release|Any CPU
{4B6E4305-C95A-4274-94A6-B04A1B01989D}.Release|x64.Build.0 = Release|Any CPU
+ {4B6E4305-C95A-4274-94A6-B04A1B01989D}.Release|x86.ActiveCfg = Release|Any CPU
+ {4B6E4305-C95A-4274-94A6-B04A1B01989D}.Release|x86.Build.0 = Release|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Debug|x64.Build.0 = Debug|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Debug|x86.Build.0 = Debug|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Release|x64.ActiveCfg = Release|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Release|x64.Build.0 = Release|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Release|x86.ActiveCfg = Release|Any CPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}.Release|x86.Build.0 = Release|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Debug|x64.Build.0 = Debug|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Debug|x86.Build.0 = Debug|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Release|x64.ActiveCfg = Release|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Release|x64.Build.0 = Release|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Release|x86.ActiveCfg = Release|Any CPU
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}.Release|x86.Build.0 = Release|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Debug|x64.Build.0 = Debug|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Debug|x86.Build.0 = Debug|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Release|x64.ActiveCfg = Release|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Release|x64.Build.0 = Release|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Release|x86.ActiveCfg = Release|Any CPU
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4}.Release|x86.Build.0 = Release|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Debug|x64.Build.0 = Debug|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Debug|x86.Build.0 = Debug|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Release|x64.ActiveCfg = Release|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Release|x64.Build.0 = Release|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Release|x86.ActiveCfg = Release|Any CPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}.Release|x86.Build.0 = Release|Any CPU
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Debug|Any CPU.Build.0 = Debug|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Debug|x64.ActiveCfg = Debug|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Debug|x64.Build.0 = Debug|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Debug|x86.ActiveCfg = Debug|Win32
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Debug|x86.Build.0 = Debug|Win32
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Release|Any CPU.ActiveCfg = Release|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Release|Any CPU.Build.0 = Release|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Release|x64.ActiveCfg = Release|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Release|x64.Build.0 = Release|x64
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Release|x86.ActiveCfg = Release|Win32
+ {30177590-0ADF-4817-9D9B-804C7C4C749A}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4B6E4305-C95A-4274-94A6-B04A1B01989D} = {CAEA7F44-149D-486A-8791-77C3C44ED139}
+ {22788A2C-7695-4A6A-A9F0-115AB9A05FD4} = {CAEA7F44-149D-486A-8791-77C3C44ED139}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6A44D8C4-D4F0-4951-A1F2-B64FFDD9A290}
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Shared\Shared.projitems*{07ecd6a8-61d0-4409-a009-c138e76dfa1f}*SharedItemsImports = 4
- Shared\Shared.projitems*{1f634b93-f4c6-45e9-894d-2f3556a74d67}*SharedItemsImports = 4
- Shared\Shared.projitems*{c21c1a1b-5045-4bbe-818b-8574756d1f34}*SharedItemsImports = 13
+ Shared\Shared.projitems*{1f36ab35-19d3-4553-a166-af8dfca39d50}*SharedItemsImports = 4
+ Shared\Shared.projitems*{447ca481-4806-48d1-8e95-d545d8294620}*SharedItemsImports = 13
+ Shared\Shared.projitems*{abe9b34c-6644-4e93-a8a1-5cad5fa638ee}*SharedItemsImports = 4
EndGlobalSection
EndGlobal
diff --git a/MainGameVR/MainGameVR.csproj b/KKS_VR/KKS_VR.csproj
similarity index 63%
rename from MainGameVR/MainGameVR.csproj
rename to KKS_VR/KKS_VR.csproj
index ec28640..48957c2 100644
--- a/MainGameVR/MainGameVR.csproj
+++ b/KKS_VR/KKS_VR.csproj
@@ -1,46 +1,41 @@
-
+
Debug
AnyCPU
- {1F634B93-F4C6-45E9-894D-2F3556A74D67}
+ {1F36AB35-19D3-4553-A166-AF8DFCA39D50}
Library
Properties
KKS_VR
KKS_MainGameVR
- v4.6.2
+ v4.7.2
512
+ true
true
- embedded
+ full
false
- bin\
- TRACE;DEBUG;KKS MainGame
+ ..\bin\KKS\
+ TRACE;DEBUG;KKS
prompt
4
+ Preview
true
- false
- 8
- embedded
+ pdbonly
true
- bin\Release\
- TRACE;KKS MainGame
+ ..\bin\KKS\
+ TRACE;KKS
prompt
4
+ Preview
true
- false
- 8
- true
-
-
- false
@@ -55,20 +50,20 @@
..\packages\IllusionLibs.KoikatsuSunshine.Assembly-CSharp-firstpass.2021.9.17\lib\net46\Assembly-CSharp-firstpass.dll
False
-
- ..\packages\IllusionLibs.BepInEx.5.4.20\lib\net35\BepInEx.dll
+
+ ..\packages\IllusionLibs.BepInEx.5.4.22\lib\net35\BepInEx.dll
False
-
- ..\packages\IllusionLibs.KoikatsuSunshine.Cinemachine.2019.4.9\lib\net46\Cinemachine.dll
+
+ ..\packages\IllusionModdingAPI.KKSAPI.1.41.0\lib\net46\KKSAPI.dll
False
-
- ..\packages\IllusionModdingAPI.KKSAPI.1.35.0\lib\net46\KKSAPI.dll
- False
+
+ False
+ ..\Libs\KK_FinalIK.dll
-
- ..\packages\ExtensibleSaveFormat.KoikatsuSunshine.16.8.1\lib\net46\KKS_ExtensibleSaveFormat.dll
+
+ ..\Libs\Obi.dll
False
@@ -79,7 +74,9 @@
+
+
..\packages\IllusionLibs.KoikatsuSunshine.UniRx.2021.9.17\lib\net46\UniRx.dll
@@ -106,16 +103,13 @@
False
- ..\VRGIN_OpenXR\Libs\Unity.Subsystem.Registration.dll
- True
+ ..\Libs\Unity.Subsystem.Registration.dll
- ..\VRGIN_OpenXR\Libs\Unity.XR.Management.dll
- True
+ ..\Libs\Unity.XR.Management.dll
- ..\VRGIN_OpenXR\Libs\Unity.XR.OpenVR.dll
- True
+ ..\Libs\Unity.XR.OpenVR.dll
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.CoreModule.2019.4.9\lib\net46\UnityEngine.dll
@@ -125,10 +119,6 @@
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.AnimationModule.2019.4.9\lib\net46\UnityEngine.AnimationModule.dll
False
-
- ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.AssetBundleModule.2019.4.9\lib\net46\UnityEngine.AssetBundleModule.dll
- False
-
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.AudioModule.2019.4.9\lib\net46\UnityEngine.AudioModule.dll
False
@@ -137,10 +127,6 @@
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.CoreModule.2019.4.9\lib\net46\UnityEngine.CoreModule.dll
False
-
- ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.ImageConversionModule.2019.4.9\lib\net46\UnityEngine.ImageConversionModule.dll
- False
-
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.IMGUIModule.2019.4.9\lib\net46\UnityEngine.IMGUIModule.dll
False
@@ -154,12 +140,7 @@
False
- ..\VRGIN_OpenXR\Libs\UnityEngine.SpatialTracking.dll
- True
-
-
- ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.TextRenderingModule.2019.4.9\lib\net46\UnityEngine.TextRenderingModule.dll
- False
+ ..\Libs\UnityEngine.SpatialTracking.dll
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.UI.2019.4.9\lib\net46\UnityEngine.UI.dll
@@ -169,94 +150,123 @@
..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.UIModule.2019.4.9\lib\net46\UnityEngine.UIModule.dll
False
-
- ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.VRModule.2019.4.9\lib\net46\UnityEngine.VRModule.dll
- False
+
+ ..\Libs\UnityEngine.UnityWebRequestAudioModule.dll
-
- ..\VRGIN_OpenXR\Libs\UnityEngine.XR.LegacyInputHelpers.dll
- True
+
+ ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.UnityWebRequestModule.2019.4.9\lib\net46\UnityEngine.UnityWebRequestModule.dll
+ False
-
- ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.XRModule.2019.4.9\lib\net46\UnityEngine.XRModule.dll
+
+ ..\packages\IllusionLibs.KoikatsuSunshine.UnityEngine.UnityWebRequestWWWModule.2019.4.9\lib\net46\UnityEngine.UnityWebRequestWWWModule.dll
False
-
- ..\VRGIN_OpenXR\Libs\Valve.Newtonsoft.Json.dll
- True
+
+ ..\Libs\UnityEngine.XR.LegacyInputHelpers.dll
-
- ..\VRGIN_OpenXR\bin\VRGIN_OpenXR.dll
+
+ ..\Libs\Valve.Newtonsoft.Json.dll
- ..\VRGIN_OpenXR\Libs\WindowsInput.dll
- True
+ ..\Libs\WindowsInput.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ LICENSE
+ PreserveNewest
+
+
+ README.md
+ PreserveNewest
+
-
+
+
+ IF EXIST "$(SolutionDir)PostBuild.bat" CALL "$(SolutionDir)PostBuild.bat" "$(TargetDir)\KKS_MainGameVR.dll" KKS
+
-
+
+
+
+
+ {4b6e4305-c95a-4274-94a6-b04a1b01989d}
+ VRGIN_OpenXR
+
+
+
+
+ Images\credits.txt
+ PreserveNewest
+
+
+ Images\cursor.png
+ PreserveNewest
+
+
+ Images\icon_call.png
+ PreserveNewest
+
+
+ Images\icon_call_xz.png
+ PreserveNewest
+
+
+ Images\icon_gripmove.png
+ PreserveNewest
+
+
+ Images\icon_hand.png
+ PreserveNewest
+
+
+ Images\icon_hand_1.png
+ PreserveNewest
+
+
+ Images\icon_hand_2.png
+ PreserveNewest
+
+
+ Images\icon_play.png
+ PreserveNewest
+
+
+ Images\icon_school.png
+ PreserveNewest
+
+
+ Images\icon_school_1.png
+ PreserveNewest
+
+
+ Images\icon_school_2.png
+ PreserveNewest
+
+
+ Images\icon_settings.png
+ PreserveNewest
+
+
+ Images\icon_warp.png
+ PreserveNewest
+
-
-
-
+
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}.
+
@@ -266,16 +276,11 @@
-
-
-
-
-
-
-
-
+
+
+
@@ -286,21 +291,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
- IF EXIST "$(SolutionDir)PostBuild.bat" CALL "$(SolutionDir)PostBuild.bat" "$(TargetDir)\KKS_MainGameVR.dll" KKS
-
-
+
+
+
\ No newline at end of file
diff --git a/MainGameVR/VRPlugin.cs b/KKS_VR/VRPlugin.cs
similarity index 75%
rename from MainGameVR/VRPlugin.cs
rename to KKS_VR/VRPlugin.cs
index 4c3ce42..87d67d6 100644
--- a/MainGameVR/VRPlugin.cs
+++ b/KKS_VR/VRPlugin.cs
@@ -5,25 +5,27 @@
using BepInEx.Logging;
using HarmonyLib;
using KKAPI;
-using KKAPI.Utilities;
-using KKS_VR.Features;
-using KKS_VR.Fixes;
-using KKS_VR.Settings;
+using KKAPI.MainGame;
+using KK_VR.Features;
+using KK_VR.Fixes;
+using KK_VR.Interpreters;
+using KK_VR.Settings;
using Unity.XR.OpenVR;
using UnityEngine;
using Valve.VR;
using VRGIN.Core;
-using WindowsInput;
+using VRGIN.Helpers;
-namespace KKS_VR
+namespace KK_VR
{
[BepInPlugin(GUID, Name, Version)]
[BepInProcess(KoikatuAPI.GameProcessName)]
[BepInDependency(KoikatuAPI.GUID, KoikatuAPI.VersionConst)]
+ [BepInDependency(KK.PluginFinalIK.GUID, KK.PluginFinalIK.Version)]
[BepInIncompatibility("bero.crossfadervr")]
public class VRPlugin : BaseUnityPlugin
{
- public const string GUID = "KKS_MainGameVR";
+ public const string GUID = "kks.vr.game";
public const string Name = "KKS Main Game VR";
public const string Version = Constants.Version;
@@ -33,23 +35,30 @@ private void Awake()
{
Logger = base.Logger;
- var vrActivated = Environment.CommandLine.Contains("--vr");
- if (vrActivated)
+ //var vrDeactivated = Environment.CommandLine.Contains("--novr");
+
+ var enabled = Environment.CommandLine.Contains("--vr") || SteamVRDetector.IsRunning;
+ // The presence of settings even outside of vr mode for comfy editing.
+ var settings = SettingsManager.Create(Config);
+ if (enabled)
{
BepInExVrLogBackend.ApplyYourself();
- OpenVRHelperTempfixHook.Patch();
- var settings = SettingsManager.Create(Config);
+
+ // This patch fixes crash(null refs?) on game exit and disables Haptic Feedback (atleast).
+ // No clue how to fix it otherwise, as most likely possible fix resides in unmanaged code.
+ //OpenVRHelperTempfixHook.Patch();
+
StartCoroutine(LoadDevice(settings));
}
- AnimationCrossFader.Initialize(Config, vrActivated);
+ CrossFader.Initialize(Config, enabled);
}
private IEnumerator LoadDevice(KoikatuSettings settings)
{
- yield return new WaitUntil(() => Manager.Scene.initialized && Manager.Scene.LoadSceneName == "Title");
-
+ yield return new WaitUntil(() => Manager.Scene.initialized);
+ //yield return new WaitUntil(() => Manager.Scene.initialized && Manager.Scene.LoadSceneName == "Title");
Logger.LogInfo("Loading OpenVR...");
var ovrsettings = OpenVRSettings.GetSettings(true);
@@ -107,61 +116,46 @@ private IEnumerator LoadDevice(KoikatuSettings settings)
Logger.LogInfo("Initializing the plugin...");
new Harmony(GUID).PatchAll(typeof(VRPlugin).Assembly);
- TopmostToolIcons.Patch();
+ //TopmostToolIcons.Patch();
VRManager.Create(new KoikatuContext(settings));
// VRGIN doesn't update the near clip plane until a first "main" camera is created, so we set it here.
UpdateNearClipPlane(settings);
+ UpdateIPD(settings);
settings.AddListener("NearClipPlane", (_, _1) => UpdateNearClipPlane(settings));
-
- SetInputSimulator(settings);
- settings.AddListener("UseLegacyInputSimulator", (_, _1) => SetInputSimulator(settings));
-
+ settings.AddListener("IPDScale", (_, _1) => UpdateIPD(settings));
VR.Manager.SetMode();
+
VRFade.Create();
PrivacyScreen.Initialize();
GraphicRaycasterPatches.Initialize();
-
+
// It's been reported in #28 that the game window defocues when
// the game is under heavy load. We disable window ghosting in
// an attempt to counter this.
NativeMethods.DisableProcessWindowsGhosting();
-
- TweakShadowSettings();
-
+
DontDestroyOnLoad(VRCamera.Instance.gameObject);
// Probably unnecessary, but just to be safe
VR.Mode.MoveToPosition(Vector3.zero, Quaternion.Euler(Vector3.zero), true);
Logger.LogInfo("Finished loading into VR mode!");
+
+ if (SettingsManager.EnableBoop.Value)
+ VRBoop.Initialize();
+ GameAPI.RegisterExtraBehaviour(GUID);
}
private void UpdateNearClipPlane(KoikatuSettings settings)
{
VR.Camera.gameObject.GetComponent().nearClipPlane = settings.NearClipPlane;
}
-
- private void SetInputSimulator(KoikatuSettings settings)
- {
- if (settings.UseLegacyInputSimulator)
- {
- VR.Manager.Input = new InputSimulator();
- }
- else
- {
- VR.Manager.Input = new RobustInputSimulator();
- }
- }
-
- private static void TweakShadowSettings()
+ private void UpdateIPD(KoikatuSettings settings)
{
- // Default shadows look too wobbly in VR.
- QualitySettings.shadowProjection = ShadowProjection.StableFit;
- QualitySettings.shadowCascades = 4;
- QualitySettings.shadowCascade4Split = new Vector4(0.05f, 0.1f, 0.2f);
+ VRCamera.Instance.SteamCam.origin.localScale = Vector3.one * settings.IPDScale;
}
private static class NativeMethods
diff --git a/KKS_VR/packages.config b/KKS_VR/packages.config
new file mode 100644
index 0000000..af262af
--- /dev/null
+++ b/KKS_VR/packages.config
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KK_VR/KK_VR.csproj b/KK_VR/KK_VR.csproj
new file mode 100644
index 0000000..fe59c73
--- /dev/null
+++ b/KK_VR/KK_VR.csproj
@@ -0,0 +1,187 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {ABE9B34C-6644-4E93-A8A1-5CAD5FA638EE}
+ Library
+ Properties
+ KK_VR
+ KoikatuVR
+ v3.5
+ 512
+ true
+
+
+
+
+ true
+ full
+ false
+ ..\bin\KK\
+ TRACE;DEBUG;KK
+ prompt
+ 4
+ true
+ Preview
+
+
+ pdbonly
+ true
+ ..\bin\KK\
+ TRACE;KK
+ prompt
+ 4
+ true
+ Preview
+
+
+ IF EXIST "$(SolutionDir)PostBuild.bat" CALL "$(SolutionDir)PostBuild.bat" "$(TargetDir)\KKS_MainGameVR.dll" KKS
+
+
+
+ ..\packages\IllusionLibs.BepInEx.Harmony.2.9.0\lib\net35\0Harmony.dll
+ False
+
+
+ ..\packages\IllusionLibs.Koikatu.Assembly-CSharp.2019.4.27.4\lib\net35\Assembly-CSharp.dll
+ False
+
+
+ ..\packages\IllusionLibs.Koikatu.Assembly-CSharp-firstpass.2019.4.27.4\lib\net35\Assembly-CSharp-firstpass.dll
+ False
+
+
+ ..\packages\IllusionLibs.BepInEx.5.4.22\lib\net35\BepInEx.dll
+ False
+
+
+ ..\packages\IllusionModdingAPI.KKAPI.1.41.0\lib\net35\KKAPI.dll
+ False
+
+
+ ..\Libs\KK_FinalIK.dll
+
+
+
+
+
+
+
+
+ ..\packages\IllusionLibs.Koikatu.UnityEngine.5.6.2.4\lib\net35\UnityEngine.dll
+ False
+
+
+ ..\packages\IllusionLibs.Koikatu.UnityEngine.UI.5.6.2.4\lib\net35\UnityEngine.UI.dll
+ False
+
+
+ ..\Libs\WindowsInput.dll
+
+
+
+
+
+
+
+ LICENSE
+ PreserveNewest
+
+
+ README.md
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Images\credits.txt
+ PreserveNewest
+
+
+ Images\cursor.png
+ PreserveNewest
+
+
+ Images\icon_call.png
+ PreserveNewest
+
+
+ Images\icon_call_xz.png
+ PreserveNewest
+
+
+ Images\icon_gripmove.png
+ PreserveNewest
+
+
+ Images\icon_hand.png
+ PreserveNewest
+
+
+ Images\icon_hand_1.png
+ PreserveNewest
+
+
+ Images\icon_hand_2.png
+ PreserveNewest
+
+
+ Images\icon_play.png
+ PreserveNewest
+
+
+ Images\icon_school.png
+ PreserveNewest
+
+
+ Images\icon_school_1.png
+ PreserveNewest
+
+
+ Images\icon_school_2.png
+ PreserveNewest
+
+
+ Images\icon_settings.png
+ PreserveNewest
+
+
+ Images\icon_warp.png
+ PreserveNewest
+
+
+
+
+ {22788a2c-7695-4a6a-a9f0-115ab9a05fd4}
+ VRGIN
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/KK_VR/VRPlugin.cs b/KK_VR/VRPlugin.cs
new file mode 100644
index 0000000..10b7ba1
--- /dev/null
+++ b/KK_VR/VRPlugin.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+using BepInEx;
+using BepInEx.Logging;
+using HarmonyLib;
+using KKAPI;
+using KKAPI.MainGame;
+using KK_VR.Features;
+using KK_VR.Fixes;
+using KK_VR.Interpreters;
+using KK_VR.Settings;
+using UnityEngine;
+using VRGIN.Core;
+using VRGIN.Helpers;
+using VRGIN.Controls.Handlers;
+
+namespace KK_VR
+{
+ [BepInPlugin(GUID, Name, Version)]
+ [BepInProcess(KoikatuAPI.GameProcessName)]
+ [BepInDependency(KoikatuAPI.GUID, KoikatuAPI.VersionConst)]
+ [BepInDependency(KK.PluginFinalIK.GUID, KK.PluginFinalIK.Version)]
+ [BepInIncompatibility("bero.crossfadervr")]
+ public class VRPlugin : BaseUnityPlugin
+ {
+ public const string GUID = "kk.vr.game";
+ public const string Name = "MainGameVR";
+ public const string Version = Constants.Version;
+
+ internal static new ManualLogSource Logger;
+
+ private void Awake()
+ {
+ Logger = base.Logger;
+
+ var settings = SettingsManager.Create(Config);
+
+ if (Environment.CommandLine.Contains("--vr") || SteamVRDetector.IsRunning)
+ {
+ BepInExVrLogBackend.ApplyYourself();
+ StartCoroutine(LoadDevice(settings));
+ }
+ CrossFader.Initialize(Config, enabled);
+ }
+
+ private const string DeviceOpenVR = "OpenVR";
+ private IEnumerator LoadDevice(KoikatuSettings settings)
+ {
+ //yield return new WaitUntil(() => Manager.Scene. initialized);
+ //yield return new WaitUntil(() => Manager.Scene.initialized && Manager.Scene.LoadSceneName == "Title");
+
+ if (UnityEngine.VR.VRSettings.loadedDeviceName != DeviceOpenVR)
+ {
+ UnityEngine.VR.VRSettings.LoadDeviceByName(DeviceOpenVR);
+ yield return null;
+ }
+ UnityEngine.VR.VRSettings.enabled = true;
+ while (UnityEngine.VR.VRSettings.loadedDeviceName != DeviceOpenVR)
+ {
+ yield return null;
+ }
+ while (true)
+ {
+ var rect = VRGIN.Native.WindowManager.GetClientRect();
+ if (rect.Right - rect.Left > 0)
+ {
+ break;
+ }
+ //VRLog.Info("waiting for the window rect to be non-empty");
+ yield return null;
+ }
+
+ new Harmony(GUID).PatchAll(typeof(VRPlugin).Assembly);
+ VRManager.Create(new KoikatuContext(settings));
+
+ // VRGIN doesn't update the near clip plane until a first "main" camera is created, so we set it here.
+ UpdateNearClipPlane(settings);
+ UpdateIPD(settings);
+ settings.AddListener("NearClipPlane", (_, _1) => UpdateNearClipPlane(settings));
+ settings.AddListener("IPDScale", (_, _1) => UpdateIPD(settings));
+
+ VR.Manager.SetMode();
+
+ VRFade.Create();
+ PrivacyScreen.Initialize();
+ GraphicRaycasterPatches.Initialize();
+
+ // It's been reported in #28 that the game window defocues when
+ // the game is under heavy load. We disable window ghosting in
+ // an attempt to counter this.
+ NativeMethods.DisableProcessWindowsGhosting();
+
+ //DontDestroyOnLoad(VRCamera.Instance.gameObject);
+
+ // Probably unnecessary, but just to be safe
+ //VR.Mode.MoveToPosition(Vector3.zero, Quaternion.Euler(Vector3.zero), true);
+
+
+ if (SettingsManager.EnableBoop.Value)
+ {
+ VRBoop.Initialize();
+ }
+ GameAPI.RegisterExtraBehaviour(GUID);
+
+ // In KK they refuse to assume proper position on init.
+
+ Logger.LogInfo("Finished loading into VR mode!");
+ }
+
+ private void UpdateNearClipPlane(KoikatuSettings settings)
+ {
+ VR.Camera.gameObject.GetComponent().nearClipPlane = settings.NearClipPlane;
+ }
+ private void UpdateIPD(KoikatuSettings settings)
+ {
+ VRCamera.Instance.SteamCam.origin.localScale = Vector3.one * settings.IPDScale;
+ }
+
+
+ private static class NativeMethods
+ {
+ [DllImport("user32.dll")]
+ public static extern void DisableProcessWindowsGhosting();
+ }
+ }
+}
diff --git a/KK_VR/packages.config b/KK_VR/packages.config
new file mode 100644
index 0000000..60af75e
--- /dev/null
+++ b/KK_VR/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Libs/KK_FinalIK.dll b/Libs/KK_FinalIK.dll
new file mode 100644
index 0000000..05c7629
Binary files /dev/null and b/Libs/KK_FinalIK.dll differ
diff --git a/Libs/Obi.dll b/Libs/Obi.dll
new file mode 100644
index 0000000..4ee1efa
Binary files /dev/null and b/Libs/Obi.dll differ
diff --git a/Libs/Unity.Subsystem.Registration.dll b/Libs/Unity.Subsystem.Registration.dll
new file mode 100644
index 0000000..92f6ff3
Binary files /dev/null and b/Libs/Unity.Subsystem.Registration.dll differ
diff --git a/Libs/Unity.XR.Management.dll b/Libs/Unity.XR.Management.dll
new file mode 100644
index 0000000..2e6e626
Binary files /dev/null and b/Libs/Unity.XR.Management.dll differ
diff --git a/Libs/Unity.XR.OpenVR.dll b/Libs/Unity.XR.OpenVR.dll
new file mode 100644
index 0000000..227eb0f
Binary files /dev/null and b/Libs/Unity.XR.OpenVR.dll differ
diff --git a/Libs/UnityEngine.SpatialTracking.dll b/Libs/UnityEngine.SpatialTracking.dll
new file mode 100644
index 0000000..f546558
Binary files /dev/null and b/Libs/UnityEngine.SpatialTracking.dll differ
diff --git a/Libs/UnityEngine.UnityWebRequestAudioModule.dll b/Libs/UnityEngine.UnityWebRequestAudioModule.dll
new file mode 100644
index 0000000..f910ae4
Binary files /dev/null and b/Libs/UnityEngine.UnityWebRequestAudioModule.dll differ
diff --git a/Libs/UnityEngine.XR.LegacyInputHelpers.dll b/Libs/UnityEngine.XR.LegacyInputHelpers.dll
new file mode 100644
index 0000000..4cf809d
Binary files /dev/null and b/Libs/UnityEngine.XR.LegacyInputHelpers.dll differ
diff --git a/Libs/Valve.Newtonsoft.Json.dll b/Libs/Valve.Newtonsoft.Json.dll
new file mode 100644
index 0000000..2674c18
Binary files /dev/null and b/Libs/Valve.Newtonsoft.Json.dll differ
diff --git a/Libs/WindowsInput.dll b/Libs/WindowsInput.dll
new file mode 100644
index 0000000..c54c03a
Binary files /dev/null and b/Libs/WindowsInput.dll differ
diff --git a/Libs/_Data/Plugins/x86_64/XRSDKOpenVR.dll b/Libs/_Data/Plugins/x86_64/XRSDKOpenVR.dll
new file mode 100644
index 0000000..1bda158
Binary files /dev/null and b/Libs/_Data/Plugins/x86_64/XRSDKOpenVR.dll differ
diff --git a/Libs/_Data/Plugins/x86_64/openvr_api.dll b/Libs/_Data/Plugins/x86_64/openvr_api.dll
new file mode 100644
index 0000000..ef336cb
Binary files /dev/null and b/Libs/_Data/Plugins/x86_64/openvr_api.dll differ
diff --git a/Libs/_Data/StreamingAssets/SteamVR/OpenVRSettings.asset b/Libs/_Data/StreamingAssets/SteamVR/OpenVRSettings.asset
new file mode 100644
index 0000000..a7f8f05
--- /dev/null
+++ b/Libs/_Data/StreamingAssets/SteamVR/OpenVRSettings.asset
@@ -0,0 +1,23 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 0}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 7a32bfe54d957ec4581fa4a630f1647a, type: 3}
+ m_Name: Open VR Settings
+ m_EditorClassIdentifier:
+ PromptToUpgradePackage: 1
+ PromptToUpgradePreviewPackages: 1
+ SkipPromptForVersion:
+ StereoRenderingMode: 0
+ InitializationType: 1
+ EditorAppKey: application.generated.unity.unity2019_4_openxr.exe
+ ActionManifestFileRelativeFilePath: StreamingAssets\SteamVR\actions.json
+ MirrorView: 2
+ HasCopiedDefaults: 0
diff --git a/Libs/_Data/StreamingAssets/SteamVR/actions.json b/Libs/_Data/StreamingAssets/SteamVR/actions.json
new file mode 100644
index 0000000..9779c7d
--- /dev/null
+++ b/Libs/_Data/StreamingAssets/SteamVR/actions.json
@@ -0,0 +1,212 @@
+{
+ "actions": [
+ {
+ "name": "/actions/legacy_emulate/in/Grip_Press",
+ "type": "boolean"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Grip_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Grip_2D",
+ "type": "vector2",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/ApplicationMenu_Press",
+ "type": "boolean"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/ApplicationMenu_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/A_Press",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/A_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis0_Press",
+ "type": "boolean"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis0_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis0_2D",
+ "type": "vector2"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis1_Press",
+ "type": "boolean"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis1_Touch",
+ "type": "boolean"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis1_2D",
+ "type": "vector2"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis2_Press",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis2_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis2_2D",
+ "type": "vector2",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis3_Press",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis3_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis3_2D",
+ "type": "vector2",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis4_Press",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis4_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis4_2D",
+ "type": "vector2",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/System_Press",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/System_Touch",
+ "type": "boolean",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Axis1_1D",
+ "type": "vector1",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Grip_1D",
+ "type": "vector1",
+ "requirement": "optional"
+ },
+ {
+ "name": "/actions/legacy_emulate/in/Pose",
+ "type": "pose"
+ },
+ {
+ "name": "/actions/legacy_emulate/out/Huptic",
+ "type": "vibration"
+ }
+ ],
+ "action_sets": [
+ {
+ "name": "/actions/legacy_emulate",
+ "usage": "single"
+ }
+ ],
+ "default_bindings": [
+ {
+ "controller_type": "vive_controller",
+ "binding_url": "bindings_vive_controller.json"
+ },
+ {
+ "controller_type": "oculus_touch",
+ "binding_url": "bindings_oculus_touch.json"
+ },
+ {
+ "controller_type": "knuckles",
+ "binding_url": "bindings_knuckles.json"
+ },
+ {
+ "controller_type": "holographic_controller",
+ "binding_url": "bindings_holographic_controller.json"
+ },
+ {
+ "controller_type": "vive_cosmos_controller",
+ "binding_url": "bindings_vive_cosmos_controller.json"
+ },
+ {
+ "controller_type": "logitech_stylus",
+ "binding_url": "bindings_logitech_stylus.json"
+ },
+ {
+ "controller_type": "vive_cosmos",
+ "binding_url": "binding_vive_cosmos.json"
+ },
+ {
+ "controller_type": "vive",
+ "binding_url": "binding_vive.json"
+ },
+ {
+ "controller_type": "indexhmd",
+ "binding_url": "binding_index_hmd.json"
+ },
+ {
+ "controller_type": "vive_pro",
+ "binding_url": "binding_vive_pro.json"
+ },
+ {
+ "controller_type": "rift",
+ "binding_url": "binding_rift.json"
+ },
+ {
+ "controller_type": "holographic_hmd",
+ "binding_url": "binding_holographic_hmd.json"
+ },
+ {
+ "controller_type": "vive_tracker_camera",
+ "binding_url": "binding_vive_tracker_camera.json"
+ }
+ ],
+ "localization": [
+ {
+ "language_tag": "en_US",
+ "/actions/legacy_emulate/in/Axis0_Press": "Touchpad (Press)",
+ "/actions/legacy_emulate/in/Axis0_Touch": "Touchpad (Touch)",
+ "/actions/legacy_emulate/in/Axis0_2D": "Touchpad (Location)",
+ "/actions/legacy_emulate/in/Axis1_Press": "Trigger (Press)",
+ "/actions/legacy_emulate/in/Axis1_Touch": "Trigger (Touch)",
+ "/actions/legacy_emulate/in/Axis1_2D": "Trigger (Analog)",
+ "/actions/legacy_emulate/in/Grip_Press": "Vive Grip (Press) | Touch Hand Trigger (Press)",
+ "/actions/legacy_emulate/in/Grip_Touch": "Vive Grip (Touch) | Touch Hand Trigger (Touch)",
+ "/actions/legacy_emulate/in/Grip_2D": "Vive Grip (Analog) | Touch Hand Trigger (Analog)",
+ "/actions/legacy_emulate/in/Axis1_1D": "Trigger (Analog)",
+ "/actions/legacy_emulate/in/Grip_1D": "Grip (Analog)",
+ "/actions/legacy_emulate/in/Pose": "Pose"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Libs/_Data/StreamingAssets/SteamVR/bindings_knuckles.json b/Libs/_Data/StreamingAssets/SteamVR/bindings_knuckles.json
new file mode 100644
index 0000000..734560b
--- /dev/null
+++ b/Libs/_Data/StreamingAssets/SteamVR/bindings_knuckles.json
@@ -0,0 +1,187 @@
+{
+ "action_manifest_version" : 0,
+ "alias_info" : {},
+ "app_key" : "kkd.charastudio.exe",
+ "bindings" : {
+ "/actions/legacy_emulate" : {
+ "haptics" : [
+ {
+ "output" : "/actions/legacy_emulate/out/huptic",
+ "path" : "/user/hand/left/output/haptic"
+ },
+ {
+ "output" : "/actions/legacy_emulate/out/huptic",
+ "path" : "/user/hand/right/output/haptic"
+ }
+ ],
+ "poses" : [
+ {
+ "output" : "/actions/legacy_emulate/in/pose",
+ "path" : "/user/hand/left/pose/raw"
+ },
+ {
+ "output" : "/actions/legacy_emulate/in/pose",
+ "path" : "/user/hand/right/pose/raw"
+ }
+ ],
+ "sources" : [
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/system_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/system_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/system"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/system_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/system_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/system"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis1_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/axis1_1d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis1_touch"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/left/input/trigger"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis1_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/axis1_1d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis1_touch"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/right/input/trigger"
+ },
+ {
+ "inputs" : {
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "trackpad",
+ "path" : "/user/hand/left/input/trackpad"
+ },
+ {
+ "inputs" : {
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "trackpad",
+ "path" : "/user/hand/right/input/trackpad"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ },
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "joystick",
+ "path" : "/user/hand/left/input/thumbstick"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ },
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "joystick",
+ "path" : "/user/hand/right/input/thumbstick"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/b"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/b"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/grip_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/a"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/grip_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/a"
+ }
+ ]
+ }
+ },
+ "category" : "steamvr_input",
+ "controller_type" : "knuckles",
+ "description" : "",
+ "name" : "knuckles_default",
+ "options" : {},
+ "simulated_actions" : []
+}
diff --git a/Libs/_Data/StreamingAssets/SteamVR/bindings_oculus_touch.json b/Libs/_Data/StreamingAssets/SteamVR/bindings_oculus_touch.json
new file mode 100644
index 0000000..2212245
--- /dev/null
+++ b/Libs/_Data/StreamingAssets/SteamVR/bindings_oculus_touch.json
@@ -0,0 +1,204 @@
+{
+ "action_manifest_version" : 0,
+ "alias_info" : {},
+ "app_key" : "application.generated.kks_charastudio.exe",
+ "bindings" : {
+ "/actions/legacy_emulate" : {
+ "poses" : [
+ {
+ "output" : "/actions/legacy_emulate/in/pose",
+ "path" : "/user/hand/left/pose/raw"
+ },
+ {
+ "output" : "/actions/legacy_emulate/in/pose",
+ "path" : "/user/hand/right/pose/raw"
+ }
+ ],
+ "sources" : [
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/grip_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/grip_1d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/grip_touch"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/left/input/grip"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/grip_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/grip_1d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/grip_touch"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/right/input/grip"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/x"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/x"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ },
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "joystick",
+ "path" : "/user/hand/left/input/joystick"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ },
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "joystick",
+ "path" : "/user/hand/right/input/joystick"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/system_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/system_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/system"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/system_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/system_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/system"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis1_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/axis1_1d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis1_touch"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/left/input/trigger"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis1_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/axis1_1d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis1_touch"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/right/input/trigger"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/y"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/y"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_touch"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/a"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/b"
+ }
+ ]
+ }
+ },
+ "category" : "steamvr_input",
+ "controller_type" : "oculus_touch",
+ "description" : "",
+ "name" : "oculus_touch",
+ "options" : {},
+ "simulated_actions" : []
+}
diff --git a/Libs/_Data/StreamingAssets/SteamVR/bindings_vive_controller.json b/Libs/_Data/StreamingAssets/SteamVR/bindings_vive_controller.json
new file mode 100644
index 0000000..e6f9eab
--- /dev/null
+++ b/Libs/_Data/StreamingAssets/SteamVR/bindings_vive_controller.json
@@ -0,0 +1,145 @@
+{
+ "action_manifest_version" : 0,
+ "alias_info" : {},
+ "app_key" : "kks.charastudio.exe",
+ "bindings" : {
+ "/actions/legacy_emulate" : {
+ "haptics" : [
+ {
+ "output" : "/actions/legacy_emulate/out/huptic",
+ "path" : "/user/hand/left/output/haptic"
+ },
+ {
+ "output" : "/actions/legacy_emulate/out/huptic",
+ "path" : "/user/hand/right/output/haptic"
+ }
+ ],
+ "poses" : [
+ {
+ "output" : "/actions/legacy_emulate/in/pose",
+ "path" : "/user/hand/left/pose/raw"
+ },
+ {
+ "output" : "/actions/legacy_emulate/in/pose",
+ "path" : "/user/hand/right/pose/raw"
+ }
+ ],
+ "sources" : [
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/grip_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/grip"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/grip_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/grip"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/application_menu"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/applicationmenu_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/application_menu"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis1_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/axis1_1d"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/left/input/trigger"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis1_press"
+ },
+ "pull" : {
+ "output" : "/actions/legacy_emulate/in/axis1_1d"
+ }
+ },
+ "mode" : "trigger",
+ "path" : "/user/hand/right/input/trigger"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ },
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "trackpad",
+ "path" : "/user/hand/left/input/trackpad"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/axis0_press"
+ },
+ "position" : {
+ "output" : "/actions/legacy_emulate/in/axis0_2d"
+ },
+ "touch" : {
+ "output" : "/actions/legacy_emulate/in/axis0_touch"
+ }
+ },
+ "mode" : "trackpad",
+ "path" : "/user/hand/right/input/trackpad"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/system_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/left/input/system"
+ },
+ {
+ "inputs" : {
+ "click" : {
+ "output" : "/actions/legacy_emulate/in/system_press"
+ }
+ },
+ "mode" : "button",
+ "path" : "/user/hand/right/input/system"
+ }
+ ]
+ }
+ },
+ "category" : "steamvr_input",
+ "controller_type" : "vive_controller",
+ "description" : "",
+ "name" : "vive defaults",
+ "options" : {},
+ "simulated_actions" : []
+}
diff --git a/Libs/_Data/UnitySubsystems/XRSDKOpenVR/UnitySubsystemsManifest.json b/Libs/_Data/UnitySubsystems/XRSDKOpenVR/UnitySubsystemsManifest.json
new file mode 100644
index 0000000..22b4ae6
--- /dev/null
+++ b/Libs/_Data/UnitySubsystems/XRSDKOpenVR/UnitySubsystemsManifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "XRSDKOpenVR",
+ "version": "1.0.0-preview.1",
+ "libraryName": "XRSDKOpenVR",
+
+ "displays": [
+ {
+ "id": "OpenVR Display"
+ }
+ ],
+ "inputs": [
+ {
+ "id": "OpenVR Input",
+ "disablesLegacyInput": true,
+ "disablesLegacyVr" : true
+ }
+ ]
+}
diff --git a/MainGameVR/Camera/CameraMoveHooks.cs b/MainGameVR/Camera/CameraMoveHooks.cs
deleted file mode 100644
index e3813dd..0000000
--- a/MainGameVR/Camera/CameraMoveHooks.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using HarmonyLib;
-using UnityEngine;
-using VRGIN.Core;
-
-// This file is a collection of hooks to move the VR camera at appropriate
-// points of the game.
-
-namespace KKS_VR.Camera
-{
- [HarmonyPatch(typeof(ADV.TextScenario))]
- internal class TextScenarioPatches1
- {
- [HarmonyPatch("ADVCameraSetting")]
- [HarmonyPostfix]
- private static void PostADVCameraSetting(ADV.TextScenario __instance)
- {
- if (Manager.Scene.initialized && Manager.Scene.NowSceneNames[0] == "Talk")
- // Talk scenes are handled separately.
- return;
-
- VRLog.Debug("PostADVCameraSetting");
- var backTrans = __instance.BackCamera?.transform;
- if (backTrans == null)
- // backTrans can be null in Roaming. We don't want to move the
- // camera anyway in that case.
- return;
- VRCameraMover.Instance.MaybeMoveADV(__instance, backTrans.position, backTrans.rotation, false);
- }
- }
-
- [HarmonyPatch]
- internal class RequestNextLinePatches
- {
- private static IEnumerable TargetMethods()
- {
- // In some versions of the base game, MainScenario._RequestNextLine
- // duplicates the logic found in TextScenario._RequestNextLine.
- // In other versions, the former simply calls the latter.
- // We want to patch both methods or the latter alone depending on
- // the version.
- yield return AccessTools.Method(typeof(ADV.TextScenario), "_RequestNextLine");
- if (AccessTools.Field(typeof(ADV.MainScenario), "textHash") == null) yield return AccessTools.Method(typeof(ADV.MainScenario), "_RequestNextLine");
- }
-
- private static void Postfix(ADV.TextScenario __instance, ref IEnumerator __result)
- {
- if (Manager.Scene.initialized && Manager.Scene.NowSceneNames[0] == "Talk")
- // Talk scenes are handled separately.
- return;
-
- if (__instance.advScene == null)
- // Outside ADV scene (probably roaming), ignore.
- return;
-
- __result = new[] { __result, Postfix() }.GetEnumerator();
-
- IEnumerator Postfix()
- {
- VRCameraMover.Instance.HandleTextScenarioProgress(__instance);
- yield break;
- }
- }
- }
-
- [HarmonyPatch(typeof(ADV.Program))]
- internal class ProgramPatches1
- {
- [HarmonyPatch(nameof(ADV.Program.SetNull))]
- [HarmonyPostfix]
- private static void PostSetNull(Transform transform)
- {
- VRLog.Debug("PostSetNull");
- VRCameraMover.Instance.MaybeMoveTo(transform.position, transform.rotation, false);
- }
- }
-
- [HarmonyPatch(typeof(HSceneProc))]
- internal class HSceneProcPatches
- {
- [HarmonyPatch("ChangeAnimator")]
- [HarmonyPostfix]
- public static void PostChangeAnimator(HSceneProc __instance, bool _isForceCameraReset, List ___lstFemale)
- {
- if (_isForceCameraReset) UpdateVRCamera(__instance, ___lstFemale, null);
- }
-
- [HarmonyPatch("ChangeCategory")]
- [HarmonyPrefix]
- public static void PreChangeCategory(List ___lstFemale, out float __state)
- {
- __state = ___lstFemale[0].objTop.transform.position.y;
- }
-
- [HarmonyPatch("ChangeCategory")]
- [HarmonyPostfix]
- public static void PostChangeCategory(HSceneProc __instance, List ___lstFemale, float __state)
- {
- UpdateVRCamera(__instance, ___lstFemale, __state);
- }
-
-
- ///
- /// Update the transform of the VR camera.
- ///
- ///
- ///
- private static void UpdateVRCamera(HSceneProc instance, List lstFemale, float? previousFemaleY)
- {
- var baseTransform = lstFemale[0].objTop.transform;
- var camDat = new Traverse(instance.flags.ctrlCamera).Field("CamDat").Value;
- var cameraRotation = baseTransform.rotation * Quaternion.Euler(camDat.Rot);
- Vector3 dir;
- switch (instance.flags.mode)
- {
- case HFlag.EMode.masturbation:
- case HFlag.EMode.peeping:
- case HFlag.EMode.lesbian:
- // Use the default distance for 3rd-person scenes.
- dir = camDat.Dir;
- break;
- default:
- // Start closer otherwise.
- dir = Vector3.back * 0.8f;
- break;
- }
-
- var cameraPosition = cameraRotation * dir + baseTransform.TransformPoint(camDat.Pos);
- if (previousFemaleY is float prevY)
- {
- // Keep the relative Y coordinate from the female.
- var cameraHeight = VR.Camera.transform.position.y + baseTransform.position.y - prevY;
- var destination = new Vector3(cameraPosition.x, cameraHeight, cameraPosition.z);
- VRCameraMover.Instance.MaybeMoveTo(destination, cameraRotation, false);
- }
- else
- {
- // We are starting from scratch.
- // TODO: the height calculation below assumes standing mode.
- var cameraHeight = lstFemale[0].transform.position.y + VR.Camera.transform.localPosition.y;
- var destination = new Vector3(cameraPosition.x, cameraHeight, cameraPosition.z);
- VRCameraMover.Instance.MoveTo(destination, cameraRotation, false);
- }
- }
- }
-}
diff --git a/MainGameVR/Camera/POV.cs b/MainGameVR/Camera/POV.cs
deleted file mode 100644
index d212d62..0000000
--- a/MainGameVR/Camera/POV.cs
+++ /dev/null
@@ -1,293 +0,0 @@
-using System.Linq;
-using UnityEngine;
-using VRGIN.Controls;
-using VRGIN.Core;
-using VRGIN.Helpers;
-using KKS_VR.Settings;
-
-
-public enum POV_MODE
-{
- // Press Key (default: Y) to change POV Mode, configurable in BepInEX Plugin Settings (F1)
- EYE = 0, // Mode1: Tracking Eye Position & Rotation
- HEAD = 1, // Mode2: Only Tracking Eye Position (Default)
- TELEPORT = 2, // Mode3: Teleport(Jump) to next character when trigger controller
- TOTAL = 3 // Total num of Enum
-}
-
-namespace KKS_VR.Camera
-{
- internal class POV : ProtectedBehaviour
- {
- private Controller _leftController, _rightController;
-
- private ChaControl _currentChara;
-
- private POV_MODE _povMode;
-
- private bool _active;
-
- private KoikatuSettings _settings;
-
- private Quaternion _tmp_head_y; // for POV_MODE.EYE
-
- public void Initialize(Controller left, Controller right)
- {
- _leftController = left;
- _rightController = right;
- }
-
- public bool IsActive()
- {
- return _active;
- }
-
- protected override void OnAwake()
- {
- base.OnAwake();
- // HScene Init
- _currentChara = null;
-
- _povMode = POV_MODE.HEAD;
-
- _active = false;
-
- _settings = VR.Context.Settings as KoikatuSettings;
-
- _tmp_head_y = Quaternion.identity;
- }
-
- private void SetCameraToCharEye(ChaControl target)
- {
- var position = GetEyes(target).position;
- var rotation = GetEyes(target).rotation;
-
- // Set Camera to Character Eye
- VRManager.Instance.Mode.MoveToPosition(position, rotation, false);
- }
-
- // from VRGIN ControlMode.cs
- private void MoveToPositionEx(Vector3 targetPosition, Quaternion rotation = default(Quaternion))
- {
- // Camera rotates with character eye
- VR.Camera.SteamCam.origin.rotation = rotation * _tmp_head_y;
-
- float targetY = targetPosition.y;
- float myY = VR.Camera.SteamCam.head.position.y;
- targetPosition = new Vector3(targetPosition.x, targetY, targetPosition.z);
- var myPosition = new Vector3(VR.Camera.SteamCam.head.position.x, myY, VR.Camera.SteamCam.head.position.z);
- VR.Camera.SteamCam.origin.position += (targetPosition - myPosition);
- }
-
- // from VRGIN ControlMode.cs
- private Quaternion MakeUpright(Quaternion rotation)
- {
- return Quaternion.Euler(0, rotation.eulerAngles.y, 0);
- }
- private void resetRotationXZ()
- {
- VR.Camera.SteamCam.origin.rotation = MakeUpright(VR.Camera.SteamCam.origin.rotation);
- _tmp_head_y = Quaternion.identity;
- }
-
- private Transform GetHead(ChaControl human)
- {
- return human.objHead.GetComponentsInParent().First((Transform t) => t.name.StartsWith("c") && t.name.ToLower().Contains("j_head"));
- }
- private Transform GetEyes(ChaControl human)
- {
- Transform transform = human.objHeadBone.transform.Descendants().FirstOrDefault((Transform t) => t.name.StartsWith("c") && t.name.ToLower().EndsWith("j_faceup_tz"));
- if (!transform)
- {
- VRLog.Info("Creating eyes, {0}", human.name);
- transform = new GameObject("cf_j_faceup_tz").transform;
- transform.SetParent(GetHead(human), false);
- transform.transform.localPosition = new Vector3(0f, 0.07f, 0.05f);
- }
- else
- {
- VRLog.Debug("Found eyes, {0}", human.name);
- }
- return transform;
- }
- private int getCurrChaIdx(ChaControl[] targets)
- {
- if (_currentChara)
- {
- for (int i = 0; i < targets.Length; i++)
- {
- if (ChaControl.ReferenceEquals(targets[i], _currentChara) &&
- ((_currentChara.sex == (int)POVConfig.targetGender.Value) || (POVConfig.targetGender.Value == POVConfig.Gender.All)))
- {
- return i;
- }
- }
- }
- // cannot find last pov character (initialize / deleted)
- return targets.Length - 1;
- }
-
- // set _currentChara
- private void nextChar(ChaControl[] targets, int currentTargetIndex, bool keep_char = false)
- {
- var cnt = 0;
-
- while (cnt < targets.Length)
- {
- if ((keep_char && cnt == 0) == false)
- {
- currentTargetIndex = (currentTargetIndex + 1) % targets.Length;
- }
- _currentChara = targets[currentTargetIndex];
-
- if (_currentChara)
- {
- if ((POVConfig.targetGender.Value == POVConfig.Gender.All) || (_currentChara.sex == (int)POVConfig.targetGender.Value)) // 1 is female
- {
- if (_povMode == POV_MODE.EYE || _povMode == POV_MODE.HEAD || _povMode == POV_MODE.TELEPORT)
- {
- SetCameraToCharEye(_currentChara);
-
- if (_povMode == POV_MODE.EYE)
- {
- // _tmp_head_y : the initial y when jump to character
- _tmp_head_y = MakeUpright(VR.Camera.SteamCam.origin.rotation) *
- Quaternion.Inverse(MakeUpright(VR.Camera.SteamCam.head.rotation));
- }
- }
- return;
- }
- }
- cnt++;
- }
- // target character not found
- _currentChara = null;
- }
-
- public void SwitchToNextChar()
- {
- // Change to next target character
- if (!_active) return;
-
- ChaControl[] targets = GameObject.FindObjectsOfType();
- var currentTargetIndex = getCurrChaIdx(targets);
- nextChar(targets, currentTargetIndex, false);
- }
-
- private void initPOVTarget()
- {
- // Inherit last target character if still alive, otherwise find a new target character
- ChaControl[] targets = GameObject.FindObjectsOfType();
- var currentTargetIndex = getCurrChaIdx(targets);
- nextChar(targets, currentTargetIndex, true);
- }
-
- private void SetPOV()
- {
- if (!_active) return;
-
- if (_currentChara)
- {
- switch (_povMode)
- {
- case POV_MODE.EYE:
- MoveToPositionEx(GetEyes(_currentChara).position, GetEyes(_currentChara).rotation);
- break;
-
- case POV_MODE.HEAD:
- VRManager.Instance.Mode.MoveToPosition(GetEyes(_currentChara).position, false);
- break;
-
- case POV_MODE.TELEPORT:
- // Already Teleport in SwitchToNextChar
- break;
-
- default:
- break;
- }
- }
- }
-
- protected override void OnUpdate()
- {
- if (_settings.EnablePOV == false) return;
- // Press Key (default: Y) to change POV Mode, configurable in BepInEX Plugin Settings (F1)
- if (POVConfig.switchPOVModeKey.Value == POVConfig.POVKeyList.VR_TRIGGER || POVConfig.switchPOVModeKey.Value == POVConfig.POVKeyList.VR_BUTTON2) // Use VR button
- {
- var button_id = (POVConfig.switchPOVModeKey.Value == POVConfig.POVKeyList.VR_TRIGGER) ? Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger : Valve.VR.EVRButtonId.k_EButton_A;
- if (_leftController.Input.GetPressDown(button_id) || _rightController.Input.GetPressDown(button_id))
- {
- if (_povMode == POV_MODE.EYE) { resetRotationXZ(); }
- _povMode = (POV_MODE)(((int)(_povMode + 1)) % (int)(POV_MODE.TOTAL));
- }
- }
- else if (Input.GetKeyDown((KeyCode)POVConfig.switchPOVModeKey.Value)) // Use Keyboard Key
- {
- if (_povMode == POV_MODE.EYE) { resetRotationXZ(); }
- _povMode = (POV_MODE)(((int)(_povMode + 1)) % (int)(POV_MODE.TOTAL));
- }
-
- if (!_active) // Activate POV under Hand Tool if user press VR Trigger button / Key
- {
- if (POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_TRIGGER || POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_BUTTON2) // Use VR button
- {
- var button_id = (POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_TRIGGER) ? Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger : Valve.VR.EVRButtonId.k_EButton_A;
- // When left hand controller is Hand Tool and visible, Press VR button to set _active
- if (VR.Mode.Left.ToolIndex == 2 && VR.Mode.Left.ActiveTool.isActiveAndEnabled && _leftController.Input.GetPressDown(button_id))
- {
- _active = true;
- initPOVTarget();
- return;
- }
- // When right hand controller is Hand Tool and visible, Press VR button to set _active
- else if (VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled && _rightController.Input.GetPressDown(button_id))
- {
- _active = true;
- initPOVTarget();
- return;
- }
- }
- else // Use Keyboard Key
- {
- if ((VR.Mode.Left.ToolIndex == 2 || VR.Mode.Right.ToolIndex == 2) && Input.GetKeyDown((KeyCode)POVConfig.POVKey.Value))
- {
- _active = true;
- initPOVTarget();
- return;
- }
- }
- }
- // When there is no Hand Tool, deactive
- else if (_active && VR.Mode.Left.ToolIndex != 2 && VR.Mode.Right.ToolIndex != 2)
- {
- _active = false;
- if (_povMode == POV_MODE.EYE) { resetRotationXZ(); }
- return;
- }
-
- if (_active)
- {
- if (POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_TRIGGER || POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_BUTTON2) // Use VR button
- {
- var button_id = (POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_TRIGGER) ? Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger : Valve.VR.EVRButtonId.k_EButton_A;
- // Press VR button to change target POV character
- if (VR.Mode.Left.ToolIndex == 2 && VR.Mode.Left.ActiveTool.isActiveAndEnabled && _leftController.Input.GetPressDown(button_id))
- {
- SwitchToNextChar();
- }
- else if (VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled && _rightController.Input.GetPressDown(button_id))
- {
- SwitchToNextChar();
- }
- }
- else // Use Keyboard Key
- {
- if (Input.GetKeyDown((KeyCode)POVConfig.POVKey.Value)) { SwitchToNextChar(); }
- }
- }
-
-
- SetPOV();
- }
- }
-}
diff --git a/MainGameVR/Caress/AibuColliderTracker.cs b/MainGameVR/Caress/AibuColliderTracker.cs
deleted file mode 100644
index 36f0bc0..0000000
--- a/MainGameVR/Caress/AibuColliderTracker.cs
+++ /dev/null
@@ -1,195 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using HarmonyLib;
-using KKS_VR.Interpreters;
-using UnityEngine;
-using VRGIN.Core;
-using Object = UnityEngine.Object;
-
-namespace KKS_VR.Caress
-{
- ///
- /// An object that tracks the set of aibu colliders that we are
- /// currently intersecting.
- /// Each instance only concerns one H scene. A fresh instance should be
- /// created for each H scene.
- ///
- internal class AibuColliderTracker
- {
- private static readonly IDictionary aibuTagTable
- = new Dictionary
- {
- { "mouth", new[] { HandCtrl.AibuColliderKind.mouth, HandCtrl.AibuColliderKind.reac_head } },
- { "muneL", new[] { HandCtrl.AibuColliderKind.muneL, HandCtrl.AibuColliderKind.reac_bodyup } },
- { "muneR", new[] { HandCtrl.AibuColliderKind.muneR, HandCtrl.AibuColliderKind.reac_bodyup } },
- { "kokan", new[] { HandCtrl.AibuColliderKind.kokan, HandCtrl.AibuColliderKind.reac_bodydown } },
- { "anal", new[] { HandCtrl.AibuColliderKind.anal, HandCtrl.AibuColliderKind.reac_bodydown } },
- { "siriL", new[] { HandCtrl.AibuColliderKind.siriL, HandCtrl.AibuColliderKind.reac_bodydown } },
- { "siriR", new[] { HandCtrl.AibuColliderKind.siriR, HandCtrl.AibuColliderKind.reac_bodydown } },
- { "Reaction/head", new[] { HandCtrl.AibuColliderKind.reac_head } },
- { "Reaction/bodyup", new[] { HandCtrl.AibuColliderKind.reac_bodyup } },
- { "Reaction/bodydown", new[] { HandCtrl.AibuColliderKind.reac_bodydown } },
- { "Reaction/armL", new[] { HandCtrl.AibuColliderKind.reac_armL } },
- { "Reaction/armR", new[] { HandCtrl.AibuColliderKind.reac_armR } },
- { "Reaction/legL", new[] { HandCtrl.AibuColliderKind.reac_legL } },
- { "Reaction/legR", new[] { HandCtrl.AibuColliderKind.reac_legR } }
- };
-
- private readonly IDictionary> _currentlyIntersecting
- = new Dictionary>();
-
- private readonly IDictionary> _knownColliders
- = new Dictionary>();
-
- private readonly Transform _referencePoint;
-
- public AibuColliderTracker(HSceneProc proc, Transform referencePoint)
- {
- Proc = proc;
- _referencePoint = referencePoint;
-
- // Populate _knwonColliders
- var lstFemale = new Traverse(proc).Field("lstFemale").GetValue>();
- for (var i = 0; i < lstFemale.Count; i++)
- {
- var colliders = lstFemale[i].GetComponentsInChildren(true);
- foreach (var collider in colliders)
- {
- var aibuHit = Extensions.StripPrefix("H/Aibu/Hit/", collider.tag);
- if (aibuHit == null) continue;
-
- if (aibuTagTable.TryGetValue(aibuHit, out var kinds)) _knownColliders[collider] = ValueTuple.Create(i, kinds);
- }
- }
- }
-
- public HSceneProc Proc { get; }
-
- ///
- /// If the given collider is an aibu collider, start tracking it.
- ///
- ///
- /// Whether the current collider kind may have changed.
- public bool AddIfRelevant(Collider other)
- {
- if (!_knownColliders.TryGetValue(other, out var idx_kinds)) return false;
-
- var idx = idx_kinds.Item1;
- var kinds = idx_kinds.Item2;
- var hand = idx == 0 ? Proc.hand : Proc.hand1;
- var kind = kinds.Where(k => AibuKindAllowed(hand, k)).FirstOrDefault();
- if (kind != HandCtrl.AibuColliderKind.none)
- {
- _currentlyIntersecting[other] = ValueTuple.Create(idx, kind);
- return true;
- }
-
- return false;
- }
-
- ///
- /// If the given collider is currently being tracked, stop tracking it.
- ///
- ///
- /// Whether the current collider kind may have changed.
- public bool RemoveIfRelevant(Collider other)
- {
- return _currentlyIntersecting.Remove(other);
- }
-
- ///
- /// Get The kind of the collider we should be interacting with.
- /// Also outputs the female who is the owner of the collider.
- ///
- public HandCtrl.AibuColliderKind GetCurrentColliderKind(out int femaleIndex)
- {
- if (_currentlyIntersecting.Count == 0)
- {
- femaleIndex = 0;
- return HandCtrl.AibuColliderKind.none;
- }
-
- // Only consider the colliders with the highest priority.
- var priority = _currentlyIntersecting.Values.Select(idx_kind => ColliderPriority(idx_kind.Item2)).Max();
- var refPosition = _referencePoint.position;
- var best = _currentlyIntersecting.Where(kv => ColliderPriority(kv.Value.Item2) == priority)
- .OrderBy(kv => (kv.Key.transform.position - refPosition).sqrMagnitude)
- .Select(kv => kv.Value).FirstOrDefault();
- femaleIndex = best.Item1;
- return best.Item2;
- }
-
- ///
- /// Return whether there is any collider we should be interacting with.
- /// This is equivalent to this.GetCurrentColliderKind() != none, but is more efficient.
- ///
- ///
- public bool IsIntersecting()
- {
- return _currentlyIntersecting.Count > 0;
- }
-
- private static int ColliderPriority(HandCtrl.AibuColliderKind kind)
- {
- if (kind == HandCtrl.AibuColliderKind.none)
- return 0;
- if (HandCtrl.AibuColliderKind.mouth <= kind && kind < HandCtrl.AibuColliderKind.reac_head)
- return 2;
- return 1;
- }
-
- ///
- /// Check whether a particular body interaction is allowed.
- ///
- ///
- ///
- ///
- private bool AibuKindAllowed(HandCtrl hand, HandCtrl.AibuColliderKind kind)
- {
- // It's ok to use lstHeroine[0] here because this variable is not used
- // when there are more than one heroine.
- var heroine = hand.flags.lstHeroine[0];
- var dicNowReaction = new Traverse(hand).Field("dicNowReaction").GetValue>();
- HandCtrl.ReactionInfo rinfo;
- switch (kind)
- {
- case HandCtrl.AibuColliderKind.none:
- return true;
- case HandCtrl.AibuColliderKind.mouth:
- return hand.nowMES.isTouchAreas[0] &&
- (hand.flags.mode == HFlag.EMode.aibu || heroine.isGirlfriend || heroine.isKiss || heroine.denial.kiss);
- case HandCtrl.AibuColliderKind.muneL:
- return hand.nowMES.isTouchAreas[1];
- case HandCtrl.AibuColliderKind.muneR:
- return hand.nowMES.isTouchAreas[2];
- case HandCtrl.AibuColliderKind.kokan:
- return hand.nowMES.isTouchAreas[3];
- case HandCtrl.AibuColliderKind.anal:
- return hand.nowMES.isTouchAreas[4] &&
- (hand.flags.mode == HFlag.EMode.aibu || heroine.hAreaExps[3] > 0f || heroine.denial.anal);
- case HandCtrl.AibuColliderKind.siriL:
- return hand.nowMES.isTouchAreas[5];
- case HandCtrl.AibuColliderKind.siriR:
- return hand.nowMES.isTouchAreas[6];
- case HandCtrl.AibuColliderKind.reac_head:
- return dicNowReaction.TryGetValue(0, out rinfo) && rinfo.isPlay;
- case HandCtrl.AibuColliderKind.reac_bodyup:
- return dicNowReaction.TryGetValue(1, out rinfo) && rinfo.isPlay;
- case HandCtrl.AibuColliderKind.reac_bodydown:
- return dicNowReaction.TryGetValue(2, out rinfo) && rinfo.isPlay;
- case HandCtrl.AibuColliderKind.reac_armL:
- return dicNowReaction.TryGetValue(3, out rinfo) && rinfo.isPlay;
- case HandCtrl.AibuColliderKind.reac_armR:
- return dicNowReaction.TryGetValue(4, out rinfo) && rinfo.isPlay;
- case HandCtrl.AibuColliderKind.reac_legL:
- return dicNowReaction.TryGetValue(5, out rinfo) && rinfo.isPlay;
- case HandCtrl.AibuColliderKind.reac_legR:
- return dicNowReaction.TryGetValue(6, out rinfo) && rinfo.isPlay;
- }
-
- VRLog.Warn("AibuKindAllowed: undefined kind: {0}", kind);
- return false;
- }
- }
-}
diff --git a/MainGameVR/Caress/CaressController.cs b/MainGameVR/Caress/CaressController.cs
deleted file mode 100644
index 41ea8bf..0000000
--- a/MainGameVR/Caress/CaressController.cs
+++ /dev/null
@@ -1,204 +0,0 @@
-using System;
-using System.Collections.Generic;
-using HarmonyLib;
-using KKS_VR.Settings;
-using Manager;
-using UnityEngine;
-using Valve.VR;
-using VRGIN.Controls;
-using VRGIN.Core;
-using VRGIN.Helpers;
-
-namespace KKS_VR.Caress
-{
- ///
- /// An extra component to be attached to each controller, providing the caress
- /// functionality in H scenes.
- /// This component is designed to exist only for the duration of an H scene.
- ///
- internal class CaressController : ProtectedBehaviour
- {
- // Basic plan:
- //
- // * Keep track of the potential caress points
- // near this controller. _aibuTracker is responsible for this.
- // * While there is at least one such point, lock the controller
- // to steal any trigger events.
- // * When the trigger is pulled, initiate caress.
- // * Delay releasing of the lock until the trigger is released.
-
- KoikatuSettings _settings;
- Controller _controller;
- AibuColliderTracker _aibuTracker;
- Undresser _undresser;
- Controller.Lock _lock; // may be null but never invalid
- bool _triggerPressed; // Whether the trigger is currently pressed. false if _lock is null.
- ValueTuple? _undressing;
-
- public Controller getController()
- {
- return _controller;
- }
-
- protected override void OnAwake()
- {
- base.OnAwake();
- _settings = VR.Context.Settings as KoikatuSettings;
- _controller = GetComponent();
- var proc = FindObjectOfType();
- if (proc == null)
- {
- VRLog.Warn("HSceneProc not found");
- return;
- }
- _aibuTracker = new AibuColliderTracker(proc, referencePoint: transform);
- _undresser = new Undresser(proc);
- }
-
- private void OnDestroy()
- {
- if (_lock != null) ReleaseLock();
- }
-
- protected override void OnUpdate()
- {
- if (_lock != null)
- {
- HandleTrigger();
- HandleToolChange();
- HandleUndress();
- }
- UpdateLock();
- }
-
- protected void OnTriggerEnter(Collider other)
- {
- try
- {
- if (Scene.NowSceneNames[0] == "HPointMove") return;
- var wasIntersecting = _aibuTracker.IsIntersecting();
- if (_aibuTracker.AddIfRelevant(other))
- {
- if (!wasIntersecting && _aibuTracker.IsIntersecting())
- {
- _controller.StartRumble(new RumbleImpulse(1000));
- if (_settings.AutomaticTouching)
- {
- var colliderKind = _aibuTracker.GetCurrentColliderKind(out int femaleIndex);
- if (HandCtrl.AibuColliderKind.reac_head <= colliderKind &&
- !CaressUtil.IsSpeaking(_aibuTracker.Proc, femaleIndex))
- {
- CaressUtil.SetSelectKindTouch(_aibuTracker.Proc, femaleIndex, colliderKind);
- StartCoroutine(CaressUtil.ClickCo());
- }
- }
- }
- }
-
- _undresser.Enter(other);
- UpdateLock();
- }
- catch (Exception e)
- {
- VRLog.Error(e);
- }
- }
-
- protected void OnTriggerExit(Collider other)
- {
- try
- {
- _aibuTracker.RemoveIfRelevant(other);
- _undresser.Exit(other);
- UpdateLock();
- }
- catch (Exception e)
- {
- VRLog.Error(e);
- }
- }
-
- private void UpdateLock()
- {
- bool shouldHaveLock = (_aibuTracker.IsIntersecting() || _undressing != null) &&
- Manager.Scene.NowSceneNames[0] != "HPointMove";
- if (shouldHaveLock && _lock == null)
- _controller.TryAcquireFocus(out _lock);
- else if (!shouldHaveLock && _lock != null && !_triggerPressed) ReleaseLock();
- }
-
- private void HandleTrigger()
- {
- var device = _controller.Input; //SteamVR_Controller.Input((int)_controller.Tracking.index);
- if (!_triggerPressed && device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger))
- {
- UpdateSelectKindTouch();
- HandCtrlHooks.InjectMouseButtonDown(0);
- _controller.StartRumble(new RumbleImpulse(1000));
- _triggerPressed = true;
- }
- else if (_triggerPressed && device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger))
- {
- HandCtrlHooks.InjectMouseButtonUp(0);
- _triggerPressed = false;
- UpdateLock();
- }
- }
-
- private void HandleToolChange()
- {
- var device = _controller.Input; //SteamVR_Controller.Input((int)_controller.Tracking.index);
- if (device.GetPressUp(EVRButtonId.k_EButton_ApplicationMenu))
- {
- UpdateSelectKindTouch();
- HandCtrlHooks.InjectMouseScroll(1f);
- }
-
- }
-
- private void HandleUndress()
- {
- var device = _controller.Input;
- var proc = _aibuTracker.Proc;
- if (_undressing == null && device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad))
- {
- var females = new Traverse(proc).Field>("lstFemale").Value;
- var toUndress = _undresser.ComputeUndressTarget(females, out int femaleIndex);
- if (toUndress is ChaFileDefine.ClothesKind kind)
- {
- _undressing = ValueTuple.Create(females[femaleIndex], kind, transform.position);
- }
- }
- if (_undressing is ValueTuple undressing
- && device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad))
- {
- if (0.3f * 0.3f < (transform.position - undressing.Item3).sqrMagnitude)
- {
- undressing.Item1.SetClothesState((int)undressing.Item2, 3);
- }
- else
- {
- undressing.Item1.SetClothesStateNext((int)undressing.Item2);
- }
- _undressing = null;
- }
- }
-
- private void ReleaseLock()
- {
- CaressUtil.SetSelectKindTouch(_aibuTracker.Proc, 0, HandCtrl.AibuColliderKind.none);
- if (_triggerPressed)
- HandCtrlHooks.InjectMouseButtonUp(0);
- _triggerPressed = false;
- _undressing = null;
- _lock.Release();
- _lock = null;
- }
-
- private void UpdateSelectKindTouch()
- {
- var colliderKind = _aibuTracker.GetCurrentColliderKind(out var femaleIndex);
- CaressUtil.SetSelectKindTouch(_aibuTracker.Proc, femaleIndex, colliderKind);
- }
- }
-}
diff --git a/MainGameVR/Caress/CaressUtil.cs b/MainGameVR/Caress/CaressUtil.cs
deleted file mode 100644
index 94de988..0000000
--- a/MainGameVR/Caress/CaressUtil.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using HarmonyLib;
-
-namespace KKS_VR.Caress
-{
- public class CaressUtil
- {
- ///
- /// Modify the internal state of the hand controls so that subsequent mouse button
- /// presses are interpreted to point to the specified (female, point) pair.
- ///
- public static void SetSelectKindTouch(HSceneProc proc, int femaleIndex, HandCtrl.AibuColliderKind colliderKind)
- {
- var hands = GetHands(proc);
- for (var i = 0; i < hands.Count; i++)
- {
- var kind = i == femaleIndex ? colliderKind : HandCtrl.AibuColliderKind.none;
- new Traverse(hands[i]).Field("selectKindTouch").SetValue(kind);
- }
- }
-
- public static List GetHands(HSceneProc proc)
- {
- var ret = new List();
- for (var i = 0; i < proc.flags.lstHeroine.Count; i++) ret.Add(i == 0 ? proc.hand : proc.hand1);
- return ret;
- }
-
- ///
- /// Send a synthetic click event to the hand controls.
- ///
- ///
- public static IEnumerator ClickCo()
- {
- var consumed = false;
- HandCtrlHooks.InjectMouseButtonDown(0, () => consumed = true);
- while (!consumed) yield return null;
- HandCtrlHooks.InjectMouseButtonUp(0);
- }
-
- ///
- /// Is the specified female speaking? Moans are ignored.
- ///
- public static bool IsSpeaking(HSceneProc proc, int femaleIndex)
- {
- return proc.voice.nowVoices[femaleIndex].state == HVoiceCtrl.VoiceKind.voice &&
- Manager.Voice.IsPlay(proc.flags.transVoiceMouth[femaleIndex], true);
- }
- }
-}
diff --git a/MainGameVR/Caress/LongDistanceKissMachine.cs b/MainGameVR/Caress/LongDistanceKissMachine.cs
deleted file mode 100644
index 191da13..0000000
--- a/MainGameVR/Caress/LongDistanceKissMachine.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using UnityEngine;
-
-namespace KKS_VR.Caress
-{
- ///
- /// A state machine for starting and finishing a kiss in the caress mode.
- ///
- /// This requires a special treatment because the female leans forward after
- /// a kiss is started. This means a kiss should start with some distance.
- ///
- public class LongDistanceKissMachine
- {
- private float? _startTime; // null iff not kissing
- private bool _prevEntryConditionMet = true;
-
- public bool Step(
- float currentTime,
- Vector3 femaleFromHmd,
- Vector3 hmdFromFemale,
- float femaleFaceAngleY)
- {
- var entryConditionMet = EntryScore(femaleFromHmd, hmdFromFemale, femaleFaceAngleY) < 0;
- bool result;
- if (_startTime is float startTime)
- {
- var duration = currentTime - startTime;
- var maxDistance = Mathf.Max(0.10f, 0.55f - 0.4f * duration);
- result = hmdFromFemale.sqrMagnitude < maxDistance * maxDistance;
- }
- else
- {
- result = entryConditionMet && !_prevEntryConditionMet;
- }
-
- _prevEntryConditionMet = entryConditionMet;
-
- if (result)
- _startTime = _startTime ?? currentTime;
- else if (_startTime != null) _startTime = null;
- return result;
- }
-
- public void Reset()
- {
- _startTime = null;
- _prevEntryConditionMet = true;
- }
-
- private static float EntryScore(Vector3 femaleFromHmd, Vector3 hmdFromFemale, float femaleFaceAngle)
- {
- var total = OneSidedScore(femaleFromHmd) + OneSidedScore(hmdFromFemale) + 0.1f * Mathf.Abs(femaleFaceAngle);
- return total - 2.0f;
- }
-
- private static float OneSidedScore(Vector3 rel)
- {
- rel.z = 0.4f * (rel.z - 0.1f);
- return 500f * rel.sqrMagnitude;
- }
- }
-}
diff --git a/MainGameVR/Caress/Undresser.cs b/MainGameVR/Caress/Undresser.cs
deleted file mode 100644
index 74f7cc6..0000000
--- a/MainGameVR/Caress/Undresser.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using UnityEngine;
-using VRGIN.Core;
-using HarmonyLib;
-
-using static ChaFileDefine;
-
-namespace KKS_VR.Caress
-{
- ///
- /// An object responsible for determining which clothing item to remove,
- /// based on the controller position.
- ///
- class Undresser
- {
- private readonly Dictionary> _knownColliders =
- new Dictionary>();
- private readonly HashSet _currentlyIntersecting = new HashSet();
-
- public Undresser(HSceneProc proc)
- {
- // Populate _knownColliders.
- var lstFemale = new Traverse(proc).Field("lstFemale").GetValue>();
- for (int i = 0; i < lstFemale.Count; i++)
- {
- var colliders = lstFemale[i].GetComponentsInChildren(includeInactive: true);
- foreach (var collider in colliders)
- {
- if (ColliderBodyPart(collider) is InteractionBodyPart part)
- {
- _knownColliders.Add(collider, ValueTuple.Create(i, part));
- }
- }
- }
- }
-
- public void Enter(Collider collider)
- {
- if (_knownColliders.ContainsKey(collider))
- {
- _currentlyIntersecting.Add(collider);
- }
- }
-
- public void Exit(Collider collider)
- {
- _currentlyIntersecting.Remove(collider);
- }
-
- public ClothesKind? ComputeUndressTarget(List females, out int femaleIndex)
- {
- femaleIndex = 0;
- if (_currentlyIntersecting.Count == 0)
- {
- return null;
- }
- var part = (InteractionBodyPart)9999;
- foreach (var collider in _currentlyIntersecting)
- {
- var item = _knownColliders[collider];
- if (item.Item2 < part)
- {
- femaleIndex = item.Item1;
- part = item.Item2;
- break;
- }
- }
-
- var female = females[femaleIndex];
- var targets = _itemsForPart[(int)part];
- if (part == InteractionBodyPart.Crotch && IsWearingSkirt(female))
- {
- // Special case: if the character is wearing a skirt, allow
- // directly removing the underwear.
- targets = _skirtCrotchTargets;
- }
- foreach (var target in targets)
- {
- if (!female.IsClothesStateKind((int)target.kind))
- {
- continue;
- }
- var state = female.fileStatus.clothesState[(int)target.kind];
- if (target.min_state <= state && state <= target.max_state)
- {
- VRLog.Info($"toUndress: {target.kind}");
- return target.kind;
- }
- }
- return null;
- }
-
- private static bool IsWearingSkirt(ChaControl female)
- {
- var objBot = female.objClothes[1];
- return objBot != null && objBot.GetComponent() != null;
- }
-
- ///
- /// A body part the user can interact with. A more specific part gets
- /// a lower number.
- ///
- private enum InteractionBodyPart
- {
- Crotch,
- Groin,
- Breast,
- LegL,
- LegR,
- Forearm,
- UpperArm,
- Thigh,
- Torso,
- }
-
- private static readonly UndressTarget[][] _itemsForPart = new[]
- {
- new[] { Target(ClothesKind.bot), Target(ClothesKind.panst), Target(ClothesKind.shorts) },
- new[] { Target(ClothesKind.bot, 0), Target(ClothesKind.panst), Target(ClothesKind.shorts) },
- new[] { Target(ClothesKind.top, 0), Target(ClothesKind.bra) },
- new[] { Target(ClothesKind.socks), Target(ClothesKind.shorts, 2, 2) },
- new[] { Target(ClothesKind.socks) },
- new UndressTarget[] { },
- new[] { Target(ClothesKind.top) },
- new[] { Target(ClothesKind.panst), Target(ClothesKind.bot), Target(ClothesKind.socks) },
- new[] { Target(ClothesKind.top) },
- };
-
- private static readonly UndressTarget[] _skirtCrotchTargets =
- new[] { Target(ClothesKind.panst), Target(ClothesKind.shorts), Target(ClothesKind.bot) };
-
- private static UndressTarget Target(ClothesKind kind, int max_state = 2, int min_state = 0)
- {
- return new UndressTarget(kind, max_state, min_state);
- }
-
- private static InteractionBodyPart? ColliderBodyPart(Collider collider)
- {
- var name = collider.name;
- if (name == "aibu_hit_kokan" ||
- name == "aibu_hit_ana")
- return InteractionBodyPart.Crotch;
- if (name.StartsWith("aibu_hit_siri") ||
- name.StartsWith("aibu_reaction_waist"))
- return InteractionBodyPart.Groin;
- if (name.StartsWith("cf_hit_bust"))
- return InteractionBodyPart.Breast;
- if (name == "aibu_reaction_legL")
- return InteractionBodyPart.LegL;
- if (name == "aibu_reaction_legR")
- return InteractionBodyPart.LegR;
- if (name.StartsWith("cf_hit_wrist"))
- return InteractionBodyPart.Forearm;
- if (name.StartsWith("cf_hit_arm"))
- return InteractionBodyPart.UpperArm;
- if (name.StartsWith("aibu_reaction_thigh"))
- return InteractionBodyPart.Thigh;
- if (name == "cf_hit_spine01" ||
- name == "cf_hit_spine03" ||
- name == "cf_hit_berry")
- return InteractionBodyPart.Torso;
- return null;
- }
-
- private struct UndressTarget
- {
- public UndressTarget(ClothesKind k, int m, int mm)
- {
- kind = k;
- max_state = m;
- min_state = mm;
- }
- public ClothesKind kind;
- public int max_state;
- public int min_state;
- }
- }
-}
diff --git a/MainGameVR/Caress/VRMouth.cs b/MainGameVR/Caress/VRMouth.cs
deleted file mode 100644
index 4214b07..0000000
--- a/MainGameVR/Caress/VRMouth.cs
+++ /dev/null
@@ -1,343 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using HarmonyLib;
-using KKS_VR.Settings;
-using UnityEngine;
-using VRGIN.Core;
-
-namespace KKS_VR.Caress
-{
- ///
- /// A component to be attached to the VR camera during an H scene.
- /// It allows the user to kiss in H scenes by moving their head.
- ///
- public class VRMouth : ProtectedBehaviour
- {
- private KoikatuSettings _settings;
- private AibuColliderTracker _aibuTracker;
- private Transform _firstFemale;
- private Transform _firstFemaleMouth;
- private VRMouthColliderObject _small, _large;
- private bool _inCaressMode = true;
- private readonly LongDistanceKissMachine _machine = new LongDistanceKissMachine();
-
- ///
- /// Indicates whether the currently running KissCo should end.
- /// null if KissCo is not running.
- ///
- private bool? _kissCoShouldEnd;
-
- ///
- /// Indicates whether the currently running KissCo should end.
- /// null if LickCo is not running.
- ///
- private bool? _lickCoShouldEnd;
-
- protected override void OnAwake()
- {
- base.OnAwake();
- _settings = VR.Context.Settings as KoikatuSettings;
-
- // Create 2 colliders, a small one for entering and a large one for exiting.
- _small = VRMouthColliderObject
- .Create("VRMouthSmall", new Vector3(0, 0, 0), new Vector3(0.05f, 0.05f, 0.07f));
- _small.TriggerEnter += HandleTriggerEnter;
- _large = VRMouthColliderObject
- .Create("VRMouthLarge", new Vector3(0, 0, 0.05f), new Vector3(0.1f, 0.1f, 0.15f));
- _large.TriggerExit += HandleTriggerExit;
-
- var hProc = FindObjectOfType();
-
- if (hProc == null)
- {
- VRLog.Error("hProc is null");
- return;
- }
-
- _aibuTracker = new AibuColliderTracker(hProc, transform);
- var lstFemale = new Traverse(hProc).Field("lstFemale").GetValue>();
- _firstFemale = lstFemale[0].objTop.transform;
- _firstFemaleMouth = lstFemale[0].objHeadBone.transform.Find(
- "cf_J_N_FaceRoot/cf_J_FaceRoot/cf_J_FaceBase/cf_J_FaceLow_tz/a_n_mouth");
- }
-
- private void OnDestroy()
- {
- Destroy(_small.gameObject);
- Destroy(_large.gameObject);
- }
-
- protected override void OnUpdate()
- {
- HandleScoreBasedKissing();
- }
-
- private void HandleScoreBasedKissing()
- {
- var inCaressMode = _aibuTracker.Proc.flags.mode == HFlag.EMode.aibu;
- if (inCaressMode)
- {
- var decision = _settings.AutomaticKissing &&
- _machine.Step(
- Time.time,
- _small.transform.InverseTransformPoint(_firstFemaleMouth.position),
- _firstFemaleMouth.InverseTransformPoint(_small.transform.position),
- Mathf.DeltaAngle(_firstFemale.eulerAngles.y, _firstFemaleMouth.transform.eulerAngles.y));
- if (decision)
- StartKiss();
- else
- FinishKiss();
- }
-
- if (_inCaressMode & !inCaressMode)
- {
- FinishKiss();
- _machine.Reset();
- }
-
- _inCaressMode = inCaressMode;
- }
-
- private void HandleTriggerEnter(Collider other)
- {
- if (_aibuTracker.AddIfRelevant(other))
- {
- var colliderKind = _aibuTracker.GetCurrentColliderKind(out var femaleIndex);
- UpdateKissLick(colliderKind);
-
- if (_kissCoShouldEnd == null &&
- HandCtrl.AibuColliderKind.reac_head <= colliderKind &&
- _settings.AutomaticTouchingByHmd &&
- !CaressUtil.IsSpeaking(_aibuTracker.Proc, femaleIndex))
- StartCoroutine(TriggerReactionCo(femaleIndex, colliderKind));
- }
- }
-
- private IEnumerator TriggerReactionCo(int femaleIndex, HandCtrl.AibuColliderKind colliderKind)
- {
- var kindFields = CaressUtil.GetHands(_aibuTracker.Proc)
- .Select(h => new Traverse(h).Field("selectKindTouch"))
- .ToList();
- var oldKinds = kindFields.Select(f => f.Value).ToList();
- CaressUtil.SetSelectKindTouch(_aibuTracker.Proc, femaleIndex, colliderKind);
- yield return CaressUtil.ClickCo();
- for (var i = 0; i < kindFields.Count(); i++) kindFields[i].Value = oldKinds[i];
- }
-
- private void HandleTriggerExit(Collider other)
- {
- if (_aibuTracker.RemoveIfRelevant(other))
- {
- var colliderKind = _aibuTracker.GetCurrentColliderKind(out var _);
- UpdateKissLick(colliderKind);
- }
- }
-
- private void UpdateKissLick(HandCtrl.AibuColliderKind colliderKind)
- {
- if (!_inCaressMode && colliderKind == HandCtrl.AibuColliderKind.mouth && _settings.AutomaticKissing)
- {
- StartKiss();
- }
- else if (_settings.AutomaticLicking && IsLickingOk(colliderKind, out var layerNum))
- {
- StartLicking(colliderKind, layerNum);
- }
- else
- {
- if (!_inCaressMode) FinishKiss();
- FinishLicking();
- }
- }
-
- private bool IsLickingOk(HandCtrl.AibuColliderKind colliderKind, out int layerNum)
- {
- layerNum = 0;
- if (colliderKind <= HandCtrl.AibuColliderKind.mouth ||
- HandCtrl.AibuColliderKind.reac_head <= colliderKind)
- return false;
-
- var bodyPartId = colliderKind - HandCtrl.AibuColliderKind.muneL;
- var hand = _aibuTracker.Proc.hand;
- var handTrav = new Traverse(hand);
- var layerInfos = handTrav.Field[]>("dicAreaLayerInfos").Value[bodyPartId];
- var clothState = handTrav.Method("GetClothState", new[] { typeof(HandCtrl.AibuColliderKind) }).GetValue(colliderKind);
- var layerKv = layerInfos.Where(kv => kv.Value.useArray == 2).FirstOrDefault();
- var layerInfo = layerKv.Value;
- layerNum = layerKv.Key;
- if (layerInfo == null)
- {
- VRLog.Warn("Licking not ok: no layer found");
- return false;
- }
-
- if (layerInfo.plays[clothState] == -1) return false;
- var heroine = _aibuTracker.Proc.flags.lstHeroine[0];
- if (_aibuTracker.Proc.flags.mode != HFlag.EMode.aibu &&
- colliderKind == HandCtrl.AibuColliderKind.anal &&
- !heroine.denial.anal &&
- heroine.hAreaExps[3] == 0f)
- return false;
-
- return true;
- }
-
- ///
- /// Attempt to start a kiss.
- ///
- private void StartKiss()
- {
- if (_kissCoShouldEnd != null || new Traverse(_aibuTracker.Proc.hand).Field("isKiss").Value)
- // Already kissing.
- return;
-
- _kissCoShouldEnd = false;
- StartCoroutine(KissCo());
- }
-
- private IEnumerator KissCo()
- {
- StopAllLicking();
-
- var hand = _aibuTracker.Proc.hand;
- var handTrav = new Traverse(hand);
- var selectKindTouchTrav = handTrav.Field("selectKindTouch");
-
- var prevKindTouch = selectKindTouchTrav.Value;
- selectKindTouchTrav.Value = HandCtrl.AibuColliderKind.mouth;
- var messageDelivered = false;
- HandCtrlHooks.InjectMouseButtonDown(0, () => messageDelivered = true);
- while (!messageDelivered) yield return null;
- yield return new WaitForEndOfFrame();
-
- // Try to restore the old value of selectKindTouch.
- if (selectKindTouchTrav.Value == HandCtrl.AibuColliderKind.mouth) selectKindTouchTrav.Value = prevKindTouch;
-
- var isKissTrav = handTrav.Field("isKiss");
- while (_kissCoShouldEnd == false && isKissTrav.Value) yield return null;
-
- HandCtrlHooks.InjectMouseButtonUp(0);
- _kissCoShouldEnd = null;
- }
-
- private void FinishKiss()
- {
- if (_kissCoShouldEnd == false) _kissCoShouldEnd = true;
- }
-
- private void StartLicking(HandCtrl.AibuColliderKind colliderKind, int layerNum)
- {
- if (_lickCoShouldEnd != null)
- // Already licking.
- return;
-
- var hand = _aibuTracker.Proc.hand;
- var handTrav = new Traverse(hand);
- var bodyPartId = colliderKind - HandCtrl.AibuColliderKind.muneL;
- var usedItem = handTrav.Field("useAreaItems").Value[bodyPartId];
-
- // If another item is being used on the target body part, detach it.
- if (usedItem != null && usedItem.idUse != 2) hand.DetachItemByUseItem(usedItem.idUse);
-
- StartCoroutine(LickCo(colliderKind, layerNum));
- }
-
- private IEnumerator LickCo(HandCtrl.AibuColliderKind colliderKind, int layerNum)
- {
- _lickCoShouldEnd = false;
-
- var hand = _aibuTracker.Proc.hand;
- var handTrav = new Traverse(hand);
- var areaItem = handTrav.Field("areaItem").Value;
- var bodyPartId = colliderKind - HandCtrl.AibuColliderKind.muneL;
- var selectKindTouchTrav = handTrav.Field("selectKindTouch");
-
-
- var oldLayerNum = areaItem[bodyPartId];
- areaItem[bodyPartId] = layerNum;
-
- while (_lickCoShouldEnd == false && areaItem[bodyPartId] == layerNum)
- {
- var oldKindTouch = selectKindTouchTrav.Value;
- selectKindTouchTrav.Value = colliderKind;
- yield return CaressUtil.ClickCo();
- selectKindTouchTrav.Value = oldKindTouch;
- yield return new WaitForSeconds(0.2f);
- }
-
- hand.DetachItemByUseItem(2);
- if (areaItem[bodyPartId] == layerNum) areaItem[bodyPartId] = oldLayerNum;
-
- _lickCoShouldEnd = null;
- }
-
- private void FinishLicking()
- {
- if (_lickCoShouldEnd == false) _lickCoShouldEnd = true;
- }
-
- private void StopAllLicking()
- {
- FinishLicking();
- _aibuTracker.Proc.hand.DetachItemByUseItem(2);
- }
-
- private class VRMouthColliderObject : ProtectedBehaviour
- {
- public delegate void TriggerHandler(Collider other);
-
- public event TriggerHandler TriggerEnter;
- public event TriggerHandler TriggerExit;
-
- public static VRMouthColliderObject Create(string name, Vector3 center, Vector3 size)
- {
- var gameObj = new GameObject(name);
- gameObj.transform.localPosition = new Vector3(0, -0.07f, 0.02f);
- gameObj.transform.SetParent(VR.Camera.transform, false);
-
- var collider = gameObj.AddComponent();
- collider.size = size;
- collider.center = center;
- collider.isTrigger = true;
-
- gameObj.AddComponent().isKinematic = true;
- return gameObj.AddComponent();
- }
-
- protected void OnTriggerEnter(Collider other)
- {
- try
- {
- TriggerEnter?.Invoke(other);
- }
- catch (Exception e)
- {
- VRLog.Error(e);
- }
- }
-
- protected void OnTriggerExit(Collider other)
- {
- try
- {
- TriggerExit?.Invoke(other);
- }
- catch (Exception e)
- {
- VRLog.Error(e);
- }
- }
- }
- }
-}
-
-// Notes on some fields in HandCtrl:
-//
-// areaItem[p] : The layer num of the item to be used on the body part p
-// useAreaItems[p] : The item currently being used on the body part p
-// useItems[s] : The item currently in the slot s
-// dicAreaLayerInfos[p][l].useArray : The slot to be used when the layer l is used on the body part p.
-// 3 means either slot 0 (left hand) or 1 (right hand).
-// item.idUse: The slot to be used for the item.
diff --git a/MainGameVR/Controls/ButtonsSubtool.cs b/MainGameVR/Controls/ButtonsSubtool.cs
deleted file mode 100644
index 887f059..0000000
--- a/MainGameVR/Controls/ButtonsSubtool.cs
+++ /dev/null
@@ -1,200 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using KKS_VR.Camera;
-using KKS_VR.Interpreters;
-using KKS_VR.Settings;
-using UnityEngine;
-using VRGIN.Core;
-using WindowsInput.Native;
-
-namespace KKS_VR.Controls
-{
- ///
- /// A subtool that handles an arbitrary number of simple actions that only
- /// requires a single button.
- ///
- internal class ButtonsSubtool
- {
- private readonly KoikatuInterpreter _Interpreter;
-
- ///
- /// The set of keys for which we've sent a down message but not a
- /// corresponding up message.
- ///
- private readonly HashSet _SentUnmatchedDown
- = new HashSet();
-
- private readonly KoikatuSettings _Settings;
- private int _ScrollRepeatAmount;
-
- private float _ScrollRepeatTime;
-
- public ButtonsSubtool(KoikatuInterpreter interpreter, KoikatuSettings settings)
- {
- _Interpreter = interpreter;
- _Settings = settings;
- }
-
- ///
- /// A method to be called in Update().
- ///
- public void Update()
- {
- if (_SentUnmatchedDown.Contains(AssignableFunction.PL2CAM)) IfActionScene(interpreter => interpreter.MovePlayerToCamera());
- if (_ScrollRepeatAmount != 0 && _ScrollRepeatTime < Time.unscaledTime)
- {
- _ScrollRepeatTime += 0.1f;
- VR.Input.Mouse.VerticalScroll(_ScrollRepeatAmount);
- }
- }
-
- ///
- /// Whether it's desirable to lock the controller.
- ///
- ///
- public bool WantLock()
- {
- return _SentUnmatchedDown.Count > 0;
- }
-
- ///
- /// A method to be called when this subtool is destroyed.
- ///
- public void Destroy()
- {
- // Make a copy because the loop below will modify the HashSet.
- var todo = _SentUnmatchedDown.ToList();
- foreach (var key in todo) ButtonUp(key);
- }
-
- ///
- /// Process a ButtonDown message.
- ///
- public void ButtonDown(AssignableFunction fun)
- {
- switch (fun)
- {
- case AssignableFunction.NONE:
- break;
- case AssignableFunction.WALK:
- IfActionScene(interpreter => interpreter.StartWalking());
- break;
- case AssignableFunction.DASH:
- IfActionScene(interpreter => interpreter.StartWalking(true));
- break;
- case AssignableFunction.PL2CAM:
- break;
- case AssignableFunction.LBUTTON:
- VR.Input.Mouse.LeftButtonDown();
- break;
- case AssignableFunction.RBUTTON:
- VR.Input.Mouse.RightButtonDown();
- break;
- case AssignableFunction.MBUTTON:
- VR.Input.Mouse.MiddleButtonDown();
- break;
- case AssignableFunction.LROTATION:
- Rotate(-_Settings.RotationAngle);
- break;
- case AssignableFunction.RROTATION:
- Rotate(_Settings.RotationAngle);
- break;
- case AssignableFunction.SCROLLUP:
- StartScroll(1);
- break;
- case AssignableFunction.SCROLLDOWN:
- StartScroll(-1);
- break;
- case AssignableFunction.CROUCH:
- IfActionScene(interpreter => interpreter.Crouch());
- break;
- case AssignableFunction.NEXT:
- throw new NotSupportedException();
- case AssignableFunction.KEYBOARD_PAGE_DOWN:
- VR.Input.Keyboard.KeyDown(VirtualKeyCode.NEXT);
- break;
- default:
- VR.Input.Keyboard.KeyDown((VirtualKeyCode)Enum.Parse(typeof(VirtualKeyCode), fun.ToString()));
- break;
- }
-
- _SentUnmatchedDown.Add(fun);
- }
-
- ///
- /// Process a ButtonUp message.
- ///
- public void ButtonUp(AssignableFunction fun)
- {
- switch (fun)
- {
- case AssignableFunction.NONE:
- break;
- case AssignableFunction.WALK:
- IfActionScene(interpreter => interpreter.StopWalking());
- break;
- case AssignableFunction.DASH:
- IfActionScene(interpreter => interpreter.StopWalking());
- break;
- case AssignableFunction.PL2CAM:
- break;
- case AssignableFunction.LBUTTON:
- VR.Input.Mouse.LeftButtonUp();
- break;
- case AssignableFunction.RBUTTON:
- VR.Input.Mouse.RightButtonUp();
- break;
- case AssignableFunction.MBUTTON:
- VR.Input.Mouse.MiddleButtonUp();
- break;
- case AssignableFunction.LROTATION:
- case AssignableFunction.RROTATION:
- break;
- case AssignableFunction.SCROLLUP:
- case AssignableFunction.SCROLLDOWN:
- _ScrollRepeatAmount = 0;
- break;
- case AssignableFunction.CROUCH:
- IfActionScene(interpreter => interpreter.StandUp());
- break;
- case AssignableFunction.NEXT:
- throw new NotSupportedException();
- case AssignableFunction.KEYBOARD_PAGE_DOWN:
- VR.Input.Keyboard.KeyUp(VirtualKeyCode.NEXT);
- break;
- default:
- VR.Input.Keyboard.KeyUp((VirtualKeyCode)Enum.Parse(typeof(VirtualKeyCode), fun.ToString()));
- break;
- }
-
- _SentUnmatchedDown.Remove(fun);
- }
-
- private void StartScroll(int amount)
- {
- VR.Input.Mouse.VerticalScroll(amount);
- _ScrollRepeatTime = Time.unscaledTime + 0.5f;
- _ScrollRepeatAmount = amount;
- }
-
- ///
- /// Rotate the camera. If we are in Roaming, rotate the protagonist as well.
- ///
- private void Rotate(float degrees)
- {
- VRLog.Debug("Rotating {0} degrees", degrees);
- var actInterpreter = _Interpreter.SceneInterpreter as ActionSceneInterpreter;
- if (actInterpreter != null) actInterpreter.MoveCameraToPlayer(true);
- var camera = VR.Camera.transform;
- var newRotation = Quaternion.AngleAxis(degrees, Vector3.up) * camera.rotation;
- VRCameraMover.Instance.MoveTo(camera.position, newRotation, false);
- if (actInterpreter != null) actInterpreter.MovePlayerToCamera();
- }
-
- private void IfActionScene(Action a)
- {
- if (_Interpreter.SceneInterpreter is ActionSceneInterpreter actInterpreter) a(actInterpreter);
- }
- }
-}
diff --git a/MainGameVR/Controls/GameplayTool.cs b/MainGameVR/Controls/GameplayTool.cs
deleted file mode 100644
index 9de9614..0000000
--- a/MainGameVR/Controls/GameplayTool.cs
+++ /dev/null
@@ -1,335 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using KKS_VR.Interpreters;
-using KKS_VR.Settings;
-using UnityEngine;
-using UnityEngine.EventSystems;
-using Valve.VR;
-using VRGIN.Controls;
-using VRGIN.Controls.Tools;
-using VRGIN.Core;
-using VRGIN.Helpers;
-
-namespace KKS_VR.Controls
-{
- public class GameplayTool : Tool
- {
- private readonly Texture2D _hand1Texture = UnityHelper.LoadImage("icon_hand_1.png");
- private readonly Texture2D _hand2Texture = UnityHelper.LoadImage("icon_hand_2.png");
- private readonly Texture2D _handTexture = UnityHelper.LoadImage("icon_hand.png");
- private readonly Texture2D _image = new Texture2D(512, 512);
- private readonly Texture2D _school1Texture = UnityHelper.LoadImage("icon_school_1.png");
- private readonly Texture2D _school2Texture = UnityHelper.LoadImage("icon_school_2.png");
- private readonly Texture2D _schoolTexture = UnityHelper.LoadImage("icon_school.png");
-
- private MoveDirection? _touchDirection;
- private MoveDirection? _lastPressDirection;
-
- // When eneabled, exactly one of the below is non-null.
- private ButtonsSubtool _buttonsSubtool;
- private bool _InHScene;
- private KoikatuInterpreter _Interpreter;
- private KeySet _KeySet;
- private int _KeySetIndex;
- //private Controller.Lock _lock = VRGIN.Controls.Controller.Lock.Invalid;
- private KoikatuSettings _Settings;
-
- public override Texture2D Image => _image;
- private GrabAction _grab;
-
- private void ChangeKeySet()
- {
- var keySets = KeySets();
-
- _KeySetIndex = (_KeySetIndex + 1) % keySets.Count;
- _KeySet = keySets[_KeySetIndex];
- UpdateIcon();
- }
-
- private List KeySets()
- {
- return _InHScene ? _Settings.HKeySets : _Settings.KeySets;
- }
-
- private void ResetKeys()
- {
- SetScene(_InHScene);
- }
-
- private void SetScene(bool inHScene)
- {
- if (_buttonsSubtool != null)
- {
- _buttonsSubtool.Destroy();
- _buttonsSubtool = new ButtonsSubtool(_Interpreter, _Settings);
- }
-
- _InHScene = inHScene;
- var keySets = KeySets();
- _KeySetIndex = 0;
- _KeySet = keySets[0];
- UpdateIcon();
- }
-
- private void UpdateIcon()
- {
- var icon =
- _InHScene
- ? _Settings.HKeySets.Count > 1
- ? _KeySetIndex == 0
- ? _hand1Texture
- : _hand2Texture
- : _handTexture
- : _Settings.KeySets.Count > 1
- ? _KeySetIndex == 0
- ? _school1Texture
- : _school2Texture
- : _schoolTexture;
- Graphics.CopyTexture(icon, _image);
- }
-
- protected override void OnStart()
- {
- base.OnStart();
-
- _Settings = VR.Context.Settings as KoikatuSettings;
- SetScene(false);
- _Settings.AddListener("KeySets", (_, _1) => ResetKeys());
- _Settings.AddListener("HKeySets", (_, _1) => ResetKeys());
- }
-
- protected override void OnDestroy()
- {
- // nothing to do.
- }
-
- protected override void OnDisable()
- {
- _buttonsSubtool?.Destroy();
- _buttonsSubtool = null;
- _grab?.Destroy();
- _grab = null;
- //if (_lock.IsValid) _lock.Release();
- _touchDirection = null;
- _lastPressDirection = null;
- base.OnDisable();
- }
-
- protected override void OnEnable()
- {
- base.OnEnable();
- _Interpreter = VR.Interpreter as KoikatuInterpreter;
- _buttonsSubtool = new ButtonsSubtool(_Interpreter, _Settings);
- }
-
- protected override void OnUpdate()
- {
- base.OnUpdate();
-
- //UpdateLock();
-
- var inHScene = _Interpreter.CurrentScene == KoikatuInterpreter.SceneType.HScene;
- if (inHScene != _InHScene) SetScene(inHScene);
-
- if (_grab != null)
- {
- if (!_grab.HandleGrabbing())
- {
- _grab.Destroy();
- _grab = null;
- _buttonsSubtool = new ButtonsSubtool(_Interpreter, _Settings);
- }
- }
-
- if (_buttonsSubtool != null) HandleButtons();
- }
-
- //private void UpdateLock()
- //{
- // var wantLock = /*_grab != null ||*/ _buttonsSubtool?.WantLock() == true;
- // if (wantLock && !_lock.IsValid)
- // _lock = Owner.AcquireFocus( /*keepTool: true*/);
- // else if (!wantLock && _lock.IsValid) _lock.Release();
- //}
-
- private void HandleButtons()
- {
- var device = Controller;
-
- if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger)) InputDown(_KeySet.Trigger, EVRButtonId.k_EButton_SteamVR_Trigger);
-
- if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) InputUp(_KeySet.Trigger);
-
- if (device.GetPressDown(EVRButtonId.k_EButton_Grip)) InputDown(_KeySet.Grip, EVRButtonId.k_EButton_Grip);
-
- if (device.GetPressUp(EVRButtonId.k_EButton_Grip)) InputUp(_KeySet.Grip);
-
- if (device.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad))
- {
- var axis = Controller.GetAxis();
- var dir = GetTrackpadDirection(axis);
- var fun = GetTrackpadFunction(dir);
- if (RequiresPress(fun))
- {
- _lastPressDirection = dir;
- InputDown(fun, EVRButtonId.k_EButton_SteamVR_Touchpad);
- }
- }
-
- if (_buttonsSubtool == null) return;
-
- // 上げたときの位置によらず、押したボタンを離す
- // Release the pressed button regardless of the position when it is raised
- if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad) && _lastPressDirection.HasValue)
- {
- InputUp(GetTrackpadFunction(_lastPressDirection.Value));
- _lastPressDirection = null;
- }
-
- // Handle touchpad actions that don't require a press, only touch
- var newTouchDirection = device.GetTouch(EVRButtonId.k_EButton_SteamVR_Touchpad)
- ? GetTrackpadDirection(Controller.GetAxis())
- : (MoveDirection?)null;
- if (_touchDirection != newTouchDirection)
- {
- //Console.WriteLine("changed to " + newTouchDirection);
- if (_touchDirection.HasValue)
- {
- var oldFun = GetTrackpadFunction(_touchDirection.Value);
- if (!RequiresPress(oldFun))
- {
- //Console.WriteLine("up " + oldFun);
- InputUp(oldFun);
- }
- }
-
- if (newTouchDirection.HasValue)
- {
- var newFun = GetTrackpadFunction(newTouchDirection.Value);
- if (!RequiresPress(newFun))
- {
- //Console.WriteLine("down " + newFun);
- InputDown(newFun, EVRButtonId.k_EButton_SteamVR_Touchpad);
- }
- }
-
- _touchDirection = newTouchDirection;
- }
-
- _buttonsSubtool.Update();
- }
-
- private AssignableFunction GetTrackpadFunction(MoveDirection dir)
- {
- switch (dir)
- {
- case MoveDirection.Left: return _KeySet.Left;
- case MoveDirection.Up: return _KeySet.Up;
- case MoveDirection.Right: return _KeySet.Right;
- case MoveDirection.Down: return _KeySet.Down;
- case MoveDirection.None: return _KeySet.Center;
- default: throw new ArgumentOutOfRangeException();
- }
- }
-
- private static MoveDirection GetTrackpadDirection(Vector2 dir)
- {
- const float deadzone = 0.5f;
- var x = dir.x;
- var y = dir.y;
- if (Mathf.Abs(x) < deadzone && y > deadzone) return MoveDirection.Up;
- if (Mathf.Abs(x) < deadzone && y < -deadzone) return MoveDirection.Down;
- if (x < -deadzone && Mathf.Abs(y) < deadzone) return MoveDirection.Left;
- if (x > deadzone && Mathf.Abs(y) < deadzone) return MoveDirection.Right;
- return MoveDirection.None;
- }
-
- ///
- /// When this function is assigned to trackpad, does it require a press
- /// or does a touch suffice?
- ///
- private static bool RequiresPress(AssignableFunction fun)
- {
- switch (fun)
- {
- case AssignableFunction.SCROLLDOWN:
- case AssignableFunction.SCROLLUP:
- case AssignableFunction.LROTATION:
- case AssignableFunction.RROTATION:
- return false;
- default:
- return true;
- }
- }
-
- private void InputDown(AssignableFunction fun, EVRButtonId buttonMask)
- {
-
- switch (fun)
- {
- case AssignableFunction.NEXT:
- break;
- case AssignableFunction.GRAB:
- _buttonsSubtool.Destroy();
- _buttonsSubtool = null;
- _grab = new GrabAction(Owner, buttonMask);
- break;
-
- case AssignableFunction.SCROLLUP:
- case AssignableFunction.SCROLLDOWN:
- case AssignableFunction.LBUTTON:
- case AssignableFunction.MBUTTON:
- case AssignableFunction.RBUTTON:
- // Move the cursor to the bottom right corner so buttons/scrolling affect the H speed control
- // Extremely fiddly but what can you do
- if (_InHScene) VR.Input.Mouse.MoveMouseBy(Screen.width - 10, Screen.height - 10);
-
- // Force focus the window here so the cursor doesn't go off into the desktop or click the window that's currently on top of the game window
- WindowTools.BringWindowToFront();
- goto default;
-
- default:
- _buttonsSubtool.ButtonDown(fun);
- break;
- }
- }
-
- private void InputUp(AssignableFunction fun)
- {
- switch (fun)
- {
- case AssignableFunction.NEXT:
- ChangeKeySet();
- break;
- case AssignableFunction.GRAB:
- break;
- default:
- _buttonsSubtool.ButtonUp(fun);
- break;
- }
- }
-
- public override List GetHelpTexts()
- {
- return new List(new[]
- {
- ToolUtil.HelpTrigger(Owner, DescriptionFor(_KeySet.Trigger)),
- ToolUtil.HelpGrip(Owner, DescriptionFor(_KeySet.Grip)),
- ToolUtil.HelpTrackpadCenter(Owner, DescriptionFor(_KeySet.Center)),
- ToolUtil.HelpTrackpadLeft(Owner, DescriptionFor(_KeySet.Left)),
- ToolUtil.HelpTrackpadRight(Owner, DescriptionFor(_KeySet.Right)),
- ToolUtil.HelpTrackpadUp(Owner, DescriptionFor(_KeySet.Up)),
- ToolUtil.HelpTrackpadDown(Owner, DescriptionFor(_KeySet.Down))
- }.Where(x => x != null));
- }
-
- private static string DescriptionFor(AssignableFunction fun)
- {
- var member = typeof(AssignableFunction).GetMember(fun.ToString()).FirstOrDefault();
- var descr = member?.GetCustomAttributes(typeof(DescriptionAttribute), false).Cast().FirstOrDefault()?.Description;
- return descr ?? fun.ToString();
- }
- }
-}
diff --git a/MainGameVR/Controls/GrabAction.cs b/MainGameVR/Controls/GrabAction.cs
deleted file mode 100644
index 94f13cb..0000000
--- a/MainGameVR/Controls/GrabAction.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-using UnityEngine;
-using Valve.VR;
-using VRGIN.Controls;
-using VRGIN.Core;
-using VRGIN.Helpers;
-
-namespace KKS_VR.Controls
-{
- internal class GrabAction
- {
- private readonly Controller _controller;
- private readonly EVRButtonId _button;
-
- public GrabAction(Controller controller, EVRButtonId button)
- {
- _controller = controller;
- _button = button;
-
- _PrevControllerPos = controller.transform.position;
- _GripStartTime = Time.unscaledTime;
- _PrevControllerPos = controller.transform.position;
- _PrevControllerRot = controller.transform.rotation;
-
- _TravelRumble = new TravelDistanceRumble(500, 0.1f, controller.transform);
- _TravelRumble.UseLocalPosition = true;
- _TravelRumble.Reset();
- //controller.StartRumble(_TravelRumble);
- }
-
- public void Destroy()
- {
- _TravelRumble.Close();
- }
-
- //private PlayArea _ProspectedPlayArea = new PlayArea();
- private TravelDistanceRumble _TravelRumble;
- private float? _GripStartTime;
- private Vector3 _PrevControllerPos;
- private Quaternion _PrevControllerRot;
-
- public bool HandleGrabbing()
- {
- float? gripStartTime;
- float? nullable;
- var isPressed = _controller.Input.GetPress(_button);
- if (isPressed)
- {
- var vector3 = _controller.transform.position - _PrevControllerPos;
- var quaternion = Quaternion.Inverse(_PrevControllerRot * Quaternion.Inverse(_controller.transform.rotation)) *
- (_controller.transform.rotation * Quaternion.Inverse(_controller.transform.rotation));
- var unscaledTime = Time.unscaledTime;
- gripStartTime = _GripStartTime;
- nullable = unscaledTime - gripStartTime;
- if (nullable.GetValueOrDefault() > 0.1f & nullable.HasValue || Calculator.Distance(vector3.magnitude) > 0.01f)
- {
- var num2 = Calculator.Angle(Vector3.forward, quaternion * Vector3.forward) * VR.Settings.RotationMultiplier;
- VR.Camera.SteamCam.origin.transform.position -= vector3;
- //_ProspectedPlayArea.Height -= vector3.y;
- //if (!VR.Settings.GrabRotationImmediateMode && _controller.Input.GetPress(12884901888UL))
- //{
- // VR.Camera.SteamCam.origin.transform.RotateAround(VR.Camera.Head.position, Vector3.up, -num2);
- // //_ProspectedPlayArea.Rotation -= num2;
- //}
-
- _GripStartTime = 0.0f;
- }
- }
- if (_controller.Input.GetPressUp(_button))
- {
- //this.EnterState(WarpTool.WarpState.None);
- var unscaledTime = Time.unscaledTime;
- gripStartTime = _GripStartTime;
- nullable = unscaledTime - gripStartTime;
- var num = 0.1f;
- if (nullable.GetValueOrDefault() < num & nullable.HasValue)
- {
- _controller.StartRumble(new RumbleImpulse(800));
- //_ProspectedPlayArea.Height = 0.0f;
- //_ProspectedPlayArea.Scale = _IPDOnStart;
- }
- }/*
- if (VRGIN.Core.VR.Settings.GrabRotationImmediateMode && _controller.Input.GetPressUp(12884901888UL))
- {
- float angle = Calculator.Angle(Vector3.ProjectOnPlane(_controller.transform.position - VRGIN.Core.VR.Camera.Head.position, Vector3.up).normalized, Vector3.ProjectOnPlane(VRGIN.Core.VR.Camera.Head.forward, Vector3.up).normalized);
- VRGIN.Core.VR.Camera.SteamCam.origin.transform.RotateAround(VRGIN.Core.VR.Camera.Head.position, Vector3.up, angle);
- this._ProspectedPlayArea.Rotation = angle;
- }*/
- _PrevControllerPos = _controller.transform.position;
- _PrevControllerRot = _controller.transform.rotation;
- //this.CheckRotationalPress();
-
- return isPressed;
- }
-
- }
-}
diff --git a/MainGameVR/Controls/KoikatuWarpTool.cs b/MainGameVR/Controls/KoikatuWarpTool.cs
deleted file mode 100644
index f75139b..0000000
--- a/MainGameVR/Controls/KoikatuWarpTool.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System.Collections;
-using ActionGame.Chara;
-using KKS_VR.Camera;
-using KKS_VR.Interpreters;
-using KKS_VR.Settings;
-using UnityEngine;
-using VRGIN.Core;
-
-namespace KKS_VR.Controls
-{
- internal class KoikatuWarpTool : BetterWarpTool
- {
- private KoikatuInterpreter _interpreter;
- private GameObject _protagonistToFollow;
- private KoikatuSettings _settings;
-
- protected override void OnStart()
- {
- base.OnStart();
- _interpreter = VR.Interpreter as KoikatuInterpreter;
- _settings = VR.Settings as KoikatuSettings;
- }
-
- protected override void OnEnable()
- {
- base.OnEnable();
- VRCameraMover.Instance.OnMove += OnCameraMove;
- }
-
- protected override void OnDisable()
- {
- base.OnDisable();
- VRCameraMover.Instance.OnMove -= OnCameraMove;
- }
-
- protected override void OnUpdate()
- {
- var origin = VR.Camera.Origin;
- var oldOriginPosition = origin.position;
- var oldOriginRotation = origin.rotation;
-
- base.OnUpdate();
-
- // Detect teleporting in Roam mode.
- if (_settings.TeleportWithProtagonist &&
- (origin.position - oldOriginPosition).sqrMagnitude > 0.04f &&
- _interpreter.SceneInterpreter is ActionSceneInterpreter act &&
- GameObject.Find("ActionScene/Player") is GameObject player &&
- player.activeInHierarchy)
- {
- // It looks like we either just teleported or become upright.
- var diffRotation = origin.rotation * Quaternion.Inverse(oldOriginRotation);
- var nonHorizontal = Vector3.Angle(Vector3.up, diffRotation * Vector3.up);
- if (nonHorizontal < 0.1f)
- {
- // Looks like we teleported.
- act.MovePlayerToCamera();
- // We undo the camera movement because we want the actual
- // teleportation to happen after the game has a chance
- // to correct the protagonist's position.
- origin.SetPositionAndRotation(oldOriginPosition, oldOriginRotation);
- _protagonistToFollow = player;
- }
- }
- }
-
- protected override void OnLateUpdate()
- {
- base.OnLateUpdate();
- if (_protagonistToFollow != null)
- {
- var player = _protagonistToFollow.GetComponent();
- StartCoroutine(FollowDelayedCo(player));
- _protagonistToFollow = null;
- }
- }
-
-
- private IEnumerator FollowDelayedCo(Player player)
- {
- // Temporarily hide the protagonist.
- var oldActive = player.chaCtrl.objTop.activeSelf;
- player.chaCtrl.objTop.SetActive(false);
- // Wait for the game to correct the protagonist's position.
- yield return null;
- if (_interpreter.SceneInterpreter is ActionSceneInterpreter act)
- {
- VRLog.Debug("Following player");
- act.MoveCameraToPlayer();
- }
-
- player.chaCtrl.objTop.SetActive(oldActive);
- }
-
- private void OnCameraMove()
- {
- OnPlayAreaUpdated();
- }
- }
-}
diff --git a/MainGameVR/Controls/TalkSceneHandler.cs b/MainGameVR/Controls/TalkSceneHandler.cs
deleted file mode 100644
index 449efab..0000000
--- a/MainGameVR/Controls/TalkSceneHandler.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using HarmonyLib;
-using UnityEngine;
-using Valve.VR;
-using VRGIN.Controls;
-using VRGIN.Core;
-using VRGIN.Helpers;
-
-namespace KKS_VR.Controls
-{
- ///
- /// A handler component to be attached to a controller, providing touch/look
- /// functionalities in talk scenes.
- /// This component is meant to remain disabled outside talk scenes.
- ///
- internal class TalkSceneHandler : ProtectedBehaviour
- {
- private Controller _controller;
-
- private readonly HashSet _currentlyIntersecting
- = new HashSet();
-
- private Controller.Lock _lock; // null or valid
- private TalkScene _talkScene;
-
- protected override void OnStart()
- {
- base.OnStart();
-
- _controller = GetComponent();
- _talkScene = FindObjectOfType();
- if (_talkScene == null) VRLog.Warn("TalkSceneHandler: TalkScene not found");
- }
-
- protected void OnDisable()
- {
- _currentlyIntersecting.Clear();
- UpdateLock();
- }
-
- protected override void OnUpdate()
- {
- if (_lock != null) HandleTrigger();
- }
-
- private void HandleTrigger()
- {
- var device = _controller.Input; //SteamVR_Controller.Input((int)_controller.Tracking.index);
- if (device.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger)) PerformAction();
- }
-
- private void PerformAction()
- {
- // Find the nearest intersecting collider.
- var nearest = _currentlyIntersecting
- .OrderBy(_col => (_col.transform.position - transform.position).sqrMagnitude)
- .FirstOrDefault();
- if (nearest == null) return;
- var kind = Extensions.StripPrefix("Com/Hit/", nearest.tag);
- if (kind != null) new Traverse(_talkScene).Method("TouchFunc", new[] { typeof(string), typeof(Vector3) }).GetValue(kind, Vector3.zero);
- }
-
- protected void OnTriggerEnter(Collider other)
- {
- var wasIntersecting = _currentlyIntersecting.Count > 0;
- if (other.tag.StartsWith("Com/Hit/"))
- {
- _currentlyIntersecting.Add(other);
- if (!wasIntersecting) _controller.StartRumble(new RumbleImpulse(1000));
- UpdateLock();
- }
- }
-
- protected void OnTriggerExit(Collider other)
- {
- if (_currentlyIntersecting.Remove(other)) UpdateLock();
- }
-
- private void UpdateLock()
- {
- if (_currentlyIntersecting.Count > 0 && _lock == null)
- {
- _controller.TryAcquireFocus(out _lock);
- }
- else if (_currentlyIntersecting.Count == 0 && _lock != null)
- {
- _lock.Release();
- _lock = null;
- }
- }
- }
-}
diff --git a/MainGameVR/Features/VRFade.cs b/MainGameVR/Features/VRFade.cs
deleted file mode 100644
index 7f4e385..0000000
--- a/MainGameVR/Features/VRFade.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using System;
-using System.Collections;
-using ActionGame;
-using UnityEngine;
-using Valve.VR;
-using VRGIN.Core;
-
-namespace KKS_VR.Features
-{
- ///
- /// A VR fader that replaces the fader of the base game.
- ///
- internal class VRFade : ProtectedBehaviour
- {
- ///
- /// Reference to the image used by the vanilla SceneFade object.
- ///
- private CanvasGroup _vanillaFade;
-
- private readonly float _gridFadeTime = 1;
- private readonly float _fadeAlphaThresholdHigh = 0.9999f;
- private readonly float _fadeAlphaThresholdLow = 0.0001f;
-
- private bool _isFading;
-
- public static void Create()
- {
- VR.Camera.gameObject.AddComponent();
- }
-
- protected override void OnAwake()
- {
- _vanillaFade = Manager.Scene.sceneFadeCanvas?.canvasGroup ?? throw new ArgumentNullException(nameof(_vanillaFade), "sceneFadeCanvas or canvasGroup is null");
- }
-
- protected override void OnUpdate()
- {
- if (!_isFading && _vanillaFade && _vanillaFade.alpha > _fadeAlphaThresholdLow)
- {
- StartCoroutine(DeepFadeCo());
- }
- }
-
- ///
- /// A coroutine for entering "deep fade", where we cut to the compositor's grid and display some overlay.
- /// Based on https://github.com/mosirnik/KK_MainGameVR/commit/12e435f1e9a70c7d7b5dd56de416d300a2836091
- ///
- private IEnumerator DeepFadeCo()
- {
- if (OpenVR.Overlay == null || _isFading)
- yield break;
-
- _isFading = true;
-
- // Make the world outside of the game the same color as the loading screen instead of the headset default skybox
- SetCompositorSkyboxOverride(GetFadeColor());
-
- var compositor = OpenVR.Compositor;
- if (compositor != null)
- {
- // Fade the game out so the ouside world is now seen instead of the laggy loading screen
- compositor.FadeGrid(_gridFadeTime, true);
-
- // It looks like we need to pause rendering here, otherwise the
- // compositor will automatically put us back from the grid.
- SteamVR_Render.pauseRendering = true;
- }
-
- // Wait for the game to fully fade in
- while (_vanillaFade.alpha <= _fadeAlphaThresholdHigh)
- {
- if (!_vanillaFade || _vanillaFade.alpha < _fadeAlphaThresholdLow)
- goto endEarly;
-
- yield return null;
- }
-
- // Wait for the game to start fading out
- while (_vanillaFade.alpha > _fadeAlphaThresholdHigh)
- {
- yield return null;
- }
-
- // Wait for things to settle down
- yield return null;
- yield return null;
-
- endEarly:
-
- // Let the game be rendered again and fade into it
- SteamVR_Render.pauseRendering = false;
- if (compositor != null)
- {
- compositor.FadeGrid(_gridFadeTime, false);
- yield return new WaitForSeconds(_gridFadeTime);
- }
-
- // Wait for the game to finish fading to make sure we are synchronized
- while (_vanillaFade && _vanillaFade.alpha > _fadeAlphaThresholdLow)
- {
- yield return null;
- }
-
- SteamVR_Skybox.ClearOverride();
-
- _isFading = false;
- }
-
- private static Color GetFadeColor()
- {
- try
- {
- var cycle = FindObjectOfType();
- switch (cycle?.nowType)
- {
- default:
- case Cycle.Type.WakeUp:
- case Cycle.Type.Morning:
- case Cycle.Type.Daytime:
- return new Color(0.44f, 0.78f, 1f);
- case Cycle.Type.Evening:
- return new Color(0.85f, 0.50f, 0.37f);
- case Cycle.Type.Night:
- case Cycle.Type.GotoMyHouse:
- case Cycle.Type.MyHouse:
- return new Color(0.12f, 0.2f, 0.5f);
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e);
- return Color.white;
- }
- }
-
- private static void SetCompositorSkyboxOverride(Color fadeColor)
- {
- var tex = new Texture2D(1, 1);
- var color = fadeColor;
- color.a = 1f;
- tex.SetPixel(0, 0, color);
- tex.Apply();
- SteamVR_Skybox.SetOverride(tex, tex, tex, tex, tex, tex);
- Destroy(tex);
- }
- }
-}
diff --git a/MainGameVR/Fixes/GameFixes.cs b/MainGameVR/Fixes/GameFixes.cs
deleted file mode 100644
index 9a09f17..0000000
--- a/MainGameVR/Fixes/GameFixes.cs
+++ /dev/null
@@ -1,365 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Reflection;
-using System.Reflection.Emit;
-using ActionGame;
-using ADV;
-using Cysharp.Threading.Tasks;
-using HarmonyLib;
-using KKAPI.Utilities;
-using KKS_VR.Interpreters;
-using KKS_VR.Settings;
-using Sirenix.Serialization.Utilities;
-using StrayTech;
-using UnityEngine;
-using UnityStandardAssets.ImageEffects;
-using VRGIN.Core;
-using Object = UnityEngine.Object;
-
-/*
- * Fixes for issues that are in the base game but are only relevant in VR.
- */
-namespace KKS_VR.Fixes
-{
- ///
- /// Suppress character update for invisible characters in some sub-scenes of Roaming.
- ///
- [HarmonyPatch(typeof(ChaControl))]
- public class ChaControlPatches1
- {
- [HarmonyPrefix]
- [HarmonyPatch(nameof(ChaControl.LateUpdateForce))]
- private static bool PreLateUpdateForce(ChaControl __instance)
- {
- return !SafeToSkipUpdate(__instance);
- }
-
- [HarmonyPrefix]
- [HarmonyPatch(nameof(ChaControl.UpdateForce))]
- private static bool PreUpdateForce(ChaControl __instance)
- {
- return !SafeToSkipUpdate(__instance);
- }
-
- public static bool SafeToSkipUpdate(ChaControl control)
- {
- return
- VR.Settings is KoikatuSettings settings &&
- settings.OptimizeHInsideRoaming &&
- control.objTop?.activeSelf == false &&
- VR.Interpreter is KoikatuInterpreter interpreter &&
- (interpreter.CurrentScene == KoikatuInterpreter.SceneType.HScene ||
- interpreter.CurrentScene == KoikatuInterpreter.SceneType.TalkScene);
- }
- }
-
- ///
- /// Fix game crash during map load
- /// todo hack, handle properly?
- ///
- [HarmonyPatch(typeof(SunLightInfo))]
- public class FogHack1
- {
- [HarmonyFinalizer]
- [HarmonyPatch(nameof(SunLightInfo.Set))]
- private static Exception PreLateUpdateForce(Exception __exception)
- {
- if (__exception != null) VRPlugin.Logger.LogDebug("Caught expected crash: " + __exception);
- return null;
- }
- }
-
- ///
- /// Fix game crash during map load
- /// todo hack, handle properly?
- ///
- [HarmonyPatch(typeof(ActionMap))]
- public class FogHack2
- {
- // todo hack, handle properly
- [HarmonyFinalizer]
- [HarmonyPatch(nameof(ActionMap.UpdateCameraFog))]
- private static Exception PreLateUpdateForce(Exception __exception)
- {
- if (__exception != null) VRPlugin.Logger.LogDebug("Caught expected crash: " + __exception);
- return null;
- }
- }
-
- ///
- /// Fix game crash during ADV scene load
- ///
- [HarmonyPatch(typeof(Manager.Game))]
- public class ADVSceneFix1
- {
- [HarmonyPostfix]
- [HarmonyPatch(nameof(Manager.Game.cameraEffector), MethodType.Getter)]
- private static void FixMissingCameraEffector(Manager.Game __instance, ref CameraEffector __result)
- {
- if (__result == null && __instance.isCameraChanged)
- // vr camera doesn't have this component on it, which crashes game code with nullref. Use the component on original advcamera instead
- __instance._cameraEffector = __result = Object.FindObjectOfType();
- }
- }
-
- ///
- /// Fix being unable to do some actions in roaming mode
- ///
- [HarmonyPatch(typeof(CameraSystem))]
- public class ADVSceneFix2
- {
- [HarmonyPrefix]
- [HarmonyPatch(nameof(CameraSystem.SystemStatus), MethodType.Getter)]
- private static bool FixNeverEndingTransition(ref CameraSystem.CameraSystemStatus __result)
- {
- __result = CameraSystem.CameraSystemStatus.Inactive;
- return false;
- }
- }
-
- ///
- /// Fix ADV scenes messing with the VR camera by moving it or setting flags on it. Feed it the default 2D camera instead so it's happy.
- ///
- [HarmonyPatch]
- public class ADVSceneFix3
- {
- private static IEnumerable TargetMethods()
- {
- yield return CoroutineUtils.GetMoveNext(AccessTools.Method(typeof(TalkScene), nameof(TalkScene.Setup)));
- }
-
- private static UnityEngine.Camera GetOriginalMainCamera()
- {
- // vr camera doesn't have this component on it
- var originalMainCamera = (Manager.Game.instance.cameraEffector ?? Object.FindObjectOfType()).GetComponent();
- VRPlugin.Logger.LogDebug($"GetOriginalMainCamera called, cam found: {originalMainCamera?.GetFullPath()}\n{new StackTrace()}");
- return originalMainCamera;
- }
-
- private static IEnumerable Transpiler(IEnumerable insts, MethodBase __originalMethod)
- {
- var targert = AccessTools.PropertyGetter(typeof(UnityEngine.Camera), nameof(UnityEngine.Camera.main));
- var replacement = AccessTools.Method(typeof(ADVSceneFix3), nameof(GetOriginalMainCamera));
- return insts.Manipulator(
- instr => instr.opcode == OpCodes.Call && (MethodInfo)instr.operand == targert,
- instr =>
- {
- instr.operand = replacement;
- VRPlugin.Logger.LogDebug("Patched Camera.main in " + __originalMethod.GetNiceName());
- });
- }
- }
-
- ///
- /// Fix ADV scenes messing with the VR camera by moving it or setting flags on it. Feed it the default 2D camera instead so it's happy.
- ///
- [HarmonyPatch]
- public class ADVSceneFix4
- {
- private static IEnumerable TargetMethods()
- {
- yield return AccessTools.Method(typeof(ADVScene), nameof(ADVScene.Init));
- }
-
- private static UnityEngine.Camera GetOriginalMainCamera()
- {
- // vr camera doesn't have this component on it
- var originalMainCamera = (Manager.Game.instance.cameraEffector ?? Object.FindObjectOfType()).GetComponent();
- VRPlugin.Logger.LogDebug($"GetOriginalMainCamera called, cam found: {originalMainCamera?.GetFullPath()}\n{new StackTrace()}");
- return originalMainCamera;
- }
-
- private static IEnumerable Transpiler(IEnumerable insts, MethodBase __originalMethod)
- {
- var targert = AccessTools.PropertyGetter(typeof(UnityEngine.Camera), nameof(UnityEngine.Camera.main));
- var replacement = AccessTools.Method(typeof(ADVSceneFix4), nameof(GetOriginalMainCamera));
- return insts.Manipulator(
- instr => instr.opcode == OpCodes.Call && (MethodInfo)instr.operand == targert,
- instr =>
- {
- instr.operand = replacement;
- VRPlugin.Logger.LogDebug("Patched Camera.main in " + __originalMethod.GetNiceName());
- });
- }
-
- private static void Postfix(ADVScene __instance)
- {
- Manager.Sound.Listener = UnityEngine.Camera.main.transform;
- }
- }
-
- ///
- /// Fix vending machines and some other action points softlocking the game
- ///
- [HarmonyPatch(typeof(Manager.PlayerAction))]
- public class VendingMachineFix
- {
- [HarmonyTranspiler]
- [HarmonyPatch(nameof(Manager.PlayerAction.Action))]
- private static IEnumerable Transpiler(IEnumerable insts)
- {
- // Multiple methods get this crossFade field and try to fade on it. Problem is, it doesn't exist.
- // Instead of patching everything, create a dummy crossFade when it's being set
- var target = AccessTools.Field(typeof(Manager.PlayerAction), nameof(Manager.PlayerAction.crossFade));
- if (target == null) throw new ArgumentNullException(nameof(target));
- return new CodeMatcher(insts).MatchForward(false, new CodeMatch(OpCodes.Stfld, target))
- .ThrowIfInvalid("crossFade not found")
- .Insert(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(VendingMachineFix), nameof(VendingMachineFix.GiveDummyCrossFade))))
- .Instructions();
- }
-
- private static CrossFade _dummyCrossFade;
- private static CrossFade GiveDummyCrossFade(CrossFade existing)
- {
- if (existing) return existing;
-
- // To disable the fade texBase has to be null. texBase is set in Start so it's delayed from creation.
- if (!_dummyCrossFade)
- _dummyCrossFade = new GameObject("DummyCrossFade").AddComponent();
- else
- _dummyCrossFade.texBase = null;
-
- return _dummyCrossFade;
- }
- }
-
- ///
- /// Fix wrong position being sometimes set in TalkScene after introduction finishes
- ///
- [HarmonyPatch]
- public class TalkScenePostAdvFix
- {
- [HarmonyPostfix]
- [HarmonyPatch(typeof(TalkScene), nameof(TalkScene.Introduction), MethodType.Normal)]
- private static void IntroductionPostfix(TalkScene __instance, UniTask __result)
- {
- __instance.StartCoroutine(__result.WaitForFinishCo().AppendCo(() => TalkSceneInterpreter.AdjustPosition(__instance)));
- }
- }
-
- ///
- /// Fix crash when playing ADV scenes
- ///
- [HarmonyPatch]
- public class CycleCrossFadeFix1
- {
- private static IEnumerable TargetMethods()
- {
- yield return CoroutineUtils.GetMoveNext(AccessTools.Method(typeof(Cycle), nameof(Cycle.WakeUp)));
- }
-
- private static bool IsProcessWithNullcheck(CrossFade instance)
- {
- return instance != null && instance.isProcess;
- }
-
- private static IEnumerable Transpiler(IEnumerable insts, MethodBase __originalMethod)
- {
- var targert = AccessTools.PropertyGetter(typeof(CrossFade), nameof(CrossFade.isProcess));
- var replacement = AccessTools.Method(typeof(CycleCrossFadeFix1), nameof(IsProcessWithNullcheck));
- return insts.Manipulator(
- instr => instr.opcode == OpCodes.Callvirt && (MethodInfo)instr.operand == targert,
- instr =>
- {
- instr.opcode = OpCodes.Call;
- instr.operand = replacement;
- VRPlugin.Logger.LogDebug("Patched CrossFade.isProcess in " + __originalMethod.GetFullName());
- });
- }
- }
-
- ///
- /// Fix hscene killing the camera at end
- ///
- [HarmonyPatch]
- public class HSceneFix1
- {
- private static IEnumerable TargetMethods()
- {
- yield return CoroutineUtils.GetMoveNext(AccessTools.Method(typeof(HScene), nameof(HScene.Start)));
- yield return CoroutineUtils.GetMoveNext(AccessTools.Method(typeof(HScene), nameof(HScene.ResultTalk)));
- }
-
- private static UnityEngine.Camera GetOriginalMainCamera()
- {
- // vr camera doesn't have this component on it
- var originalMainCamera = (Manager.Game.instance.cameraEffector ?? Object.FindObjectOfType()).GetComponent();
- VRPlugin.Logger.LogDebug($"GetOriginalMainCamera called, cam found: {originalMainCamera?.GetFullPath()}\n{new StackTrace()}");
- return originalMainCamera;
- }
-
- private static IEnumerable Transpiler(IEnumerable insts, MethodBase __originalMethod)
- {
- var targert = AccessTools.PropertyGetter(typeof(UnityEngine.Camera), nameof(UnityEngine.Camera.main));
-
- VRPlugin.Logger.LogDebug("Patching Camera.main -> null in " + __originalMethod.GetNiceName());
-
- // Change Camera.main property get to return null instead to skip code that messes with player camera.
- // Only last instance needs to be patched or HScene.ResultTalk will break.
- return new CodeMatcher(insts).End()
- .MatchBack(false, new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(UnityEngine.Camera), nameof(UnityEngine.Camera.main))))
- .ThrowIfInvalid("Camera.main not found in " + __originalMethod.GetNiceName())
- .Set(OpCodes.Ldnull, null)
- .Instructions();
- }
- }
- ///
- /// Fix hscene killing the camera at end
- ///
- [HarmonyPatch(typeof(HScene))]
- public class HSceneFix2
- {
- [HarmonyPrefix]
- [HarmonyPatch(nameof(HScene.HResultADVCameraSetting), MethodType.Normal)]
- private static bool SkipCameraSetup()
- {
- VRPlugin.Logger.LogDebug("Skipping HScene.HResultADVCameraSetting");
- return false;
- }
- }
-
- ///
- /// Fix mainly for character maker, the mask doesn't work properly in VR and goes all over the place.
- /// This removes the mask and applies the amplify effect to the whole camera, with downside of darkening the UI.
- /// This component also exists in some places in main game, but it seems like this patch has no ill effects related to that.
- ///
- [HarmonyPatch(typeof(CameraEffectorColorMask))]
- public class CameraEffectorColorMaskFix
- {
- [HarmonyPrefix]
- [HarmonyPatch(nameof(CameraEffectorColorMask.Awake), MethodType.Normal)]
- private static bool SkipCameraSetup(CameraEffectorColorMask __instance)
- {
- VRPlugin.Logger.LogDebug("Skipping CameraEffectorColorMask.Awake and destroying the component");
- GameObject.Destroy(__instance);
- return false;
- }
- }
-
- ///
- /// The game includes an old version of GlobalFog, which assumes that the
- /// viewing frustum is always centered at the camera. This assumption is
- /// invalid in VR, so we fix it up here.
- ///
- [HarmonyPatch(typeof(GlobalFog))]
- public class GlobalFogPatches
- {
- [HarmonyPatch(nameof(GlobalFog.CustomGraphicsBlit))]
- [HarmonyPrefix]
- private static void PreCustomGraphicsBlit(Material fxMaterial)
- {
- UnityEngine.Camera camera = UnityEngine.Camera.current;
- camera.CalculateFrustumCorners(
- new Rect(0, 0, 1, 1), camera.farClipPlane, camera.stereoActiveEye, _frustumBuffer);
- Matrix4x4 corners = Matrix4x4.zero;
- corners.SetRow(0, camera.transform.TransformDirection(_frustumBuffer[1]));
- corners.SetRow(1, camera.transform.TransformDirection(_frustumBuffer[2]));
- corners.SetRow(2, camera.transform.TransformDirection(_frustumBuffer[3]));
- corners.SetRow(3, camera.transform.TransformDirection(_frustumBuffer[0]));
- fxMaterial.SetMatrix("_FrustumCornersWS", corners);
- }
-
- static readonly Vector3[] _frustumBuffer = new Vector3[4];
- }
-}
diff --git a/MainGameVR/Fixes/Mirror/mirror-shader b/MainGameVR/Fixes/Mirror/mirror-shader
deleted file mode 100644
index 05ef3d1..0000000
Binary files a/MainGameVR/Fixes/Mirror/mirror-shader and /dev/null differ
diff --git a/MainGameVR/Fixes/ReduceAssetUnloads.cs b/MainGameVR/Fixes/ReduceAssetUnloads.cs
deleted file mode 100644
index 466dd90..0000000
--- a/MainGameVR/Fixes/ReduceAssetUnloads.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
-using HarmonyLib;
-using KKAPI.Utilities;
-using Sirenix.Serialization.Utilities;
-using UnityEngine;
-using VRGIN.Core;
-
-namespace KKS_VR.Fixes
-{
- ///
- /// Avoid triggering resource unload when loading UI-only scenes.
- /// todo move into illusionfixes?
- ///
- [HarmonyPatch]
- public class ReduceAssetUnloads
- {
- private static IEnumerable TargetMethods()
- {
- yield return CoroutineUtils.GetMoveNext(AccessTools.Method(typeof(Manager.Scene), nameof(Manager.Scene.LoadStart)));
- }
-
- private static AsyncOperation MaybeUnloadUnusedAssets()
- {
- var shouldUnload = Manager.Scene.IsFadeNow;
- if (shouldUnload)
- {
- return Resources.UnloadUnusedAssets();
- }
- else
- {
- VRLog.Info("Skipping unload");
- return null;
- }
- }
-
- private static IEnumerable Transpiler(IEnumerable insts, MethodBase __originalMethod)
- {
- foreach (var inst in insts)
- if (inst.opcode == OpCodes.Call &&
- inst.operand is MethodInfo method &&
- method.Name == "UnloadUnusedAssets")
- {
- yield return CodeInstruction.Call(() => MaybeUnloadUnusedAssets());
- VRPlugin.Logger.LogDebug("Patched UnloadUnusedAssets in " + __originalMethod.GetFullName());
- }
- else
- {
- yield return inst;
- }
- }
- }
-}
diff --git a/MainGameVR/Interpreters/ActionSceneInterpreter.cs b/MainGameVR/Interpreters/ActionSceneInterpreter.cs
deleted file mode 100644
index 1317aa5..0000000
--- a/MainGameVR/Interpreters/ActionSceneInterpreter.cs
+++ /dev/null
@@ -1,224 +0,0 @@
-using KKS_VR.Camera;
-using KKS_VR.Features;
-using KKS_VR.Settings;
-using StrayTech;
-using UnityEngine;
-using VRGIN.Core;
-using WindowsInput.Native;
-
-namespace KKS_VR.Interpreters
-{
- internal class ActionSceneInterpreter : SceneInterpreter
- {
- private KoikatuSettings _Settings;
- private ActionScene _ActionScene;
-
- private GameObject _Map;
- private GameObject _CameraSystem;
- private bool _NeedsResetCamera;
- private bool _IsStanding = true;
- private bool _Walking = false;
- private bool _Dashing = false; // ダッシュ時は_Walkingと両方trueになる
-
- public override void OnStart()
- {
- VRLog.Info("ActionScene OnStart");
-
- _Settings = VR.Context.Settings as KoikatuSettings;
- _ActionScene = Object.FindObjectOfType();
-
- ResetState();
- HoldCamera();
- }
-
- public override void OnDisable()
- {
- VRLog.Info("ActionScene OnDisable");
-
- ResetState();
- ReleaseCamera();
- }
-
- private void ResetState()
- {
- VRLog.Info("ActionScene ResetState");
-
- StandUp();
- StopWalking();
- _NeedsResetCamera = false;
- }
-
- private void ResetCamera()
- {
- var pl = _ActionScene.Player?.chaCtrl.objTop;
-
- if (pl != null && pl.activeSelf)
- {
- _CameraSystem = MonoBehaviourSingleton.Instance.gameObject;
-
- // トイレなどでFPS視点になっている場合にTPS視点に戻す
- _CameraSystem.GetComponent().ModeChangeForce((ActionGame.CameraMode?)ActionGame.CameraMode.TPS, true);
- //scene.GetComponent().isCursorLock = false;
-
- // カメラをプレイヤーの位置に移動
- MoveCameraToPlayer();
-
- _NeedsResetCamera = false;
- VRLog.Info("ResetCamera succeeded");
- }
- }
-
- private void HoldCamera()
- {
- VRLog.Info("ActionScene HoldCamera");
-
- _CameraSystem = MonoBehaviourSingleton.Instance.gameObject;
-
- if (_CameraSystem != null)
- {
- _CameraSystem.SetActive(false);
-
- VRLog.Info("succeeded");
- }
- }
-
- private void ReleaseCamera()
- {
- VRLog.Info("ActionScene ReleaseCamera");
-
- if (_CameraSystem != null)
- {
- _CameraSystem.SetActive(true);
-
- VRLog.Info("succeeded");
- }
- }
-
- public override void OnUpdate()
- {
- var map = _ActionScene.Map.mapRoot?.gameObject;
-
- if (map != _Map)
- {
- VRLog.Info("! map changed.");
-
- ResetState();
- _Map = map;
- _NeedsResetCamera = true;
- }
-
- if (_Walking) MoveCameraToPlayer(true, true);
-
- if (_NeedsResetCamera) ResetCamera();
-
- UpdateCrouch();
- }
-
- private void UpdateCrouch()
- {
- var pl = _ActionScene.Player?.chaCtrl.objTop;
-
- if (_Settings.CrouchByHMDPos && pl?.activeInHierarchy == true)
- {
- var cam = VR.Camera.transform;
- var delta_y = cam.position.y - pl.transform.position.y;
-
- if (_IsStanding && delta_y < _Settings.CrouchThreshold)
- Crouch();
- else if (!_IsStanding && delta_y > _Settings.StandUpThreshold) StandUp();
- }
- }
-
- public void MoveCameraToPlayer(bool onlyPosition = false, bool quiet = false)
- {
- var player = _ActionScene.Player;
-
- var playerHead = player.chaCtrl.objHead.transform;
- var headCam = VR.Camera.transform;
-
- var cf = Vector3.Scale(player.transform.forward, new Vector3(1, 0, 1)).normalized;
-
- Vector3 pos;
- if (_Settings.UsingHeadPos)
- {
- pos = playerHead.position;
- }
- else
- {
- pos = player.position;
- pos.y += _IsStanding ? _Settings.StandingCameraPos : _Settings.CrouchingCameraPos;
- }
-
- VRCameraMover.Instance.MoveTo(
- pos + cf * 0.23f, // 首が見えるとうざいのでほんの少し前目にする
- onlyPosition ? headCam.rotation : player.rotation,
- false,
- quiet);
- }
-
- public void MovePlayerToCamera(bool onlyRotation = false)
- {
- var player = _ActionScene.Player;
- var playerHead = player.chaCtrl.objHead.transform;
- var headCam = VR.Camera.transform;
-
- var pos = headCam.position;
- pos.y += player.position.y - playerHead.position.y;
-
- var delta_y = headCam.rotation.eulerAngles.y - player.rotation.eulerAngles.y;
- player.transform.Rotate(Vector3.up * delta_y);
- var cf = Vector3.Scale(player.transform.forward, new Vector3(1, 0, 1)).normalized;
-
- if (!onlyRotation) player.position = pos - cf * 0.1f;
- }
-
- public void Crouch()
- {
- if (_IsStanding)
- {
- _IsStanding = false;
- VR.Input.Keyboard.KeyDown(VirtualKeyCode.VK_Z);
- }
- }
-
- public void StandUp()
- {
- if (!_IsStanding)
- {
- _IsStanding = true;
- VR.Input.Keyboard.KeyUp(VirtualKeyCode.VK_Z);
- }
- }
-
- public void StartWalking(bool dash = false)
- {
- MovePlayerToCamera(true);
-
- if (!dash)
- {
- VR.Input.Keyboard.KeyDown(VirtualKeyCode.LSHIFT);
- _Dashing = true;
- }
-
- VR.Input.Mouse.LeftButtonDown();
- _Walking = true;
- // Force hide the protagonist's head while walking, so that it
- // remains hidden when the game lags.
- HideMaleHead.ForceHideHead = true;
- }
-
- public void StopWalking()
- {
- VR.Input.Mouse.LeftButtonUp();
-
- if (_Dashing)
- {
- VR.Input.Keyboard.KeyUp(VirtualKeyCode.LSHIFT);
- _Dashing = false;
- }
-
- _Walking = false;
- HideMaleHead.ForceHideHead = false;
- }
- }
-}
diff --git a/MainGameVR/Interpreters/CustomSceneInterpreter.cs b/MainGameVR/Interpreters/CustomSceneInterpreter.cs
deleted file mode 100644
index 243b9bd..0000000
--- a/MainGameVR/Interpreters/CustomSceneInterpreter.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace KKS_VR.Interpreters
-{
- internal class CustomSceneInterpreter : SceneInterpreter
- {
- public override void OnStart()
- {
- }
-
- public override void OnDisable()
- {
- // nothing to do.
- }
-
- public override void OnUpdate()
- {
- }
- }
-}
diff --git a/MainGameVR/Interpreters/HSceneInterpreter.cs b/MainGameVR/Interpreters/HSceneInterpreter.cs
deleted file mode 100644
index 223f982..0000000
--- a/MainGameVR/Interpreters/HSceneInterpreter.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using UnityEngine;
-using VRGIN.Core;
-
-namespace KKS_VR.Interpreters
-{
- internal class HSceneInterpreter : SceneInterpreter
- {
- private bool _active;
- private HSceneProc _proc;
- private Caress.VRMouth _vrMouth;
- private Caress.CaressController _leftController;
- private Caress.CaressController _rightController;
- private Camera.POV _pov;
-
- private Color _currentBackgroundColor;
- private bool _currentShowMap;
-
- public override void OnStart()
- {
- _leftController = VR.Mode.Left.gameObject.AddComponent();
- _rightController = VR.Mode.Right.gameObject.AddComponent();
- _pov = VR.Camera.gameObject.AddComponent();
- _pov.Initialize(_leftController.getController(), _rightController.getController());
- _currentBackgroundColor = Manager.Config.HData.BackColor;
- _currentShowMap = Manager.Config.HData.Map;
- UpdateCameraState();
- }
-
- public override void OnDisable()
- {
- Deactivate();
- Object.Destroy(_pov);
- Object.Destroy(_leftController);
- Object.Destroy(_rightController);
- }
-
- public override void OnUpdate()
- {
- if (_currentShowMap != Manager.Config.HData.Map || _currentBackgroundColor != Manager.Config.HData.BackColor)
- {
- if (!_active || !_pov.IsActive())
- UpdateCameraState();
- }
-
- if (_active && (!_proc || !_proc.enabled))
- {
- // The HProc scene is over, but there may be one more coming.
- Deactivate();
- }
-
- if (!_active &&
- Manager.Scene.GetRootComponent("HProc") is HSceneProc proc &&
- proc.enabled)
- {
- _vrMouth = VR.Camera.gameObject.AddComponent();
- _proc = proc;
- _active = true;
- }
- }
-
- private void Deactivate()
- {
- if (_active)
- {
- VR.Camera.SteamCam.camera.clearFlags = CameraClearFlags.Skybox;
- Object.Destroy(_vrMouth);
- _proc = null;
- _active = false;
- }
- }
-
- private void UpdateCameraState()
- {
- if (!Manager.Config.HData.Map)
- {
- VR.Camera.SteamCam.camera.backgroundColor = Manager.Config.HData.BackColor;
- VR.Camera.SteamCam.camera.clearFlags = CameraClearFlags.SolidColor;
- }
- else
- {
- VR.Camera.SteamCam.camera.clearFlags = CameraClearFlags.Skybox;
- }
- _currentBackgroundColor = Manager.Config.HData.BackColor;
- _currentShowMap = Manager.Config.HData.Map;
- }
- }
-}
diff --git a/MainGameVR/Interpreters/KoikatuGameInterpreter.cs b/MainGameVR/Interpreters/KoikatuGameInterpreter.cs
deleted file mode 100644
index 2e5c0d5..0000000
--- a/MainGameVR/Interpreters/KoikatuGameInterpreter.cs
+++ /dev/null
@@ -1,302 +0,0 @@
-using System;
-using System.Collections;
-using Funly.SkyStudio;
-using KKAPI.MainGame;
-using KKAPI.Maker;
-using KKS_VR.Camera;
-using KKS_VR.Features;
-using UnityEngine;
-using UnityEngine.SceneManagement;
-using VRGIN.Core;
-
-namespace KKS_VR.Interpreters
-{
- internal class KoikatuInterpreter : GameInterpreter
- {
- public enum SceneType
- {
- OtherScene,
- ActionScene,
- TalkScene,
- HScene,
- NightMenuScene,
- CustomScene
- }
-
- public SceneType CurrentScene { get; private set; }
- public SceneInterpreter SceneInterpreter;
-
- private Fixes.Mirror.Manager _mirrorManager;
- private int _kkapiCanvasHackWait;
- private Canvas _kkSubtitlesCaption;
- private GameObject _sceneObjCache;
-
- protected override void OnAwake()
- {
- base.OnAwake();
-
- CurrentScene = SceneType.OtherScene;
- SceneInterpreter = new OtherSceneInterpreter();
- SceneManager.sceneLoaded += OnSceneLoaded;
- _mirrorManager = new Fixes.Mirror.Manager();
- VR.Camera.gameObject.AddComponent();
- }
-
- protected override void OnUpdate()
- {
- base.OnUpdate();
-
- UpdateScene();
- SceneInterpreter.OnUpdate();
- }
-
- protected override void OnLateUpdate()
- {
- base.OnLateUpdate();
- if (_kkSubtitlesCaption != null) FixupKkSubtitles();
- }
-
- private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
- {
- foreach (var reflection in FindObjectsOfType()) _mirrorManager.Fix(reflection);
-
- if (scene.name == "Title" || scene.name == "FreeH" || scene.name == "Uploader" || scene.name == "Downloader")
- LoadTitleSkybox();
- }
-
- private static void LoadTitleSkybox()
- {
- if (GameObject.FindObjectOfType()) return;
-
- try
- {
- var stockSkyProfiles = new string[]
- {
- "_morning_stu",
- "_daytime_stu",
- "_evening_stu",
- "_night_stu",
- };
- // Use either day or night skybox depending on real world time to reduce eye abuse at night
- // morning and evening skyboxes are not worth using for title screen
- var timeNow = DateTime.Now;
- var isNight = timeNow.Hour < 6 || timeNow.Hour > 20;
- var skyType = isNight ? stockSkyProfiles[3] : stockSkyProfiles[1];
- // var skyType = stockSkyProfiles[UnityEngine.Random.RandomRangeInt(0, stockSkyProfiles.Length)];
-
- VRLog.Info($"Loading skybox {skyType}...");
-
- var skyProfile = CommonLib.LoadAsset(@"studio\sky\01.unity3d", "SkyProfile" + skyType, true, null, true);
- var skyMaterial = CommonLib.LoadAsset(@"studio\sky\01.unity3d", "SkyboxMaterial" + skyType, true, null, true);
- if (skyProfile != null && skyMaterial != null)
- {
- VRLog.Info($"SkyProfile: {skyProfile} SkyboxMaterial: {skyMaterial}");
-
- var instanceGameObject = new GameObject("KKSVR_Skybox");
- var skyController = instanceGameObject.AddComponent();
-
- // Need to add dummy sun and mun objects or the controller will refuse to work
- var sun = new GameObject("Sun");
- sun.transform.parent = instanceGameObject.transform;
- new GameObject("Position", typeof(RotateBody)).transform.parent = sun.transform;
- skyController.sunOrbit = sun.AddComponent();
-
- var mun = new GameObject("Moon");
- mun.transform.parent = instanceGameObject.transform;
- new GameObject("Position", typeof(RotateBody)).transform.parent = mun.transform;
- skyController.moonOrbit = mun.AddComponent();
-
- // For some reason the profile doesn't come with the material, which is required
- skyProfile.skyboxMaterial = skyMaterial;
- // This applies the skybox right away
- skyController.skyProfile = skyProfile;
- }
- else
- {
- VRLog.Warn("Skybox not found! Missing CharaStudio assets?");
- }
- }
- catch (Exception e)
- {
- VRLog.Error("Failed to load Skybox! Error: " + e);
- }
- }
-
- ///
- /// Fix up scaling of subtitles added by KK_Subtitles. See
- /// https://github.com/IllusionMods/KK_Plugins/pull/91 for details.
- ///
- private void FixupKkSubtitles()
- {
- foreach (Transform child in _kkSubtitlesCaption.transform)
- if (child.localScale != Vector3.one)
- {
- VRLog.Info($"Fixing up scale for {child}");
- child.localScale = Vector3.one;
- }
- }
-
- public override bool IsIgnoredCanvas(Canvas canvas)
- {
- if (PrivacyScreen.IsOwnedCanvas(canvas))
- {
- return true;
- }
- else if (canvas.name == "Canvas_BackGround")
- {
- BackgroundDisplayer.Instance.TakeCanvas(canvas);
- return true;
- }
- else if (canvas.name == "CvsMenuTree")
- {
- // Here, we attempt to avoid some unfortunate conflict with
- // KKAPI.
- //
- // In order to support plugin-defined subcategories in Maker,
- // KKAPI clones some UI elements out of CvsMenuTree when the
- // canvas is created, then uses them as templates for custom
- // UI items.
- //
- // At the same time, VRGIN attempts to claim the canvas by
- // setting its mode to ScreenSpaceCamera, which changes
- // localScale of the canvas by a factor of 100 or so. If this
- // happens between KKAPI's cloning out and cloning in, the
- // resulting UI items will have the wrong scale, 72x the correct
- // size to be precise.
- //
- // So our solution here is to hide the canvas from VRGIN for a
- // couple of frames. Crude but works.
-
- if (_kkapiCanvasHackWait == 0)
- {
- _kkapiCanvasHackWait = 3;
- return true;
- }
- else
- {
- _kkapiCanvasHackWait -= 1;
- return 0 < _kkapiCanvasHackWait;
- }
- }
- else if (canvas.name == "KK_Subtitles_Caption")
- {
- _kkSubtitlesCaption = canvas;
- }
-
- return false;
- }
-
- // 前回とSceneが変わっていれば切り替え処理をする
- private void UpdateScene()
- {
- var nextSceneType = DetectScene();
-
- if (nextSceneType != CurrentScene)
- {
- VRLog.Info($"Load interpreter for new scene type: {nextSceneType}");
- SceneInterpreter.OnDisable();
-
- CurrentScene = nextSceneType;
- SceneInterpreter = CreateSceneInterpreter(nextSceneType);
- SceneInterpreter.OnStart();
- }
- }
-
- private SceneType DetectScene()
- {
- if (GameAPI.InsideHScene) return SceneType.HScene;
- if (MakerAPI.InsideMaker) return SceneType.CustomScene;
- if (TalkScene.isPaly) return SceneType.TalkScene;
-
- var stack = Manager.Scene.NowSceneNames;
- foreach (var name in stack)
- {
- //if (name == "H" && SceneObjPresent("HScene"))
- // return SceneType.HScene;
- if (ActionScene.initialized && name == "Action")
- return SceneType.ActionScene;
- //if (name == "Talk" && SceneObjPresent("TalkScene"))
- // return SceneType.TalkScene;
- if (name == "NightMenu" && SceneObjPresent("NightMenuScene"))
- return SceneType.NightMenuScene;
- //if (name == "CustomScene" && SceneObjPresent("CustomScene"))
- // return SceneType.CustomScene;
- }
-
- return SceneType.OtherScene;
- }
-
- private bool SceneObjPresent(string name)
- {
- if (_sceneObjCache != null && _sceneObjCache.name == name) return true;
- var obj = GameObject.Find(name);
- if (obj != null)
- {
- _sceneObjCache = obj;
- return true;
- }
-
- return false;
- }
-
- private static SceneInterpreter CreateSceneInterpreter(SceneType ty)
- {
- switch (ty)
- {
- case SceneType.OtherScene:
- return new OtherSceneInterpreter();
- case SceneType.ActionScene:
- return new ActionSceneInterpreter();
- case SceneType.CustomScene:
- return new CustomSceneInterpreter();
- case SceneType.NightMenuScene:
- return new NightMenuSceneInterpreter();
- case SceneType.HScene:
- return new HSceneInterpreter();
- case SceneType.TalkScene:
- return new TalkSceneInterpreter();
- default:
- VRLog.Warn($"Unknown scene type: {ty}");
- return new OtherSceneInterpreter();
- }
- }
-
- protected override CameraJudgement JudgeCameraInternal(UnityEngine.Camera camera)
- {
- if (camera.CompareTag("MainCamera")) StartCoroutine(HandleMainCameraCo(camera));
- return base.JudgeCameraInternal(camera);
- }
-
- ///
- /// A coroutine to be called when a new main camera is detected.
- ///
- ///
- ///
- private IEnumerator HandleMainCameraCo(UnityEngine.Camera camera)
- {
- // Unity might have messed with the camera transform for this frame,
- // so we wait for the next frame to get clean data.
- yield return null;
-
- if (camera.name == "ActionCamera" || camera.name == "FrontCamera")
- {
- VRLog.Info("Adding ActionCameraControl");
- camera.gameObject.AddComponent();
- }
- else if (camera.GetComponent() != null)
- {
- VRLog.Info("New main camera detected: moving to {0} {1}", camera.transform.position, camera.transform.eulerAngles);
- VRCameraMover.Instance.MoveTo(camera.transform.position, camera.transform.rotation, false);
- VRLog.Info("moved to {0} {1}", VR.Camera.Head.position, VR.Camera.Head.eulerAngles);
- VRLog.Info("Adding CameraControlControl");
- camera.gameObject.AddComponent();
- }
- else
- {
- VRLog.Warn($"Unknown kind of main camera was added: {camera.name}");
- }
- }
-
- //public override bool ApplicationIsQuitting => Manager.Scene.isGameEnd;
- }
-}
diff --git a/MainGameVR/Interpreters/NightMenuSceneInterpreter.cs b/MainGameVR/Interpreters/NightMenuSceneInterpreter.cs
deleted file mode 100644
index 0737671..0000000
--- a/MainGameVR/Interpreters/NightMenuSceneInterpreter.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace KKS_VR.Interpreters
-{
- internal class NightMenuSceneInterpreter : SceneInterpreter
- {
- public override void OnStart()
- {
- }
-
- public override void OnDisable()
- {
- // nothing to do.
- }
-
- public override void OnUpdate()
- {
- // nothing to do.
- }
- }
-}
diff --git a/MainGameVR/Interpreters/OtherSceneInterpreter.cs b/MainGameVR/Interpreters/OtherSceneInterpreter.cs
deleted file mode 100644
index fcdbad1..0000000
--- a/MainGameVR/Interpreters/OtherSceneInterpreter.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-namespace KKS_VR.Interpreters
-{
- internal class OtherSceneInterpreter : SceneInterpreter
- {
- public override void OnStart()
- {
- // nothing to do.
- }
-
- public override void OnDisable()
- {
- // nothing to do.
- }
-
- public override void OnUpdate()
- {
- // nothing to do.
- }
- }
-}
diff --git a/MainGameVR/Interpreters/SceneInterpreter.cs b/MainGameVR/Interpreters/SceneInterpreter.cs
deleted file mode 100644
index fdcced2..0000000
--- a/MainGameVR/Interpreters/SceneInterpreter.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using UnityEngine;
-using VRGIN.Core;
-
-namespace KKS_VR.Interpreters
-{
- internal abstract class SceneInterpreter
- {
- public abstract void OnStart();
- public abstract void OnDisable();
- public abstract void OnUpdate();
-
- protected void AddControllerComponent()
- where T : Component
- {
- VR.Mode.Left.gameObject.AddComponent();
- VR.Mode.Right.gameObject.AddComponent();
- }
-
- protected void DestroyControllerComponent()
- where T : Component
- {
- var left = VR.Mode.Left.GetComponent();
- if (left != null) Object.Destroy(left);
- var right = VR.Mode.Right.GetComponent();
- if (right != null) Object.Destroy(right);
- }
- }
-}
diff --git a/MainGameVR/Interpreters/TalkSceneInterpreter.cs b/MainGameVR/Interpreters/TalkSceneInterpreter.cs
deleted file mode 100644
index 302a92d..0000000
--- a/MainGameVR/Interpreters/TalkSceneInterpreter.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-using Illusion.Extensions;
-using KKS_VR.Camera;
-using UnityEngine;
-using VRGIN.Core;
-
-namespace KKS_VR.Interpreters
-{
- internal class TalkSceneInterpreter : SceneInterpreter
- {
- private Canvas _canvasBack;
- public static float TalkDistance = 0.65f;
-
- public override void OnDisable()
- {
- DestroyControllerComponent();
- if (_canvasBack != null) _canvasBack.enabled = true;
- }
-
- public override void OnStart()
- {
- AddControllerComponent();
-
- if (!TalkScene.initialized)
- {
- VRLog.Warn("TalkScene object not found");
- return;
- }
-
- VRLog.Warn("TalkScene init");
-
- var talkScene = TalkScene.instance;
-
- talkScene.otherInitialize += () =>
- {
- VRLog.Warn("talkScene.otherInitialize");
-
- AdjustPosition(talkScene);
-
- // talkscene messes with camera settings
- UnityEngine.Camera.main.clearFlags = CameraClearFlags.Skybox;
-
- talkScene.backGround.visible = false;
- talkScene.canvasBack.gameObject.SetActiveIfDifferent(false);
- };
-
- _canvasBack = talkScene.canvasBack;
- }
-
- public static void AdjustPosition(TalkScene talkScene)
- {
- if (talkScene == null) return;
-
- // The default camera location is a bit too far for a friendly
- // conversation.
- var heroine = talkScene.targetHeroine.transform;
- VRCameraMover.Instance.MoveTo(
- heroine.TransformPoint(new Vector3(0, ActionCameraControl.GetPlayerHeight(), TalkDistance)),
- heroine.rotation * Quaternion.Euler(0, 180f, 0),
- false);
- }
-
- public override void OnUpdate()
- {
- // We don't need the background image because we directly see
- // background objects.
- if (_canvasBack != null) _canvasBack.enabled = false;
- }
- }
-}
diff --git a/MainGameVR/MainGameVR.csproj.DotSettings b/MainGameVR/MainGameVR.csproj.DotSettings
deleted file mode 100644
index 3439569..0000000
--- a/MainGameVR/MainGameVR.csproj.DotSettings
+++ /dev/null
@@ -1,2 +0,0 @@
-
- True
\ No newline at end of file
diff --git a/MainGameVR/RobustInputSimulator.cs b/MainGameVR/RobustInputSimulator.cs
deleted file mode 100644
index 94fe0db..0000000
--- a/MainGameVR/RobustInputSimulator.cs
+++ /dev/null
@@ -1,459 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using WindowsInput;
-using WindowsInput.Native;
-using VRGIN.Core;
-using VRGIN.Native;
-using HarmonyLib;
-using UnityEngine;
-using System.Threading;
-using System.Runtime.InteropServices;
-
-namespace KKS_VR
-{
- ///
- /// A version of InputSimulator that tries to avoid the issue of
- /// requiring focus & accidentally clicking outside the application window.
- ///
- public class RobustInputSimulator : IInputSimulator
- {
- public IKeyboardSimulator Keyboard { get; private set; }
- public IMouseSimulator Mouse { get; private set; }
- public IInputDeviceStateAdaptor InputDeviceState { get; private set; }
-
- public RobustInputSimulator()
- {
- Keyboard = new RobustKeyboardSimulator(this);
- Mouse = new RobustMouseSimulator(this);
- InputDeviceState = new WindowsInputDeviceStateAdaptor();
- }
-
- ///
- /// Make Unity think we have focus, if it doesn't already. This is necessary to prevent
- /// messages from being ignored.
- ///
- internal static void FakeFocus()
- {
- if (!Application.isFocused)
- {
- NativeMethods.PostMessage(
- WindowManager.Handle,
- 0x6, // WM_ACTIVATE
- new IntPtr(0x2), // Activated by a mouse click
- IntPtr.Zero); // Handle to the previously active window
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("user32.dll", SetLastError = true)]
- internal static extern bool GetKeyboardState([Out] byte[] lpKeyState);
-
- [DllImport("user32.dll", SetLastError = true)]
- internal static extern bool SetKeyboardState([In] byte[] lpKeyState);
-
- [DllImport("user32.dll", SetLastError = true)]
- internal static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
- }
- }
-
- ///
- /// This class is similar to MouseSimulator, but avoids generating
- /// button down messages using SendInput. Instead it uses PostMessage
- /// to send a fake WndProc message to the game window. This means
- /// the plugin continues to work fine if the game window loses focus.
- /// It also avoids the risk of accidentally clicking a random window.
- /// The overall strategy is:
- ///
- /// * Down and Up events: Use a WndProc message.
- /// * Wheel scroll: Use WM_MOUSEWHEEL, but this only affects IMGui for
- /// some reason. So we additionally patch UnityEngine.Input
- /// to inject synthetic wheel scrolls for UI and game code.
- /// * Cursor movement: Use SendInput to make sure that the actual cursor
- /// moves. This is necessary because game code often queries for the
- /// cursor position. However this is insufficient for IMGUI to recognize
- /// a drag. For this reason, an additional WM_MOUSEMOVE message is
- /// generated when dragging.
- ///
- public class RobustMouseSimulator : IMouseSimulator
- {
- private readonly MouseSimulator _systemSimulator;
- private Buttons _pressedMask = 0;
- private WindowsInterop.POINT? _dragCurrent;
-
- // Bitmask that can be passed to WM_MOUSEMOVE
- enum Buttons
- {
- Left = 0x1,
- Right = 0x2,
- Middle = 0x10,
- }
-
- public IKeyboardSimulator Keyboard => _inputSimulator.Keyboard;
-
- public RobustMouseSimulator(RobustInputSimulator inputSimulator)
- {
- _inputSimulator = inputSimulator;
- _systemSimulator = new MouseSimulator(inputSimulator);
- }
-
- public IMouseSimulator MoveMouseBy(int pixelDeltaX, int pixelDeltaY)
- {
- RobustInputSimulator.FakeFocus();
- _systemSimulator.MoveMouseBy(pixelDeltaX, pixelDeltaY);
- if (_pressedMask != 0)
- {
- var startingPoint = _dragCurrent ?? MouseOperations.GetCursorPosition();
- DragToScreenCoordinate(startingPoint.X + pixelDeltaX, startingPoint.Y + pixelDeltaY);
- }
- return this;
- }
-
- public IMouseSimulator MoveMouseTo(double absoluteX, double absoluteY)
- {
- RobustInputSimulator.FakeFocus();
- _systemSimulator.MoveMouseTo(absoluteX, absoluteY);
- if (_pressedMask != 0)
- {
- int width = WindowsInterop.GetSystemMetrics(WindowsInterop.SystemMetric.SM_CXSCREEN);
- int height = WindowsInterop.GetSystemMetrics(WindowsInterop.SystemMetric.SM_CYSCREEN);
- DragToScreenCoordinate(
- (int)Math.Round(absoluteX / 65535 * width),
- (int)Math.Round(absoluteY / 65535 * height));
- }
- return this;
- }
-
- public IMouseSimulator MoveMouseToPositionOnVirtualDesktop(double absoluteX, double absoluteY)
- {
- RobustInputSimulator.FakeFocus();
- _systemSimulator.MoveMouseToPositionOnVirtualDesktop(absoluteX, absoluteY);
- if (_pressedMask != 0)
- {
- var vRect = WindowManager.GetVirtualScreenRect();
- DragToScreenCoordinate(
- (int)Math.Round(absoluteX / 65535 * (vRect.Right - vRect.Left)) + vRect.Left,
- (int)Math.Round(absoluteY / 65535 * (vRect.Bottom - vRect.Top)) + vRect.Top);
-
- }
- return this;
- }
-
- public IMouseSimulator LeftButtonDown()
- {
- RobustInputSimulator.FakeFocus();
- _pressedMask |= Buttons.Left;
- return PostButtonMessage(0x201); // WM_LBUTTONDOWN
- }
-
- public IMouseSimulator LeftButtonUp()
- {
- ClearPressed(Buttons.Left);
- return PostButtonMessage(0x202); // WM_LBUTTONUP
- }
-
- public IMouseSimulator LeftButtonClick()
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator LeftButtonDoubleClick()
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator MiddleButtonDown()
- {
- RobustInputSimulator.FakeFocus();
- _pressedMask |= Buttons.Middle;
- return PostButtonMessage(0x207); // WM_MBUTTONDOWN
- }
-
- public IMouseSimulator MiddleButtonUp()
- {
- ClearPressed(Buttons.Middle);
- return PostButtonMessage(0x208); // WM_MBUTTONUP
- }
-
- public IMouseSimulator MiddleButtonClick()
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator MiddleButtonDoubleClick()
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator RightButtonDown()
- {
- RobustInputSimulator.FakeFocus();
- _pressedMask |= Buttons.Right;
- return PostButtonMessage(0x204); // WM_RBUTTONDOWN
- }
-
- public IMouseSimulator RightButtonUp()
- {
- ClearPressed(Buttons.Right);
- return PostButtonMessage(0x205); // WM_RBUTTONUP
- }
-
- public IMouseSimulator RightButtonClick()
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator RightButtonDoubleClick()
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator XButtonDown(int buttonId)
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator XButtonUp(int buttonId)
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator XButtonClick(int buttonId)
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator XButtonDoubleClick(int buttonId)
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator VerticalScroll(int scrollAmountInClicks)
- {
- RobustInputSimulator.FakeFocus();
- InputPatches.RequestScroll(scrollAmountInClicks);
- return PostScrollMessage(0x20a, scrollAmountInClicks * 120); // WM_MOUSEWHEEL
- }
-
- public IMouseSimulator VerticalScrollAbsolute(int scrollAmount)
- {
- RobustInputSimulator.FakeFocus();
- InputPatches.RequestScroll(scrollAmount);
- return PostScrollMessage(0x20a, scrollAmount * 120); // WM_MOUSEWHEEL
- }
-
- public IMouseSimulator HorizontalScroll(int scrollAmountInClicks)
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator HorizontalScrollAbsolute(int scrollAmount)
- {
- throw new NotImplementedException();
- }
-
- public IMouseSimulator Sleep(int millsecondsTimeout)
- {
- _systemSimulator.Sleep(millsecondsTimeout);
- return this;
- }
-
- public IMouseSimulator Sleep(TimeSpan timeout)
- {
- _systemSimulator.Sleep(timeout);
- return this;
- }
-
- private IMouseSimulator PostButtonMessage(uint msg)
- {
- // wParam represents the modifier key state,
- // but Unity doesn't seem to care.
- return PostMouseMessage(msg, IntPtr.Zero);
- }
-
- private IMouseSimulator PostScrollMessage(uint msg, int amount)
- {
- return PostMouseMessage(msg, PackWords(amount, 0));
- }
-
- private IMouseSimulator PostMouseMessage(uint msg, IntPtr wParam)
- {
- WindowsInterop.GetCursorPos(out var mousePosition);
- var clientRect = WindowManager.GetClientRect();
- var x = mousePosition.X - clientRect.Left;
- var y = mousePosition.Y - clientRect.Top;
- RobustInputSimulator.NativeMethods.PostMessage(
- WindowManager.Handle,
- msg,
- wParam,
- PackWords(y, x));
- return this;
- }
-
- private void DragToScreenCoordinate(int x, int y)
- {
- var clientRect = WindowManager.GetClientRect();
- RobustInputSimulator.NativeMethods.PostMessage(
- WindowManager.Handle,
- 0x200, // WM_MOUSEMOVE
- new IntPtr((int)_pressedMask),
- PackWords(y - clientRect.Top, x - clientRect.Left));
- _dragCurrent = new WindowsInterop.POINT(x, y);
- }
-
- private void ClearPressed(Buttons button)
- {
- _pressedMask &= ~button;
- if (_pressedMask == 0)
- {
- _dragCurrent = null;
- }
- }
- private static IntPtr PackWords(int hi, int lo)
- {
- return new IntPtr((hi << 16) | (lo & 0xffff));
- }
-
- private readonly RobustInputSimulator _inputSimulator;
- }
-
- ///
- /// A keyboard simulator that uses PostMessage and SetKeyboardState to
- /// simulate keypresses.
- ///
- public class RobustKeyboardSimulator : IKeyboardSimulator
- {
- public IMouseSimulator Mouse => _inputSimulator.Mouse;
-
- public RobustKeyboardSimulator(IInputSimulator inputSimulator)
- {
- _inputSimulator = inputSimulator;
- }
-
- public IKeyboardSimulator KeyDown(VirtualKeyCode code)
- {
- RobustInputSimulator.FakeFocus();
- RobustInputSimulator.NativeMethods.PostMessage(
- WindowManager.Handle,
- 0x100, // WM_KEYDOWN
- (IntPtr)code,
- IntPtr.Zero);
- ModifyInputState(code, true);
- return this;
- }
- public IKeyboardSimulator KeyUp(VirtualKeyCode code)
- {
- RobustInputSimulator.NativeMethods.PostMessage(
- WindowManager.Handle,
- 0x101, // WM_KEYUP
- (IntPtr)code,
- new IntPtr(0xc000_0001u)); // repeat=1, context=0, previous=1, transition=1
- ModifyInputState(code, false);
- return this;
- }
- public IKeyboardSimulator KeyPress(VirtualKeyCode code)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator KeyPress(params VirtualKeyCode[] code)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator ModifiedKeyStroke(IEnumerable mods, IEnumerable codes)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator ModifiedKeyStroke(IEnumerable mods, VirtualKeyCode code)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator ModifiedKeyStroke(VirtualKeyCode mod, IEnumerable codes)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator ModifiedKeyStroke(VirtualKeyCode mod, VirtualKeyCode code)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator TextEntry(string str)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator TextEntry(char c)
- {
- throw new NotImplementedException();
- }
- public IKeyboardSimulator Sleep(int millisecondsTimeout)
- {
- Thread.Sleep(millisecondsTimeout);
- return this;
- }
- public IKeyboardSimulator Sleep(TimeSpan timeout)
- {
- Thread.Sleep(timeout);
- return this;
- }
-
- private void ModifyInputState(VirtualKeyCode code, bool value)
- {
- var state = new byte[256];
- if (!RobustInputSimulator.NativeMethods.GetKeyboardState(state))
- {
- VRLog.Error($"GetKeyboardState failed");
- return;
- }
- state[(int)code] = (value ? (byte)0x80 : (byte)0);
- if (!RobustInputSimulator.NativeMethods.SetKeyboardState(state))
- {
- VRLog.Error($"SetKeyboardState failed");
- return;
- }
- }
-
- private readonly IInputSimulator _inputSimulator;
- }
-
- [HarmonyPatch(typeof(Input))]
- class InputPatches
- {
- [HarmonyPatch(nameof(Input.mouseScrollDelta), MethodType.Getter)]
- [HarmonyPostfix]
- private static void PostGetMouseScrollDelta(ref Vector2 __result)
- {
- UpdateForFrame();
- __result.y += _scrollCurrent;
- }
-
- [HarmonyPatch(nameof(Input.GetAxis))]
- [HarmonyPostfix]
- private static void PostGetAxis(string axisName, ref float __result)
- {
- if (axisName == "Mouse ScrollWheel")
- {
- UpdateForFrame();
- __result += _scrollCurrent;
- }
- }
-
- private static void UpdateForFrame()
- {
- if (Time.frameCount != _lastUpdate)
- {
- _lastUpdate = Time.frameCount;
- _scrollCurrent = _scrollRequest;
- _scrollRequest = 0;
- }
- }
-
- internal static void RequestScroll(int amount)
- {
- _scrollRequest += amount;
- }
-
- private static int _lastUpdate = -1;
- private static int _scrollRequest = 0;
- private static int _scrollCurrent = 0;
- }
-}
diff --git a/MainGameVR/Settings/KoikatuSettings.cs b/MainGameVR/Settings/KoikatuSettings.cs
deleted file mode 100644
index 2eb1c04..0000000
--- a/MainGameVR/Settings/KoikatuSettings.cs
+++ /dev/null
@@ -1,290 +0,0 @@
-using System.Collections.Generic;
-using System.ComponentModel;
-using VRGIN.Core;
-
-namespace KKS_VR.Settings
-{
- ///
- /// User settings. SettingsManager is responsible for updating this.
- ///
- public class KoikatuSettings : VRSettings
- {
- public List KeySets
- {
- get => _KeySets;
- set
- {
- _KeySets = value;
- TriggerPropertyChanged("KeySets");
- }
- }
-
- private List _KeySets = null;
-
- public List HKeySets
- {
- get => _HKeySets;
- set
- {
- _HKeySets = value;
- TriggerPropertyChanged("HKeySets");
- }
- }
-
- private List _HKeySets = null;
-
- public bool UsingHeadPos
- {
- get => _UsingHeadPos;
- set => _UsingHeadPos = value;
- }
-
- private bool _UsingHeadPos = false;
-
- public float StandingCameraPos
- {
- get => _StandingCameraPos;
- set => _StandingCameraPos = value;
- }
-
- private float _StandingCameraPos = 1.5f;
-
- public float CrouchingCameraPos
- {
- get => _CrouchingCameraPos;
- set => _CrouchingCameraPos = value;
- }
-
- private float _CrouchingCameraPos = 0.7f;
-
- public bool CrouchByHMDPos
- {
- get => _CrouchByHMDPos;
- set => _CrouchByHMDPos = value;
- }
-
- private bool _CrouchByHMDPos = true;
-
- public float CrouchThreshold { get; set; }
-
- public float StandUpThreshold { get; set; }
-
- public float RotationAngle
- {
- get => _RotationAngle;
- set => _RotationAngle = value;
- }
-
- private float _RotationAngle = 45f;
-
- public bool AutomaticTouching
- {
- get => _AutomaticTouching;
- set => _AutomaticTouching = value;
- }
-
- private bool _AutomaticTouching = false;
-
- public bool AutomaticTouchingByHmd { get; set; } = false;
-
- public bool AutomaticKissing
- {
- get => _AutomaticKissing;
- set => _AutomaticKissing = value;
- }
-
- private bool _AutomaticKissing = false;
-
- public bool AutomaticLicking { get; set; }
-
- public bool FirstPersonADV { get; set; }
-
- public bool TeleportWithProtagonist { get; set; }
-
- public bool PrivacyScreen
- {
- get => _PrivacyScreen;
- set
- {
- _PrivacyScreen = value;
- TriggerPropertyChanged("PrivacyScreen");
- }
- }
-
- private bool _PrivacyScreen = false;
-
- public bool OptimizeHInsideRoaming { get; set; }
-
- public float NearClipPlane
- {
- get => _NearClipPlane;
- set
- {
- _NearClipPlane = value;
- TriggerPropertyChanged("NearClipPlane");
- }
- }
-
- private float _NearClipPlane;
-
- public bool UseLegacyInputSimulator
- {
- get => _UseLegacyInputSimulator;
- set
- {
- _UseLegacyInputSimulator = value;
- TriggerPropertyChanged("UseLegacyInputSimulator");
- }
- }
-
- private bool _UseLegacyInputSimulator;
-
- public bool EnablePOV
- {
- get => _EnablePOV;
- set
- {
- _EnablePOV = value;
- TriggerPropertyChanged("EnablePOV");
- }
- }
-
- private bool _EnablePOV = true;
- }
-
- public class KeySet
- {
- public KeySet(
- AssignableFunction trigger,
- AssignableFunction grip,
- AssignableFunction Up,
- AssignableFunction Down,
- AssignableFunction Right,
- AssignableFunction Left,
- AssignableFunction Center)
- {
- Trigger = trigger;
- Grip = grip;
- this.Up = Up;
- this.Down = Down;
- this.Right = Right;
- this.Left = Left;
- this.Center = Center;
- }
-
- public AssignableFunction Trigger { get; set; }
-
- public AssignableFunction Grip { get; set; }
-
- public AssignableFunction Up { get; set; }
-
- public AssignableFunction Down { get; set; }
-
- public AssignableFunction Right { get; set; }
-
- public AssignableFunction Left { get; set; }
-
- public AssignableFunction Center { get; set; }
- }
-
- public enum AssignableFunction
- {
- [Description("None")] NONE,
- [Description("Walk (Roam mode)")] WALK,
- [Description("Dash (Roam mode)")] DASH,
-
- [Description("Move protagonist to camera (Roam mode)")]
- PL2CAM,
- [Description("Crouch (Roam mode)")] CROUCH,
- [Description("Turn left")] LROTATION,
- [Description("Turn right")] RROTATION,
- [Description("Left mouse button")] LBUTTON,
- [Description("Right mouse button")] RBUTTON,
- [Description("Middle mouse button")] MBUTTON,
- [Description("Mouse wheel scroll up")] SCROLLUP,
-
- [Description("Mouse wheel scroll down")]
- SCROLLDOWN,
-
- [Description("Switch button assignments")]
- NEXT,
- [Description("Grab space to move")] GRAB,
- [Description("Keyboard Tab")] TAB,
- [Description("Keyboard Enter")] RETURN,
- [Description("Keyboard Esc")] ESCAPE,
- [Description("Keyboard Space")] SPACE,
- [Description("Keyboard Home")] HOME,
- [Description("Keyboard End")] END,
- [Description("Keyboard arrow left")] LEFT,
- [Description("Keyboard arrow up")] UP,
- [Description("Keyboard arrow right")] RIGHT,
- [Description("Keyboard arrow down")] DOWN,
- [Description("Keyboard Ins")] INSERT,
- [Description("Keyboard Del")] DELETE,
- [Description("Keyboard Page Up")] PRIOR,
- [Description("Keyboard Page Down")] KEYBOARD_PAGE_DOWN,
- [Description("Keyboard Backspace")] BACK,
- [Description("Keyboard Shift")] SHIFT,
- [Description("Keyboard Ctrl")] CONTROL,
- [Description("Keyboard Alt")] MENU,
- [Description("Keyboard Pause")] PAUSE,
- [Description("Keyboard F1")] F1,
- [Description("Keyboard F2")] F2,
- [Description("Keyboard F3")] F3,
- [Description("Keyboard F4")] F4,
- [Description("Keyboard F5")] F5,
- [Description("Keyboard F6")] F6,
- [Description("Keyboard F7")] F7,
- [Description("Keyboard F8")] F8,
- [Description("Keyboard F9")] F9,
- [Description("Keyboard F10")] F10,
- [Description("Keyboard F11")] F11,
- [Description("Keyboard F12")] F12,
- [Description("Keyboard A")] VK_A,
- [Description("Keyboard B")] VK_B,
- [Description("Keyboard C")] VK_C,
- [Description("Keyboard D")] VK_D,
- [Description("Keyboard E")] VK_E,
- [Description("Keyboard F")] VK_F,
- [Description("Keyboard G")] VK_G,
- [Description("Keyboard H")] VK_H,
- [Description("Keyboard I")] VK_I,
- [Description("Keyboard J")] VK_J,
- [Description("Keyboard K")] VK_K,
- [Description("Keyboard L")] VK_L,
- [Description("Keyboard M")] VK_M,
- [Description("Keyboard N")] VK_N,
- [Description("Keyboard O")] VK_O,
- [Description("Keyboard P")] VK_P,
- [Description("Keyboard Q")] VK_Q,
- [Description("Keyboard R")] VK_R,
- [Description("Keyboard S")] VK_S,
- [Description("Keyboard T")] VK_T,
- [Description("Keyboard U")] VK_U,
- [Description("Keyboard V")] VK_V,
- [Description("Keyboard W")] VK_W,
- [Description("Keyboard X")] VK_X,
- [Description("Keyboard Y")] VK_Y,
- [Description("Keyboard Z")] VK_Z,
- [Description("Keyboard 0")] VK_0,
- [Description("Keyboard 1")] VK_1,
- [Description("Keyboard 2")] VK_2,
- [Description("Keyboard 3")] VK_3,
- [Description("Keyboard 4")] VK_4,
- [Description("Keyboard 5")] VK_5,
- [Description("Keyboard 6")] VK_6,
- [Description("Keyboard 7")] VK_7,
- [Description("Keyboard 8")] VK_8,
- [Description("Keyboard 9")] VK_9,
- [Description("Keyboard Numpad 0")] NUMPAD0,
- [Description("Keyboard Numpad 1")] NUMPAD1,
- [Description("Keyboard Numpad 2")] NUMPAD2,
- [Description("Keyboard Numpad 3")] NUMPAD3,
- [Description("Keyboard Numpad 4")] NUMPAD4,
- [Description("Keyboard Numpad 5")] NUMPAD5,
- [Description("Keyboard Numpad 6")] NUMPAD6,
- [Description("Keyboard Numpad 7")] NUMPAD7,
- [Description("Keyboard Numpad 8")] NUMPAD8,
- [Description("Keyboard Numpad 9")] NUMPAD9
- }
-}
diff --git a/MainGameVR/Settings/SettingsManager.cs b/MainGameVR/Settings/SettingsManager.cs
deleted file mode 100644
index 10ad00c..0000000
--- a/MainGameVR/Settings/SettingsManager.cs
+++ /dev/null
@@ -1,517 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using BepInEx.Configuration;
-using KKAPI.Utilities;
-using VRGIN.Core;
-using UnityEngine;
-
-namespace KKS_VR.Settings
-{
- ///
- /// Manages configuration and keeps it up to date.
- ///
- /// BepInEx wants us to store the config in a bunch of ConfigEntry objects,
- /// but VRGIN wants it stored inside a class inheriting VRSettings. So
- /// our plan is:
- ///
- /// * We have both ConfigEntry objects and KoikatuSettings around.
- /// * The ConfigEntry objects are the master copy and the KoikatuSettings
- /// object is a mirror.
- /// * SettingsManager is responsible for keeping KoikatuSettings up to date.
- /// * No other parts of code should modify KoikatuSettings. In fact, there
- /// are code paths where VRGIN tries to modify it. We simply attempt
- /// to avoid executing those code paths.
- ///
- public class SettingsManager
- {
- public const string SectionGeneral = "0. General";
- public const string SectionRoaming = "1. Roaming";
- public const string SectionCaress = "1. Caress";
- public const string SectionEventScenes = "1. Event scenes";
-
- public static ConfigEntry EnableBoop { get; private set; }
-
- ///
- /// Create config entries under the given ConfigFile. Also create a fresh
- /// KoikatuSettings object and arrange that it be synced with the config
- /// entries.
- ///
- /// The new KoikatuSettings object.
- public static KoikatuSettings Create(ConfigFile config)
- {
- var settings = new KoikatuSettings();
-
- var ipdScale = config.Bind(SectionGeneral, "IPD Scale", 1f,
- new ConfigDescription(
- "Scale of the camera. The higher, the more gigantic the player is.",
- new AcceptableValueRange(0.25f, 4f)));
- Tie(ipdScale, v => settings.IPDScale = v);
-
- var rumble = config.Bind(SectionGeneral, "Rumble", true,
- "Whether or not rumble is activated.");
- Tie(rumble, v => settings.Rumble = v);
-
- var rotationMultiplier = config.Bind(SectionGeneral, "Rotation multiplier", 1f,
- new ConfigDescription(
- "How quickly the the view should rotate when doing so with the controllers.",
- new AcceptableValueRange(-4f, 4f),
- new ConfigurationManagerAttributes { Order = -1 }));
- Tie(rotationMultiplier, v => settings.RotationMultiplier = v);
-
- //todo missing
- //var touchpadThreshold = config.Bind(sectionGeneral, "Touchpad direction threshold", 0.8f,
- // new ConfigDescription(
- // "Touchpad presses within this radius are considered center clicks rather than directional ones.",
- // new AcceptableValueRange(0f, 1f)));
- //Tie(touchpadThreshold, v => settings.TouchpadThreshold = v);
-
- var logLevel = config.Bind(SectionGeneral, "Log level", VRLog.LogMode.Info,
- new ConfigDescription(
- "The minimum severity for a message to be logged.",
- null,
- new ConfigurationManagerAttributes { IsAdvanced = true }));
- Tie(logLevel, v => VRLog.Level = v);
-
- var rotationAngle = config.Bind(SectionGeneral, "Rotation angle", 45f,
- new ConfigDescription(
- "Angle of rotation, in degrees",
- new AcceptableValueRange(0f, 180f)));
- Tie(rotationAngle, v => settings.RotationAngle = v);
-
- var privacyScreen = config.Bind(SectionGeneral, "Privacy screen", false,
- "Attempt to hide everything in the desktop mirror window");
- Tie(privacyScreen, v => settings.PrivacyScreen = v);
-
- var nearClipPlane = config.Bind(SectionGeneral, "Near clip plane", 0.002f,
- new ConfigDescription(
- "Minimum distance from camera for an object to be shown (causes visual glitches on some maps when set too small)",
- new AcceptableValueRange(0.001f, 0.2f)));
- Tie(nearClipPlane, v => settings.NearClipPlane = v);
-
- var useLegacyInputSimulator = config.Bind(SectionGeneral, "Use legacy input simulator", false,
- new ConfigDescription(
- "Simulate mouse and keyboard input by generating system-wide fake events",
- null,
- new ConfigurationManagerAttributes { IsAdvanced = true }));
- Tie(useLegacyInputSimulator, v => settings.UseLegacyInputSimulator = v);
-
- var usingHeadPos = config.Bind(SectionRoaming, "Use head position", false,
- new ConfigDescription(
- "Place the camera exactly at the protagonist's head (may cause motion sickness). If disabled, use a fixed height from the floor.",
- null,
- new ConfigurationManagerAttributes { Order = -1 }));
- Tie(usingHeadPos, v => settings.UsingHeadPos = v);
-
- var standingCameraPos = config.Bind(SectionRoaming, "Camera height", 1.5f,
- new ConfigDescription(
- "Default camera height for when not using the head position.",
- new AcceptableValueRange(0.2f, 3f),
- new ConfigurationManagerAttributes { Order = -2 }));
- Tie(standingCameraPos, v => settings.StandingCameraPos = v);
-
- var crouchingCameraPos = config.Bind(SectionRoaming, "Crouching camera height", 0.7f,
- new ConfigDescription(
- "Crouching camera height for when not using the head position",
- new AcceptableValueRange(0.2f, 3f),
- new ConfigurationManagerAttributes { Order = -2 }));
- Tie(crouchingCameraPos, v => settings.CrouchingCameraPos = v);
-
- var crouchByHMDPos = config.Bind(SectionRoaming, "Crouch by HMD position", true,
- new ConfigDescription(
- "Crouch when the HMD position is below some threshold.",
- null,
- new ConfigurationManagerAttributes { Order = -3 }));
- Tie(crouchByHMDPos, v => settings.CrouchByHMDPos = v);
-
- var crouchThreshold = config.Bind(SectionRoaming, "Crouch height", 0.9f,
- new ConfigDescription(
- "Trigger crouching when the camera is below this height",
- new AcceptableValueRange(0.05f, 3f),
- new ConfigurationManagerAttributes { Order = -4 }));
- Tie(crouchThreshold, v => settings.CrouchThreshold = v);
-
- var standUpThreshold = config.Bind(SectionRoaming, "Stand up height", 1f,
- new ConfigDescription(
- "End crouching when the camera is above this height",
- new AcceptableValueRange(0.05f, 3f),
- new ConfigurationManagerAttributes { Order = -4 }));
- Tie(standUpThreshold, v => settings.StandUpThreshold = v);
-
- var teleportWithProtagonist = config.Bind(SectionRoaming, "Teleport with protagonist", true,
- "When teleporting, the protagonist also teleports");
- Tie(teleportWithProtagonist, v => settings.TeleportWithProtagonist = v);
-
- var optimizeHInsideRoaming = config.Bind(SectionRoaming, "Aggressive performance optimizations", true,
- "Improve framerate and reduce stutter in H and Talk scenes inside Roaming. May cause visual glitches.");
- Tie(optimizeHInsideRoaming, v => settings.OptimizeHInsideRoaming = v);
-
- var automaticTouching = config.Bind(SectionCaress, "Automatic touching", false,
- "Touching the female's body with controllers triggers reaction");
- Tie(automaticTouching, v => settings.AutomaticTouching = v);
-
- var automaticKissing = config.Bind(SectionCaress, "Automatic kissing", true,
- "Initiate kissing by moving your head");
- Tie(automaticKissing, v => settings.AutomaticKissing = v);
-
- var automaticLicking = config.Bind(SectionCaress, "Automatic licking", true,
- "Initiate licking by moving your head");
- Tie(automaticLicking, v => settings.AutomaticLicking = v);
-
- var automaticTouchingByHmd = config.Bind(SectionCaress, "Kiss body", true,
- "Touch the female's body by moving your head");
- Tie(automaticTouchingByHmd, v => settings.AutomaticTouchingByHmd = v);
-
- var firstPersonADV = config.Bind(SectionEventScenes, "First person", true,
- "Prefer first person view in event scenes");
- Tie(firstPersonADV, v => settings.FirstPersonADV = v);
-
- EnableBoop = config.Bind(SectionGeneral, "Enable Boop", true,
- "Adds colliders to the controllers so you can boop things.\nGame restart required for change to take effect.");
-
- KeySetsConfig keySetsConfig = null;
-
- void updateKeySets()
- {
- keySetsConfig.CurrentKeySets(out var keySets, out var hKeySets);
- settings.KeySets = keySets;
- settings.HKeySets = hKeySets;
- }
-
- keySetsConfig = new KeySetsConfig(config, updateKeySets);
- updateKeySets();
-
- POVConfig pOVConfig = new POVConfig(config, settings);
-
- // Fixed settings
- settings.ApplyEffects = false; // We manage effects ourselves.
-
- return settings;
- }
-
- private static void Tie(ConfigEntry entry, Action set)
- {
- set(entry.Value);
- entry.SettingChanged += (_, _1) => set(entry.Value);
- }
- }
-
- internal class KeySetsConfig
- {
- private readonly KeySetConfig _main;
- private readonly KeySetConfig _main1;
- private readonly KeySetConfig _h;
- private readonly KeySetConfig _h1;
-
- private readonly ConfigEntry _useMain1;
- private readonly ConfigEntry _useH1;
-
- public KeySetsConfig(ConfigFile config, Action onUpdate)
- {
- const string sectionP = "2. Non-H button assignments (primary)";
- const string sectionS = "2. Non-H button assignments (secondary)";
- const string sectionHP = "3. H button assignments (primary)";
- const string sectionHS = "3. H button assignments (secondary)";
-
- _main = new KeySetConfig(config, onUpdate, sectionP, false, false);
- _main1 = new KeySetConfig(config, onUpdate, sectionS, false, true);
- _h = new KeySetConfig(config, onUpdate, sectionHP, true, false);
- _h1 = new KeySetConfig(config, onUpdate, sectionHS, true, true);
-
- _useMain1 = config.Bind(sectionS, "Use secondary assignments", false,
- new ConfigDescription("", null, new ConfigurationManagerAttributes { IsAdvanced = true }));
- _useMain1.SettingChanged += (_, _1) => onUpdate();
- _useH1 = config.Bind(sectionHS, "Use secondary assignments", false,
- new ConfigDescription("", null, new ConfigurationManagerAttributes { IsAdvanced = true }));
- _useH1.SettingChanged += (_, _1) => onUpdate();
- }
-
- public void CurrentKeySets(out List keySets, out List hKeySets)
- {
- keySets = new List();
- keySets.Add(_main.CurrentKeySet());
- if (_useMain1.Value) keySets.Add(_main1.CurrentKeySet());
-
- hKeySets = new List();
- hKeySets.Add(_h.CurrentKeySet());
- if (_useH1.Value) hKeySets.Add(_h1.CurrentKeySet());
- }
- }
-
- internal class KeySetConfig
- {
- private readonly ConfigEntry _trigger;
- private readonly ConfigEntry _grip;
- private readonly ConfigEntry _up;
- private readonly ConfigEntry _down;
- private readonly ConfigEntry _right;
- private readonly ConfigEntry _left;
- private readonly ConfigEntry _center;
-
- public KeySetConfig(ConfigFile config, Action onUpdate, string section, bool isH, bool advanced)
- {
- var order = -1;
-
- ConfigEntry create(string name, AssignableFunction def)
- {
- var entry = config.Bind(section, name, def, new ConfigDescription("", null,
- new ConfigurationManagerAttributes { Order = order, IsAdvanced = advanced }));
- entry.SettingChanged += (_, _1) => onUpdate();
- order -= 1;
- return entry;
- }
-
- if (isH)
- {
- _trigger = create("Trigger", AssignableFunction.LBUTTON);
- _grip = create("Grip", AssignableFunction.GRAB);
- _up = create("Up", AssignableFunction.SCROLLUP);
- _down = create("Down", AssignableFunction.SCROLLDOWN);
- _left = create("Left", AssignableFunction.NONE);
- _right = create("Right", AssignableFunction.RBUTTON);
- _center = create("Center", AssignableFunction.MBUTTON);
- }
- else
- {
- _trigger = create("Trigger", AssignableFunction.WALK);
- _grip = create("Grip", AssignableFunction.GRAB);
- _up = create("Up", AssignableFunction.F3);
- _down = create("Down", AssignableFunction.F1);
- _left = create("Left", AssignableFunction.LROTATION);
- _right = create("Right", AssignableFunction.RROTATION);
- _center = create("Center", AssignableFunction.RBUTTON);
- }
- }
-
- public KeySet CurrentKeySet()
- {
- return new KeySet(
- _trigger.Value,
- _grip.Value,
- _up.Value,
- _down.Value,
- _right.Value,
- _left.Value,
- _center.Value);
- }
- }
-
- public class POVConfig
- {
- private const string sectionPOV = "4. POV between characters (Hand Tool in free H)";
- public static ConfigEntry switchPOVModeKey { get; private set; }
- public static ConfigEntry POVKey { get; private set; }
- public static ConfigEntry targetGender { get; private set; }
-
- public enum POVKeyList
- {
- [Description("VR Trigger Button")] // k_EButton_SteamVR_Trigger
- VR_TRIGGER = KeyCode.None,
- [Description("VR Button2(A/X).Depend on device")] // k_EButton_A
- VR_BUTTON2 = 1, // Any number, not in KeyCode
- [Description("Left mouse(=VR Trigger Button)")]
- LBUTTON = KeyCode.Mouse0,
- [Description("Right mouse(=VR Right Touchpad Click)")]
- RBUTTON = KeyCode.Mouse1,
- [Description("Middle mouse(=VR Touchpad Click)")]
- MBUTTON = KeyCode.Mouse2,
- [Description("Keyboard A")]
- A = KeyCode.A,
- [Description("Keyboard B")]
- B = KeyCode.B,
- [Description("Keyboard C")]
- C = KeyCode.C,
- [Description("Keyboard D")]
- D = KeyCode.D,
- [Description("Keyboard E")]
- E = KeyCode.E,
- [Description("Keyboard F")]
- F = KeyCode.F,
- [Description("Keyboard G")]
- G = KeyCode.G,
- [Description("Keyboard H")]
- H = KeyCode.H,
- [Description("Keyboard I")]
- I = KeyCode.I,
- [Description("Keyboard J")]
- J = KeyCode.J,
- [Description("Keyboard K")]
- K = KeyCode.K,
- [Description("Keyboard L")]
- L = KeyCode.L,
- [Description("Keyboard M")]
- M = KeyCode.M,
- [Description("Keyboard N")]
- N = KeyCode.N,
- [Description("Keyboard O")]
- O = KeyCode.O,
- [Description("Keyboard P")]
- P = KeyCode.P,
- [Description("Keyboard Q")]
- Q = KeyCode.Q,
- [Description("Keyboard R")]
- R = KeyCode.R,
- [Description("Keyboard S")]
- S = KeyCode.S,
- [Description("Keyboard T")]
- T = KeyCode.T,
- [Description("Keyboard U")]
- U = KeyCode.U,
- [Description("Keyboard V")]
- V = KeyCode.V,
- [Description("Keyboard W")]
- W = KeyCode.W,
- [Description("Keyboard X")]
- X = KeyCode.X,
- [Description("Keyboard Y")]
- Y = KeyCode.Y,
- [Description("Keyboard Z")]
- Z = KeyCode.Z,
- [Description("Keyboard 0")]
- ALPHA0 = KeyCode.Alpha0,
- [Description("Keyboard 1")]
- ALPHA1 = KeyCode.Alpha1,
- [Description("Keyboard 2")]
- ALPHA2 = KeyCode.Alpha2,
- [Description("Keyboard 3")]
- ALPHA3 = KeyCode.Alpha3,
- [Description("Keyboard 4")]
- ALPHA4 = KeyCode.Alpha4,
- [Description("Keyboard 5")]
- ALPHA5 = KeyCode.Alpha5,
- [Description("Keyboard 6")]
- ALPHA6 = KeyCode.Alpha6,
- [Description("Keyboard 7")]
- ALPHA7 = KeyCode.Alpha7,
- [Description("Keyboard 8")]
- ALPHA8 = KeyCode.Alpha8,
- [Description("Keyboard 9")]
- ALPHA9 = KeyCode.Alpha9,
- [Description("Keyboard Numpad 0")]
- NUMPAD0 = KeyCode.Keypad0,
- [Description("Keyboard Numpad 1")]
- NUMPAD1 = KeyCode.Keypad1,
- [Description("Keyboard Numpad 2")]
- NUMPAD2 = KeyCode.Keypad2,
- [Description("Keyboard Numpad 3")]
- NUMPAD3 = KeyCode.Keypad3,
- [Description("Keyboard Numpad 4")]
- NUMPAD4 = KeyCode.Keypad4,
- [Description("Keyboard Numpad 5")]
- NUMPAD5 = KeyCode.Keypad5,
- [Description("Keyboard Numpad 6")]
- NUMPAD6 = KeyCode.Keypad6,
- [Description("Keyboard Numpad 7")]
- NUMPAD7 = KeyCode.Keypad7,
- [Description("Keyboard Numpad 8")]
- NUMPAD8 = KeyCode.Keypad8,
- [Description("Keyboard Numpad 9")]
- NUMPAD9 = KeyCode.Keypad9,
- [Description("Keyboard F1")]
- F1 = KeyCode.F1,
- [Description("Keyboard F2")]
- F2 = KeyCode.F2,
- [Description("Keyboard F3")]
- F3 = KeyCode.F3,
- [Description("Keyboard F4")]
- F4 = KeyCode.F4,
- [Description("Keyboard F5")]
- F5 = KeyCode.F5,
- [Description("Keyboard F6")]
- F6 = KeyCode.F6,
- [Description("Keyboard F7")]
- F7 = KeyCode.F7,
- [Description("Keyboard F8")]
- F8 = KeyCode.F8,
- [Description("Keyboard F9")]
- F9 = KeyCode.F9,
- [Description("Keyboard F10")]
- F10 = KeyCode.F10,
- [Description("Keyboard F11")]
- F11 = KeyCode.F11,
- [Description("Keyboard F12")]
- F12 = KeyCode.F12,
- [Description("Keyboard Tab")]
- TAB = KeyCode.Tab,
- [Description("Keyboard Enter")]
- RETURN = KeyCode.Return,
- [Description("Keyboard Esc")]
- ESC = KeyCode.Escape,
- [Description("Keyboard Space")]
- SPACE = KeyCode.Space,
- [Description("Keyboard Home")]
- HOME = KeyCode.Home,
- [Description("Keyboard End")]
- END = KeyCode.End,
- [Description("Keyboard arrow left")]
- LEFT = KeyCode.LeftArrow,
- [Description("Keyboard arrow up")]
- UP = KeyCode.UpArrow,
- [Description("Keyboard arrow right")]
- RIGHT = KeyCode.RightArrow,
- [Description("Keyboard arrow down")]
- DOWN = KeyCode.DownArrow,
- [Description("Keyboard Ins")]
- INSERT = KeyCode.Insert,
- [Description("Keyboard Del")]
- DELETE = KeyCode.Delete,
- [Description("Keyboard Page Up")]
- PAGEUP = KeyCode.PageUp,
- [Description("Keyboard Page Down")]
- PAGEDOWN = KeyCode.PageDown,
- [Description("Keyboard Backspace")]
- BACK = KeyCode.Backspace,
- [Description("Keyboard Left Shift")]
- LEFTSHIFT = KeyCode.LeftShift,
- [Description("Keyboard Right Shift")]
- RIGHTSHIFT = KeyCode.RightShift,
- [Description("Keyboard Left Ctrl")]
- LEFTCTRL = KeyCode.LeftControl,
- [Description("Keyboard Right Ctrl")]
- RIGHTCTRL = KeyCode.RightControl,
- [Description("Keyboard Left Alt")]
- LEFTALT = KeyCode.LeftAlt,
- [Description("Keyboard Right Alt")]
- RIGHTALT = KeyCode.RightAlt
- }
- public enum Gender
- {
- Male = 0, // must same as Koikatsu Male ChaControl.sex = 0
- Female = 1, // must same as Koikatsu Female ChaControl.sex = 1
- All
- }
- public POVConfig(ConfigFile config, KoikatuSettings settings)
- {
- var enablePOV = config.Bind(sectionPOV, "POV", true,
- "Switch POV between characters in free H scenes (only works in Hand Tool)");
- Tie(enablePOV, v => settings.EnablePOV = v);
-
- switchPOVModeKey = config.Bind(sectionPOV, "Switch POV Mode (1~3)", POVKeyList.Y,
- new ConfigDescription(
- "Use VR Button/Key to switch POV between characters. " +
- "Three Modes:\r\n" +
- "1: Camera is fixed at character's eye.\r\n" +
- "2: Camera moves when character's head moves. (Default)\r\n" +
- "3: Camera doesn't move when character's head moves (jump to character).",
- null,
- new ConfigurationManagerAttributes { Order = -1 }));
-
- POVKey = config.Bind(sectionPOV, "Switch POV Camera", POVKeyList.VR_TRIGGER,
- new ConfigDescription(
- "Use this hotkey to switch the POV camera between target characters.",
- null,
- new ConfigurationManagerAttributes { Order = -2 }));
-
- targetGender = config.Bind(sectionPOV, "Target", Gender.All,
- new ConfigDescription(
- "The Gender of the POV targets.",
- null,
- new ConfigurationManagerAttributes { Order = -3 }));
- }
- private static void Tie(ConfigEntry entry, Action set)
- {
- set(entry.Value);
- entry.SettingChanged += (_, _1) => set(entry.Value);
- }
- }
-}
diff --git a/MainGameVR/VRAssetBundles/.gitignore b/MainGameVR/VRAssetBundles/.gitignore
deleted file mode 100644
index 16aeaaf..0000000
--- a/MainGameVR/VRAssetBundles/.gitignore
+++ /dev/null
@@ -1,74 +0,0 @@
-# This .gitignore file should be placed at the root of your Unity project directory
-#
-# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
-#
-/[Ll]ibrary/
-/[Tt]emp/
-/[Oo]bj/
-/[Bb]uild/
-/[Bb]uilds/
-/[Ll]ogs/
-/[Uu]ser[Ss]ettings/
-
-# MemoryCaptures can get excessive in size.
-# They also could contain extremely sensitive data
-/[Mm]emoryCaptures/
-
-# Recordings can get excessive in size
-/[Rr]ecordings/
-
-# Uncomment this line if you wish to ignore the asset store tools plugin
-# /[Aa]ssets/AssetStoreTools*
-
-# Autogenerated Jetbrains Rider plugin
-/[Aa]ssets/Plugins/Editor/JetBrains*
-
-# Visual Studio cache directory
-.vs/
-
-# Gradle cache directory
-.gradle/
-
-# Autogenerated VS/MD/Consulo solution and project files
-ExportedObj/
-.consulo/
-*.csproj
-*.unityproj
-*.sln
-*.suo
-*.tmp
-*.user
-*.userprefs
-*.pidb
-*.booproj
-*.svd
-*.pdb
-*.mdb
-*.opendb
-*.VC.db
-
-# Unity3D generated meta files
-*.pidb.meta
-*.pdb.meta
-*.mdb.meta
-
-# Unity3D generated file on crash reports
-sysinfo.txt
-
-# Builds
-*.apk
-*.aab
-*.unitypackage
-*.app
-
-# Crashlytics generated file
-crashlytics-build.properties
-
-# Packed Addressables
-/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
-
-# Temporary auto-generated Android Assets
-/[Aa]ssets/[Ss]treamingAssets/aa.meta
-/[Aa]ssets/[Ss]treamingAssets/aa/*
-
-/Assets/AssetBundles
diff --git a/MainGameVR/VRAssetBundles/Assets/AssetBundles.meta b/MainGameVR/VRAssetBundles/Assets/AssetBundles.meta
deleted file mode 100644
index e4bbe6c..0000000
--- a/MainGameVR/VRAssetBundles/Assets/AssetBundles.meta
+++ /dev/null
@@ -1,9 +0,0 @@
-fileFormatVersion: 2
-guid: a4bba4eb05e596647b49ba9213988c37
-folderAsset: yes
-timeCreated: 1694326413
-licenseType: Free
-DefaultImporter:
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/MainGameVR/VRAssetBundles/Assets/Editor.meta b/MainGameVR/VRAssetBundles/Assets/Editor.meta
deleted file mode 100644
index aa3003c..0000000
--- a/MainGameVR/VRAssetBundles/Assets/Editor.meta
+++ /dev/null
@@ -1,9 +0,0 @@
-fileFormatVersion: 2
-guid: 93e6af1384dad6146bd3234cb70373cf
-folderAsset: yes
-timeCreated: 1694324809
-licenseType: Free
-DefaultImporter:
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/MainGameVR/VRAssetBundles/Assets/Editor/BuildAssetBundles.cs b/MainGameVR/VRAssetBundles/Assets/Editor/BuildAssetBundles.cs
deleted file mode 100644
index 49aa4f5..0000000
--- a/MainGameVR/VRAssetBundles/Assets/Editor/BuildAssetBundles.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using UnityEditor;
-using System.IO;
-
-public class CreateAssetBundles
-{
- [MenuItem("Assets/Build AssetBundles")]
- static void BuildAllAssetBundles()
- {
- string assetBundleDirectory = "Assets/AssetBundles";
- if (!Directory.Exists(assetBundleDirectory))
- {
- Directory.CreateDirectory(assetBundleDirectory);
- }
- BuildPipeline.BuildAssetBundles(assetBundleDirectory,
- BuildAssetBundleOptions.None,
- BuildTarget.StandaloneWindows);
- }
-}
\ No newline at end of file
diff --git a/MainGameVR/VRAssetBundles/Assets/Editor/BuildAssetBundles.cs.meta b/MainGameVR/VRAssetBundles/Assets/Editor/BuildAssetBundles.cs.meta
deleted file mode 100644
index e9f98a8..0000000
--- a/MainGameVR/VRAssetBundles/Assets/Editor/BuildAssetBundles.cs.meta
+++ /dev/null
@@ -1,12 +0,0 @@
-fileFormatVersion: 2
-guid: 299b82424bb52b749bbd1df7ab5a8bd2
-timeCreated: 1694324825
-licenseType: Free
-MonoImporter:
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/MainGameVR/VRAssetBundles/Assets/MirrorReflection.shader b/MainGameVR/VRAssetBundles/Assets/MirrorReflection.shader
deleted file mode 100644
index dcc99d5..0000000
--- a/MainGameVR/VRAssetBundles/Assets/MirrorReflection.shader
+++ /dev/null
@@ -1,95 +0,0 @@
-// Upgrade NOTE: replaced 'UNITY_INSTANCE_ID' with 'UNITY_VERTEX_INPUT_INSTANCE_ID'
-// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
-
-Shader "FX/MirrorReflection"
-{
- Properties
- {
- _MainTex("Base (RGB)", 2D) = "white" {}
- [HideInInspector] _LeftReflectionTex("", 2D) = "white" {}
- [HideInInspector] _RightReflectionTex("", 2D) = "white" {}
- }
- SubShader
- {
- Tags{ "RenderType" = "Opaque" }
- LOD 100
-
- Pass{
- CGPROGRAM
-#pragma vertex vert
-#pragma fragment frag
-#include "UnityCG.cginc"
-
- float4 _MainTex_ST;
- sampler2D _MainTex;
- sampler2D _LeftReflectionTex;
- sampler2D _RightReflectionTex;
-
- struct VertexInput
- {
- float4 pos : POSITION;
- float2 uv: TEXCOORD0;
- UNITY_VERTEX_INPUT_INSTANCE_ID
- };
-
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 refl : TEXCOORD1;
- float4 pos : SV_POSITION;
- UNITY_VERTEX_INPUT_INSTANCE_ID
- UNITY_VERTEX_OUTPUT_STEREO
- };
-
- // Same as standard ComputeScreenPos() except that it doesn't call TransformStereoScreenSpaceTex()
- // when stereo instance rendering is enabled. This is important because we need to be able to sample
- // from the entire reflection texture, and not just the left/right half, which is what the normal
- // ComputeScreenPos() would get us.
- inline float4 ComputeScreenPosIgnoreStereo(float4 pos) {
- float4 o = pos * 0.5f;
-#if defined(UNITY_HALF_TEXEL_OFFSET)
- o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w * _ScreenParams.zw;
-#else
- o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
-#endif
- o.zw = pos.zw;
- return o;
- }
-
- v2f vert(VertexInput v)
- {
- UNITY_SETUP_INSTANCE_ID(v);
- v2f o;
- UNITY_INITIALIZE_OUTPUT(v2f, o);
- UNITY_TRANSFER_INSTANCE_ID(v, o);
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
-
- o.pos = UnityObjectToClipPos(v.pos);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- o.refl = ComputeScreenPosIgnoreStereo(o.pos);
- return o;
- }
-
- fixed4 frag(v2f i) : SV_Target
- {
- UNITY_SETUP_INSTANCE_ID(i)
- fixed4 tex = tex2D(_MainTex, i.uv);
- fixed4 refl;
-
- bool leftEye = unity_StereoEyeIndex == 0;
- if (leftEye)
- {
- refl = tex2Dproj(_LeftReflectionTex, UNITY_PROJ_COORD(i.refl));
- }
- else
- {
- refl = tex2Dproj(_RightReflectionTex, UNITY_PROJ_COORD(i.refl));
- }
- return tex * refl;
- }
- ENDCG
- }
- }
-
- Fallback "VertexLit" // For the shadow caster
-}
\ No newline at end of file
diff --git a/MainGameVR/VRAssetBundles/Assets/MirrorReflection.shader.meta b/MainGameVR/VRAssetBundles/Assets/MirrorReflection.shader.meta
deleted file mode 100644
index 0783a11..0000000
--- a/MainGameVR/VRAssetBundles/Assets/MirrorReflection.shader.meta
+++ /dev/null
@@ -1,9 +0,0 @@
-fileFormatVersion: 2
-guid: 6ae78fa632a56c54ea116450a0709670
-timeCreated: 1694324919
-licenseType: Free
-ShaderImporter:
- defaultTextures: []
- userData:
- assetBundleName: mirror-shader
- assetBundleVariant:
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/AudioManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/AudioManager.asset
deleted file mode 100644
index 2c4f5a1..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/AudioManager.asset
+++ /dev/null
@@ -1,16 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!11 &1
-AudioManager:
- m_ObjectHideFlags: 0
- m_Volume: 1
- Rolloff Scale: 1
- Doppler Factor: 1
- Default Speaker Mode: 2
- m_SampleRate: 0
- m_DSPBufferSize: 0
- m_VirtualVoiceCount: 512
- m_RealVoiceCount: 32
- m_SpatializerPlugin:
- m_DisableAudio: 0
- m_VirtualizeEffects: 1
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/ClusterInputManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/ClusterInputManager.asset
deleted file mode 100644
index e7886b2..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/ClusterInputManager.asset
+++ /dev/null
@@ -1,6 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!236 &1
-ClusterInputManager:
- m_ObjectHideFlags: 0
- m_Inputs: []
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/DynamicsManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/DynamicsManager.asset
deleted file mode 100644
index 6be6910..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/DynamicsManager.asset
+++ /dev/null
@@ -1,18 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!55 &1
-PhysicsManager:
- m_ObjectHideFlags: 0
- serializedVersion: 3
- m_Gravity: {x: 0, y: -9.81, z: 0}
- m_DefaultMaterial: {fileID: 0}
- m_BounceThreshold: 2
- m_SleepThreshold: 0.005
- m_DefaultContactOffset: 0.01
- m_DefaultSolverIterations: 6
- m_DefaultSolverVelocityIterations: 1
- m_QueriesHitBackfaces: 0
- m_QueriesHitTriggers: 1
- m_EnableAdaptiveForce: 0
- m_EnablePCM: 1
- m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/EditorBuildSettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/EditorBuildSettings.asset
deleted file mode 100644
index 6dc24f7..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/EditorBuildSettings.asset
+++ /dev/null
@@ -1,7 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!1045 &1
-EditorBuildSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Scenes: []
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/EditorSettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/EditorSettings.asset
deleted file mode 100644
index 7f72f1b..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/EditorSettings.asset
+++ /dev/null
@@ -1,14 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!159 &1
-EditorSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 3
- m_ExternalVersionControlSupport: Visible Meta Files
- m_SerializationMode: 2
- m_DefaultBehaviorMode: 0
- m_SpritePackerMode: 0
- m_SpritePackerPaddingPower: 1
- m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd
- m_ProjectGenerationRootNamespace:
- m_UserGeneratedProjectSuffix:
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/GraphicsSettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/GraphicsSettings.asset
deleted file mode 100644
index d74737e..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/GraphicsSettings.asset
+++ /dev/null
@@ -1,62 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!30 &1
-GraphicsSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 12
- m_Deferred:
- m_Mode: 1
- m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
- m_DeferredReflections:
- m_Mode: 1
- m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
- m_ScreenSpaceShadows:
- m_Mode: 1
- m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
- m_LegacyDeferred:
- m_Mode: 1
- m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
- m_DepthNormals:
- m_Mode: 1
- m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
- m_MotionVectors:
- m_Mode: 1
- m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
- m_LightHalo:
- m_Mode: 1
- m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
- m_LensFlare:
- m_Mode: 1
- m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
- m_AlwaysIncludedShaders:
- - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
- - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
- - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
- - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
- - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0}
- m_PreloadedShaders: []
- m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
- type: 0}
- m_CustomRenderPipeline: {fileID: 0}
- m_TransparencySortMode: 0
- m_TransparencySortAxis: {x: 0, y: 0, z: 1}
- m_DefaultRenderingPath: 1
- m_DefaultMobileRenderingPath: 1
- m_TierSettings: []
- m_LightmapStripping: 0
- m_FogStripping: 0
- m_InstancingStripping: 0
- m_LightmapKeepPlain: 1
- m_LightmapKeepDirCombined: 1
- m_LightmapKeepDynamicPlain: 1
- m_LightmapKeepDynamicDirCombined: 1
- m_LightmapKeepShadowMask: 1
- m_LightmapKeepSubtractive: 1
- m_FogKeepLinear: 1
- m_FogKeepExp: 1
- m_FogKeepExp2: 1
- m_AlbedoSwatchInfos: []
- m_LightsUseLinearIntensity: 0
- m_LightsUseColorTemperature: 0
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/InputManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/InputManager.asset
deleted file mode 100644
index 17c8f53..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/InputManager.asset
+++ /dev/null
@@ -1,295 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!13 &1
-InputManager:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Axes:
- - serializedVersion: 3
- m_Name: Horizontal
- descriptiveName:
- descriptiveNegativeName:
- negativeButton: left
- positiveButton: right
- altNegativeButton: a
- altPositiveButton: d
- gravity: 3
- dead: 0.001
- sensitivity: 3
- snap: 1
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Vertical
- descriptiveName:
- descriptiveNegativeName:
- negativeButton: down
- positiveButton: up
- altNegativeButton: s
- altPositiveButton: w
- gravity: 3
- dead: 0.001
- sensitivity: 3
- snap: 1
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Fire1
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: left ctrl
- altNegativeButton:
- altPositiveButton: mouse 0
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Fire2
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: left alt
- altNegativeButton:
- altPositiveButton: mouse 1
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Fire3
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: left shift
- altNegativeButton:
- altPositiveButton: mouse 2
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Jump
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: space
- altNegativeButton:
- altPositiveButton:
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Mouse X
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton:
- altNegativeButton:
- altPositiveButton:
- gravity: 0
- dead: 0
- sensitivity: 0.1
- snap: 0
- invert: 0
- type: 1
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Mouse Y
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton:
- altNegativeButton:
- altPositiveButton:
- gravity: 0
- dead: 0
- sensitivity: 0.1
- snap: 0
- invert: 0
- type: 1
- axis: 1
- joyNum: 0
- - serializedVersion: 3
- m_Name: Mouse ScrollWheel
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton:
- altNegativeButton:
- altPositiveButton:
- gravity: 0
- dead: 0
- sensitivity: 0.1
- snap: 0
- invert: 0
- type: 1
- axis: 2
- joyNum: 0
- - serializedVersion: 3
- m_Name: Horizontal
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton:
- altNegativeButton:
- altPositiveButton:
- gravity: 0
- dead: 0.19
- sensitivity: 1
- snap: 0
- invert: 0
- type: 2
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Vertical
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton:
- altNegativeButton:
- altPositiveButton:
- gravity: 0
- dead: 0.19
- sensitivity: 1
- snap: 0
- invert: 1
- type: 2
- axis: 1
- joyNum: 0
- - serializedVersion: 3
- m_Name: Fire1
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: joystick button 0
- altNegativeButton:
- altPositiveButton:
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Fire2
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: joystick button 1
- altNegativeButton:
- altPositiveButton:
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Fire3
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: joystick button 2
- altNegativeButton:
- altPositiveButton:
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Jump
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: joystick button 3
- altNegativeButton:
- altPositiveButton:
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Submit
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: return
- altNegativeButton:
- altPositiveButton: joystick button 0
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Submit
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: enter
- altNegativeButton:
- altPositiveButton: space
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
- - serializedVersion: 3
- m_Name: Cancel
- descriptiveName:
- descriptiveNegativeName:
- negativeButton:
- positiveButton: escape
- altNegativeButton:
- altPositiveButton: joystick button 1
- gravity: 1000
- dead: 0.001
- sensitivity: 1000
- snap: 0
- invert: 0
- type: 0
- axis: 0
- joyNum: 0
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/NavMeshAreas.asset b/MainGameVR/VRAssetBundles/ProjectSettings/NavMeshAreas.asset
deleted file mode 100644
index 6dd520f..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/NavMeshAreas.asset
+++ /dev/null
@@ -1,89 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!126 &1
-NavMeshProjectSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- areas:
- - name: Walkable
- cost: 1
- - name: Not Walkable
- cost: 1
- - name: Jump
- cost: 2
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- - name:
- cost: 1
- m_LastAgentTypeID: -887442657
- m_Settings:
- - serializedVersion: 2
- agentTypeID: 0
- agentRadius: 0.5
- agentHeight: 2
- agentSlope: 45
- agentClimb: 0.75
- ledgeDropHeight: 0
- maxJumpAcrossDistance: 0
- minRegionArea: 2
- manualCellSize: 0
- cellSize: 0.16666667
- manualTileSize: 0
- tileSize: 256
- accuratePlacement: 0
- m_SettingNames:
- - Humanoid
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/NetworkManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/NetworkManager.asset
deleted file mode 100644
index 5dc6a83..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/NetworkManager.asset
+++ /dev/null
@@ -1,8 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!149 &1
-NetworkManager:
- m_ObjectHideFlags: 0
- m_DebugLevel: 0
- m_Sendrate: 15
- m_AssetToPrefab: {}
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/Physics2DSettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/Physics2DSettings.asset
deleted file mode 100644
index 5f6ffab..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/Physics2DSettings.asset
+++ /dev/null
@@ -1,35 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!19 &1
-Physics2DSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 3
- m_Gravity: {x: 0, y: -9.81}
- m_DefaultMaterial: {fileID: 0}
- m_VelocityIterations: 8
- m_PositionIterations: 3
- m_VelocityThreshold: 1
- m_MaxLinearCorrection: 0.2
- m_MaxAngularCorrection: 8
- m_MaxTranslationSpeed: 100
- m_MaxRotationSpeed: 360
- m_BaumgarteScale: 0.2
- m_BaumgarteTimeOfImpactScale: 0.75
- m_TimeToSleep: 0.5
- m_LinearSleepTolerance: 0.01
- m_AngularSleepTolerance: 2
- m_DefaultContactOffset: 0.01
- m_QueriesHitTriggers: 1
- m_QueriesStartInColliders: 1
- m_ChangeStopsCallbacks: 0
- m_CallbacksOnDisable: 1
- m_AlwaysShowColliders: 0
- m_ShowColliderSleep: 1
- m_ShowColliderContacts: 0
- m_ShowColliderAABB: 0
- m_ContactArrowScale: 0.2
- m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
- m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
- m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
- m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
- m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/ProjectSettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/ProjectSettings.asset
deleted file mode 100644
index ca84efd..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/ProjectSettings.asset
+++ /dev/null
@@ -1,589 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!129 &1
-PlayerSettings:
- m_ObjectHideFlags: 0
- serializedVersion: 11
- productGUID: eed6064fe0a601a4e99e68470b5c3824
- AndroidProfiler: 0
- defaultScreenOrientation: 4
- targetDevice: 2
- useOnDemandResources: 0
- accelerometerFrequency: 60
- companyName: DefaultCompany
- productName: VRAssetBundles
- defaultCursor: {fileID: 0}
- cursorHotspot: {x: 0, y: 0}
- m_SplashScreenBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21176471, a: 1}
- m_ShowUnitySplashScreen: 1
- m_ShowUnitySplashLogo: 1
- m_SplashScreenOverlayOpacity: 1
- m_SplashScreenAnimation: 1
- m_SplashScreenLogoStyle: 1
- m_SplashScreenDrawMode: 0
- m_SplashScreenBackgroundAnimationZoom: 1
- m_SplashScreenLogoAnimationZoom: 1
- m_SplashScreenBackgroundLandscapeAspect: 1
- m_SplashScreenBackgroundPortraitAspect: 1
- m_SplashScreenBackgroundLandscapeUvs:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- m_SplashScreenBackgroundPortraitUvs:
- serializedVersion: 2
- x: 0
- y: 0
- width: 1
- height: 1
- m_SplashScreenLogos: []
- m_SplashScreenBackgroundLandscape: {fileID: 0}
- m_SplashScreenBackgroundPortrait: {fileID: 0}
- m_VirtualRealitySplashScreen: {fileID: 0}
- m_HolographicTrackingLossScreen: {fileID: 0}
- defaultScreenWidth: 1024
- defaultScreenHeight: 768
- defaultScreenWidthWeb: 960
- defaultScreenHeightWeb: 600
- m_StereoRenderingPath: 0
- m_ActiveColorSpace: 0
- m_MTRendering: 1
- m_MobileMTRendering: 0
- m_StackTraceTypes: 010000000100000001000000010000000100000001000000
- iosShowActivityIndicatorOnLoading: -1
- androidShowActivityIndicatorOnLoading: -1
- tizenShowActivityIndicatorOnLoading: -1
- iosAppInBackgroundBehavior: 0
- displayResolutionDialog: 1
- iosAllowHTTPDownload: 1
- allowedAutorotateToPortrait: 1
- allowedAutorotateToPortraitUpsideDown: 1
- allowedAutorotateToLandscapeRight: 1
- allowedAutorotateToLandscapeLeft: 1
- useOSAutorotation: 1
- use32BitDisplayBuffer: 1
- disableDepthAndStencilBuffers: 0
- defaultIsFullScreen: 1
- defaultIsNativeResolution: 1
- runInBackground: 0
- captureSingleScreen: 0
- muteOtherAudioSources: 0
- Prepare IOS For Recording: 0
- submitAnalytics: 1
- usePlayerLog: 1
- bakeCollisionMeshes: 0
- forceSingleInstance: 0
- resizableWindow: 0
- useMacAppStoreValidation: 0
- macAppStoreCategory: public.app-category.games
- gpuSkinning: 0
- graphicsJobs: 0
- xboxPIXTextureCapture: 0
- xboxEnableAvatar: 0
- xboxEnableKinect: 0
- xboxEnableKinectAutoTracking: 0
- xboxEnableFitness: 0
- visibleInBackground: 0
- allowFullscreenSwitch: 1
- graphicsJobMode: 0
- macFullscreenMode: 2
- d3d9FullscreenMode: 1
- d3d11FullscreenMode: 1
- xboxSpeechDB: 0
- xboxEnableHeadOrientation: 0
- xboxEnableGuest: 0
- xboxEnablePIXSampling: 0
- n3dsDisableStereoscopicView: 0
- n3dsEnableSharedListOpt: 1
- n3dsEnableVSync: 0
- ignoreAlphaClear: 0
- xboxOneResolution: 0
- xboxOneMonoLoggingLevel: 0
- xboxOneLoggingLevel: 1
- videoMemoryForVertexBuffers: 0
- psp2PowerMode: 0
- psp2AcquireBGM: 1
- wiiUTVResolution: 0
- wiiUGamePadMSAA: 1
- wiiUSupportsNunchuk: 0
- wiiUSupportsClassicController: 0
- wiiUSupportsBalanceBoard: 0
- wiiUSupportsMotionPlus: 0
- wiiUSupportsProController: 0
- wiiUAllowScreenCapture: 1
- wiiUControllerCount: 0
- m_SupportedAspectRatios:
- 4:3: 1
- 5:4: 1
- 16:10: 1
- 16:9: 1
- Others: 1
- bundleVersion: 1.0
- preloadedAssets: []
- metroInputSource: 0
- m_HolographicPauseOnTrackingLoss: 1
- xboxOneDisableKinectGpuReservation: 0
- xboxOneEnable7thCore: 0
- vrSettings:
- cardboard:
- depthFormat: 0
- enableTransitionView: 0
- daydream:
- depthFormat: 0
- useSustainedPerformanceMode: 0
- hololens:
- depthFormat: 1
- protectGraphicsMemory: 0
- useHDRDisplay: 0
- applicationIdentifier: {}
- buildNumber: {}
- AndroidBundleVersionCode: 1
- AndroidMinSdkVersion: 16
- AndroidTargetSdkVersion: 0
- AndroidPreferredInstallLocation: 1
- aotOptions:
- stripEngineCode: 1
- iPhoneStrippingLevel: 0
- iPhoneScriptCallOptimization: 0
- ForceInternetPermission: 0
- ForceSDCardPermission: 0
- CreateWallpaper: 0
- APKExpansionFiles: 0
- keepLoadedShadersAlive: 0
- StripUnusedMeshComponents: 0
- VertexChannelCompressionMask:
- serializedVersion: 2
- m_Bits: 238
- iPhoneSdkVersion: 988
- iOSTargetOSVersionString:
- tvOSSdkVersion: 0
- tvOSRequireExtendedGameController: 0
- tvOSTargetOSVersionString:
- uIPrerenderedIcon: 0
- uIRequiresPersistentWiFi: 0
- uIRequiresFullScreen: 1
- uIStatusBarHidden: 1
- uIExitOnSuspend: 0
- uIStatusBarStyle: 0
- iPhoneSplashScreen: {fileID: 0}
- iPhoneHighResSplashScreen: {fileID: 0}
- iPhoneTallHighResSplashScreen: {fileID: 0}
- iPhone47inSplashScreen: {fileID: 0}
- iPhone55inPortraitSplashScreen: {fileID: 0}
- iPhone55inLandscapeSplashScreen: {fileID: 0}
- iPadPortraitSplashScreen: {fileID: 0}
- iPadHighResPortraitSplashScreen: {fileID: 0}
- iPadLandscapeSplashScreen: {fileID: 0}
- iPadHighResLandscapeSplashScreen: {fileID: 0}
- appleTVSplashScreen: {fileID: 0}
- tvOSSmallIconLayers: []
- tvOSLargeIconLayers: []
- tvOSTopShelfImageLayers: []
- tvOSTopShelfImageWideLayers: []
- iOSLaunchScreenType: 0
- iOSLaunchScreenPortrait: {fileID: 0}
- iOSLaunchScreenLandscape: {fileID: 0}
- iOSLaunchScreenBackgroundColor:
- serializedVersion: 2
- rgba: 0
- iOSLaunchScreenFillPct: 100
- iOSLaunchScreenSize: 100
- iOSLaunchScreenCustomXibPath:
- iOSLaunchScreeniPadType: 0
- iOSLaunchScreeniPadImage: {fileID: 0}
- iOSLaunchScreeniPadBackgroundColor:
- serializedVersion: 2
- rgba: 0
- iOSLaunchScreeniPadFillPct: 100
- iOSLaunchScreeniPadSize: 100
- iOSLaunchScreeniPadCustomXibPath:
- iOSDeviceRequirements: []
- iOSURLSchemes: []
- iOSBackgroundModes: 0
- iOSMetalForceHardShadows: 0
- metalEditorSupport: 1
- metalAPIValidation: 1
- iOSRenderExtraFrameOnPause: 0
- appleDeveloperTeamID:
- iOSManualSigningProvisioningProfileID:
- tvOSManualSigningProvisioningProfileID:
- appleEnableAutomaticSigning: 0
- AndroidTargetDevice: 0
- AndroidSplashScreenScale: 0
- androidSplashScreen: {fileID: 0}
- AndroidKeystoreName:
- AndroidKeyaliasName:
- AndroidTVCompatibility: 1
- AndroidIsGame: 1
- androidEnableBanner: 1
- m_AndroidBanners:
- - width: 320
- height: 180
- banner: {fileID: 0}
- androidGamepadSupportLevel: 0
- resolutionDialogBanner: {fileID: 0}
- m_BuildTargetIcons: []
- m_BuildTargetBatching: []
- m_BuildTargetGraphicsAPIs: []
- m_BuildTargetVRSettings: []
- openGLRequireES31: 0
- openGLRequireES31AEP: 0
- webPlayerTemplate: APPLICATION:Default
- m_TemplateCustomTags: {}
- wiiUTitleID: 0005000011000000
- wiiUGroupID: 00010000
- wiiUCommonSaveSize: 4096
- wiiUAccountSaveSize: 2048
- wiiUOlvAccessKey: 0
- wiiUTinCode: 0
- wiiUJoinGameId: 0
- wiiUJoinGameModeMask: 0000000000000000
- wiiUCommonBossSize: 0
- wiiUAccountBossSize: 0
- wiiUAddOnUniqueIDs: []
- wiiUMainThreadStackSize: 3072
- wiiULoaderThreadStackSize: 1024
- wiiUSystemHeapSize: 128
- wiiUTVStartupScreen: {fileID: 0}
- wiiUGamePadStartupScreen: {fileID: 0}
- wiiUDrcBufferDisabled: 0
- wiiUProfilerLibPath:
- playModeTestRunnerEnabled: 0
- actionOnDotNetUnhandledException: 1
- enableInternalProfiler: 0
- logObjCUncaughtExceptions: 1
- enableCrashReportAPI: 0
- cameraUsageDescription:
- locationUsageDescription:
- microphoneUsageDescription:
- switchNetLibKey:
- switchSocketMemoryPoolSize: 6144
- switchSocketAllocatorPoolSize: 128
- switchSocketConcurrencyLimit: 14
- switchScreenResolutionBehavior: 2
- switchUseCPUProfiler: 0
- switchApplicationID: 0x01004b9000490000
- switchNSODependencies:
- switchTitleNames_0:
- switchTitleNames_1:
- switchTitleNames_2:
- switchTitleNames_3:
- switchTitleNames_4:
- switchTitleNames_5:
- switchTitleNames_6:
- switchTitleNames_7:
- switchTitleNames_8:
- switchTitleNames_9:
- switchTitleNames_10:
- switchTitleNames_11:
- switchPublisherNames_0:
- switchPublisherNames_1:
- switchPublisherNames_2:
- switchPublisherNames_3:
- switchPublisherNames_4:
- switchPublisherNames_5:
- switchPublisherNames_6:
- switchPublisherNames_7:
- switchPublisherNames_8:
- switchPublisherNames_9:
- switchPublisherNames_10:
- switchPublisherNames_11:
- switchIcons_0: {fileID: 0}
- switchIcons_1: {fileID: 0}
- switchIcons_2: {fileID: 0}
- switchIcons_3: {fileID: 0}
- switchIcons_4: {fileID: 0}
- switchIcons_5: {fileID: 0}
- switchIcons_6: {fileID: 0}
- switchIcons_7: {fileID: 0}
- switchIcons_8: {fileID: 0}
- switchIcons_9: {fileID: 0}
- switchIcons_10: {fileID: 0}
- switchIcons_11: {fileID: 0}
- switchSmallIcons_0: {fileID: 0}
- switchSmallIcons_1: {fileID: 0}
- switchSmallIcons_2: {fileID: 0}
- switchSmallIcons_3: {fileID: 0}
- switchSmallIcons_4: {fileID: 0}
- switchSmallIcons_5: {fileID: 0}
- switchSmallIcons_6: {fileID: 0}
- switchSmallIcons_7: {fileID: 0}
- switchSmallIcons_8: {fileID: 0}
- switchSmallIcons_9: {fileID: 0}
- switchSmallIcons_10: {fileID: 0}
- switchSmallIcons_11: {fileID: 0}
- switchManualHTML:
- switchAccessibleURLs:
- switchLegalInformation:
- switchMainThreadStackSize: 1048576
- switchPresenceGroupId:
- switchLogoHandling: 0
- switchReleaseVersion: 0
- switchDisplayVersion: 1.0.0
- switchStartupUserAccount: 0
- switchTouchScreenUsage: 0
- switchSupportedLanguagesMask: 0
- switchLogoType: 0
- switchApplicationErrorCodeCategory:
- switchUserAccountSaveDataSize: 0
- switchUserAccountSaveDataJournalSize: 0
- switchApplicationAttribute: 0
- switchCardSpecSize: -1
- switchCardSpecClock: -1
- switchRatingsMask: 0
- switchRatingsInt_0: 0
- switchRatingsInt_1: 0
- switchRatingsInt_2: 0
- switchRatingsInt_3: 0
- switchRatingsInt_4: 0
- switchRatingsInt_5: 0
- switchRatingsInt_6: 0
- switchRatingsInt_7: 0
- switchRatingsInt_8: 0
- switchRatingsInt_9: 0
- switchRatingsInt_10: 0
- switchRatingsInt_11: 0
- switchLocalCommunicationIds_0:
- switchLocalCommunicationIds_1:
- switchLocalCommunicationIds_2:
- switchLocalCommunicationIds_3:
- switchLocalCommunicationIds_4:
- switchLocalCommunicationIds_5:
- switchLocalCommunicationIds_6:
- switchLocalCommunicationIds_7:
- switchParentalControl: 0
- switchAllowsScreenshot: 1
- switchDataLossConfirmation: 0
- switchSupportedNpadStyles: 3
- switchSocketConfigEnabled: 0
- switchTcpInitialSendBufferSize: 32
- switchTcpInitialReceiveBufferSize: 64
- switchTcpAutoSendBufferSizeMax: 256
- switchTcpAutoReceiveBufferSizeMax: 256
- switchUdpSendBufferSize: 9
- switchUdpReceiveBufferSize: 42
- switchSocketBufferEfficiency: 4
- ps4NPAgeRating: 12
- ps4NPTitleSecret:
- ps4NPTrophyPackPath:
- ps4ParentalLevel: 11
- ps4ContentID: ED1633-NPXX51362_00-0000000000000000
- ps4Category: 0
- ps4MasterVersion: 01.00
- ps4AppVersion: 01.00
- ps4AppType: 0
- ps4ParamSfxPath:
- ps4VideoOutPixelFormat: 0
- ps4VideoOutInitialWidth: 1920
- ps4VideoOutBaseModeInitialWidth: 1920
- ps4VideoOutReprojectionRate: 120
- ps4PronunciationXMLPath:
- ps4PronunciationSIGPath:
- ps4BackgroundImagePath:
- ps4StartupImagePath:
- ps4SaveDataImagePath:
- ps4SdkOverride:
- ps4BGMPath:
- ps4ShareFilePath:
- ps4ShareOverlayImagePath:
- ps4PrivacyGuardImagePath:
- ps4NPtitleDatPath:
- ps4RemotePlayKeyAssignment: -1
- ps4RemotePlayKeyMappingDir:
- ps4PlayTogetherPlayerCount: 0
- ps4EnterButtonAssignment: 1
- ps4ApplicationParam1: 0
- ps4ApplicationParam2: 0
- ps4ApplicationParam3: 0
- ps4ApplicationParam4: 0
- ps4DownloadDataSize: 0
- ps4GarlicHeapSize: 2048
- ps4ProGarlicHeapSize: 2560
- ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ
- ps4UseDebugIl2cppLibs: 0
- ps4pnSessions: 1
- ps4pnPresence: 1
- ps4pnFriends: 1
- ps4pnGameCustomData: 1
- playerPrefsSupport: 0
- restrictedAudioUsageRights: 0
- ps4UseResolutionFallback: 0
- ps4ReprojectionSupport: 0
- ps4UseAudio3dBackend: 0
- ps4SocialScreenEnabled: 0
- ps4ScriptOptimizationLevel: 3
- ps4Audio3dVirtualSpeakerCount: 14
- ps4attribCpuUsage: 0
- ps4PatchPkgPath:
- ps4PatchLatestPkgPath:
- ps4PatchChangeinfoPath:
- ps4PatchDayOne: 0
- ps4attribUserManagement: 0
- ps4attribMoveSupport: 0
- ps4attrib3DSupport: 0
- ps4attribShareSupport: 0
- ps4attribExclusiveVR: 0
- ps4disableAutoHideSplash: 0
- ps4videoRecordingFeaturesUsed: 0
- ps4contentSearchFeaturesUsed: 0
- ps4attribEyeToEyeDistanceSettingVR: 0
- ps4IncludedModules: []
- monoEnv:
- psp2Splashimage: {fileID: 0}
- psp2NPTrophyPackPath:
- psp2NPSupportGBMorGJP: 0
- psp2NPAgeRating: 12
- psp2NPTitleDatPath:
- psp2NPCommsID:
- psp2NPCommunicationsID:
- psp2NPCommsPassphrase:
- psp2NPCommsSig:
- psp2ParamSfxPath:
- psp2ManualPath:
- psp2LiveAreaGatePath:
- psp2LiveAreaBackroundPath:
- psp2LiveAreaPath:
- psp2LiveAreaTrialPath:
- psp2PatchChangeInfoPath:
- psp2PatchOriginalPackage:
- psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui
- psp2KeystoneFile:
- psp2MemoryExpansionMode: 0
- psp2DRMType: 0
- psp2StorageType: 0
- psp2MediaCapacity: 0
- psp2DLCConfigPath:
- psp2ThumbnailPath:
- psp2BackgroundPath:
- psp2SoundPath:
- psp2TrophyCommId:
- psp2TrophyPackagePath:
- psp2PackagedResourcesPath:
- psp2SaveDataQuota: 10240
- psp2ParentalLevel: 1
- psp2ShortTitle: Not Set
- psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF
- psp2Category: 0
- psp2MasterVersion: 01.00
- psp2AppVersion: 01.00
- psp2TVBootMode: 0
- psp2EnterButtonAssignment: 2
- psp2TVDisableEmu: 0
- psp2AllowTwitterDialog: 1
- psp2Upgradable: 0
- psp2HealthWarning: 0
- psp2UseLibLocation: 0
- psp2InfoBarOnStartup: 0
- psp2InfoBarColor: 0
- psp2UseDebugIl2cppLibs: 0
- psmSplashimage: {fileID: 0}
- splashScreenBackgroundSourceLandscape: {fileID: 0}
- splashScreenBackgroundSourcePortrait: {fileID: 0}
- spritePackerPolicy:
- webGLMemorySize: 256
- webGLExceptionSupport: 1
- webGLNameFilesAsHashes: 0
- webGLDataCaching: 0
- webGLDebugSymbols: 0
- webGLEmscriptenArgs:
- webGLModulesDirectory:
- webGLTemplate: APPLICATION:Default
- webGLAnalyzeBuildSize: 0
- webGLUseEmbeddedResources: 0
- webGLUseWasm: 0
- webGLCompressionFormat: 1
- scriptingDefineSymbols: {}
- platformArchitecture: {}
- scriptingBackend: {}
- incrementalIl2cppBuild: {}
- additionalIl2CppArgs:
- apiCompatibilityLevelPerPlatform: {}
- m_RenderingPath: 1
- m_MobileRenderingPath: 1
- metroPackageName: VRAssetBundles
- metroPackageVersion:
- metroCertificatePath:
- metroCertificatePassword:
- metroCertificateSubject:
- metroCertificateIssuer:
- metroCertificateNotAfter: 0000000000000000
- metroApplicationDescription: VRAssetBundles
- wsaImages: {}
- metroTileShortName:
- metroCommandLineArgsFile:
- metroTileShowName: 0
- metroMediumTileShowName: 0
- metroLargeTileShowName: 0
- metroWideTileShowName: 0
- metroDefaultTileSize: 1
- metroTileForegroundText: 2
- metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0}
- metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628,
- a: 1}
- metroSplashScreenUseBackgroundColor: 0
- platformCapabilities: {}
- metroFTAName:
- metroFTAFileTypes: []
- metroProtocolName:
- metroCompilationOverrides: 1
- tizenProductDescription:
- tizenProductURL:
- tizenSigningProfileName:
- tizenGPSPermissions: 0
- tizenMicrophonePermissions: 0
- tizenDeploymentTarget:
- tizenDeploymentTargetType: -1
- tizenMinOSVersion: 1
- n3dsUseExtSaveData: 0
- n3dsCompressStaticMem: 1
- n3dsExtSaveDataNumber: 0x12345
- n3dsStackSize: 131072
- n3dsTargetPlatform: 2
- n3dsRegion: 7
- n3dsMediaSize: 0
- n3dsLogoStyle: 3
- n3dsTitle: GameName
- n3dsProductCode:
- n3dsApplicationId: 0xFF3FF
- stvDeviceAddress:
- stvProductDescription:
- stvProductAuthor:
- stvProductAuthorEmail:
- stvProductLink:
- stvProductCategory: 0
- XboxOneProductId:
- XboxOneUpdateKey:
- XboxOneSandboxId:
- XboxOneContentId:
- XboxOneTitleId:
- XboxOneSCId:
- XboxOneGameOsOverridePath:
- XboxOnePackagingOverridePath:
- XboxOneAppManifestOverridePath:
- XboxOnePackageEncryption: 0
- XboxOnePackageUpdateGranularity: 2
- XboxOneDescription:
- XboxOneLanguage:
- - enus
- XboxOneCapability: []
- XboxOneGameRating: {}
- XboxOneIsContentPackage: 0
- XboxOneEnableGPUVariability: 0
- XboxOneSockets: {}
- XboxOneSplashScreen: {fileID: 0}
- XboxOneAllowedProductIds: []
- XboxOnePersistentLocalStorageSize: 0
- xboxOneScriptCompiler: 0
- vrEditorSettings:
- daydream:
- daydreamIconForeground: {fileID: 0}
- daydreamIconBackground: {fileID: 0}
- cloudServicesEnabled: {}
- facebookSdkVersion: 7.9.1
- apiCompatibilityLevel: 2
- cloudProjectId:
- projectName:
- organizationId:
- cloudEnabled: 0
- enableNewInputSystem: 0
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/ProjectVersion.txt b/MainGameVR/VRAssetBundles/ProjectSettings/ProjectVersion.txt
deleted file mode 100644
index 735bd8a..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/ProjectVersion.txt
+++ /dev/null
@@ -1 +0,0 @@
-m_EditorVersion: 5.6.2f1
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/QualitySettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/QualitySettings.asset
deleted file mode 100644
index 3b1bea2..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/QualitySettings.asset
+++ /dev/null
@@ -1,181 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!47 &1
-QualitySettings:
- m_ObjectHideFlags: 0
- serializedVersion: 5
- m_CurrentQuality: 5
- m_QualitySettings:
- - serializedVersion: 2
- name: Fastest
- pixelLightCount: 0
- shadows: 0
- shadowResolution: 0
- shadowProjection: 1
- shadowCascades: 1
- shadowDistance: 15
- shadowNearPlaneOffset: 3
- shadowCascade2Split: 0.33333334
- shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
- blendWeights: 1
- textureQuality: 1
- anisotropicTextures: 0
- antiAliasing: 0
- softParticles: 0
- softVegetation: 0
- realtimeReflectionProbes: 0
- billboardsFaceCameraPosition: 0
- vSyncCount: 0
- lodBias: 0.3
- maximumLODLevel: 0
- particleRaycastBudget: 4
- asyncUploadTimeSlice: 2
- asyncUploadBufferSize: 4
- excludedTargetPlatforms: []
- - serializedVersion: 2
- name: Fast
- pixelLightCount: 0
- shadows: 0
- shadowResolution: 0
- shadowProjection: 1
- shadowCascades: 1
- shadowDistance: 20
- shadowNearPlaneOffset: 3
- shadowCascade2Split: 0.33333334
- shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
- blendWeights: 2
- textureQuality: 0
- anisotropicTextures: 0
- antiAliasing: 0
- softParticles: 0
- softVegetation: 0
- realtimeReflectionProbes: 0
- billboardsFaceCameraPosition: 0
- vSyncCount: 0
- lodBias: 0.4
- maximumLODLevel: 0
- particleRaycastBudget: 16
- asyncUploadTimeSlice: 2
- asyncUploadBufferSize: 4
- excludedTargetPlatforms: []
- - serializedVersion: 2
- name: Simple
- pixelLightCount: 1
- shadows: 1
- shadowResolution: 0
- shadowProjection: 1
- shadowCascades: 1
- shadowDistance: 20
- shadowNearPlaneOffset: 3
- shadowCascade2Split: 0.33333334
- shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
- blendWeights: 2
- textureQuality: 0
- anisotropicTextures: 1
- antiAliasing: 0
- softParticles: 0
- softVegetation: 0
- realtimeReflectionProbes: 0
- billboardsFaceCameraPosition: 0
- vSyncCount: 1
- lodBias: 0.7
- maximumLODLevel: 0
- particleRaycastBudget: 64
- asyncUploadTimeSlice: 2
- asyncUploadBufferSize: 4
- excludedTargetPlatforms: []
- - serializedVersion: 2
- name: Good
- pixelLightCount: 2
- shadows: 2
- shadowResolution: 1
- shadowProjection: 1
- shadowCascades: 2
- shadowDistance: 40
- shadowNearPlaneOffset: 3
- shadowCascade2Split: 0.33333334
- shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
- blendWeights: 2
- textureQuality: 0
- anisotropicTextures: 1
- antiAliasing: 0
- softParticles: 0
- softVegetation: 1
- realtimeReflectionProbes: 1
- billboardsFaceCameraPosition: 1
- vSyncCount: 1
- lodBias: 1
- maximumLODLevel: 0
- particleRaycastBudget: 256
- asyncUploadTimeSlice: 2
- asyncUploadBufferSize: 4
- excludedTargetPlatforms: []
- - serializedVersion: 2
- name: Beautiful
- pixelLightCount: 3
- shadows: 2
- shadowResolution: 2
- shadowProjection: 1
- shadowCascades: 2
- shadowDistance: 70
- shadowNearPlaneOffset: 3
- shadowCascade2Split: 0.33333334
- shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
- blendWeights: 4
- textureQuality: 0
- anisotropicTextures: 2
- antiAliasing: 2
- softParticles: 1
- softVegetation: 1
- realtimeReflectionProbes: 1
- billboardsFaceCameraPosition: 1
- vSyncCount: 1
- lodBias: 1.5
- maximumLODLevel: 0
- particleRaycastBudget: 1024
- asyncUploadTimeSlice: 2
- asyncUploadBufferSize: 4
- excludedTargetPlatforms: []
- - serializedVersion: 2
- name: Fantastic
- pixelLightCount: 4
- shadows: 2
- shadowResolution: 2
- shadowProjection: 1
- shadowCascades: 4
- shadowDistance: 150
- shadowNearPlaneOffset: 3
- shadowCascade2Split: 0.33333334
- shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
- blendWeights: 4
- textureQuality: 0
- anisotropicTextures: 2
- antiAliasing: 2
- softParticles: 1
- softVegetation: 1
- realtimeReflectionProbes: 1
- billboardsFaceCameraPosition: 1
- vSyncCount: 1
- lodBias: 2
- maximumLODLevel: 0
- particleRaycastBudget: 4096
- asyncUploadTimeSlice: 2
- asyncUploadBufferSize: 4
- excludedTargetPlatforms: []
- m_PerPlatformDefaultQuality:
- Android: 2
- Nintendo 3DS: 5
- PS4: 5
- PSM: 5
- PSP2: 2
- Samsung TV: 2
- Standalone: 5
- Switch: 5
- Tizen: 2
- Web: 5
- WebGL: 3
- WiiU: 5
- Windows Store Apps: 5
- XboxOne: 5
- iPhone: 2
- tvOS: 2
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/TagManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/TagManager.asset
deleted file mode 100644
index 1c92a78..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/TagManager.asset
+++ /dev/null
@@ -1,43 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!78 &1
-TagManager:
- serializedVersion: 2
- tags: []
- layers:
- - Default
- - TransparentFX
- - Ignore Raycast
- -
- - Water
- - UI
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- m_SortingLayers:
- - name: Default
- uniqueID: 0
- locked: 0
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/TimeManager.asset b/MainGameVR/VRAssetBundles/ProjectSettings/TimeManager.asset
deleted file mode 100644
index 558a017..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/TimeManager.asset
+++ /dev/null
@@ -1,9 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!5 &1
-TimeManager:
- m_ObjectHideFlags: 0
- Fixed Timestep: 0.02
- Maximum Allowed Timestep: 0.33333334
- m_TimeScale: 1
- Maximum Particle Timestep: 0.03
diff --git a/MainGameVR/VRAssetBundles/ProjectSettings/UnityConnectSettings.asset b/MainGameVR/VRAssetBundles/ProjectSettings/UnityConnectSettings.asset
deleted file mode 100644
index ec1ab29..0000000
--- a/MainGameVR/VRAssetBundles/ProjectSettings/UnityConnectSettings.asset
+++ /dev/null
@@ -1,32 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!310 &1
-UnityConnectSettings:
- m_ObjectHideFlags: 0
- m_Enabled: 0
- m_TestMode: 0
- m_TestEventUrl:
- m_TestConfigUrl:
- m_TestInitMode: 0
- CrashReportingSettings:
- m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes
- m_Enabled: 0
- m_CaptureEditorExceptions: 1
- UnityPurchasingSettings:
- m_Enabled: 0
- m_TestMode: 0
- UnityAnalyticsSettings:
- m_Enabled: 0
- m_InitializeOnStartup: 1
- m_TestMode: 0
- m_TestEventUrl:
- m_TestConfigUrl:
- UnityAdsSettings:
- m_Enabled: 0
- m_InitializeOnStartup: 1
- m_TestMode: 0
- m_EnabledPlatforms: 4294967295
- m_IosGameId:
- m_AndroidGameId:
- PerformanceReportingSettings:
- m_Enabled: 0
diff --git a/MainGameVR/packages.config b/MainGameVR/packages.config
deleted file mode 100644
index 3a806ad..0000000
--- a/MainGameVR/packages.config
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/PatcherLoader/Loader.cs b/PatcherLoader/Loader.cs
new file mode 100644
index 0000000..8a12bbf
--- /dev/null
+++ b/PatcherLoader/Loader.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Reflection;
+using Mono.Cecil;
+using BepInEx;
+using BepInEx.Logging;
+using System.Diagnostics;
+using System.Linq;
+
+namespace PatcherLoader
+{
+ ///
+ /// This "patcher" doesn't patch any .NET assemblies. It just loads and
+ /// executes a native DLL, which applies some patches to in-memory native
+ /// code.
+ ///
+ /// This needs to be implemented as a preloading-time patcher rather than
+ /// a regular plugin because the latter doesn't run early enough in the
+ /// startup sequence of the game.
+ ///
+ public static class Loader
+ {
+ public static IEnumerable TargetDLLs => GetDLLs();
+
+ public static void Patch(AssemblyDefinition assembly)
+ {
+ }
+
+ private readonly static ManualLogSource logger
+ = Logger.CreateLogSource("KK_MainGameVR_Patcher");
+
+ private delegate void SetupAll();
+
+ private static IEnumerable GetDLLs()
+ {
+ var processName = Paths.ProcessName;
+ if ((processName != "Koikatu" && processName != "Koikatsu Party")
+ || (!Environment.CommandLine.Contains("--vr")
+ && !Process.GetProcesses().Where(p => p != null && p.ProcessName == "vrcompositor").Any()))
+ {
+ yield break;
+ }
+
+ var patcherPath = Path.Combine(
+ Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
+ "native_patcher.dll");
+
+ logger.LogInfo($"Loading {patcherPath}");
+
+ var hModule = NativeMethods.LoadLibraryW(patcherPath);
+ if (hModule == IntPtr.Zero)
+ {
+ logger.LogError($"Failed to load native DLL. Error code: {Marshal.GetLastWin32Error()}");
+ yield break;
+ }
+ var funPtr = NativeMethods.GetProcAddress(hModule, "setup_all");
+ if (funPtr == IntPtr.Zero)
+ {
+ logger.LogError($"GetProcAddress failed: {Marshal.GetLastWin32Error()}");
+ yield break;
+ }
+ var setupAll = (SetupAll)Marshal.GetDelegateForFunctionPointer(funPtr, typeof(SetupAll));
+ setupAll();
+
+ yield break;
+ }
+ }
+
+ internal static class NativeMethods
+ {
+ [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern IntPtr LoadLibraryW(string name);
+
+ [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
+ public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
+ }
+}
diff --git a/PatcherLoader/PatcherLoader.csproj b/PatcherLoader/PatcherLoader.csproj
new file mode 100644
index 0000000..0de68b4
--- /dev/null
+++ b/PatcherLoader/PatcherLoader.csproj
@@ -0,0 +1,72 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {7B4A46E3-629C-46CC-ADF4-8FE8FCED992D}
+ Library
+ Properties
+ PatcherLoader
+ PatcherLoader
+ v3.5
+ 512
+ true
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+ ..\packages\IllusionLibs.BepInEx.Harmony.2.2.0.1\lib\net35\0Harmony.dll
+ False
+
+
+ ..\packages\IllusionLibs.BepInEx.5.4.4\lib\net35\BepInEx.dll
+ False
+
+
+ ..\packages\IllusionLibs.BepInEx.Harmony.2.2.0.1\lib\net35\BepInEx.Harmony.dll
+ False
+
+
+ ..\packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.dll
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
\ No newline at end of file
diff --git a/PatcherLoader/Properties/AssemblyInfo.cs b/PatcherLoader/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9da7747
--- /dev/null
+++ b/PatcherLoader/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PatcherLoader")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PatcherLoader")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7b4a46e3-629c-46cc-adf4-8fe8fced992d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/PatcherLoader/packages.config b/PatcherLoader/packages.config
new file mode 100644
index 0000000..930e5ba
--- /dev/null
+++ b/PatcherLoader/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 754acd9..6a48d88 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# KKS_VR - VR Plugin for Koikatsu Sunshine
-A BepInEx plugin for Koikatsu Sunshine (KKS) that allows you to play both the main game and studio in VR.
+# KKS_VR - VR Plugin for Koikatsu and Koikatsu Sunshine
+A BepInEx plugin for Koikatsu (KK) and Koikatsu Sunshine (KKS) that allows you to play the main game and studio (Sunshine only) in VR.
The difference from the official VR modules is that you have access to the full game/studio, while the official modules have limited features and spotty mod support.
Currently only the standing (aka room-scale) mode is fully supported.
@@ -10,22 +10,150 @@ The studio part is a fork of the [KKS_CharaStudioVR](https://vr-erogamer.com/arc
## Prerequisites
-* Koikatsu Sunshine
+* Koikatsu or Koikatsu Sunshine
* Latest version of BepInEx 5.x and KKSAPI/ModdingAPI
* SteamVR
* A VR headset supported by SteamVR
* VR controllers
+
## Installation
1. Make sure BepInEx, KKSAPI and all their dependencies have been installed.
-2. Download the latest [release](https://github.com/IllusionMods/KKS_VR/releases).
+2. Download the latest [release](https://github.com/IllusionMods/KKS_VR/releases) for the corresponding game.
3. Extract the zip into the game folder (where the abdata and BepInEx folders are).
-4. Create a shortcut to KoikatsuSunshine.exe and/or CharaStudio.exe, and add `--vr` to the command line.
-
-## Control
-
-**Warning: This section was written for KK_MainGameVR and might not be accurate, especially in Studio.**
+4. Create a shortcut to Koikatu.exe and/or KoikatsuSunshine.exe and/or CharaStudio.exe, and add `--vr` to the command line.
+
+The game (not the studio) also can be launched without any added arguments if SteamVR is running.
+
+## Tips
+ * Be advised to set InterPupillary Distance (IPD) in the settings to change the scale of the world according to own taste and used hardware.
+ * If VR mode doesn't launch, make sure that neither of controllers is asleep during game launch.*
+
+## Controls Game
+### Overview
+
+There are two controllers for each hand with identical functional without any tools or modes.
+There is no input customization or helping texts. Designed to be able to do any action with a single hand.
+The only means of movement are native in-game functions and *GripMove*, no *Warp*.
+No double clicks, only *Short* or *LongPress* for buttons and *DirectionalInput* for *Touchpad*. The sole function of *Menu* button is to toggle the floating menu's visibility.
+
+The plugin assumes that VR controller has:
+* **Grip** used as a **Grab** button. Grabs things to move them around.
+* **Trigger** used as an **Action** button. Performs actions where applicable or completes their wait period if one is already queued but not yet determined whether it's a *Short* or *LongPress*.
+* **Touchpad** aka *Thumbstick* aka *Joystick* used as a **Generic** button. Never requires a click in non-centered positions.
+
+### Modules and their inputs:
+
+### GripMove
+Grab the world and move around oneself.
+Available in **Any Scene** as the last priority action i.e. when no better actions are available.
+* **Grip** to start *GripMove*.
+* **Trigger** while in *GripMove* to manipulate **Yaw** while using controller as an axis.
+* **Touchpad** while in *GripMove* with pressed *Trigger* to manipulate **Rotation** of the camera.
+* **Touchpad** while in *GripMove* without pressed *Trigger* to become **Upright**. Registers after *LongPress*.
+
+Has settings for stabilization. Depending on the context may behave differently.
+
+### Impersonation aka PoV
+Assume orientation of a character head and follow it loosely.
+Available in **H Scene** outside of character interactions.
+* **Touchpad** to start, stop, change or reset *Impersonation*. Registers after *LongPress*.
+* **Touchpad** while in *Impersonation* and in *GripMove* with pressed *Trigger* to set custom offset.
+
+Has settings for gender preferences and automatization.
+
+### Assisted kiss/lick
+Attach the camera to a partner's PoI to follow it.
+Available in **H Scene** when the camera is in direct proximity to the said PoI. Outside of the caress positions requires *GripMove*.
+* **Grip** while *Assisted* to start altered version of *GripMove* to acquire precise offsets on the fly. The long gap between the camera and the PoI will cause disengagement.
+* **Trigger** while *Assisted* and not in *GripMove* to stop the action and disengage.
+
+Has plenty of settings for customization.
+
+### Controller representation
+Native in-game items serving as the controller representation.
+Available in **Any Scene** as the last priority action i.e. when no better actions are available.
+They won't go inside of things easily, preferring instead to stick to the surface.
+* **Touchpad** with pressed *Trigger* to cycle available items.
+* **DirectionHorizontal** with pressed *Trigger* to cycle through item animations.
+
+### IK Manipulator aka Grasp
+Alter currently playing animation on the fly.
+Available in **H, Talk and Text Scenes** when interacting with a character i.e. controller is in close proximity to it.
+* **Grip** to start *Grasp* i.e. hold relevant bodyParts and reposition them with the controller movements.
+* **Trigger** while in *Grasp* and the visual cue of the held bodyPart is green to attach it.
+ Currently only to self/different character or controller. ~~Hand holding.~~
+* **Trigger** while in *Grasp* to extend the amount of held bodyParts, up to the whole character. Registers after *ShortPress*.
+* **Trigger** while in *Grasp* to extend the amount of held bodyParts temporarily. Registers after *LongPress*.
+* **Touchpad** while in *Grasp* to reset currently held bodyParts to default offsets.
+* **Touchpad** while not in *Grasp* to reset relevant bodyPart to the default offset. Registers after *LongPress*.
+* **Touchpad** while not in *Grasp* but in *Impersonation* to start or stop the synchronization of a relevant bodyPart with the controller. Registers after *LongPress*.
+* **DirectionHorizontal** while in *Grasp* and the main held bodyPart is the hand to scroll through it's animations. Goes full circle then resets to the animation's default.
+* **DirectionHorizontal** while in *Grasp* and holding the whole character to change *Yaw*.
+* **DirectionVertical** while in *Grasp* and holding the whole character to move in direction of the camera.
+* **DirectionVertical** while in *Grasp* to Show/Hide guide objects of held bodyParts. Temporarily overrides setting.
+
+Setting *Maintain limb orientation* changes drastically behavior of arms.
+
+### Menu interaction
+Available in **Any Scene** when aiming controller at the floating in-game *Menu*.
+* **Grip** to grab *Menu*.
+* **Touchpad** while holding *Menu* with pressed *Trigger* to abandon it in the world.
+* **DirectionHorizontal** while holding *Menu* to change it's size.
+* **DirectionVertical** while holding *Menu* to move it in controller direction.
+
+### H Interpreter
+Available in **H Scene**, relies heavily on [SensibleH](https://github.com/lotsofbears/KK_SensibleH), without it many functions will be unavailable.
+Described horizonal directions assume the right controller, for the left controller the directions will be mirrored.
+
+#### Generic
+* **DirectionLeft** to choose random position from the current category. Registers after *LongPress*. Add *Trigger* for any available position.
+* **DirectionRight** to enter *PointMove*. Registers after *LongPress*.
+* **DirectionVertical** on partner's bodyPart to (un)dress it.
+
+#### PointMove
+* **DirectionLeft** to exit *PointMove*.
+* **DirectionRight** to choose one at random and exit *PointMove*. Registers after *LongPress*.
+* **DirectionVertical** to scroll through available categories.
+
+#### Caress
+*AutoCaress* can be overtaken in any way by *Assisted kiss/lick*.
+* **Grip** on attached caress item while in *AutoCaress* to take the manual control.
+* **Trigger** on attached caress item to start *AutoCaress*. Registers after *LongPress*.
+* **Trigger** on attached caress item while in *AutoCaress* to stop it.
+* **Trigger** while in manual control of a caress item to squeeze. Might not always work if *AutoCaress* still runs some other item.
+* **DirectionDown** on attached caress item while not in *AutoCaress* to detach it.
+* **DirectionDown** while not in *AutoCaress* to prompt the partner to initiate the kiss. Limited to the caress positions. Registers after *LongPress*.
+* **DirectionHorizontal** on attached caress item to toggle it's visibility.
+* **DirectionHorizontal** while an attached caress item is present to scroll through animations. Limited to caress positions.
+
+#### Service, Intercourse
+* **DirectionUp** to insert, start, finish, change speed. Registers after *LongPress*.
+* **DirectionUp** with pressed *Trigger* to opt for an options without voice . Registers after *LongPress*.
+* **DirectionUp** with pressed *Touchpad* to opt for anal if applicable. Can be used with pressed *Trigger*. Registers after *LongPress*.
+* **DirectionDown** to set condom, pullout, stop, change to outside during climax, change speed. Registers after *LongPress*.
+* **DirectionHorizontal** to scroll through animations.
+
+### Talk/Text Interpreter
+Available in **Talk and Text Scenes**.
+* **Trigger** on partner's bodyPart to provoke a reaction.
+* **DirectionVertical** on partner's bodyPart to (un)dress it.
+* **DirectionVertical** to scroll buttons on the left side of the screen or choices from the text scenario.
+* **DirectionHorizontal** to select/deselect current button/category.
+* **DirectionHorizontal** to click on previous action. Registers after *LongPress*.
+* **DirectionHorizontal** while text is visible to advance the text scenario.
+* **DirectionHorizontal** while text is visible to toggle *Auto*. Registers after *LongPress*.
+
+### Roaming Interpreter
+Available in **Roaming Scene**.
+* **Trigger** to start locomotion.
+* **DirectionUp** to interact or speed up.
+* **DirectionDown** to crouch or stand up.
+* **Horizontal direction** to turn.
+
+## Controls Studio
+**Warning: This section was written for [KK_MainGameVR](https://github.com/mosirnik/KK_MainGameVR) and serves as a loose, vague reference for an actual functional.**
This plugin assumes that your VR controller has the following buttons/controls:
@@ -109,69 +237,6 @@ Just touching the touchpad or tilting the thumbstick won't be recognized.
Exceptions to this rule are mouse wheel scroll actions and rotate actions,
which only require touching.
-## Situation-specific controls
-
-**Warning: This section was written for KK_MainGameVR and might not be accurate, especially in Studio.**
-
-The school tool can be used when you need more complex interactions than simple
-mouse clicks.
-
-There are also a few types of context-specific controls, where you can interact
-directly with 3D objects using the controllers. This type of interaction does
-not require any specific tool to be selected. The tool icon disappears when
-such an interaction is available.
-
-Below is a list of situations that offer special controls.
-
-### Roaming
-
-In the Roaming mode, you can move around by using the school tool to walk
-(default: Trigger), and turn left and right (default: Touchpad left and right).
-You can also use the warp tool to teleport.
-
-You can use the school tool to simulate ordinary mouse and keyboard
-inputs, e.g. right click (default: touchpad center) for interacting with an
-object.
-
-Use the laser pointer (touchpad center) to open the middle-button menu.
-
-You can crouch by lowering your viewpoint relative to the floor. To do this,
-you can either physically move your head or use grab action to bring the
-floor closer. This behavior can be disabled in the config.
-
-### Talk scene
-
-When talking to a character, most interactions are done through the menu.
-In addition, you can touch or look at the character by putting one of the
-controllers at the position you want to touch/look at, then pulling the
-Trigger.
-
-### H scene
-
-Caressing can be done in the same way as touching in talk scenes. Additionally,
-you can switch to a different mode of caressing by pressing the Application
-menu button with the controller in place.
-
-Optionally, automatic touching can be enabled, so that you don't even need to
-pull the Trigger.
-
-You can also kiss or lick the female by moving your head to the right place.
-This can be turned off in the config.
-
-You can undress a female character by putting a controller on one of her
-clothing items, then pressing the touchpad. A single touchpad click will
-perform one level of undressing. If you press and hold the touchpad,
-move the controller away and then release the touchpad, it will completely
-remove that part of clothing.
-
-Unfortunately this direct undressing operation doesn't work as expected for
-all clothes because the plugin doesn't exactly know what parts of
-body each clothing item covers. You can always fall back to
-using the menu for clothing state changes.
-
-When changing location, you can use the green laser to point to a new location
-icon and pull the Trigger to confirm.
-
## Configuration
**Warning: This section was written for KK_MainGameVR and might not be accurate, especially in Studio.**
@@ -180,9 +245,6 @@ This plugin has a lot of configuration options. It is recommended that you use
[ConfigurationManager](https://github.com/BepInEx/BepInEx.ConfigurationManager),
which allows you to change settings of this plugin from within the game.
-Alternatively you can manually edit `BepInEx\config\mosirnik.kk-main-game-vr.cfg`
-with a text editor.
-
## Controller Support
At the moment, most VR controllers seem to work out of the box with this plugin.
diff --git a/Shared/AssemblyInfo.cs b/Shared/AssemblyInfo.cs
index db7544d..c37dc8a 100644
--- a/Shared/AssemblyInfo.cs
+++ b/Shared/AssemblyInfo.cs
@@ -1,8 +1,8 @@
using System.Reflection;
-using KKS_VR;
+using KK_VR;
[assembly: AssemblyTitle(VRPlugin.Name)]
-[assembly: AssemblyDescription("Adds VR support. Launch the game with a --vr switch to enable the plugin.")]
+[assembly: AssemblyDescription("Adds VR support. Launch the game with running SteamVR.")]
[assembly: AssemblyCompany("https://github.com/IllusionMods/KKS_VR")]
[assembly: AssemblyProduct(VRPlugin.Name)]
[assembly: AssemblyCopyright("Copyright © 2020, 2021")]
diff --git a/MainGameVR/Camera/ActionCameraControl.cs b/Shared/Camera/ActionCameraControl.cs
similarity index 67%
rename from MainGameVR/Camera/ActionCameraControl.cs
rename to Shared/Camera/ActionCameraControl.cs
index 8423e55..007ef53 100644
--- a/MainGameVR/Camera/ActionCameraControl.cs
+++ b/Shared/Camera/ActionCameraControl.cs
@@ -3,11 +3,11 @@
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
-using KKS_VR.Interpreters;
+using KK_VR.Interpreters;
using UnityEngine;
using VRGIN.Core;
-namespace KKS_VR.Camera
+namespace KK_VR.Camera
{
///
/// This component takes over control of an Action camera.
@@ -83,51 +83,64 @@ public static Transform GetIdealTransformFor(Component c)
return GetIdealTransformForObject(c.gameObject);
}
- public static Transform GetIdealTransformForObject(GameObject o)
+ public static Transform GetIdealTransformForObject(GameObject gameObject)
{
// TODO: cache?
- var control = o.GetComponent();
+#if KK
+ var control = gameObject.GetComponent();
if (control != null)
+#elif KKS
+ if (gameObject.TryGetComponent(out var control))
+#endif
+ {
return control.VRIdealCamera;
+ }
else
- return o.transform;
+ {
+ return gameObject.transform;
+ }
}
public static void SetIdealPositionAndRotation(Transform t, Vector3 position, Quaternion rotation)
{
- if (position.Equals(Vector3.zero))
+ // No clue how it all works, but this way atleast it works.
+ if (!position.Equals(Vector3.zero))
{
- VRLog.Warn("position=0,0,0 in " + new StackTrace());
- return;
+ GetIdealTransformFor(t).SetPositionAndRotation(position, rotation);
}
+ }
+ //public static void SetIdealPositionAndRotation(Transform t, Vector3 position, Quaternion rotation)
+ //{
+ // if (position.Equals(Vector3.zero))
+ // {
+ // VRLog.Warn("position=0,0,0 in " + new StackTrace());
+ // return;
+ // }
- if (TalkScene.isPaly)
- {
- // todo keep old height?
- var heroine = TalkScene.instance.targetHeroine.transform;
- var newPosition = heroine.TransformPoint(new Vector3(0, GetPlayerHeight(), TalkSceneInterpreter.TalkDistance));
- if (HeadIsAwayFromPosition(newPosition))
- GetIdealTransformFor(t).SetPositionAndRotation(newPosition, heroine.rotation * Quaternion.Euler(0, 180f, 0));
- }
- else
- {
- var add = rotation.eulerAngles.normalized * 1f;
- add.y = 0;
- var added = position + add;
+ // if (TalkScene.isPaly)
+ // {
+ // VRLog.Debug($"SetIdealPositionAndRotation[isPaly]");
+ // // todo keep old height?
+ // var heroine = TalkScene.instance.targetHeroine.transform;
+ // var newPosition = heroine.TransformPoint(new Vector3(0, GetPlayerHeight(), TalkSceneInterpreter.TalkDistance));
+ // if (HeadIsAwayFromPosition(newPosition))
+ // GetIdealTransformFor(t).SetPositionAndRotation(newPosition, rotation);// , heroine.rotation * Quaternion.Euler(0, 180f, 0));
+ // }
+ // else
+ // {
+ // var add = rotation.eulerAngles.normalized * 1f;
+ // add.y = 0;
+ // var added = position + add;
- // breaks position at talk scene start
- //if (HeadIsAwayFromPosition(added))
- GetIdealTransformFor(t).SetPositionAndRotation(added, rotation);
- }
- }
+ // // breaks position at talk scene start
+ // //if (HeadIsAwayFromPosition(added))
+ // GetIdealTransformFor(t).SetPositionAndRotation(added, rotation);
+ // }
+ //}
public static float GetPlayerHeight()
{
- //todo setting?
- //var playerHeight = VR.Camera.Head.position.y - VR.Camera.Origin.position.y;
- //Console.WriteLine("height: " + playerHeight);
- //return playerHeight;
- return 1.4f;
+ return TalkSceneInterpreter.height != 0f ? TalkSceneInterpreter.height : 1.4f;
}
public static bool HeadIsAwayFromPosition(Vector3 targetPosition)
@@ -137,8 +150,8 @@ public static bool HeadIsAwayFromPosition(Vector3 targetPosition)
public static float GetDistanceFromCurrentHeadPos(Vector3 targetPosition)
{
- var dist = Vector3.Distance(targetPosition, VR.Camera.SteamCam.head.position);
- VRLog.Debug("Distance of head from pos={0} is {1}", targetPosition, dist);
+ var dist = Vector3.Distance(targetPosition, VR.Camera.Head.position);
+ //VRLog.Debug("Distance of head from pos={0} is {1}", targetPosition, dist);
return dist;
}
}
@@ -217,58 +230,58 @@ private static void PreSetNull(ref Transform transform)
}
}
- // todo different lambda in kks
- //[HarmonyPatch]
- //class TalkScenePatches
- //{
- // static IEnumerable TargetMethods()
- // {
- // // Our target is a particular lambda defined in TalkScene.Start.
- // // The code below is ugly and fragile, but there doesn't seem to be
- // // any good alternative.
- // var nested1 = typeof(TalkScene).GetNestedType("c__Iterator0", BindingFlags.NonPublic);
- // if (nested1 == null)
- // {
- // VRLog.Error("nested1 is null!");
- // yield break;
- // }
- //
- // var nested2 = nested1.GetNestedType("c__AnonStorey8", BindingFlags.NonPublic);
- // if (nested2 == null)
- // {
- // VRLog.Error("nested2 is null");
- // yield break;
- // }
- //
- // yield return AccessTools.Method(nested2, "<>m__3");
- // }
- //
- // static IEnumerable Transpiler(IEnumerable code)
- // {
- // // Replace the second (!) call to Transform.SetPositionAndRotation.
- // // This is laughably fragile, but it doesn't seem worthwhile to
- // // make it more robust until an actual conflict is reported...
- // int found = 0;
- // foreach (var inst in code)
- // {
- // if ((inst.opcode == OpCodes.Call || inst.opcode == OpCodes.Callvirt) &&
- // inst.operand is MethodInfo method &&
- // method.ReflectedType == typeof(Transform) &&
- // method.Name == "SetPositionAndRotation" &&
- // found++ == 1)
- // {
- // yield return new CodeInstruction(
- // OpCodes.Call,
- // AccessTools.Method(typeof(ActionCameraControl), nameof(ActionCameraControl.SetIdealPositionAndRotation)));
- // }
- // else
- // {
- // yield return inst;
- // }
- // }
- // }
- //
- //}
+#if KK
+ [HarmonyPatch]
+ class TalkScenePatches
+ {
+ static IEnumerable TargetMethods()
+ {
+ // Our target is a particular lambda defined in TalkScene.Start.
+ // The code below is ugly and fragile, but there doesn't seem to be
+ // any good alternative.
+ var nested1 = typeof(TalkScene).GetNestedType("c__Iterator0", BindingFlags.NonPublic);
+ if (nested1 == null)
+ {
+ VRLog.Error("nested1 is null!");
+ yield break;
+ }
+
+ var nested2 = nested1.GetNestedType("c__AnonStorey8", BindingFlags.NonPublic);
+ if (nested2 == null)
+ {
+ VRLog.Error("nested2 is null");
+ yield break;
+ }
+
+ yield return AccessTools.Method(nested2, "<>m__3");
+ }
+
+ static IEnumerable Transpiler(IEnumerable code)
+ {
+ // Replace the second (!) call to Transform.SetPositionAndRotation.
+ // This is laughably fragile, but it doesn't seem worthwhile to
+ // make it more robust until an actual conflict is reported...
+ int found = 0;
+ foreach (var inst in code)
+ {
+ if ((inst.opcode == OpCodes.Call || inst.opcode == OpCodes.Callvirt) &&
+ inst.operand is MethodInfo method &&
+ method.ReflectedType == typeof(Transform) &&
+ method.Name == "SetPositionAndRotation" &&
+ found++ == 1)
+ {
+ yield return new CodeInstruction(
+ OpCodes.Call,
+ AccessTools.Method(typeof(ActionCameraControl), nameof(ActionCameraControl.SetIdealPositionAndRotation)));
+ }
+ else
+ {
+ yield return inst;
+ }
+ }
+ }
+ }
+#endif
[HarmonyPatch(typeof(ADV.EventCG.Data))]
internal class EventCGDataPatches
diff --git a/MainGameVR/Camera/BackgroundDisplayer.cs b/Shared/Camera/BackgroundDisplayer.cs
similarity index 95%
rename from MainGameVR/Camera/BackgroundDisplayer.cs
rename to Shared/Camera/BackgroundDisplayer.cs
index 1031ddb..26d577d 100644
--- a/MainGameVR/Camera/BackgroundDisplayer.cs
+++ b/Shared/Camera/BackgroundDisplayer.cs
@@ -3,7 +3,7 @@
using UnityEngine.UI;
using VRGIN.Core;
-namespace KKS_VR.Camera
+namespace KK_VR.Camera
{
///
/// A singleton object that is responsible for displaying the
@@ -39,7 +39,10 @@ public void OnCameraMove()
public void TakeCanvas(Canvas canvas)
{
VRLog.Info("Taking canvas: {0}", canvas.name);
- if (_bgCanvas != null) VRLog.Warn($"Taking a second canvas? {_bgCanvas}");
+ if (_bgCanvas != null)
+ {
+ VRLog.Warn($"Taking a second canvas? {_bgCanvas}");
+ }
canvas.renderMode = RenderMode.WorldSpace;
canvas.worldCamera = null;
canvas.gameObject.layer = 0;
@@ -53,7 +56,10 @@ public void TakeCanvas(Canvas canvas)
private void UpdateCanvasPlacement()
{
- if (_bgCanvas == null) return;
+ if (_bgCanvas == null)
+ {
+ return;
+ }
var level = Mathf.Clamp(EyeLevel, 0.25f, 0.75f);
var y = (0.5f - level) * Height;
diff --git a/MainGameVR/Camera/CameraControlControl.cs b/Shared/Camera/CameraControlControl.cs
similarity index 84%
rename from MainGameVR/Camera/CameraControlControl.cs
rename to Shared/Camera/CameraControlControl.cs
index ba5c96b..9fd883e 100644
--- a/MainGameVR/Camera/CameraControlControl.cs
+++ b/Shared/Camera/CameraControlControl.cs
@@ -1,6 +1,6 @@
using VRGIN.Core;
-namespace KKS_VR.Camera
+namespace KK_VR.Camera
{
///
/// CameraControlControl disables a CameraControl_Ver2 object and
@@ -31,7 +31,10 @@ internal class CameraControlControl : ProtectedBehaviour
protected override void OnStart()
{
_control = GetComponent();
- if (_control == null) VRLog.Error("CameraControlControl: CameraControl_Ver2 was not found");
+ if (_control == null)
+ {
+ VRLog.Error("CameraControlControl: CameraControl_Ver2 was not found");
+ }
if (_control.enabled)
_control.enabled = false;
@@ -45,12 +48,18 @@ protected override void OnUpdate()
transform.SetPositionAndRotation(head.position, head.rotation);
// One of the default macros from GameObjectList enables the camera
// control. We make sure that it remains desabled.
- if (_control != null) _control.enabled = false;
+ if (_control != null)
+ {
+ _control.enabled = false;
+ }
}
protected override void OnLateUpdate()
{
- if (_control.isCursorLock && Singleton.IsInstance()) Singleton.Instance.SetCursorLock(false);
+ if (_control.isCursorLock && Singleton.IsInstance())
+ {
+ Singleton.Instance.SetCursorLock(false);
+ }
}
}
}
diff --git a/Shared/Camera/CameraMoveHooks.cs b/Shared/Camera/CameraMoveHooks.cs
new file mode 100644
index 0000000..e51f379
--- /dev/null
+++ b/Shared/Camera/CameraMoveHooks.cs
@@ -0,0 +1,306 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using HarmonyLib;
+using IllusionUtility.SetUtility;
+using KK_VR.Caress;
+using KK_VR.Features;
+using KK_VR.Grasp;
+using KK_VR.Interactors;
+using KK_VR.Interpreters;
+using UnityEngine;
+using VRGIN.Core;
+
+// This file is a collection of hooks to move the VR camera at appropriate
+// points of the game.
+
+namespace KK_VR.Camera
+{
+ [HarmonyPatch]
+ internal class TextScenarioPatches1
+ {
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(ADV.TextScenario), nameof(ADV.TextScenario.ADVCameraSetting))]
+ private static void PostADVCameraSetting(ADV.TextScenario __instance)
+ {
+#if KK
+
+ if (Manager.Scene.IsInstance() && Manager.Scene.Instance.NowSceneNames[0] == "Talk")
+#elif KKS
+ if (Manager.Scene.initialized && Manager.Scene.NowSceneNames[0] == "Talk")
+#endif
+ {
+ // Talk scenes are handled separately.
+ return;
+ }
+
+ VRLog.Debug("PostADVCameraSetting");
+ var backTrans = __instance.BackCamera?.transform;
+ if (backTrans == null)
+ {
+ // backTrans can be null in Roaming. We don't want to move the
+ // camera anyway in that case.
+ return;
+ }
+ VRCameraMover.Instance.MaybeMoveADV(__instance, backTrans.position, backTrans.rotation);
+ }
+ }
+
+ [HarmonyPatch]
+ internal class RequestNextLinePatches
+ {
+ private static IEnumerable TargetMethods()
+ {
+ // In some versions of the base game, MainScenario._RequestNextLine
+ // duplicates the logic found in TextScenario._RequestNextLine.
+ // In other versions, the former simply calls the latter.
+ // We want to patch both methods or the latter alone depending on
+ // the version.
+ yield return AccessTools.Method(typeof(ADV.TextScenario), "_RequestNextLine");
+ if (AccessTools.Field(typeof(ADV.MainScenario), "textHash") == null)
+ {
+ yield return AccessTools.Method(typeof(ADV.MainScenario), "_RequestNextLine");
+ }
+ }
+
+ private static void Postfix(ADV.TextScenario __instance, ref IEnumerator __result)
+ {
+#if KK
+
+ if (Manager.Scene.IsInstance() && Manager.Scene.Instance.NowSceneNames[0] == "Talk")
+#elif KKS
+ if (Manager.Scene.initialized && Manager.Scene.NowSceneNames[0] == "Talk")
+#endif
+ {
+ // Talk scenes are handled separately.
+ return;
+ }
+ if (__instance.advScene == null)
+ {
+ // Outside ADV scene (probably roaming), ignore.
+ return;
+ }
+ __result = new[] { __result, Postfix() }.GetEnumerator();
+
+ IEnumerator Postfix()
+ {
+ VRCameraMover.Instance.HandleTextScenarioProgress(__instance);
+ yield break;
+ }
+ }
+ }
+
+ [HarmonyPatch]
+ internal class ProgramPatches1
+ {
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(ADV.Program), nameof(ADV.Program.SetNull))]
+ private static void PostSetNull(Transform transform)
+ {
+ VRLog.Debug("PostSetNull");
+ VRCameraMover.Instance.MaybeMoveTo(transform.position, transform.rotation);
+ }
+
+#if KKS
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(HSceneProc), nameof(HSceneProc.ChangeAnimator))]
+ public static void ChangeAnimatorPrefix(HSceneProc __instance)
+ {
+ __instance.ctrlObi.solver.gameObject.SetActive(true);
+ }
+#endif
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(HSceneProc), nameof(HSceneProc.ChangeAnimator))]
+ public static void PostChangeAnimator(HSceneProc.AnimationListInfo _nextAinmInfo, bool _isForceCameraReset, HSceneProc __instance, List ___lstFemale)
+ {
+ HSceneInterpreter.OnPoseChange(_nextAinmInfo);
+ UpdateVRCamera(__instance, ___lstFemale);
+#if KKS
+ Fixes.ObiCtrlFix.SetFluidsState(false);
+#endif
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(HSceneProc), nameof(HSceneProc.ChangeCategory))]
+ public static void PostChangeCategory(HSceneProc __instance, List ___lstFemale)//, float __state)
+ {
+ HSceneInterpreter.OnSpotChange();
+ UpdateVRCamera(__instance, ___lstFemale);
+
+#if KKS
+ Fixes.ObiCtrlFix.SetFluidsState(false);
+#endif
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(typeof(HSceneProc), nameof(HSceneProc.GotoPointMoveScene))]
+ public static void GotoPointMoveScenePostfix()
+ {
+ if (SmoothMover.Instance != null)
+ {
+ SmoothMover.Instance.MakeUpright();
+ }
+ }
+
+ private static void UpdateVRCamera(HSceneProc instance, List lstFemale)
+ {
+ var spotChange = Vector3.Distance(VR.Camera.transform.position, lstFemale[0].transform.position) > 2f;
+ //VRPlugin.Logger.LogDebug($"UpdateVRCamera:spotChange = {spotChange}");
+ var baseTransform = lstFemale[0].objTop.transform;
+ var camDat = instance.flags.ctrlCamera.CamDat;// new Traverse(instance.flags.ctrlCamera).Field("CamDat").Value;
+ var cameraRotation = baseTransform.rotation * Quaternion.Euler(camDat.Rot);
+ Vector3 dir;
+ switch (instance.flags.mode)
+ {
+ case HFlag.EMode.masturbation:
+ case HFlag.EMode.peeping:
+ case HFlag.EMode.lesbian:
+ // Use the default distance for 3rd-person scenes.
+ dir = camDat.Dir;
+ break;
+ default:
+ // Start closer otherwise.
+ dir = Vector3.back * 0.8f;
+ break;
+ }
+
+ var cameraPosition = cameraRotation * dir + baseTransform.TransformPoint(camDat.Pos);
+ //if (previousFemaleY is float prevY)
+ //{
+ // // Keep the relative Y coordinate from the female.
+ // var cameraHeight = VR.Camera.transform.position.y + baseTransform.position.y - prevY;
+ // var destination = new Vector3(cameraPosition.x, cameraHeight, cameraPosition.z);
+
+ // if (VRMoverH.Instance != null && VRMoverH.Instance._settings.FlyInH)
+ // {
+ // VRMoverH.Instance.MoveToInH(position: destination);
+ // }
+ // else
+ // {
+ // VRCameraMover.Instance.MaybeMoveTo(destination, cameraRotation, false);
+ // }
+ //}
+ //else
+ {
+ // We are starting from scratch.
+ // TODO: the height calculation below assumes standing mode.
+
+ if (KoikatuInterpreter.Settings.SmoothTransition && SmoothMover.Instance != null && !VRFade.IsFade)
+ {
+ SmoothMover.Instance.MoveToInH(cameraPosition, cameraRotation, spotChange);
+ }
+ else
+ {
+ var cameraHeight = lstFemale[0].transform.position.y + VR.Camera.transform.localPosition.y;
+ var destination = new Vector3(cameraPosition.x, cameraHeight, cameraPosition.z);
+ VRCameraMover.Instance.MoveTo(destination, cameraRotation);
+ }
+
+
+ }
+ }
+ }
+
+ //[HarmonyPatch(typeof(HSceneProc))]
+ //internal class HSceneProcPatches
+ //{
+
+
+ // //[HarmonyPatch("ChangeAnimator")]
+ // //[HarmonyPostfix]
+ // //public static void PostChangeAnimator(HSceneProc.AnimationListInfo _nextAinmInfo, bool _isForceCameraReset, HSceneProc __instance, List ___lstFemale)
+ // //{
+ // // UpdateVRCamera(__instance, ___lstFemale, null);
+ // // HSceneInterpreter.OnPoseChange(_nextAinmInfo);
+
+ // // Fixes.ObiCtrlFix.SetFluidsState(false);
+ // //}
+
+
+ // //[HarmonyPatch("ChangeCategory")]
+ // //[HarmonyPrefix]
+ // //public static void PreChangeCategory()
+ // //{
+ // // if (GraspHelper.Instance != null) GraspHelper.Instance.OnSpotChangePre();
+ // //}
+
+ // //[HarmonyPatch("ChangeCategory")]
+ // //[HarmonyPostfix]
+ // //public static void PostChangeCategory(HSceneProc __instance, List ___lstFemale)//, float __state)
+ // //{
+ // // if (KoikatuInterpreter.SceneInterpreter is HSceneInterpreter hScene)
+ // // hScene.OnSpotChangePost();
+ // // UpdateVRCamera(__instance, ___lstFemale, null);// __state);
+
+ // // Fixes.ObiCtrlFix.SetFluidsState(false);
+ // //}
+ // //[HarmonyPatch(nameof(HSceneProc.GotoPointMoveScene))]
+ // //[HarmonyPostfix]
+ // //public static void GotoPointMoveScenePostfix()
+ // //{
+ // // if (VRMoverH.Instance != null)
+ // // {
+ // // VRMoverH.Instance.MakeUpright();
+ // // }
+ // //}
+
+ // ///
+ // /// Update the transform of the VR camera.
+ // ///
+ // //private static void UpdateVRCamera(HSceneProc instance, List lstFemale, float? previousFemaleY)
+ // //{
+ // // var baseTransform = lstFemale[0].objTop.transform;
+ // // var camDat = instance.flags.ctrlCamera.CamDat;// new Traverse(instance.flags.ctrlCamera).Field("CamDat").Value;
+ // // var cameraRotation = baseTransform.rotation * Quaternion.Euler(camDat.Rot);
+ // // Vector3 dir;
+ // // switch (instance.flags.mode)
+ // // {
+ // // case HFlag.EMode.masturbation:
+ // // case HFlag.EMode.peeping:
+ // // case HFlag.EMode.lesbian:
+ // // // Use the default distance for 3rd-person scenes.
+ // // dir = camDat.Dir;
+ // // break;
+ // // default:
+ // // // Start closer otherwise.
+ // // dir = Vector3.back * 0.8f;
+ // // break;
+ // // }
+
+ // // var cameraPosition = cameraRotation * dir + baseTransform.TransformPoint(camDat.Pos);
+ // // //if (previousFemaleY is float prevY)
+ // // //{
+ // // // // Keep the relative Y coordinate from the female.
+ // // // var cameraHeight = VR.Camera.transform.position.y + baseTransform.position.y - prevY;
+ // // // var destination = new Vector3(cameraPosition.x, cameraHeight, cameraPosition.z);
+
+ // // // if (VRMoverH.Instance != null && VRMoverH.Instance._settings.FlyInH)
+ // // // {
+ // // // VRMoverH.Instance.MoveToInH(position: destination);
+ // // // }
+ // // // else
+ // // // {
+ // // // VRCameraMover.Instance.MaybeMoveTo(destination, cameraRotation, false);
+ // // // }
+ // // //}
+ // // //else
+ // // {
+ // // // We are starting from scratch.
+ // // // TODO: the height calculation below assumes standing mode.
+
+ // // if (VRMoverH.Instance != null && KoikatuInterpreter.settings.FlyInH)
+ // // {
+ // // VRMoverH.Instance.MoveToInH(cameraPosition, cameraRotation, previousFemaleY == null, instance.flags.mode);
+ // // }
+ // // else
+ // // {
+ // // var cameraHeight = lstFemale[0].transform.position.y + VR.Camera.transform.localPosition.y;
+ // // var destination = new Vector3(cameraPosition.x, cameraHeight, cameraPosition.z);
+ // // VRCameraMover.Instance.MoveTo(destination, cameraRotation);
+ // // }
+
+
+ // // }
+ // //}
+ //}
+}
diff --git a/Shared/Camera/MoveToPoi.cs b/Shared/Camera/MoveToPoi.cs
new file mode 100644
index 0000000..6dbd185
--- /dev/null
+++ b/Shared/Camera/MoveToPoi.cs
@@ -0,0 +1,344 @@
+using KK_VR.Interpreters;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using VRGIN.Core;
+using Random = UnityEngine.Random;
+
+namespace KK_VR.Camera
+{
+ ///
+ /// Provides movement to a predefined poi of the provided character.
+ ///
+ internal class MoveToPoi
+ {
+ private struct PoIPatternInfo
+ {
+ internal string teleportTo;
+ internal List lookAt;
+ internal float forwardMin;
+ internal float forwardMax;
+ internal float upMin;
+ internal float upMax;
+ internal float rightMin;
+ internal float rightMax;
+ }
+ internal MoveToPoi(ChaControl chara, Action onFinish)
+ {
+ var dicValue = _poiDic.ElementAt(Random.Range(0, _poiDic.Count)).Value;
+
+ var transforms = chara.transform.GetComponentsInChildren(includeInactive: true);
+ _teleportTo = transforms
+ .Where(t => t.name.Equals(dicValue.teleportTo))
+ .FirstOrDefault();
+
+ if (_teleportTo == null)
+ {
+ throw new NullReferenceException($"{GetType().Name}:Bad dic, can't find the target.");
+ }
+
+ var lookAtName = dicValue.lookAt[Random.Range(0, dicValue.lookAt.Count)];
+ _lookAt = transforms
+ .Where(t => t.name.Equals(lookAtName))
+ .FirstOrDefault();
+
+ _offset = new Vector3(
+ Random.Range(dicValue.rightMin, dicValue.rightMax),
+ Random.Range(dicValue.upMin, dicValue.upMax),
+ Random.Range(dicValue.forwardMin, dicValue.forwardMax));
+
+ _startRotation = VR.Camera.Origin.rotation;
+ _startPosition = VR.Camera.Head.position;
+ var offsetPos = _teleportTo.TransformPoint(_offset);
+ _targetRotation = Quaternion.LookRotation(_lookAt.position - offsetPos);
+
+ _lerpMultiplier = Mathf.Min(
+ KoikatuInterpreter.Settings.FlightSpeed / Vector3.Distance(offsetPos, _startPosition),
+ KoikatuInterpreter.Settings.FlightSpeed * 60f / Quaternion.Angle(_startRotation, _targetRotation));
+
+ }
+ private readonly Quaternion _startRotation;
+ private readonly Quaternion _targetRotation;
+ private readonly Vector3 _startPosition;
+
+ private readonly Transform _teleportTo;
+ private readonly Transform _lookAt;
+ private readonly Vector3 _offset;
+ private readonly float _lerpMultiplier;
+
+ private readonly Action _onFinish;
+
+ private float _lerp;
+
+ internal void Move()
+ {
+ var step = Mathf.SmoothStep(0f, 1f, _lerp += Time.deltaTime * _lerpMultiplier);
+ var offsetPos = _teleportTo.TransformPoint(_offset);
+ var pos = Vector3.Slerp(_startPosition, offsetPos, step);
+ VR.Camera.Origin.rotation = Quaternion.Slerp(_startRotation, _targetRotation, step);
+ VR.Camera.Origin.position += pos - VR.Camera.Head.position;
+ if (step >= 1f)
+ {
+ _onFinish?.Invoke();
+ }
+ }
+
+ //private readonly Dictionary poiDicDev = new()
+ //{
+
+ // {
+ // "NavelUpFront", // Upfront
+ // new PoIPatternInfo {
+ // teleportTo = "cf_j_spine01",
+ // lookAt = [
+ // "cf_j_spine03",
+ // "cf_j_spine01",
+ // "cf_j_spine02"
+ // ],
+ // forwardMin = 0.05f,
+ // forwardMax = 0.15f,
+ // upMin = -0.1f,
+ // upMax = 0.1f,
+ // rightMin = -0.1f,
+ // rightMax = 0.1f
+ // }
+ // },
+ // {
+ // "NavelLeftSide",
+ // new PoIPatternInfo {
+ // teleportTo = "cf_j_spine01",
+ // lookAt = [
+ // "cf_j_spine03",
+ // "cf_j_spine01",
+ // "cf_j_spine02"
+ // ],
+ // forwardMin = -0.1f,
+ // forwardMax = 0.1f,
+ // upMin = -0.1f,
+ // upMax = 0.1f,
+ // rightMin = -0.15f,
+ // rightMax = -0.25f
+ // }
+ // },
+ // {
+ // "NavelRightSide",
+ // new PoIPatternInfo {
+ // teleportTo = "cf_j_spine01",
+ // lookAt = [
+ // "cf_j_spine03",
+ // "cf_j_spine01",
+ // "cf_j_spine02"
+ // ],
+ // forwardMin = -0.1f,
+ // forwardMax = 0.1f,
+ // upMin = -0.1f,
+ // upMax = 0.1f,
+ // rightMin = 0.15f,
+ // rightMax = 0.25f
+ // }
+ // }
+ //};
+ private readonly Dictionary _poiDic = new()
+ {
+ {
+ "FaceUpFront", // Upfront
+ new PoIPatternInfo {
+ teleportTo = "cf_J_FaceUp_tz",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_neck"
+ },
+ forwardMin = 0.15f,
+ forwardMax = 0.3f,
+ upMin = -0.05f,
+ upMax = 0.05f,
+ rightMin = -0.2f,
+ rightMax = 0.2f
+ }
+ },
+ {
+ "FaceLeftSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_J_FaceUp_tz",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_neck"
+ },
+ forwardMin = 0.1f,
+ forwardMax = 0.2f,
+ upMin = -0.05f,
+ upMax = 0.05f,
+ rightMin = -0.15f,
+ rightMax = -0.3f
+ }
+ },
+ {
+ "FaceRightSide", // Right
+ new PoIPatternInfo {
+ teleportTo = "cf_J_FaceUp_tz",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_neck"
+ },
+ forwardMin = 0.1f,
+ forwardMax = 0.2f,
+ upMin = -0.05f,
+ upMax = 0.05f,
+ rightMin = 0.15f,
+ rightMax = 0.3f
+ }
+ },
+ {
+ "NeckUpFront", // Upfront
+ new PoIPatternInfo {
+ teleportTo = "cf_j_neck",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_spine03"
+ },
+ forwardMin = 0.2f,
+ forwardMax = 0.3f,
+ upMin = -0.05f,
+ upMax = 0.05f,
+ rightMin = -0.2f,
+ rightMax = 0.2f
+ }
+ },
+ {
+ "NeckLeftSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_j_neck",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_spine03"
+ },
+ forwardMin = 0.1f,
+ forwardMax = 0.2f,
+ upMin = -0.05f,
+ upMax = 0.05f,
+ rightMin = -0.15f,
+ rightMax = -0.25f
+ }
+ },
+ {
+ "NeckRightSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_j_neck",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_spine03"
+ },
+ forwardMin = 0.1f,
+ forwardMax = 0.2f,
+ upMin = -0.05f,
+ upMax = 0.05f,
+ rightMin = 0.15f,
+ rightMax = 0.25f
+ }
+ },
+ {
+ "BreastUpFront", // Upfront
+ new PoIPatternInfo {
+ teleportTo = "cf_j_spine03",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_neck",
+ "cf_j_spine03"
+ },
+ forwardMin = 0.05f,
+ forwardMax = 0.15f,
+ upMin = -0.1f,
+ upMax = 0.1f,
+ rightMin = -0.1f,
+ rightMax = 0.1f
+ }
+ },
+ {
+ "BreastLeftSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_j_spine03",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_neck",
+ "cf_j_spine03"
+ },
+ forwardMin = -0.1f,
+ forwardMax = 0.1f,
+ upMin = -0.1f,
+ upMax = 0.1f,
+ rightMin = -0.15f,
+ rightMax = -0.25f
+ }
+ },
+ {
+ "BreastRightSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_j_spine03",
+ lookAt = new List {
+ "cf_J_FaceUp_tz",
+ "cf_j_neck",
+ "cf_j_spine03"
+ },
+ forwardMin = -0.1f,
+ forwardMax = 0.1f,
+ upMin = -0.1f,
+ upMax = 0.1f,
+ rightMin = 0.15f,
+ rightMax = 0.25f
+ }
+ },
+ {
+ "NavelUpFront", // Upfront
+ new PoIPatternInfo {
+ teleportTo = "cf_j_spine01",
+ lookAt = new List {
+ "cf_j_spine03",
+ "cf_j_spine01",
+ "cf_j_spine02"
+ },
+ forwardMin = 0.05f,
+ forwardMax = 0.15f,
+ upMin = -0.1f,
+ upMax = 0.1f,
+ rightMin = -0.1f,
+ rightMax = 0.1f
+ }
+ },
+ {
+ "NavelLeftSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_j_spine01",
+ lookAt = new List {
+ "cf_j_spine03",
+ "cf_j_spine01",
+ "cf_j_spine02"
+ },
+ forwardMin = -0.1f,
+ forwardMax = 0.1f,
+ upMin = -0.1f,
+ upMax = 0.1f,
+ rightMin = -0.15f,
+ rightMax = -0.25f
+ }
+ },
+ {
+ "NavelRightSide",
+ new PoIPatternInfo {
+ teleportTo = "cf_j_spine01",
+ lookAt = new List {
+ "cf_j_spine03",
+ "cf_j_spine01",
+ "cf_j_spine02"
+ },
+ forwardMin = -0.1f,
+ forwardMax = 0.1f,
+ upMin = -0.1f,
+ upMax = 0.1f,
+ rightMin = 0.15f,
+ rightMax = 0.25f
+ }
+ }
+ };
+ }
+}
diff --git a/Shared/Camera/SmoothMover.cs b/Shared/Camera/SmoothMover.cs
new file mode 100644
index 0000000..47ebb09
--- /dev/null
+++ b/Shared/Camera/SmoothMover.cs
@@ -0,0 +1,217 @@
+using KK_VR.Features;
+using System;
+using System.Collections;
+using UnityEngine;
+using VRGIN.Core;
+using KK_VR.Interpreters;
+using KK_VR.Handlers;
+using KKAPI.Utilities;
+
+namespace KK_VR.Camera
+{
+ ///
+ /// We fly towards adjusted positions. By flying rather then teleporting the sense of actual scene is created. No avoidance system (yet).
+ ///
+ internal class SmoothMover : MonoBehaviour
+ {
+ internal static SmoothMover Instance => _instance;
+ private static SmoothMover _instance;
+ //private Transform _chara;
+ //private Transform _eyes;
+ //private Transform _torso;
+ //private Transform _kokan;
+ //private List _activeCoroutines = new List();
+ private void Awake()
+ {
+ _instance = this;
+ }
+ internal void MoveToPoV()
+ {
+ var mode = HSceneInterpreter.mode;
+ if (PoV.Active || (KoikatuInterpreter.Settings.AutoEnterPov && (mode == HFlag.EMode.houshi || mode == HFlag.EMode.sonyu)))
+ {
+ PoV.Instance.TryDisable(moveTo: false);
+ StartCoroutine(WaitForLag(PoV.Instance.StartPov, null));
+ }
+ }
+ internal void MoveToInH(Vector3 position, Quaternion rotation, bool spotChange)
+ {
+ //VRPlugin.Logger.LogDebug("VRMoverH:MoveToInH");
+ StopAllCoroutines();
+ var mode = HSceneInterpreter.mode;
+ if (PoV.Active || (KoikatuInterpreter.Settings.AutoEnterPov && (mode == HFlag.EMode.houshi || mode == HFlag.EMode.sonyu)))
+ {
+ PoV.Instance.TryDisable(moveTo: false);
+ if (spotChange)
+ {
+ StartCoroutine(WaitForLag(PoV.Instance.OnSpotChange, null));
+ }
+ else
+ {
+ StartCoroutine(WaitForLag(PoV.Instance.StartPov, null));
+ }
+ }
+ else
+ {
+ StartCoroutine(FlyToPosition(position, rotation, spotChange));
+ }
+ }
+
+ internal void MakeUpright(Action method = null, params object[] args)
+ {
+ StartCoroutine(RotateToUpright(method, args));
+ }
+
+ private IEnumerator RotateToUpright(Action method = null, params object[] args)
+ {
+ // Wait for lag.
+ yield return null;
+ yield return new WaitUntil(() => Time.deltaTime < 0.05f);
+
+ // Wait for IK to put transforms back.
+ yield return CoroutineUtils.WaitForEndOfFrame;
+ var origin = VR.Camera.Origin;
+ if (origin.eulerAngles.x != 0f || origin.eulerAngles.z != 0f)
+ {
+ var head = VR.Camera.Head;
+ var uprightRot = Quaternion.Euler(0f, origin.eulerAngles.y, 0f);
+ //var uprightRot = Quaternion.Euler(0f, head.eulerAngles.y, 0f);
+ var lerpMultiplier = KoikatuInterpreter.Settings.FlightSpeed * 90f / Quaternion.Angle(head.rotation, uprightRot);
+ var lerp = 0f;
+ var startRot = origin.rotation;
+ Vector3 oldPos;
+ while (lerp < 1f)
+ {
+ var step = Mathf.SmoothStep(0f, 1f, lerp += Time.deltaTime * lerpMultiplier);
+ oldPos = head.position;
+ origin.rotation = Quaternion.Lerp(startRot, uprightRot, step); //Quaternion.RotateTowards(origin.rotation, uprightRot, Time.deltaTime * 120f);
+ origin.position += oldPos - head.position;
+ yield return CoroutineUtils.WaitForEndOfFrame;
+ }
+ //oldPos = head.position;
+ //origin.rotation = uprightRot;
+ //origin.position += oldPos - head.position;
+ }
+ method?.DynamicInvoke(args);
+ //VRPlugin.Logger.LogDebug($"VRMoverH:MakeUpright:Done");
+ }
+ private IEnumerator WaitForLag(Action action, params object[] args)
+ {
+ //VRPlugin.Logger.LogDebug($"VRMoverH:WaitForLag");
+ // We wait for the lag of position change.
+ yield return null;
+ yield return new WaitUntil(() => Time.deltaTime < 0.05f);
+ //if (actionChange)
+ //{
+ // yield return CoroutineUtils.WaitForEndOfFrame;
+ // var destination = _pov.GetDestination();
+ // if (destination != Vector3.zero)
+ // {
+ // var head = VR.Camera.Head;
+ // var origin = VR.Camera.Origin;
+ // var distance = Vector3.Distance(destination, head.position);
+ // var target = destination + _pov.GetRotation() * (Vector3.forward * 0.4f);
+ // var rotation = Quaternion.LookRotation(target - head.position);
+ // if (distance > 2f && Quaternion.Angle(origin.rotation, rotation) > 30f)
+ // {
+ // //VRPlugin.Logger.LogDebug($"VRMoverH:FlyToPov:MovementOverride");
+ // var moveSpeed = 0.5f + distance * 0.5f * _settings.FlightSpeed;
+ // var halfDist = distance * 0.5f;
+ // while (true)
+ // {
+ // var angleDelta = Mathf.Clamp(Quaternion.Angle(origin.rotation, rotation) - 30f, 0f, 180f);
+ // if (angleDelta == 0f)
+ // {
+ // break;
+ // }
+ // distance = Vector3.Distance(destination, head.position) - halfDist;
+ // var step = Time.deltaTime * moveSpeed;
+ // var moveTowards = Vector3.MoveTowards(head.position, destination, step);
+ // var rotSpeed = angleDelta / (distance / step);
+ // origin.rotation = Quaternion.RotateTowards(origin.rotation, rotation, 1f * rotSpeed);
+ // origin.position += moveTowards - head.position;
+ // yield return CoroutineUtils.WaitForEndOfFrame;
+ // }
+ // while (true)
+ // {
+ // distance = Vector3.Distance(destination, head.position);
+ // var step = Time.deltaTime * moveSpeed;
+ // var angleDelta = Quaternion.Angle(origin.rotation, rotation);
+ // var moveTowards = Vector3.MoveTowards(head.position, destination, step);
+ // var rotSpeed = angleDelta / (distance / step);
+ // origin.rotation = Quaternion.RotateTowards(origin.rotation, rotation, 1f * rotSpeed);
+ // origin.position += moveTowards - head.position;
+ // yield return CoroutineUtils.WaitForEndOfFrame;
+ // if (distance < step)
+ // {
+ // break;
+ // }
+ // }
+ // }
+ // }
+ //}
+ //VRPlugin.Logger.LogDebug($"VRMoverH:FlyToPov:Done");
+ action?.DynamicInvoke(args);
+ }
+ private IEnumerator FlyToPosition(Vector3 position, Quaternion rotation, bool spotChange)
+ {
+ yield return null;
+ yield return new WaitUntil(() => Time.deltaTime < 0.05f);
+ yield return CoroutineUtils.WaitForEndOfFrame;
+ var origin = VR.Camera.Origin;
+ var head = VR.Camera.Head;
+ MouthGuide.Instance.PauseInteractions = true;
+
+ var chara = HSceneInterpreter.lstFemale[0];
+ var eyes = chara.objHeadBone.transform.Find("cf_J_N_FaceRoot/cf_J_FaceRoot/cf_J_FaceBase/cf_J_FaceUp_ty/cf_J_FaceUp_tz/cf_J_Eye_tz");
+ //_torso = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_spine01/cf_j_spine02/cf_j_spine03");
+ var kokan = chara.objBodyBone.transform.Find("cf_n_height/cf_j_hips/cf_j_waist01/cf_j_waist02/cf_d_kokan/cf_j_kokan");
+
+ var eyeLevel = eyes.transform.position.y;
+
+ if (eyeLevel - chara.transform.position.y > 1f)
+ {
+ //VRLog.Debug($"VRMoverH:FlyToPosition[height is high, resetting rotation]");
+ // Prob upright position, some of them have weird rotations.
+ rotation = Quaternion.Euler(0f, rotation.eulerAngles.y, 0f);
+ if (position.y < eyeLevel)
+ {
+ //VRLog.Debug($"VRMoverH:FlyToPosition[height is low, meeting eye level]");
+ position.y = eyeLevel;
+ }
+ else
+ {
+ position.y += 0.2f;
+ //VRLog.Debug($"VRMoverH:FlyToPosition[height is low, increasing a bit]");
+ }
+
+ }
+
+ // distKokan = Vector3.Distance(position, kokan.position);
+ //var distTorso = Vector3.Distance(position, _torso.position);
+ //var distEyes = Vector3.Distance(position, eyes.position);
+ var proximity = Mathf.Min(Vector3.Distance(position, eyes.position), Vector3.Distance(position, kokan.position));
+ if (proximity > 0.4f)
+ {
+ // We are moving.. somewhere, maybe we'll get closer. Changing rotation dulls it more often then not.
+ //VRLog.Debug($"VRMoverH:FlyToPosition[not close enough, moving forward for {proximity - 0.4f}]");
+ position += rotation * Vector3.forward * (proximity - 0.4f);
+
+ }
+ var lerp = 0f;
+ var lerpModifier = KoikatuInterpreter.Settings.FlightSpeed * (spotChange ? 3f : 1f) / Vector3.Distance(head.position, position);
+ var startPos = head.position;
+ var startRot = origin.rotation;
+ while (lerp < 1f)
+ {
+ var step = Mathf.SmoothStep(0f, 1f, lerp += Time.deltaTime * lerpModifier);
+
+ var pos = Vector3.Lerp(startPos, position, step);
+ origin.rotation = Quaternion.Slerp(startRot, rotation, step);
+ origin.position += pos - head.position;
+ yield return CoroutineUtils.WaitForEndOfFrame;
+ }
+ MouthGuide.Instance.PauseInteractions = false;
+ }
+ }
+}
diff --git a/MainGameVR/Camera/VRCameraMover.cs b/Shared/Camera/VRCameraMover.cs
similarity index 50%
rename from MainGameVR/Camera/VRCameraMover.cs
rename to Shared/Camera/VRCameraMover.cs
index a314498..000f6ba 100644
--- a/MainGameVR/Camera/VRCameraMover.cs
+++ b/Shared/Camera/VRCameraMover.cs
@@ -3,13 +3,15 @@
using System.Diagnostics;
using System.Linq;
using ADV;
+using ADV.Commands.Object;
using HarmonyLib;
-using KKS_VR.Interpreters;
-using KKS_VR.Settings;
+using KK_VR.Interpreters;
+using KK_VR.Settings;
+using Manager;
using UnityEngine;
using VRGIN.Core;
-namespace KKS_VR.Camera
+namespace KK_VR.Camera
{
///
/// A class responsible for moving the VR camera.
@@ -17,13 +19,11 @@ namespace KKS_VR.Camera
///
public class VRCameraMover
{
- public static VRCameraMover Instance => _instance ?? (_instance = new VRCameraMover());
-
+ public static VRCameraMover Instance => _instance ??= new VRCameraMover();
private static VRCameraMover _instance;
private Vector3 _lastPosition;
private Quaternion _lastRotation;
- private readonly KoikatuSettings _settings;
public delegate void OnMoveAction();
@@ -33,36 +33,33 @@ public VRCameraMover()
{
_lastPosition = Vector3.zero;
_lastRotation = Quaternion.identity;
- _settings = VR.Settings as KoikatuSettings;
}
///
/// Move the camera to the specified pose.
///
- public void MoveTo(Vector3 position, Quaternion rotation, bool keepHeight, bool quiet = false)
+ public void MoveTo(Vector3 position, Quaternion rotation)
{
if (position.Equals(Vector3.zero))
{
- VRLog.Warn($"Prevented something from moving camera to pos={position} rot={rotation.eulerAngles} Trace:\n{new StackTrace(1)}");
- Console.WriteLine();
return;
}
- if (!quiet)
- {
-#if DEBUG
- VRLog.Debug("Moving camera to pos={0} rot={1} Trace:\n{2}", position, rotation.eulerAngles, new StackTrace(1));
-#else
- VRLog.Debug("Moving camera to pos={0} rot={1}", position, rotation.eulerAngles);
-#endif
- }
-
-
+//#if DEBUG
+// VRPlugin.Logger.LogDebug($"{GetType().Name}:MoveTo\n{new StackTrace(0)}");
+//#endif
_lastPosition = position;
_lastRotation = rotation;
- // Trim out X (pitch) and Z (roll) to prevent player from being upside down and such
- var trimmedRotation = Quaternion.Euler(0, rotation.eulerAngles.y, 0);
- VR.Mode.MoveToPosition(position, trimmedRotation, keepHeight);
+ // We don't want to respect head rotations when we deal with adv text.
+ VR.Camera.Origin.rotation = Quaternion.Euler(0f, rotation.eulerAngles.y, 0f);
+ VR.Camera.Origin.position += position - VR.Camera.Head.position;
+
+
+ //// Trim out X (pitch) and Z (roll) to prevent player from being upside down and such
+ //var trimmedRotation = Quaternion.Euler(0, rotation.eulerAngles.y, 0);
+ //VR.Mode.MoveToPosition(position, trimmedRotation, keepHeight);
+
+ //VR.Mode.MoveToPosition(position, rotation, ignoreHeight: keepHeight);
OnMove?.Invoke();
}
@@ -72,39 +69,40 @@ public void MoveTo(Vector3 position, Quaternion rotation, bool keepHeight, bool
/// The position and rotation arguments should represent the pose
/// the camera would take in the 2D version of the game.
///
- ///
- ///
- ///
- public void MaybeMoveTo(Vector3 position, Quaternion rotation, bool keepHeight)
+ public void MaybeMoveTo(Vector3 position, Quaternion rotation)
{
- MoveWithHeuristics(position, rotation, keepHeight, false);
+ MoveWithHeuristics(position, rotation, false);
}
///
/// Similar to MaybeMoveTo, but also considers the ADV fade state.
///
- public void MaybeMoveADV(ADV.TextScenario textScenario, Vector3 position, Quaternion rotation, bool keepHeight)
+ public void MaybeMoveADV(ADV.TextScenario textScenario, Vector3 position, Quaternion rotation)
{
- var advFade = new Traverse(textScenario).Field("advFade").Value;
+ var advFade = textScenario.advFade;// new Traverse(textScenario).Field("advFade").Value;
var closerPosition = AdjustAdvPosition(textScenario, position, rotation);
-
+#if KKS
AdjustBasedOnMap(ref closerPosition, ref rotation);
-
- MoveWithHeuristics(closerPosition, rotation, keepHeight, !advFade.IsEnd);
+#endif
+ MoveWithHeuristics(closerPosition, rotation, !advFade.IsEnd);
}
- private static Vector3 AdjustAdvPosition(TextScenario textScenario, Vector3 position, Quaternion rotation)
+ private Vector3 AdjustAdvPosition(TextScenario textScenario, Vector3 position, Quaternion rotation)
{
// Needed for zero checks later
if (position.Equals(Vector3.zero)) return Vector3.zero;
- var characterTransforms = textScenario.commandController?.Characters.Where(x => x.Value?.transform != null).Select(x => x.Value.transform.position).ToArray();
- if (characterTransforms != null && characterTransforms.Length > 0)
+ var characterTransforms = textScenario.commandController?.Characters
+ .Where(x => x.Value?.transform != null)
+ .Select(x => x.Value.transform.position);
+
+ if (characterTransforms != null && characterTransforms.Count() > 0)
{
//var closerPosition = position + (rotation * Vector3.forward) * 1f;
- var averageV = new Vector3(characterTransforms.Sum(x => x.x), characterTransforms.Sum(x => x.y), characterTransforms.Sum(x => x.z));
+ var averageV = new Vector3(characterTransforms.Sum(x => x.x), characterTransforms.Sum(x => x.y), characterTransforms.Sum(x => x.z)) / characterTransforms.Count();
+
var positionNoY = position;
positionNoY.y = 0;
@@ -113,11 +111,11 @@ private static Vector3 AdjustAdvPosition(TextScenario textScenario, Vector3 posi
//if (Vector3.Angle(positionNoY, averageNoY) < 90)
{
- var closerPosition = Vector3.MoveTowards(positionNoY, averageNoY, Vector3.Distance(positionNoY, averageNoY) - TalkSceneInterpreter.TalkDistance);
+ var closerPosition = Vector3.MoveTowards(positionNoY, averageNoY, Vector3.Distance(positionNoY, averageNoY) - TalkSceneInterpreter.talkDistance);
closerPosition.y = averageV.y + ActionCameraControl.GetPlayerHeight();
- VRLog.Warn("Adjusting position {0} -> {1} for rotation {2}", position, closerPosition, rotation.eulerAngles);
+ //VRLog.Warn("Adjusting position {0} -> {1} for rotation {2}", position, closerPosition, rotation.eulerAngles);
return closerPosition;
}
@@ -134,26 +132,35 @@ public void HandleTextScenarioProgress(ADV.TextScenario textScenario)
{
var isFadingOut = IsFadingOut(textScenario.advFade);
- VRLog.Debug("HandleTextScenarioProgress isFadingOut={0}", isFadingOut);
-
- if (_settings.FirstPersonADV &&
- FindMaleToImpersonate(out var male) &&
- male.objHead != null)
+ //VRLog.Debug("HandleTextScenarioProgress isFadingOut={0}", isFadingOut);
+
+ // We catch it in TalkSceneInterpreter as we have visible male all the time.
+ //if (_settings.FirstPersonADV &&
+ // FindMaleToImpersonate(out var male) &&
+ // male.objHead != null)
+ //{
+ // VRLog.Debug("Maybe impersonating male");
+ // male.StartCoroutine(ImpersonateCo(isFadingOut, male.objHead.transform));
+ //}
+ if (ShouldApproachCharacter(textScenario, out var character))
{
- VRLog.Debug("Maybe impersonating male");
- male.StartCoroutine(ImpersonateCo(isFadingOut, male.objHead.transform));
- }
- else if (ShouldApproachCharacter(textScenario, out var character))
- {
- var distance = InCafe() ? 0.75f : TalkSceneInterpreter.TalkDistance;
+#if KK
+ var distance = InCafe() ? 0.75f : TalkSceneInterpreter.talkDistance;
+#elif KKS
+ var distance = TalkSceneInterpreter.talkDistance;
+#endif
float height;
Quaternion rotation;
+#if KK
+ if (Manager.Scene.Instance.NowSceneNames[0] == "H")
+#elif KKS
if (Manager.Scene.NowSceneNames[0] == "H")
+#endif
{
VRLog.Debug("Approaching character (H)");
// TODO: find a way to get a proper height.
height = character.transform.position.y + 1.3f;
- rotation = character.transform.rotation * Quaternion.AngleAxis(180f, Vector3.up);
+ rotation = character.transform.rotation * Quaternion.Euler(0f, 180f, 0f);
}
else
{
@@ -167,7 +174,6 @@ public void HandleTextScenarioProgress(ADV.TextScenario textScenario)
MoveWithHeuristics(
new Vector3(cameraXZ.x, height, cameraXZ.z),
rotation,
- false,
isFadingOut);
}
else
@@ -177,15 +183,15 @@ public void HandleTextScenarioProgress(ADV.TextScenario textScenario)
var targetRotation = target.rotation;
targetPosition = AdjustAdvPosition(textScenario, targetPosition, target.rotation);
-
+#if KKS
AdjustBasedOnMap(ref targetPosition, ref targetRotation);
-
+#endif
if (ActionCameraControl.HeadIsAwayFromPosition(targetPosition))
- MoveWithHeuristics(targetPosition, targetRotation, false, isFadingOut);
+ MoveWithHeuristics(targetPosition, targetRotation, isFadingOut);
}
}
-
- private static void AdjustBasedOnMap(ref Vector3 targetPosition, ref Quaternion targetRotation)
+#if KKS
+ private void AdjustBasedOnMap(ref Vector3 targetPosition, ref Quaternion targetRotation)
{
var insideMyRoom = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name == "GasyukuMyroom";
if (insideMyRoom)
@@ -200,77 +206,125 @@ private static void AdjustBasedOnMap(ref Vector3 targetPosition, ref Quaternion
}
}
}
+#endif
+
- private static bool IsFadingOut(ADVFade fade)
+ private bool IsFadingOut(ADVFade fade)
{
- bool IsFadingOutSub(ADVFade.Fade f) => f.initColor.a > 0.5f && !f.IsEnd;
+#if KK
+ static bool IsFadingOutSub(ADVFade.Fade f) => f.initColor.a > 0.5f && !f.IsEnd;
return IsFadingOutSub(fade.front) || IsFadingOutSub(fade.back);
+#else
+ // KKS doesn't have working advFade.
+ return Scene.sceneFadeCanvas.isFading;
+#endif
+
}
- private IEnumerator ImpersonateCo(bool isFadingOut, Transform head)
+ //private IEnumerator ImpersonateCo(bool isFadingOut, Transform head)
+ //{
+ // // For reasons I don't understand, the male may not have a correct pose
+ // // until later in the update loop.
+ // yield return CoroutineUtils.WaitForEndOfFrame;
+ // MoveWithHeuristics(
+ // head.TransformPoint(0, 0.15f, 0.15f),
+ // head.rotation,
+ // false,
+ // isFadingOut);
+ //}
+
+ public void Impersonate(ChaControl chara)
{
- // For reasons I don't understand, the male may not have a correct pose
- // until later in the update loop.
- yield return new WaitForEndOfFrame();
- MoveWithHeuristics(
- head.TransformPoint(0, 0.15f, 0.15f),
- head.rotation,
- false,
- isFadingOut);
+ if (chara != null && chara.objTop.activeSelf)
+ {
+ // Some inconsistent interference happens.
+ chara.visibleAll = true;
+ chara.fileStatus.visibleBodyAlways = true;
+
+ var eyes = chara.objHeadBone.transform
+ .Find("cf_J_N_FaceRoot/cf_J_FaceRoot/cf_J_FaceBase/cf_J_FaceUp_ty/cf_J_FaceUp_tz/cf_J_Eye_tz");
+ var position = eyes.TransformPoint(0f, KoikatuInterpreter.Settings.PositionOffsetY, KoikatuInterpreter.Settings.PositionOffsetZ);
+ MoveTo(position, eyes.rotation);
+ }
}
-
- private void MoveWithHeuristics(Vector3 position, Quaternion rotation, bool keepHeight, bool pretendFading)
+ private void MoveWithHeuristics(Vector3 position, Quaternion rotation, bool pretendFading)
{
- var fade = Manager.Scene.sceneFadeCanvas;
- var fadeOk = fade.isEnd; //(fade._Fade == SimpleFade.Fade.Out) ^ fade.IsEnd;
+#if KK
+ var fade = Manager.Scene.Instance.sceneFade;
+ bool fadeOk = (fade._Fade == SimpleFade.Fade.Out) ^ fade.IsEnd;
if (pretendFading || fadeOk || IsDestinationFar(position, rotation))
- MoveTo(position, rotation, keepHeight);
+#elif KKS
+ //var fade = Manager.Scene.sceneFadeCanvas;
+ if (Features.VRFade.IsFade || IsDestinationFar(position, rotation)) //(pretendFading || IsDestinationFar(position, rotation))
+
+ // No clue what this condition should be about, in KKS it doesn't work (always true).
+ // KK has no problem with it('s alternative).
+ //var fadeOk = fade.isEnd; //(fade._Fade == SimpleFade.Fade.Out) ^ fade.IsEnd;
+#endif
+ {
+#if DEBUG
+ VRPlugin.Logger.LogDebug($"MoveWithHeuristics:Move:Pos = {position}");
+#endif
+ MoveTo(position, rotation);
+ }
+#if DEBUG
else
- VRLog.Debug("Not moving because heuristic conditions are not met");
+ {
+ VRPlugin.Logger.LogDebug($"MoveWithHeuristics:Stay:Pos = {position}");
+ }
+#endif
}
private bool IsDestinationFar(Vector3 position, Quaternion rotation)
{
var distance = (position - _lastPosition).magnitude;
- var angleDistance = Mathf.DeltaAngle(rotation.eulerAngles.y, _lastRotation.eulerAngles.y);
- return 1f < distance / 2f + angleDistance / 90f;
- }
-
- private static bool FindMaleToImpersonate(out ChaControl male)
- {
- male = null;
-
- if (!Manager.Character.IsInstance()) return false;
-
- var males = Manager.Character.dictEntryChara.Values
- .Where(ch => ch.isActiveAndEnabled && ch.sex == 0 && ch.objTop?.activeSelf == true && ch.visibleAll)
- .ToArray();
- if (males.Length == 1)
- {
- male = males[0];
- return true;
- }
-
- return false;
+ var deltaAngle = Mathf.Abs(Mathf.DeltaAngle(rotation.eulerAngles.y, _lastRotation.eulerAngles.y));
+ return 1f < distance * 0.5f + deltaAngle / 90f;
}
- private static bool ShouldApproachCharacter(ADV.TextScenario textScenario, out ChaControl control)
+// private static bool FindMaleToImpersonate(out ChaControl male)
+// {
+// male = null;
+
+// if (!Manager.Character.IsInstance()) return false;
+
+//#if KK
+// var males = Manager.Character.Instance.dictEntryChara.Values
+//#elif KKS
+// var males = Manager.Character.dictEntryChara.Values
+//#endif
+// .Where(ch => ch.isActiveAndEnabled && ch.sex == 0 && ch.objTop?.activeSelf == true && ch.visibleAll)
+// .ToArray();
+// if (males.Length == 1)
+// {
+// male = males[0];
+// return true;
+// }
+// return false;
+// }
+
+ private bool ShouldApproachCharacter(ADV.TextScenario textScenario, out ChaControl control)
{
- if ((Manager.Scene.NowSceneNames[0] == "H" || textScenario.BGParam.visible) &&
- textScenario.currentChara != null)
+#if KK
+ if ((Manager.Scene.Instance.NowSceneNames[0] == "H" || textScenario.BGParam.visible)
+#elif KKS
+ if ((Manager.Scene.NowSceneNames[0] == "H" || textScenario.BGParam.visible)
+#endif
+ && textScenario.currentChara != null)
{
control = textScenario.currentChara.chaCtrl;
return true;
}
-
control = null;
return false;
}
- private static bool InCafe()
+#if KK
+ private bool InCafe()
{
- return ActionScene.initialized &&
- ActionScene.instance.transform.Find("cafeChair"); //todo taken from kk, needs a test, probably not working
+ return Manager.Game.IsInstance()
+ && Manager.Game.Instance.actScene.transform.Find("cafeChair");
}
+#endif
}
}
diff --git a/MainGameVR/Camera/VREffector.cs b/Shared/Camera/VREffector.cs
similarity index 90%
rename from MainGameVR/Camera/VREffector.cs
rename to Shared/Camera/VREffector.cs
index 96f7c9a..5339f58 100644
--- a/MainGameVR/Camera/VREffector.cs
+++ b/Shared/Camera/VREffector.cs
@@ -3,7 +3,7 @@
using UnityStandardAssets.ImageEffects;
using VRGIN.Core;
-namespace KKS_VR.Camera
+namespace KK_VR.Camera
{
///
/// A component to be attached to the VR camera. Ensures that it has the
@@ -13,8 +13,6 @@ class VREffector : ProtectedBehaviour
{
protected override void OnUpdate()
{
- base.OnUpdate();
-
var blueprint = VR.Camera.Blueprint;
if (blueprint && _source != blueprint)
{
@@ -25,8 +23,6 @@ protected override void OnUpdate()
protected override void OnLateUpdate()
{
- base.OnLateUpdate();
-
_fog.UpdateEnabled();
_amplifyColor.UpdateEnabled();
if (_amplifyColor.mirror && _amplifyColor.source)
@@ -41,6 +37,7 @@ protected override void OnLateUpdate()
{
_sunShafts.mirror.sunColor = _sunShafts.source.sunColor;
_sunShafts.mirror.sunTransform = _sunShafts.source.sunTransform;
+
TweakSunShaftSettings(_sunShafts.mirror);
}
_vignette.UpdateEnabled();
@@ -113,7 +110,20 @@ private static void TweakSunShaftSettings(SunShafts sunShafts)
sunShafts.sunShaftIntensity = 0.6f;
}
- struct Mirrored
+ ///
+ /// Keep up with constant VFX updates
+ ///
+ internal static void Refresh()
+ {
+ var effector = VR.Camera.GetComponent();
+ if (effector != null && VR.Camera.Blueprint != null)
+ {
+ effector.HandleNewGameCamera(VR.Camera.Blueprint);
+ }
+ }
+
+
+ struct Mirrored
where T : Behaviour
{
public T mirror;
diff --git a/Shared/Caress/CaressUtil.cs b/Shared/Caress/CaressUtil.cs
new file mode 100644
index 0000000..ebce327
--- /dev/null
+++ b/Shared/Caress/CaressUtil.cs
@@ -0,0 +1,20 @@
+using System.Collections;
+using System.Collections.Generic;
+using HarmonyLib;
+
+namespace KK_VR.Caress
+{
+ public class CaressUtil
+ {
+ ///
+ /// Send a synthetic click event to the hand controls.
+ ///
+ public static IEnumerator ClickCo()
+ {
+ var consumed = false;
+ HandCtrlHooks.InjectMouseButtonDown(0, () => consumed = true);
+ while (!consumed) yield return null;
+ HandCtrlHooks.InjectMouseButtonUp(0);
+ }
+ }
+}
diff --git a/MainGameVR/Caress/HandCtrlHooks.cs b/Shared/Caress/HandCtrlHooks.cs
similarity index 86%
rename from MainGameVR/Caress/HandCtrlHooks.cs
rename to Shared/Caress/HandCtrlHooks.cs
index a900a49..14306bb 100644
--- a/MainGameVR/Caress/HandCtrlHooks.cs
+++ b/Shared/Caress/HandCtrlHooks.cs
@@ -4,16 +4,17 @@
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
+using KK_VR.Handlers;
using UnityEngine;
-namespace KKS_VR.Caress
+namespace KK_VR.Caress
{
///
/// Allows injecting simulated user inputs to HandCtrl. This is similar to
/// faking mouse clicks using VR.Input, but is safer because it doesn't
/// accidentally interact with the game UI.
///
- internal class HandCtrlHooks
+ public class HandCtrlHooks
{
private static HandCtrlHooks _instance;
@@ -81,13 +82,16 @@ public static float GetAxis(string name)
private static HandCtrlHooks GetInstance()
{
- if (_instance == null) _instance = new HandCtrlHooks();
+ _instance ??= new HandCtrlHooks();
return _instance;
}
private ButtonHandler GetButtonHandler(int button)
{
- if (!_buttonHandlers.ContainsKey(button)) _buttonHandlers.Add(button, new ButtonHandler(button));
+ if (!_buttonHandlers.ContainsKey(button))
+ {
+ _buttonHandlers.Add(button, new ButtonHandler(button));
+ }
return _buttonHandlers[button];
}
@@ -217,5 +221,30 @@ inst.operand is MethodInfo method &&
yield return inst;
}
}
+
+ [HarmonyPatch]
+ internal class HandCtrlHelperHook
+ {
+ // Should be safe kill switch.
+ // Triggered by overlap menus too (does so beforehand).
+ [HarmonyPostfix, HarmonyPatch(typeof(HandCtrl), nameof(HandCtrl.ForceFinish))]
+ public static void ForceFinishPostfix()
+ {
+ if (MouthGuide.Instance != null)
+ MouthGuide.Instance.Halt(disengage: false);
+ }
+
+ //[HarmonyPostfix, HarmonyPatch(typeof(HAibu), nameof(HAibu.GotoDislikes))]
+ //public static void GotoDislikesPostfix()
+ //{
+ // var helper = CaressHelper.Instance;
+ // if (helper != null && !helper.IsEndKissCo)
+ // {
+ // helper.Halt(disengage: true);
+ // }
+ //}
+
+ }
}
+
}
diff --git a/Shared/Constants.cs b/Shared/Constants.cs
index 10d6d7e..983f540 100644
--- a/Shared/Constants.cs
+++ b/Shared/Constants.cs
@@ -1,4 +1,4 @@
-namespace KKS_VR
+namespace KK_VR
{
internal static class Constants
{
diff --git a/Shared/Controls/GameplayTool.cs b/Shared/Controls/GameplayTool.cs
new file mode 100644
index 0000000..f913140
--- /dev/null
+++ b/Shared/Controls/GameplayTool.cs
@@ -0,0 +1,227 @@
+using UnityEngine;
+using VRGIN.Controls;
+using VRGIN.Controls.Tools;
+using VRGIN.Core;
+using KK_VR.Interpreters;
+using Valve.VR;
+using KK_VR.Holders;
+//using EVRButtonId = Unity.XR.OpenVR.EVRButtonId;
+
+namespace KK_VR.Controls
+{
+ public class GameplayTool : Tool
+ {
+ private int _index;
+
+ private KoikatuMenuTool _menu;
+
+ private KoikatuMenuHandler _menuHandler;
+
+ private Controller.TrackpadDirection _lastDirection;
+
+ private GripMove _grip;
+
+ internal bool IsGrip => _grip != null;
+
+ internal bool IsInit => _init;
+
+ private bool _init;
+ public override Texture2D Image
+ {
+ get;
+ }
+
+ protected override void OnDisable()
+ {
+ DestroyGripMove();
+ base.OnDisable();
+ }
+ protected override void OnDestroy()
+ {
+
+ }
+ protected override void OnEnable()
+ {
+ if (!_init
+ && Neighbor != null
+ && Neighbor.Tools[0] is GameplayTool tool
+ && tool.IsInit)
+ {
+ // Ancient bug, can happen if controller was asleep at the VRGIN's init phase.
+ OnRenderModelLoaded();
+ }
+ base.OnEnable();
+ }
+ protected override void OnUpdate()
+ {
+ if (_init)
+ {
+ HandleInput();
+ _grip?.HandleGrabbing();
+ }
+ }
+ internal void OnRenderModelLoaded()
+ {
+ _init = true;
+ _index = Owner == VR.Mode.Left ? 0 : 1;
+ _menu = new KoikatuMenuTool(_index);
+ _menuHandler = new KoikatuMenuHandler(Owner);
+ }
+ internal void DestroyGripMove()
+ {
+ _grip = null;
+ KoikatuInterpreter.SceneInput.OnGripMove(_index, active: false);
+ }
+ internal void LazyGripMove(int avgFrame)
+ {
+ // In all honesty tho, the proper name would be retarded, not lazy as it does way more in this mode and lags behind.
+ _grip?.StartLag(avgFrame);
+ }
+ internal void AttachGripMove(Transform attachPoint)
+ {
+ _grip?.AttachGripMove(attachPoint);
+ }
+ internal void UnlazyGripMove()
+ {
+ _grip?.StopLag();
+ }
+ internal void HideLaser()
+ {
+ _menuHandler?.SetLaserVisibility(false);
+ }
+
+ private void HandleInput()
+ {
+ var direction = Owner.GetTrackpadDirection();
+ var menuInteractable = !_menu.IsAttached && _menuHandler.CheckMenu();
+
+ if (menuInteractable && !_menuHandler.LaserVisible)
+ {
+ // Don't show laser if something of interest is going on.
+ var handler = HandHolder.GetHand(_index).Handler;
+ if (KoikatuInterpreter.SceneInput.IsBusy || (handler != null && handler.IsBusy))
+ {
+ menuInteractable = false;
+ }
+ else
+ {
+ _menuHandler.SetLaserVisibility(true);
+ }
+ }
+
+ if (Controller.GetPressDown(EVRButtonId.k_EButton_ApplicationMenu))
+ {
+ if (!KoikatuInterpreter.SceneInput.OnButtonDown(_index, EVRButtonId.k_EButton_ApplicationMenu, direction))
+ {
+ KoikatuMenuTool.ToggleState();
+ }
+ }
+
+ if (Controller.GetPressDown(EVRButtonId.k_EButton_SteamVR_Trigger))
+ {
+ if (menuInteractable)
+ {
+ _menuHandler.OnTrigger(true);
+ }
+ else if (!KoikatuInterpreter.SceneInput.OnButtonDown(_index, EVRButtonId.k_EButton_SteamVR_Trigger, direction))
+ {
+ _grip?.OnTrigger(true);
+ }
+
+ }
+ else if (Controller.GetPressUp(EVRButtonId.k_EButton_SteamVR_Trigger))
+ {
+ if (menuInteractable)
+ {
+ _menuHandler.OnTrigger(false);
+ }
+ else
+ {
+ _grip?.OnTrigger(false);
+ KoikatuInterpreter.SceneInput.OnButtonUp(_index, EVRButtonId.k_EButton_SteamVR_Trigger, direction);
+ }
+ }
+
+ if (Controller.GetPressDown(EVRButtonId.k_EButton_Grip))
+ {
+
+ if (_menu.IsAttached)
+ {
+ _menu.AbandonGUI();
+ }
+ else if (menuInteractable)
+ {
+ _menuHandler.OnGrip(true);
+ }
+ // If particular interpreter doesn't want grip move right now, it will be blocked.
+ else if (!KoikatuInterpreter.SceneInput.OnButtonDown(_index, EVRButtonId.k_EButton_Grip, direction))
+ {
+ _grip = new GripMove(HandHolder.GetHand(_index), HandHolder.GetHand(_index == 0 ? 1 : 0));
+ // Grab initial Trigger/Touchpad modifiers, if they were already pressed.
+ if (Controller.GetPress(EVRButtonId.k_EButton_SteamVR_Trigger)) _grip.OnTrigger(true);
+ if (Controller.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad)) _grip.OnTouchpad(true);
+ KoikatuInterpreter.SceneInput.OnGripMove(_index, active: true);
+ }
+ }
+ else if (Controller.GetPressUp(EVRButtonId.k_EButton_Grip))
+ {
+ if (menuInteractable)
+ {
+ _menuHandler.OnGrip(false);
+ }
+ else
+ {
+ KoikatuInterpreter.SceneInput.OnButtonUp(_index, EVRButtonId.k_EButton_Grip, direction);
+ if (_grip != null)
+ {
+ DestroyGripMove();
+ }
+ }
+ }
+
+ if (Controller.GetPressDown(EVRButtonId.k_EButton_SteamVR_Touchpad))
+ {
+ if (menuInteractable)
+ {
+ _menuHandler.OnTouchpad(true);
+ }
+ else if (!KoikatuInterpreter.SceneInput.OnButtonDown(_index, EVRButtonId.k_EButton_SteamVR_Touchpad, direction))
+ {
+ _grip?.OnTouchpad(true);
+ }
+ }
+ else if (Controller.GetPressUp(EVRButtonId.k_EButton_SteamVR_Touchpad))
+ {
+ if (menuInteractable)
+ {
+ _menuHandler.OnTouchpad(false);
+ }
+ else
+ {
+ _grip?.OnTouchpad(false);
+ KoikatuInterpreter.SceneInput.OnButtonUp(_index, EVRButtonId.k_EButton_SteamVR_Touchpad, direction);
+ }
+ }
+
+ if (_lastDirection != direction)
+ {
+ if (menuInteractable)
+ {
+ _menuHandler.SetLastDirection(direction);
+ }
+ else
+ {
+ if (_lastDirection != VRGIN.Controls.Controller.TrackpadDirection.Center)
+ {
+ KoikatuInterpreter.SceneInput.OnDirectionUp(_index, _lastDirection);
+ }
+ if (direction != VRGIN.Controls.Controller.TrackpadDirection.Center)
+ {
+ KoikatuInterpreter.SceneInput.OnDirectionDown(_index, direction);
+ }
+ }
+ _lastDirection = direction;
+ }
+ }
+ }
+}
diff --git a/Shared/Controls/GripMove.cs b/Shared/Controls/GripMove.cs
new file mode 100644
index 0000000..c5da60f
--- /dev/null
+++ b/Shared/Controls/GripMove.cs
@@ -0,0 +1,264 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Valve.VR;
+using VRGIN.Controls;
+using VRGIN.Core;
+using VRGIN.Helpers;
+using UnityEngine;
+using KK_VR.Handlers;
+using KK_VR.Holders;
+using KK_VR.Interpreters;
+
+namespace KK_VR.Controls
+{
+ // Placed directly in KK part for comfy use, and easy new features.
+ internal class GripMove
+ {
+ private readonly GameplayTool _other;
+ private readonly Transform _controller;
+
+ //private readonly TravelDistanceRumble _travelRumble;
+
+
+ ///
+ /// If present, orbiting it instead of changing Yaw around controller.
+ ///
+ private Transform _attachPoint;
+ private Vector3 _prevAttachVec;
+ private Vector3 _prevAttachPos;
+ //private Quaternion _prevAttachRot;
+
+ private GripMoveLag _moveLag;
+
+ // Is current instance active or superseded by neighbor.
+ private bool _main;
+
+ private bool _otherGrip;
+ private bool _alterYaw;
+ private bool _alterRotation;
+
+ private Vector3 _prevPos;
+ private Quaternion _prevRot;
+ private readonly bool _rotInPlace = KoikatuInterpreter.Settings.GripMoveLimitRotation;
+
+ internal GripMove(HandHolder hand, HandHolder otherHand)
+ {
+ _main = true;
+ _controller = hand.Controller.transform;
+ _other = otherHand.Tool;
+ _otherGrip = _other.IsGrip;
+ // Feels too much with those forced vibrations on trigger/grip - press/release.
+ //_travelRumble = new TravelDistanceRumble(500, 0.1f, _owner.transform)
+ //{
+ // UseLocalPosition = true
+ //};
+
+ // _travelRumble.Reset();
+ //_owner.StartRumble(_travelRumble);
+
+ _prevPos = _controller.position;
+ _prevRot = _controller.rotation;
+ }
+
+ ///
+ /// Used as means to acquire highly precise offsets. Adds extra source to evaluate movements and provides the point we start to "orbit".
+ ///
+ internal void AttachGripMove(Transform attachPoint)
+ {
+ // All calculations are done through deltas due to saturated input.
+ _attachPoint = attachPoint;
+ _prevAttachPos = _attachPoint.position;
+ _moveLag.ResetPositions(Vector3.zero);
+
+ // Necessary is we started with trigger already.
+ _prevAttachVec = VR.Camera.Head.TransformPoint(new Vector3(0f, 0.05f, 0f)) - attachPoint.position;
+ // With full trigger + touchpad.
+ //_prevAttachRot = _attachPoint.rotation;
+ }
+
+ public void HandleGrabbing()
+ {
+ // We check if other controller wants to joint us, or override control if other has ended gripMove.
+ // Then we use deltas of orientation to setup origin orientation directly, or through evaluation of multiple frames and "averaging it out" if current action requests it.
+ if (_main)
+ {
+ if (_otherGrip && !_other.IsGrip)
+ {
+ _otherGrip = false;
+ }
+ if (!_otherGrip && _other.IsGrip)
+ {
+ _main = false;
+ }
+ else
+ {
+ var origin = VR.Camera.SteamCam.origin;
+ if (_alterYaw)
+ {
+ var deltaRot = _prevRot * Quaternion.Inverse(_controller.rotation);
+ //var invRot = Quaternion.Inverse(_prevRot) * _owner.transform.rotation;
+ if (_moveLag == null)
+ {
+ if (_alterRotation)
+ {
+ origin.rotation = deltaRot * origin.rotation;
+ }
+ else
+ {
+ origin.RotateAround(_controller.position, Vector3.up, deltaRot.eulerAngles.y);
+ }
+ origin.position += _prevPos - _controller.position;
+ }
+ else
+ {
+ if (_alterRotation)
+ {
+ if (_attachPoint == null)
+ {
+ if (_rotInPlace)
+ {
+ var head = VR.Camera.SteamCam.head;
+ var preRotPos = head.position;
+ _moveLag.SetDeltaRotation(deltaRot);
+ origin.position += preRotPos - head.position;
+ }
+ else
+ {
+ _moveLag.SetDeltaRotation(deltaRot);
+ origin.position += (_prevPos - _controller.position);
+ }
+ //_moveLag.SetPositionAndRotation(deltaRot);
+ }
+ else
+ {
+ _moveLag.SetDeltaPositionAndRotation(
+ (_attachPoint.position - _prevAttachPos),
+ deltaRot
+ );
+ _prevAttachPos = _attachPoint.position;
+ //_prevAttachRot = _attachPoint.rotation;
+ }
+ }
+ else
+ {
+ if (_attachPoint == null)
+ {
+ _moveLag.SetDeltaRotation(Quaternion.Euler(0f, deltaRot.eulerAngles.y, 0f));
+ origin.position += _prevPos - _controller.position;
+
+ //_moveLag.SetPositionAndRotation(
+ // //origin.position +
+ // _controller.transform.position +
+ // deltaRotY * vec,
+ // //deltaRotY * (origin.position - new Vector3(_controller.position.x, origin.position.y, _controller.position.z)),
+ // deltaRotY);
+ }
+ else
+ {
+ var newAttachVec = deltaRot * _prevAttachVec;
+ _moveLag.SetDeltaPositionAndRotation(
+ (newAttachVec - _prevAttachVec) + (_prevPos - _controller.position) + (_attachPoint.position - _prevAttachPos),
+ deltaRot
+ );
+ _prevAttachVec = newAttachVec;
+ _prevAttachPos = _attachPoint.position;
+ }
+ }
+
+ }
+ }
+ else
+ {
+ if (_moveLag == null)
+ {
+ origin.position += _prevPos - _controller.position;
+ }
+ else
+ {
+ if (_attachPoint == null)
+ {
+ _moveLag.SetPosition();
+ }
+ else
+ {
+ _moveLag.SetDeltaPosition(_attachPoint.position - _prevAttachPos + (_prevPos - _controller.position));
+ _prevAttachPos = _attachPoint.position;
+ }
+ }
+ }
+ }
+ _prevPos = _controller.position;
+ _prevRot = _controller.rotation;
+ }
+ else
+ {
+ if (!_other.IsGrip)
+ {
+ _main = true;
+ _otherGrip = false;
+ _prevPos = _controller.position;
+ _prevRot = _controller.rotation;
+ }
+ }
+ }
+
+ internal void StartLag(int avgFrame)
+ {
+ _moveLag = new GripMoveLag(_controller, avgFrame);
+ }
+ internal void StopLag()
+ {
+ _moveLag = null;
+ _attachPoint = null;
+ }
+ internal void OnTrigger(bool press)
+ {
+ _alterYaw = press;
+ if (press)
+ {
+ UpdateAttachVec();
+ if (_moveLag == null && KoikatuInterpreter.Settings.GripMoveStabilize == Settings.KoikatuSettings.GripMoveStabilization.YawAndRotation)
+ {
+ _moveLag = new GripMoveLag(_controller, KoikatuInterpreter.ScaleWithFps(KoikatuInterpreter.Settings.GripMoveStabilizationAmount));
+ }
+ }
+ }
+
+ internal void OnTouchpad(bool press)
+ {
+ if (KoikatuInterpreter.Settings.GripMoveEnableRotation)
+ {
+ _alterRotation = press;
+ if (press)
+ {
+ if (_moveLag == null
+ && (KoikatuInterpreter.Settings.GripMoveStabilize == Settings.KoikatuSettings.GripMoveStabilization.YawAndRotation
+ || KoikatuInterpreter.Settings.GripMoveStabilize == Settings.KoikatuSettings.GripMoveStabilization.OnlyRotation))
+ {
+ _moveLag = new GripMoveLag(_controller, KoikatuInterpreter.ScaleWithFps(KoikatuInterpreter.Settings.GripMoveStabilizationAmount));
+ }
+ }
+ else
+ {
+ UpdateAttachVec();
+ if (_attachPoint == null && _moveLag != null && KoikatuInterpreter.Settings.GripMoveStabilize == Settings.KoikatuSettings.GripMoveStabilization.OnlyRotation)
+ {
+ _moveLag = null;
+ }
+ }
+ }
+
+ }
+ private void UpdateAttachVec()
+ {
+ // Due to vec being utilized only by Trigger-mode, other modes don't update it, so we do it on button input.
+
+ if (_moveLag != null && _attachPoint != null)
+ {
+ _prevAttachVec = VR.Camera.SteamCam.head.TransformPoint(new Vector3(0f, 0.05f, 0f)) - _attachPoint.position;
+ }
+ }
+ }
+}
diff --git a/Shared/Controls/GripMoveLag.cs b/Shared/Controls/GripMoveLag.cs
new file mode 100644
index 0000000..bc4a14d
--- /dev/null
+++ b/Shared/Controls/GripMoveLag.cs
@@ -0,0 +1,274 @@
+using ADV.Commands.Object;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+using Valve.VR;
+using VRGIN.Core;
+using static UnityEngine.UI.GridLayoutGroup;
+
+namespace KK_VR.Handlers
+{
+ ///
+ /// Evaluates orientation from previous frames and sets as needed.
+ ///
+ internal class GripMoveLag
+ {
+ private readonly Transform _origin = VR.Camera.SteamCam.origin;
+ private readonly Transform _head = VR.Camera.SteamCam.head;
+ private readonly Transform _controller;
+ private readonly int _frameAmount;
+ private readonly float _frameAmountCoef;
+ private int _frameIndex;
+ private readonly float[] _frameCoefs;
+ private readonly Quaternion[] _prevRotations;
+ private readonly Vector3[] _prevPositions;
+ private Vector3 _lastAvgPos;
+ private bool _resetRequired;
+ internal GripMoveLag(Transform controller, int frameAvg, Vector3 inheritedPosition = default)
+ {
+ _controller = controller;
+ _frameAmount = frameAvg;
+ _frameAmountCoef = 1f / frameAvg;
+ _prevRotations = new Quaternion[frameAvg];
+ _prevPositions = new Vector3[frameAvg];
+ _frameCoefs = new float[frameAvg];
+ _lastAvgPos = _controller.position;
+
+ // Coefficients can be customized to change rotation follow type, even non-linear should look good.
+ for (var i = 0; i < frameAvg; i++)
+ {
+ _frameCoefs[i] = 1f / (i + 2f);
+ }
+ var pos = inheritedPosition == Vector3.zero ? _controller.position : inheritedPosition;
+ var rot = Quaternion.identity;
+ for (var i = 0; i < frameAvg; i++)
+ {
+ _prevRotations[i] = rot;
+ _prevPositions[i] = pos;
+ }
+ }
+ ///
+ /// Fills previous positions with supplied whatever.
+ ///
+ internal void ResetPositions(Vector3 position)
+ {
+ for (var i = 0; i < _frameAmount; i++)
+ {
+ _prevPositions[i] = position;
+ }
+ _lastAvgPos = position;
+ _resetRequired = false;
+ }
+ ///
+ /// Sets Origin to a "catching up" rotation. Same as other methods, but rotation only.
+ ///
+ internal void SetDeltaRotation(Quaternion rotation)
+ {
+ _resetRequired = true;
+ _prevRotations[_frameIndex] = rotation;
+ _frameIndex++;
+ if (_frameIndex == _frameAmount) _frameIndex = 0;
+ UpdateRotation();
+ }
+ private void UpdateRotation()
+ {
+ // Not average at all, is a biased catch-up. All averages I've seen suck tremendously.
+ // The most stale frame is grabbed on init part.
+ var count = _frameAmount - 1;
+
+ // The most stale rotation. Doesn't get touched in the loop.
+ var avgRot = _prevRotations[_frameIndex];
+ var j = _frameIndex;
+ for (var i = 0; i < count; i++)
+ {
+ if (++j == _frameAmount) j = 0;
+ avgRot = Quaternion.Lerp(avgRot, _prevRotations[j], _frameCoefs[i]);
+ }
+ _origin.rotation = avgRot * _origin.rotation;
+ }
+ ///
+ /// Sets Origin to an "average" of supplied orientation.
+ ///
+ internal void SetPositionAndRotation(Vector3 position, Quaternion rotation)
+ {
+ _prevRotations[_frameIndex] = rotation;
+ if (_resetRequired)
+ {
+ ResetPositions(position);
+ }
+ else
+ {
+ _prevPositions[_frameIndex] = position;
+ }
+ _frameIndex++;
+ if (_frameIndex == _frameAmount) _frameIndex = 0;
+ UpdatePositionAndRotation();
+ }
+ internal void SetDeltaPositionAndRotation(Vector3 deltaPosition, Quaternion deltaRotation)
+ {
+ _prevRotations[_frameIndex] = deltaRotation;
+ _prevPositions[_frameIndex] = deltaPosition;
+ _frameIndex++;
+ if (_frameIndex == _frameAmount) _frameIndex = 0;
+ UpdateDeltaPositionAndRotation();
+ }
+ private void UpdateDeltaPositionAndRotation()
+ {
+ // The most stale frame is grabbed on init part.
+ var count = _frameAmount - 1;
+
+ // The most stale rotation. Doesn't get touched in the loop.
+ var avgRot = _prevRotations[_frameIndex];
+ // Position that won't get touched in the loop. Don't care about the order, we use average.
+ var avgPos = _prevPositions[count];
+
+ var j = _frameIndex;
+ for (var i = 0; i < count; i++)
+ {
+ if (++j == _frameAmount) j = 0;
+ avgRot = Quaternion.Lerp(avgRot, _prevRotations[j], _frameCoefs[i]);
+ avgPos += _prevPositions[i];
+ }
+
+ avgPos *= _frameAmountCoef;
+ var preRotPos = _head.position;
+ _origin.rotation = avgRot * _origin.rotation;
+ _origin.position += (preRotPos - _head.position) + avgPos;
+ }
+
+ ///
+ /// Sets Origin to an "average" of supplied rotation and Controller position.
+ ///
+ internal void SetPositionAndRotation(Quaternion rotation)
+ {
+ // Can also reset rotations when switching away from this method,
+ // but hey, those movement look very human-esque,
+ // well, as long as they weren't something crazy, like 180 deg/frame.
+ _prevRotations[_frameIndex] = rotation;
+ if (_resetRequired)
+ {
+ ResetPositions(_controller.position);
+ }
+ else
+ {
+ _prevPositions[_frameIndex] = _controller.position;
+ }
+ _frameIndex++;
+ if (_frameIndex == _frameAmount) _frameIndex = 0;
+ UpdatePositionAndRotation();
+ }
+ private void UpdatePositionAndRotation()
+ {
+ // The most stale frame is grabbed on init part.
+ var count = _frameAmount - 1;
+
+ // The most stale rotation. Doesn't get touched in the loop.
+ var avgRot = _prevRotations[_frameIndex];
+ // Position that won't get touched in the loop. Don't care about the order, we use average.
+ var avgPos = _prevPositions[count];
+
+ var j = _frameIndex;
+ for (var i = 0; i < count; i++)
+ {
+ if (++j == _frameAmount) j = 0;
+ avgRot = Quaternion.Lerp(avgRot, _prevRotations[j], _frameCoefs[i]);
+ avgPos += _prevPositions[i];
+ }
+
+ avgPos *= _frameAmountCoef;
+ var preRotPos = _head.position;
+ _origin.rotation = avgRot * _origin.rotation;
+ //_origin.position += (preRotPos - _origin.position) + (_lastAvgPos - avgPos);
+ _origin.position += (preRotPos - _head.position) + (_lastAvgPos - avgPos);
+ _lastAvgPos = avgPos;
+ }
+ ///
+ /// Sets Origin to an average of Controller position.
+ ///
+ internal void SetPosition()
+ {
+ if (_resetRequired)
+ {
+ ResetPositions(_controller.position);
+ }
+ else
+ {
+ _prevPositions[_frameIndex] = _controller.position;
+ }
+ _frameIndex++;
+ if (_frameIndex == _frameAmount) _frameIndex = 0;
+ UpdatePosition(inverse: true);
+ }
+ ///
+ /// Sets Origin to an average of supplied delta of positions.
+ ///
+ internal void SetDeltaPosition(Vector3 deltaPosition)
+ {
+ //if (_resetRequired)
+ //{
+ // ResetPositions(deltaPosition);
+ //}
+ //else
+ //{
+ _prevPositions[_frameIndex] = deltaPosition;
+ //}
+ _frameIndex++;
+ if (_frameIndex == _frameAmount) _frameIndex = 0;
+ UpdatePositionDelta();
+ }
+ private void UpdatePositionDelta()
+ {
+ var avgPos = Vector3.zero;
+ for (var i = 0; i < _frameAmount; i++)
+ {
+ avgPos += _prevPositions[i];
+ }
+ avgPos *= _frameAmountCoef;
+ _origin.position += avgPos;
+ }
+
+ private void UpdatePosition(bool inverse)
+ {
+ var avgPos = Vector3.zero;
+ for (var i = 0; i < _frameAmount; i++)
+ {
+ avgPos += _prevPositions[i];
+ }
+ avgPos *= _frameAmountCoef;
+ if (inverse)
+ {
+ _origin.position += _lastAvgPos - avgPos;
+ }
+ else
+ {
+ _origin.position += avgPos - _lastAvgPos;
+ }
+ _lastAvgPos = avgPos;
+ }
+
+
+ // Way easier to create a new one instead.
+ //internal void ChangeLagAmount(bool increase)
+ //{
+ // if (increase)
+ // {
+ // if (_frameCurAmount != _frameCeiling)
+ // {
+ // _frameCurAmount++;
+ // _frameCurAmountCoef = 1f / _frameCurAmount;
+ // }
+ // }
+ // else
+ // {
+ // if (_frameCurAmount != _frameFloor)
+ // {
+ // _frameCurAmount--;
+ // _frameCurAmountCoef = 1f / _frameCurAmount;
+ // }
+ // }
+ //}
+
+ }
+}
diff --git a/Shared/Controls/KoikatuMenuHandler.cs b/Shared/Controls/KoikatuMenuHandler.cs
new file mode 100644
index 0000000..1411d47
--- /dev/null
+++ b/Shared/Controls/KoikatuMenuHandler.cs
@@ -0,0 +1,434 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+using Valve.VR;
+using VRGIN.Core;
+using VRGIN.Controls;
+using VRGIN.Visuals;
+using System.Linq;
+using VRGIN.Native;
+using static VRGIN.Native.WindowsInterop;
+using KK_VR.Holders;
+
+namespace KK_VR.Controls
+{
+ internal class KoikatuMenuHandler
+ { ///
+ /// Handler that is in charge of the menu interaction with controllers
+ ///
+ private readonly Transform _controller;
+ private const int MOUSE_STABILIZER_THRESHOLD = 30; // pixels
+ //private Controller.Lock _LaserLock = Controller.Lock.Invalid;
+ private LineRenderer Laser;
+ private Vector2? _mouseDownPosition;
+ private GUIQuad _quad;
+ private Vector3 _scaleVector;
+ private Buttons _pressedButtons;
+ private Controller.TrackpadDirection _lastDirection;
+ private float? _NextScrollTime;
+ internal bool LaserVisible
+ {
+ get
+ {
+ return Laser.gameObject.activeSelf;
+ }
+ set
+ {
+ // Toggle laser
+ Laser.gameObject.SetActive(value);
+ //VRPlugin.Logger.LogDebug($"LaserVisible = {value}");
+ // Initialize start position
+ if (value)
+ {
+ Laser.SetPosition(0, Laser.transform.position);
+ Laser.SetPosition(1, Laser.transform.position);
+ }
+ else
+ {
+ _mouseDownPosition = null;
+ }
+ }
+ }
+
+ internal void SetLastDirection(Controller.TrackpadDirection direction) => _lastDirection = direction;
+
+ internal KoikatuMenuHandler(Controller controller)
+ {
+ //_controller = controller;
+ _scaleVector = new Vector2((float)VRGUI.Width / Screen.width, (float)VRGUI.Height / Screen.height);
+ _controller = controller.transform;
+ var attachPosition = controller.FindAttachPosition("tip");
+
+ if (!attachPosition)
+ {
+ VRLog.Error("Attach position not found for laser!");
+ attachPosition = _controller;
+ }
+ Laser = new GameObject("Laser").AddComponent();
+ Laser.transform.SetParent(_controller, worldPositionStays: false); // (attachPosition, false);
+ //Laser.transform.SetParent(controller.transform, false); // (attachPosition, false);
+ Laser.transform.SetPositionAndRotation(attachPosition.position, attachPosition.rotation);
+ Laser.material = new Material(Shader.Find("Sprites/Default"));
+ Laser.material.renderQueue += 5000;
+ Laser.startColor = new Color(0f, 1f, 1f, 0f);
+ Laser.endColor = Color.cyan;
+
+ if (SteamVR.instance.hmd_TrackingSystemName == "lighthouse")
+ {
+ Laser.transform.localRotation = Quaternion.Euler(60, 0, 0);
+ Laser.transform.position += Laser.transform.forward * 0.06f;
+ }
+ else
+ {
+#if KK
+ Laser.transform.localRotation *= Quaternion.Euler(-10f, 0, 0);
+#else
+ Laser.transform.localRotation *= Quaternion.Euler(25f, 0, 0);
+#endif
+ }
+ Laser.SetVertexCount(2);
+ Laser.useWorldSpace = true;
+ Laser.SetWidth(0.002f, 0.002f);
+ LaserVisible = false;
+ }
+
+ enum Buttons
+ {
+ Left = 1,
+ Right = 2,
+ Middle = 4,
+ }
+
+ internal bool CheckMenu()
+ {
+ if (LaserVisible)
+ {
+ CheckInput();
+ return UpdateLaser();
+ }
+ else
+ {
+ return CheckForNearMenu();
+ }
+ }
+
+ internal void SetLaserVisibility(bool show)
+ {
+ LaserVisible = show;
+ }
+
+ internal void OnTrigger(bool press)
+ {
+ if (press)
+ {
+ VR.Input.Mouse.LeftButtonDown();
+ _pressedButtons |= Buttons.Left;
+ _mouseDownPosition = Vector2.Scale(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y), _scaleVector);
+ }
+ else
+ {
+ VR.Input.Mouse.LeftButtonUp();
+ _pressedButtons &= ~Buttons.Left;
+ _mouseDownPosition = null;
+ }
+ }
+ internal void OnGrip(bool press)
+ {
+ if (press && !_quad.IsOwned)
+ {
+ _quad.transform.SetParent(_controller, worldPositionStays: true);
+ _quad.IsOwned = true;
+ }
+ else
+ {
+ AbandonGUI();
+ }
+ }
+ internal void OnTouchpad(bool press)
+ {
+ if (press)
+ {
+ if (_quad.IsOwned && (_pressedButtons & Buttons.Left) != 0)
+ {
+ _quad.transform.SetParent(VR.Manager.transform, worldPositionStays: true);
+ _quad.IsOwned = false;
+ }
+ else
+ {
+
+ VR.Input.Mouse.MiddleButtonDown();
+ _pressedButtons |= Buttons.Middle;
+ }
+ }
+ else if ((_pressedButtons & Buttons.Middle) != 0)
+ {
+ VR.Input.Mouse.MiddleButtonUp();
+ _pressedButtons &= ~Buttons.Middle;
+ }
+ }
+ private void CheckInput()
+ {
+ switch (_lastDirection)
+ {
+ case Controller.TrackpadDirection.Up:
+ if (_quad.IsOwned)
+ {
+ if ((_pressedButtons & Buttons.Left) != 0)
+ {
+ MoveGui(Time.deltaTime);
+ }
+ else
+ {
+ ChangeGuiSize(Time.deltaTime);
+ }
+ }
+ else
+ {
+ Scroll(1);
+ }
+ break;
+ case Controller.TrackpadDirection.Down:
+ if (_quad.IsOwned)
+ {
+ if ((_pressedButtons & Buttons.Left) != 0)
+ {
+ MoveGui(-Time.deltaTime);
+ }
+ else
+ {
+ ChangeGuiSize(-Time.deltaTime);
+ }
+ }
+ else
+ {
+ Scroll(-1);
+ }
+ break;
+ default:
+ _NextScrollTime = null;
+ break;
+ }
+ }
+
+ private void ChangeGuiSize(float number)
+ {
+ _quad.transform.localScale *= 1 + number;
+ }
+
+ private void MoveGui(float number)
+ {
+ _quad.transform.position += number * 0.6f * Laser.transform.forward;
+ }
+
+ private void Scroll(int amount)
+ {
+ if (_NextScrollTime == null)
+ {
+ _NextScrollTime = Time.unscaledTime + 0.5f;
+ }
+ else if (_NextScrollTime < Time.unscaledTime)
+ {
+ _NextScrollTime += 0.1f;
+ }
+ else
+ {
+ return;
+ }
+ VR.Input.Mouse.VerticalScroll(amount);
+ }
+
+ private bool CheckForNearMenu()
+ {
+ _quad = GUIQuadRegistry.Quads.FirstOrDefault(IsLaserable);
+ if (_quad != null)
+ {
+ //VRPlugin.Logger.LogDebug($"CheckForNearMenu:Hit");
+ return true;
+ }
+ //VRPlugin.Logger.LogDebug($"CheckForNearMenu:Miss");
+ return false;
+ }
+
+ private bool IsLaserable(GUIQuad quad)
+ {
+ //return IsWithinRange(quad) && Raycast(quad, out _);
+ return Raycast(quad, out _);
+ }
+
+ private float GetRange(GUIQuad quad)
+ {
+ return quad.transform.localScale.z;
+ }
+ private bool IsWithinRange(GUIQuad quad)
+ {
+ return (quad.transform.position - Laser.transform.position).magnitude < GetRange(quad);
+ }
+
+ private bool Raycast(GUIQuad quad, out RaycastHit hit)
+ {
+ return quad.GetComponent().Raycast(new Ray(Laser.transform.position, Laser.transform.forward), out hit, GetRange(quad));
+ }
+
+ private bool UpdateLaser()
+ {
+ if (_quad && _quad.gameObject.activeInHierarchy
+ && Raycast(_quad, out var hit))
+ {
+ Laser.SetPosition(0, Laser.transform.position);
+ Laser.SetPosition(1, hit.point);
+
+ var newPos = new Vector2(hit.textureCoord.x * VRGUI.Width, (1 - hit.textureCoord.y) * VRGUI.Height);
+ //VRLog.Info("New Pos: {0}, textureCoord: {1}", newPos, hit.textureCoord);
+ if (!_mouseDownPosition.HasValue || Vector2.Distance(_mouseDownPosition.Value, newPos) > MOUSE_STABILIZER_THRESHOLD)
+ {
+ SetMousePosition(newPos);
+ _mouseDownPosition = null;
+ }
+ //VRPlugin.Logger.LogDebug($"UpdateLaser:On");
+ //VRPlugin.Logger.LogDebug($"MenuHandler:UpdateLaser:Success");
+ return true;
+ }
+ else
+ {
+ // May day, may day -- window is gone!
+
+ //VRPlugin.Logger.LogDebug($"UpdateLaser:Off");
+ LaserVisible = false;
+ ClearPresses();
+ return false;
+ }
+ }
+
+ private void ClearPresses()
+ {
+ AbandonGUI();
+ if ((_pressedButtons & Buttons.Left) != 0)
+ {
+ VR.Input.Mouse.LeftButtonUp();
+ }
+ if ((_pressedButtons & Buttons.Right) != 0)
+ {
+ VR.Input.Mouse.RightButtonUp();
+ }
+ if ((_pressedButtons & Buttons.Middle) != 0)
+ {
+ VR.Input.Mouse.MiddleButtonUp();
+ }
+ _pressedButtons = 0;
+ _NextScrollTime = null;
+ }
+
+ private void AbandonGUI()
+ {
+ if (_quad && _quad.transform.parent == _controller.transform)
+ {
+ _quad.transform.SetParent(VR.Camera.Origin, true);
+ _quad.IsOwned = false;
+ }
+ }
+
+
+
+
+ private static void SetMousePosition(Vector2 newPos)
+ {
+ int x = (int)Mathf.Round(newPos.x);
+ int y = (int)Mathf.Round(newPos.y);
+ var clientRect = WindowManager.GetClientRect();
+ var virtualScreenRect = WindowManager.GetVirtualScreenRect();
+ VR.Input.Mouse.MoveMouseToPositionOnVirtualDesktop(
+ (clientRect.Left + x - virtualScreenRect.Left) * 65535.0 / (virtualScreenRect.Right - virtualScreenRect.Left),
+ (clientRect.Top + y - virtualScreenRect.Top) * 65535.0 / (virtualScreenRect.Bottom - virtualScreenRect.Top));
+ }
+
+ //class ResizeHandler : ProtectedBehaviour
+ //{
+ // GUIQuad _Gui;
+ // Vector3? _StartLeft;
+ // Vector3? _StartRight;
+ // Vector3? _StartScale;
+ // Quaternion? _StartRotation;
+ // Vector3? _StartPosition;
+ // Quaternion _StartRotationController;
+ // Vector3? _OffsetFromCenter;
+
+ // public bool IsDragging { get; private set; }
+ // protected override void OnStart()
+ // {
+ // base.OnStart();
+ // _Gui = GetComponent();
+ // }
+
+ // protected override void OnUpdate()
+ // {
+ // base.OnUpdate();
+ // IsDragging = GetDevice(VR.Mode.Left).GetPress(EVRButtonId.k_EButton_Grip) &&
+ // GetDevice(VR.Mode.Right).GetPress(EVRButtonId.k_EButton_Grip);
+
+ // if (IsDragging)
+ // {
+ // if (_StartScale == null)
+ // {
+ // Initialize();
+ // }
+ // var newLeft = VR.Mode.Left.transform.position;
+ // var newRight = VR.Mode.Right.transform.position;
+
+ // var distance = Vector3.Distance(newLeft, newRight);
+ // var originalDistance = Vector3.Distance(_StartLeft.Value, _StartRight.Value);
+ // var newDirection = newRight - newLeft;
+ // var newCenter = newLeft + newDirection * 0.5f;
+
+ // // It would probably be easier than that but Quaternions have never been a strength of mine...
+ // var inverseOriginRot = Quaternion.Inverse(VR.Camera.SteamCam.origin.rotation);
+ // var avgRot = GetAverageRotation();
+ // var rotation = (inverseOriginRot * avgRot) * Quaternion.Inverse(inverseOriginRot * _StartRotationController);
+
+ // _Gui.transform.localScale = (distance / originalDistance) * _StartScale.Value;
+ // _Gui.transform.localRotation = rotation * _StartRotation.Value;
+ // _Gui.transform.position = newCenter + (avgRot * Quaternion.Inverse(_StartRotationController)) * _OffsetFromCenter.Value;
+
+ // }
+ // else
+ // {
+ // _StartScale = null;
+ // }
+ // }
+
+ // private Quaternion GetAverageRotation()
+ // {
+ // var leftPos = VR.Mode.Left.transform.position;
+ // var rightPos = VR.Mode.Right.transform.position;
+
+ // var right = (rightPos - leftPos).normalized;
+ // var up = Vector3.Lerp(VR.Mode.Left.transform.forward, VR.Mode.Right.transform.forward, 0.5f);
+ // var forward = Vector3.Cross(right, up).normalized;
+
+ // return Quaternion.LookRotation(forward, up);
+ // }
+ // private void Initialize()
+ // {
+ // _StartLeft = VR.Mode.Left.transform.position;
+ // _StartRight = VR.Mode.Right.transform.position;
+ // _StartScale = _Gui.transform.localScale;
+ // _StartRotation = _Gui.transform.localRotation;
+ // _StartPosition = _Gui.transform.position;
+ // _StartRotationController = GetAverageRotation();
+
+ // var originalDistance = Vector3.Distance(_StartLeft.Value, _StartRight.Value);
+ // var originalDirection = _StartRight.Value - _StartLeft.Value;
+ // var originalCenter = _StartLeft.Value + originalDirection * 0.5f;
+ // _OffsetFromCenter = transform.position - originalCenter;
+ // }
+
+
+ // private SteamVR_Controller.Device GetDevice(Controller controller)
+ // {
+ // return SteamVR_Controller.Input((int)controller.Tracking.index);
+ // }
+ //}
+ }
+}
+
+
diff --git a/Shared/Controls/KoikatuMenuTool.cs b/Shared/Controls/KoikatuMenuTool.cs
new file mode 100644
index 0000000..3ac12b1
--- /dev/null
+++ b/Shared/Controls/KoikatuMenuTool.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using VRGIN.Controls;
+using UnityEngine;
+using static Illusion.Utils;
+using VRGIN.Visuals;
+using VRGIN.Core;
+
+namespace KK_VR.Controls
+{
+ internal class KoikatuMenuTool
+ {
+ internal bool IsAttached => _attached;
+ private bool _attached;
+ private static GUIQuad _gui;
+ internal KoikatuMenuTool(int index)
+ {
+ if (!_gui && index == 1)
+ {
+ _gui = GUIQuad.Create();
+ _gui.transform.parent = VR.Mode.Right.transform;
+ _gui.transform.localScale = Vector3.one * 0.3f;
+ _gui.transform.localPosition = new Vector3(0, 0.05f, -0.06f);
+ _gui.transform.localRotation = Quaternion.Euler(90, 0, 0);
+ _gui.IsOwned = true;
+ _gui.gameObject.SetActive(true);
+ _attached = true;
+ }
+ }
+ internal static void ToggleState()
+ {
+ _gui.gameObject.SetActive(!_gui.gameObject.activeSelf);
+ }
+ //internal void TakeGUI(GUIQuad quad)
+ //{
+ // if (quad && !Gui && !quad.IsOwned)
+ // {
+ // Gui = quad;
+ // //Gui.transform.parent = transform;
+ // Gui.transform.SetParent(transform, worldPositionStays: true);
+
+ // quad.IsOwned = true;
+ // }
+ // VRLog.Debug($"TakeGui:{Gui}:{quad.IsOwned}");
+ //}
+
+ internal static void TakeGui()
+ {
+ if (_gui != null && !_gui.transform.parent.name.Contains("Controller") && _gui.transform.parent != VR.Camera.Origin)
+ {
+ var head = VR.Camera.Head;
+ var origin = VR.Camera.Origin;
+
+ _gui.transform.SetParent(origin, worldPositionStays: true);
+
+ // If no menu in proximity after the scene load. (was abandoned beforehand)
+ if (Vector3.Distance(_gui.transform.position, head.position) > 3f)
+ {
+ _gui.transform.SetPositionAndRotation(
+ head.position + (origin.rotation * Quaternion.Euler(0f, 60f, 0f)) * head.forward,
+ head.rotation * Quaternion.Euler(0f, 90f, 0f)
+ );
+ }
+ }
+ }
+
+ internal void AbandonGUI()
+ {
+ if (_attached)
+ {
+ //timeAbandoned = Time.unscaledTime;
+ _gui.IsOwned = false;
+ _gui.transform.SetParent(VR.Camera.Origin, true);
+ _attached = false;
+ }
+ }
+ }
+}
diff --git a/MainGameVR/Controls/LocationPicker.cs b/Shared/Controls/LocationPicker.cs
similarity index 62%
rename from MainGameVR/Controls/LocationPicker.cs
rename to Shared/Controls/LocationPicker.cs
index d59c4ea..9510b02 100644
--- a/MainGameVR/Controls/LocationPicker.cs
+++ b/Shared/Controls/LocationPicker.cs
@@ -11,12 +11,12 @@
using VRGIN.Core;
using Utils = Illusion.Game.Utils;
-namespace KKS_VR.Controls
+namespace KK_VR.Controls
{
///
/// A component to add to the controllers the ability to pick a new location in H scenes.
///
- internal class LocationPicker : ProtectedBehaviour
+ internal class LocationPicker : MonoBehaviour
{
private Controller _controller;
private LineRenderer _laser;
@@ -25,20 +25,47 @@ internal class LocationPicker : ProtectedBehaviour
private HPointData _selection; // may be null
private Animator _selectionAnim; // may be null. Also, null if _selection is null.
-
- protected override void OnAwake()
+ internal static void AddComponents()
{
- base.OnAwake();
+ VR.Mode.Left.gameObject.AddComponent();
+ VR.Mode.Right.gameObject.AddComponent();
+ }
+ internal static void DestroyComponents()
+ {
+#if KK
+ var leftComponent = VR.Mode.Left.gameObject.GetComponent();
+ if (leftComponent != null)
+#elif KKS
+ if (VR.Mode.Left.gameObject.TryGetComponent(out var leftComponent))
+#endif
+ {
+ UnityEngine.Object.Destroy(leftComponent);
+ }
+#if KK
+ var rightComponent = VR.Mode.Right.gameObject.GetComponent();
+ if (rightComponent != null)
+#elif KKS
+ if (VR.Mode.Right.gameObject.TryGetComponent(out var rightComponent))
+#endif
+ {
+ UnityEngine.Object.Destroy(rightComponent);
+ }
+ }
+ private void Awake()
+ {
_controller = GetComponent();
+ AddLaser();
}
- protected override void OnUpdate()
+ private void Update()
{
- base.OnUpdate();
-
// TODO: somehow arrange that this component is only enabled during location selection?
+#if KK
+ if (Manager.Scene.Instance.NowSceneNames[0].Equals("HPointMove")
+#elif KKS
if (Scene.NowSceneNames[0] == "HPointMove"
+#endif
&& (_lock != null || _controller.CanAcquireFocus()))
{
if (!_laserEnabled)
@@ -67,13 +94,15 @@ private void UpdateSelection()
{
var ray = new Ray(_laser.transform.position, _laser.transform.TransformDirection(Vector3.forward));
var hit = Physics.RaycastAll(ray)
- .Where(h => h.collider.tag == "H/HPoint")
+ .Where(h => h.collider.CompareTag("H/HPoint"))
.OrderBy(h => h.distance)
.FirstOrDefault();
- if (hit.collider?.transform.parent.GetComponent() is HPointData point)
+ if (hit.collider != null)
{
- if (point != _selection) Select(point);
+ var hPointData = hit.collider.transform.parent.GetComponent();
+ if (hPointData != _selection)
+ Select(hPointData);
}
else
{
@@ -107,7 +136,11 @@ private static IEnumerator ChangeLocation(Action action)
{
yield return null;
action();
+#if KK
+ Manager.Scene.Instance.UnLoad();
+#else
Scene.Unload();
+#endif
}
private void Unselect()
@@ -115,11 +148,14 @@ private void Unselect()
if (_selectionAnim != null)
{
if (_selectionAnim.GetCurrentAnimatorStateInfo(0).IsName("upidle"))
+ {
_selectionAnim.SetTrigger("down");
+ }
else
+ {
_selectionAnim.Play("idle");
+ }
}
-
CleanupSelection();
}
@@ -146,35 +182,29 @@ private void Select(HPointData point)
_controller.TryAcquireFocus(out _lock);
}
- // This method is called by VRGIN via SendMessage.
- private void OnRenderModelLoaded()
+ private void AddLaser()
{
- try
+ var attachPosition = _controller.transform.Find("Laser");
+ if (!attachPosition)
{
- var attachPosition = _controller.FindAttachPosition("tip");
+ VRPlugin.Logger.LogWarning("Attach position not found for laser!");
+ attachPosition = transform;
+ }
- if (!attachPosition)
- {
- VRLog.Warn("LocationPicker: Attach position not found for laser!");
- attachPosition = transform;
- }
+ _laser = new GameObject("LocationPicker").AddComponent();
- _laser = new GameObject("LocationPicker laser").AddComponent();
- _laser.transform.SetParent(attachPosition, false);
- _laser.material = new Material(Shader.Find("Sprites/Default"));
- _laser.startColor = _laser.endColor = new Color(0.21f, 0.96f, 1.00f);
+ _laser.transform.parent = _controller.transform;
+ _laser.transform.SetPositionAndRotation(attachPosition.position, attachPosition.rotation);
- _laser.positionCount = 2;
- _laser.useWorldSpace = false;
- _laser.startWidth = _laser.endWidth = 0.002f;
- _laser.SetPosition(0, Vector3.zero);
- _laser.SetPosition(1, Vector3.forward * 20);
- _laser.gameObject.SetActive(false);
- }
- catch (Exception e)
- {
- VRLog.Error(e);
- }
+ _laser.material = new Material(Shader.Find("Sprites/Default"));
+ _laser.startColor = Color.cyan;
+ _laser.endColor = new Color(1f, 1f, 1f, 0f);
+ _laser.positionCount = 2;
+ _laser.useWorldSpace = false;
+ _laser.startWidth = _laser.endWidth = 0.002f;
+ _laser.SetPosition(0, Vector3.zero);
+ _laser.SetPosition(1, Vector3.forward * 5);
+ _laser.gameObject.SetActive(false);
}
}
}
diff --git a/Shared/Controls/ToolUtil.cs b/Shared/Controls/ToolUtil.cs
deleted file mode 100644
index b05fff9..0000000
--- a/Shared/Controls/ToolUtil.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using System.Linq;
-using UnityEngine;
-using VRGIN.Controls;
-using VRGIN.Core;
-
-namespace KKS_VR.Controls
-{
- internal class ToolUtil
- {
- public static HelpText HelpTrigger(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(0.06f, -0.04f, -0.05f), Vector3.zero, "trigger");
- }
-
- public static HelpText HelpGrip(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(-0.06f, 0, -0.05f), Vector3.zero, "lgrip", "handgrip");
- }
-
- public static HelpText HelpTrackpadCenter(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(0, 0.06f, 0.02f), Vector3.zero, "trackpad", "thumbstick");
- }
-
- public static HelpText HelpTrackpadLeft(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(-0.05f, 0.04f, 0), new Vector3(-0.01f, 0, 0), "trackpad", "thumbstick");
- }
-
- public static HelpText HelpTrackpadRight(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(0.05f, 0.04f, 0), new Vector3(0.01f, 0, 0), "trackpad", "thumbstick");
- }
-
- public static HelpText HelpTrackpadUp(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(0, 0.04f, 0.07f), new Vector3(0, 0, 0.01f), "trackpad", "thumbstick");
- }
-
- public static HelpText HelpTrackpadDown(Controller controller, string description)
- {
- return MakeHelpText(controller, description, new Vector3(0, 0.04f, -0.05f), new Vector3(0, 0, -0.01f), "trackpad", "thumbstick");
- }
-
-
- public static HelpText MakeHelpText(
- Controller controller,
- string description,
- Vector3 textOffset,
- Vector3 lineOffset,
- params string[] attachNames)
- {
- var attach = attachNames
- .Select(name => controller.FindAttachPosition(name))
- .Where(x => x != null)
- .FirstOrDefault();
- if (attach == null)
- {
- VRLog.Warn($"HelpText: attach point not found for {attachNames}");
- return null;
- }
-
- return HelpText.Create(description, attach, textOffset, lineOffset);
- }
- }
-}
diff --git a/MainGameVR/AnimationCrossFader.cs b/Shared/Features/CrossFader.cs
similarity index 76%
rename from MainGameVR/AnimationCrossFader.cs
rename to Shared/Features/CrossFader.cs
index c56ed33..6cc7638 100644
--- a/MainGameVR/AnimationCrossFader.cs
+++ b/Shared/Features/CrossFader.cs
@@ -1,26 +1,34 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
+using System.Text.RegularExpressions;
using ADV;
using ADV.Commands.Base;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
+using KKAPI.MainGame;
using KKAPI.Utilities;
-using KKS_VR.Settings;
+using KK_VR.Interpreters;
+using KK_VR.Settings;
+using Manager;
+using Unity.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using Motion = Illusion.Game.Elements.EasyLoader.Motion;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
-namespace KKS_VR
+namespace KK_VR.Features
{
///
/// Based on KKS_CrossFader by Sabakan
///
- public static class AnimationCrossFader
+ public static class CrossFader
{
+ public static bool InTransition => _inTransition;
+ private static bool _inTransition;
public enum CrossFaderMode
{
Disabled,
@@ -37,7 +45,6 @@ public static void Initialize(ConfigFile config, bool vrActivated)
VRPlugin.Logger.LogWarning("Disabling the AnimationCrossFader feature because KKS_CrossFader is installed");
return;
}
-
var enabled = config.Bind(SettingsManager.SectionGeneral, "Cross-fade character animations", CrossFaderMode.OnlyInVr,
"Interpolate between animations/poses to make transitions look less jarring.\nChanges take effect after a scene change.");
@@ -70,7 +77,7 @@ private static void ApplyHooks(bool enable)
{
if (enable && _hi == null)
{
- _hi = new Harmony(typeof(AnimationCrossFader).FullName);
+ _hi = new Harmony(typeof(CrossFader).FullName);
_hi.PatchAll(typeof(AdvHooks));
_hi.PatchAll(typeof(HSceneHooks));
}
@@ -92,20 +99,31 @@ private static void ApplyHooks(bool enable)
}
// CrossFade animations in ADV and TalkScene
- private static class AdvHooks
+ internal static class AdvHooks
{
+ internal static bool Reaction { get; private set; }
[HarmonyPrefix]
- [HarmonyWrapSafe]
+ //[HarmonyWrapSafe]
[HarmonyPatch(typeof(Motion), nameof(Motion.Play))]
public static void AdvMotionAddCrossfadeHook(Motion __instance, Animator animator)
{
// Make the animation cross fade from the current one, uses stock game code
__instance.isCrossFade = true;
- __instance.transitionDuration = Random.Range(0.1f, 0.3f);
- }
+ if (KoikatuInterpreter.CurrentScene == KoikatuInterpreter.SceneType.TalkScene)
+ {
+ // Speed up considerably crossFade after Talk/AdvScene TouchReaction function.
+ __instance.transitionDuration = Reaction ? Random.Range(0.1f, 0.2f) : Random.Range(0.5f, 1f);
+ Reaction = false;
+ if (__instance.state.StartsWith("f_reaction_", StringComparison.Ordinal))
+ {
+ Reaction = true;
+ }
+ }
+ else
+ __instance.transitionDuration = Random.Range(0.3f, 0.6f);
+ }
#region Disable screen fade effect when ADV is changing character animations
-
[HarmonyPrefix]
[HarmonyWrapSafe]
[HarmonyPatch(typeof(TalkScene), nameof(TalkScene.AnimePlay))]
@@ -122,7 +140,6 @@ public static void AdvMotionPlayRemoveFadeHook(ADV.Commands.Base.Motion.Data mot
{
if (isCrossFade)
{
- VRPlugin.Logger.LogDebug("Disabling isCrossFade in MotionPlay");
isCrossFade = false;
}
}
@@ -164,14 +181,14 @@ public static void AdvMotionDoFadeOverridePost(ADV.Commands.Chara.Motion __insta
}
#if DEBUG
- [HarmonyPrefix]
- [HarmonyWrapSafe]
- [HarmonyPatch(typeof(CrossFade), nameof(CrossFade.FadeStart))]
- public static void DebugCrossFadeStartHook(CrossFade __instance, float time)
- {
- if (__instance.texBase != null)
- VRPlugin.Logger.LogWarning($"CrossFade.FadeStart called (obj={__instance.GetFullPath()} time={time}) from:\n{new StackTrace(2)}");
- }
+ //[HarmonyPrefix]
+ //[HarmonyWrapSafe]
+ //[HarmonyPatch(typeof(CrossFade), nameof(CrossFade.FadeStart))]
+ //public static void DebugCrossFadeStartHook(CrossFade __instance, float time)
+ //{
+ // if (__instance.texBase != null)
+ // VRPlugin.Logger.LogWarning($"CrossFade.FadeStart called (obj={__instance.GetFullPath()} time={time}) from:\n{new StackTrace(2)}");
+ //}
#endif
#endregion
@@ -196,7 +213,7 @@ public static bool LoadAnimatorOverridePre(Motion __instance, Animator animator,
var newHash = __instance.bundle + "|" + __instance.asset;
if (newHash == hash)
{
- VRPlugin.Logger.LogDebug($"Skipping loading already loaded animator controller from [{newHash}] on [{animator.GetFullPath()}]");
+ //VRPlugin.Logger.LogDebug($"Skipping loading already loaded animator controller from [{newHash}] on [{animator.GetFullPath()}]");
return false;
}
else _AnimationControllerLookup.Remove(animatorController);
@@ -223,31 +240,42 @@ public static void LoadAnimatorOverridePost(Motion __instance, Animator animator
}
// CrossFade animations in HScenes, same as the KKS_CrossFader plugin but more compact
- private static class HSceneHooks
+ internal static class HSceneHooks
{
+ // Because first crossFade matters.
+ internal static void SetFlag(HFlag flag) => _hflag = flag;
private static HFlag _hflag;
[HarmonyPrefix]
- [HarmonyPatch(typeof(CrossFade), nameof(CrossFade.FadeStart), new[] { typeof(float) }, null)]
+ [HarmonyPatch(typeof(CrossFade), nameof(CrossFade.FadeStart), [typeof(float)], null)]
public static bool HSceneFadeStartOverrideHook()
{
return _hflag == null;
}
[HarmonyPrefix]
- [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.syncPlay), new[] { typeof(string), typeof(int), typeof(float) }, null)]
+#if KK
+ [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.setPlay), [typeof(string), typeof(int)], null)]
+ public static bool HSceneSetPlayHook(string _strAnmName, int _nLayer, ChaControl __instance, ref bool __result)
+#else
+ [HarmonyPatch(typeof(ChaControl), nameof(ChaControl.syncPlay), [typeof(string), typeof(int), typeof(float)], null)]
public static bool HSceneSyncPlayHook(ChaControl __instance, string _strameHash, int _nLayer, float _fnormalizedTime, ref bool __result)
+#endif
{
if (!KKAPI.MainGame.GameAPI.InsideHScene) return true;
if (_hflag == null) _hflag = Object.FindObjectOfType();
if (_hflag == null) return true;
-
- //VRPlugin.Logger.LogDebug($"syncPlay hflag={_hflag} namehash={_strameHash} nlayer={_nLayer} normalizedtime={_fnormalizedTime} chara={__instance}");
+#if KK
+ var str = _strAnmName;
+#else
+ var str = _strameHash;
+#endif
+ //VRPlugin.Logger.LogDebug($"ChaControl:syncPlay hflag={_hflag} namehash={_strameHash} nlayer={_nLayer} normalizedtime={_fnormalizedTime} chara={__instance}");
switch (_hflag.mode)
{
case HFlag.EMode.peeping:
- __instance.animBody.CrossFadeInFixedTime(_strameHash, 0f, _nLayer);
+ __instance.animBody.CrossFadeInFixedTime(str, 0f, _nLayer);
__result = true;
return false;
@@ -255,9 +283,9 @@ public static bool HSceneSyncPlayHook(ChaControl __instance, string _strameHash,
case HFlag.EMode.houshi3P:
case HFlag.EMode.houshi3PMMF:
{
- if (_strameHash == "Oral_Idle_IN" || _strameHash == "M_OUT_Start")
+ if (str == "Oral_Idle_IN" || str == "M_OUT_Start")
{
- __instance.animBody.CrossFadeInFixedTime(_strameHash, 0.2f, _nLayer);
+ __instance.animBody.CrossFadeInFixedTime(str, 0.2f, _nLayer);
__result = true;
return false;
}
@@ -265,12 +293,12 @@ public static bool HSceneSyncPlayHook(ChaControl __instance, string _strameHash,
}
}
- if ((_strameHash == "M_Idle" && __instance.animBody.GetCurrentAnimatorStateInfo(0).IsName("M_Touch"))
- || (_strameHash == "A_Idle" && __instance.animBody.GetCurrentAnimatorStateInfo(0).IsName("A_Touch"))
- || (_strameHash == "S_Idle" && __instance.animBody.GetCurrentAnimatorStateInfo(0).IsName("S_Touch")))
+ if ((str == "M_Idle" && __instance.animBody.GetCurrentAnimatorStateInfo(0).IsName("M_Touch"))
+ || (str == "A_Idle" && __instance.animBody.GetCurrentAnimatorStateInfo(0).IsName("A_Touch"))
+ || (str == "S_Idle" && __instance.animBody.GetCurrentAnimatorStateInfo(0).IsName("S_Touch")))
return true;
- __instance.animBody.CrossFadeInFixedTime(_strameHash, Random.Range(0.5f, 1f), _nLayer);
+ __instance.animBody.CrossFadeInFixedTime(str, Random.Range(0.5f, 1f), _nLayer);
__result = true;
return false;
}
@@ -288,8 +316,8 @@ public static bool HSceneSyncPlayHook(ChaControl __instance, string _strameHash,
[HarmonyPatch(typeof(H3PDarkSonyu), nameof(H3PDarkSonyu.Proc))]
public static bool HSceneProcOverrideHook(HActionBase __instance)
{
- var inTransition = !__instance.female.animBody.GetCurrentAnimatorStateInfo(0).IsName(__instance.flags.nowAnimStateName);
- return !inTransition;
+ _inTransition = !__instance.female.animBody.GetCurrentAnimatorStateInfo(0).IsName(__instance.flags.nowAnimStateName);
+ return !_inTransition;
}
}
}
diff --git a/MainGameVR/Features/HideMaleHead.cs b/Shared/Features/HideMaleHead.cs
similarity index 77%
rename from MainGameVR/Features/HideMaleHead.cs
rename to Shared/Features/HideMaleHead.cs
index af496d3..b4a464e 100644
--- a/MainGameVR/Features/HideMaleHead.cs
+++ b/Shared/Features/HideMaleHead.cs
@@ -1,8 +1,7 @@
using HarmonyLib;
using VRGIN.Core;
-using KKS_VR.Settings;
-namespace KKS_VR.Features
+namespace KK_VR.Features
{
///
/// A component to be attached to every male character.
@@ -10,6 +9,7 @@ namespace KKS_VR.Features
internal class HideMaleHead : ProtectedBehaviour
{
public static bool ForceHideHead { get; set; }
+ public static bool ForceShowHead { get; set; }
private ChaControl _control;
@@ -23,6 +23,11 @@ protected override void OnLateUpdate()
// Hide the head if the VR camera is inside it.
// This also essentially negates the effect of scenairo-controlled
// head hiding, which is found in some ADV scenes.
+ if (ForceShowHead)
+ {
+ _control.fileStatus.visibleHeadAlways = true;
+ return;
+ }
var head = _control.objHead?.transform;
if (_control.objTop?.activeSelf == true && head != null)
{
@@ -38,7 +43,10 @@ protected override void OnLateUpdate()
// this case, it's important that the head disappears with
// 0 frame delay, so we proactively deactive it here.
_control.objHead.SetActive(false);
- foreach (var hair in _control.objHair) hair.SetActive(false);
+ foreach (var hair in _control.objHair)
+ {
+ hair.SetActive(false);
+ }
}
}
else
@@ -53,12 +61,11 @@ internal class HideMaleHeadPatches
{
[HarmonyPatch(nameof(ChaControl.Initialize))]
[HarmonyPostfix]
- private static void PostInitialize(ChaControl __instance)
+ static void PostInitialize(ChaControl __instance)
{
- if ((__instance.sex == 0 && POVConfig.targetGender.Value == POVConfig.Gender.Male) ||
- (__instance.sex == 1 && POVConfig.targetGender.Value == POVConfig.Gender.Female) ||
- (POVConfig.targetGender.Value == POVConfig.Gender.All))
+ if (__instance.sex == 0 && !__instance.transform.parent.name.Equals("HScene"))
{
+ // In H we do this more lazily/appropriately through POV.
__instance.GetOrAddComponent();
}
}
diff --git a/Shared/Features/LoadVoice.cs b/Shared/Features/LoadVoice.cs
new file mode 100644
index 0000000..c4d9e79
--- /dev/null
+++ b/Shared/Features/LoadVoice.cs
@@ -0,0 +1,214 @@
+using BepInEx.Configuration;
+using HarmonyLib;
+using Illusion.Game;
+using KK_VR.Features.Extras;
+using KK_VR.Interpreters;
+using Manager;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data.SqlTypes;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using UnityEngine;
+using UnityEngine.Networking;
+using Random = UnityEngine.Random;
+
+namespace KK_VR.Features
+{
+ ///
+ /// Plays native voice lines for any chara at any moment
+ ///
+ public static class LoadVoice
+ {
+ public enum VoiceType
+ {
+ Laugh,
+ Short
+ }
+ private static Func _maleBreathPersonality;
+ private const string _path = "sound/data/pcm/c**/";
+ private static string GetBundleH(int personalityId)
+ {
+#if KK
+ return personalityId switch
+ {
+ 30 => "14",
+ 31 => "15",
+ 32 => "16",
+ 33 => "17",
+ 34 or 35 or 36 or 37 => "20",
+ 38 => "50",
+ _ => "00"
+ };
+#else
+ return personalityId switch
+ {
+ 40 or 41 or 42 or 43 => "71",
+ _ => "01"
+ };
+#endif
+ }
+ private static string GetBundleNonH(int personalityId)
+ {
+ return personalityId switch
+ {
+ 40 or 41 or 42 or 43 => "70",
+ _ => "00"
+ };
+ }
+ public static void Init()
+ {
+ var type = AccessTools.TypeByName("KK_MaleBreath.MaleBreath");
+ if (type != null)
+ {
+ _maleBreathPersonality = AccessTools.MethodDelegate>(AccessTools.FirstMethod(type, m => m.Name.Equals("GetPlayerPersonality")));
+ }
+ }
+ private static void Play(VoiceType type, ChaControl chara)//, bool setCooldown)
+ {
+ // Copy MaleBreath method here, prettier.
+ //VRPlugin.Logger.LogDebug($"Voice:Play:{type}:{chara}");
+
+ var voiceList = GetVoiceList(type);
+ if (voiceList == null)
+ {
+ return;
+ }
+#if KK
+ var hExp = Game.Instance.HeroineList
+#else
+ var hExp = Game.HeroineList
+#endif
+ .Where(h => h.chaCtrl == chara)
+ .Select(h => h.HExperience)
+ .FirstOrDefault();
+
+ var personalityId = chara.fileParam.personality;
+ if (chara.sex == 0 && _maleBreathPersonality != null)
+ {
+ personalityId = _maleBreathPersonality();
+ }
+
+ if (hExp == SaveData.Heroine.HExperienceKind.不慣れ)
+ {
+ // They often use the same asset.
+ // Hook for this?
+ hExp = SaveData.Heroine.HExperienceKind.初めて;
+ }
+ var bundle = _path + voiceList[Random.Range(0, voiceList.Count)];
+
+ // Replace personality id.
+ bundle = bundle.Replace("**", (personalityId < 10 ? "0" : "") + personalityId.ToString());
+
+ // Replace hExp if there is any.
+ bundle = bundle.Replace("^", ((int)hExp).ToString());
+ var index = bundle.LastIndexOf('/');
+
+ // Extract Asset from the string at the end.
+ var asset = bundle.Substring(index + 1);
+
+ // Remove it from the string.
+ bundle = bundle.Remove(index + 1);
+
+ var h = bundle.EndsWith("h/", StringComparison.OrdinalIgnoreCase);
+ bundle += GetBundle(personalityId, hVoice: h);
+
+ //VRPlugin.Logger.LogDebug($"{bundle} + {asset}");
+ var setting = new Utils.Voice.Setting
+ {
+ no = personalityId,
+ assetBundleName = bundle,
+ assetName = asset,
+ pitch = chara.fileParam.voicePitch,
+ voiceTrans = chara.dictRefObj[ChaReference.RefObjKey.a_n_mouth].transform,
+
+ };
+ //chara.ChangeMouthPtn(0, true);
+#if KK
+ chara.SetVoiceTransform(Utils.Voice.OnecePlayChara(setting));
+#else
+ chara.SetLipSync(Utils.Voice.OncePlayChara(setting));
+#endif
+
+ // We respect hScene voices.
+ if (KoikatuInterpreter.CurrentScene == KoikatuInterpreter.SceneType.HScene)
+ {
+ for (var i = 0; i < HSceneInterpreter.lstFemale.Count; i++)
+ {
+ if (HSceneInterpreter.lstFemale[i] == chara)
+ {
+ // Something of this is probably unnecessary, but figuring it out is a huge pain, given 'HVoiceCtrl' structure.
+ var voice = HSceneInterpreter.hVoice.nowVoices[i];
+ voice.state = HVoiceCtrl.VoiceKind.breathShort;
+ voice.notOverWrite = true;
+ voice.shortInfo.isPlay = true;
+ voice.link = new HVoiceCtrl.LinkInfo();
+ voice.shortInfo.pathAsset = bundle;
+ voice.shortInfo.nameFile = asset;
+ HSceneInterpreter.hVoice.linkUseBreathPtn[i] = null;
+ HSceneInterpreter.hVoice.linkUseVoicePtn[i] = null;
+ break;
+ }
+ }
+ }
+ }
+ public static void PlayVoice(VoiceType voiceType, ChaControl chara, bool voiceWait = true)
+ {
+ if (!voiceWait || chara.asVoice == null || !IsVoiceActive(chara))
+ {
+ Play(voiceType, chara);
+ }
+ }
+ private static bool IsVoiceActive(ChaControl chara)
+ {
+ if (KoikatuInterpreter.CurrentScene == KoikatuInterpreter.SceneType.HScene)
+ {
+ for (var i = 0; i < HSceneInterpreter.lstFemale.Count; i++)
+ {
+ if (HSceneInterpreter.lstFemale[i] == chara)
+ {
+ return HSceneInterpreter.hVoice.nowVoices[i].state != HVoiceCtrl.VoiceKind.breath || HSceneInterpreter.IsKissAnim;
+ }
+ }
+ }
+ return chara.asVoice != null
+ && !(chara.asVoice.name.StartsWith("h_ko", StringComparison.Ordinal)
+ // Match "0**_0*" at the end for 'Short'. e.g. in "h_ko_27_00_006_04" - [006_04] = Match!
+ || (Regex.IsMatch(chara.asVoice.name, @"0..\S0.$", RegexOptions.CultureInvariant)
+ && _kissBreaths.Any(s => chara.asVoice.name.EndsWith(s, StringComparison.Ordinal))));
+ }
+ private static readonly List _kissBreaths =
+ [
+ "013",
+ "014",
+ "015",
+ "016",
+ "017",
+ "018",
+ "019",
+ "020"
+ ];
+ private static string GetBundle(int id, bool hVoice)
+ {
+#if KK
+ return GetBundleH(id) + (hVoice ? "_00.unity3d" : ".unity3d");
+#else
+ return (hVoice ? GetBundleH(id) : GetBundleNonH(id)) + ".unity3d";
+#endif
+ }
+ private static List GetVoiceList(VoiceType type)
+ {
+ return type switch
+ {
+ VoiceType.Laugh => VoiceBundles.Laughs,
+ VoiceType.Short => VoiceBundles.Shorts,
+ _ => null
+ };
+
+ }
+ }
+}
diff --git a/Shared/Features/OldVRFade.cs b/Shared/Features/OldVRFade.cs
new file mode 100644
index 0000000..36c698c
--- /dev/null
+++ b/Shared/Features/OldVRFade.cs
@@ -0,0 +1,147 @@
+//using System;
+//using System.Collections;
+//using ActionGame;
+//using UnityEngine;
+//using Valve.VR;
+//using VRGIN.Core;
+
+//namespace KK_VR.Features
+//{
+// ///
+// /// A VR fader that replaces the fader of the base game.
+// ///
+// internal class OldVRFade : ProtectedBehaviour
+// {
+// ///
+// /// Reference to the image used by the vanilla SceneFade object.
+// ///
+// private CanvasGroup _vanillaFade;
+
+// private readonly float _gridFadeTime = 1;
+// private readonly float _fadeAlphaThresholdHigh = 0.9999f;
+// private readonly float _fadeAlphaThresholdLow = 0.0001f;
+
+// private bool _isFading;
+
+// public static void Create()
+// {
+// VR.Camera.gameObject.AddComponent();
+// }
+
+// protected override void OnAwake()
+// {
+// _vanillaFade = Manager.Scene.sceneFadeCanvas?.canvasGroup ?? throw new ArgumentNullException(nameof(_vanillaFade), "sceneFadeCanvas or canvasGroup is null");
+// }
+
+// protected override void OnUpdate()
+// {
+// if (!_isFading && _vanillaFade && _vanillaFade.alpha > _fadeAlphaThresholdLow)
+// {
+// StartCoroutine(DeepFadeCo());
+// }
+// }
+
+// ///
+// /// A coroutine for entering "deep fade", where we cut to the compositor's grid and display some overlay.
+// /// Based on https://github.com/mosirnik/KK_MainGameVR/commit/12e435f1e9a70c7d7b5dd56de416d300a2836091
+// ///
+// private IEnumerator DeepFadeCo()
+// {
+// if (OpenVR.Overlay == null || _isFading)
+// yield break;
+
+// _isFading = true;
+
+// // Make the world outside of the game the same color as the loading screen instead of the headset default skybox
+// SetCompositorSkyboxOverride(GetFadeColor());
+
+// var compositor = OpenVR.Compositor;
+// if (compositor != null)
+// {
+// // Fade the game out so the ouside world is now seen instead of the laggy loading screen
+// compositor.FadeGrid(_gridFadeTime, true);
+
+// // It looks like we need to pause rendering here, otherwise the
+// // compositor will automatically put us back from the grid.
+// SteamVR_Render.pauseRendering = true;
+// }
+
+// // Wait for the game to fully fade in
+// while (_vanillaFade.alpha <= _fadeAlphaThresholdHigh)
+// {
+// if (!_vanillaFade || _vanillaFade.alpha < _fadeAlphaThresholdLow)
+// goto endEarly;
+
+// yield return null;
+// }
+
+// // Wait for the game to start fading out
+// while (_vanillaFade.alpha > _fadeAlphaThresholdHigh)
+// {
+// yield return null;
+// }
+
+// // Wait for things to settle down
+// yield return null;
+// yield return null;
+
+// endEarly:
+
+// // Let the game be rendered again and fade into it
+// SteamVR_Render.pauseRendering = false;
+// if (compositor != null)
+// {
+// compositor.FadeGrid(_gridFadeTime, false);
+// yield return new WaitForSeconds(_gridFadeTime);
+// }
+
+// // Wait for the game to finish fading to make sure we are synchronized
+// while (_vanillaFade && _vanillaFade.alpha > _fadeAlphaThresholdLow)
+// {
+// yield return null;
+// }
+
+// SteamVR_Skybox.ClearOverride();
+
+// _isFading = false;
+// }
+
+// private static Color GetFadeColor()
+// {
+// try
+// {
+// var cycle = FindObjectOfType();
+// switch (cycle?.nowType)
+// {
+// default:
+// case Cycle.Type.WakeUp:
+// case Cycle.Type.Morning:
+// case Cycle.Type.Daytime:
+// return new Color(0.44f, 0.78f, 1f);
+// case Cycle.Type.Evening:
+// return new Color(0.85f, 0.50f, 0.37f);
+// case Cycle.Type.Night:
+// case Cycle.Type.GotoMyHouse:
+// case Cycle.Type.MyHouse:
+// return new Color(0.12f, 0.2f, 0.5f);
+// }
+// }
+// catch (Exception e)
+// {
+// Console.WriteLine(e);
+// return Color.white;
+// }
+// }
+
+// private static void SetCompositorSkyboxOverride(Color fadeColor)
+// {
+// var tex = new Texture2D(1, 1);
+// var color = fadeColor;
+// color.a = 1f;
+// tex.SetPixel(0, 0, color);
+// tex.Apply();
+// SteamVR_Skybox.SetOverride(tex, tex, tex, tex, tex, tex);
+// Destroy(tex);
+// }
+// }
+//}
diff --git a/Shared/Features/Pov.cs b/Shared/Features/Pov.cs
new file mode 100644
index 0000000..19c1880
--- /dev/null
+++ b/Shared/Features/Pov.cs
@@ -0,0 +1,560 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using VRGIN.Core;
+using UniRx;
+using Manager;
+using KK_VR.Settings;
+using KK_VR.Interpreters;
+using KK_VR.Handlers;
+using KK_VR.Camera;
+
+namespace KK_VR.Features
+{
+ public class PoV : MonoBehaviour
+ {
+ private class OneWayTrip
+ {
+ internal OneWayTrip(float lerpMultiplier, Quaternion targetRotation)
+ {
+ _lerpMultiplier = lerpMultiplier;
+ _startPosition = VR.Camera.Head.position;
+ _startRotation = VR.Camera.Origin.rotation;
+ _targetRotation = targetRotation;
+ }
+ private float _lerp;
+ private readonly float _lerpMultiplier;
+ private readonly Quaternion _startRotation;
+ private readonly Vector3 _startPosition;
+
+ // Quaternion (S)Lerp will go awry with constantly changing end point.
+ private readonly Quaternion _targetRotation;
+
+ internal float Move(Vector3 position)
+ {
+ var smoothStep = Mathf.SmoothStep(0f, 1f, _lerp += Time.deltaTime * _lerpMultiplier);
+ position = Vector3.Lerp(_startPosition, position, smoothStep);
+
+ VR.Camera.Origin.rotation = Quaternion.Slerp(_startRotation, _targetRotation, smoothStep);
+ VR.Camera.Origin.position += position - VR.Camera.Head.position;
+ return smoothStep;
+ }
+ }
+
+ public static PoV Instance;
+ ///
+ /// girlPOV is NOT set proactively, use "active" to monitor state.
+ ///
+ public static bool GirlPoV;
+ public static bool Active => Instance != null && Instance._active;
+ public static ChaControl Target => _target;
+
+ enum Mode
+ {
+ Disable,
+ Move,
+ Follow
+ }
+
+
+ private bool _active;
+ private static ChaControl _target;
+ private ChaControl _prevTarget;
+
+ private Transform _targetEyes;
+ private Mode _mode;
+ private bool _newAttachPoint;
+ private Vector3 _offsetVecNewAttach;
+ private bool _rotationRequired;
+ private int _rotDeviationThreshold;
+ private int _rotDeviationHalf;
+ private Vector3 _offsetVecEyes;
+ private OneWayTrip _trip;
+ private MoveToPoi _moveTo;
+ private SmoothDamp _smoothDamp;
+ private float _degPerSec;
+ private bool _sync;
+ private float _syncTimestamp;
+ private Vector3 _prevFramePos;
+ private bool _forceHideHead;
+
+ private Vector3 GetEyesPosition() => _targetEyes.TransformPoint(_offsetVecEyes);
+ private bool IsClimax => HSceneInterpreter.hFlag.nowAnimStateName.EndsWith("_Loop", System.StringComparison.Ordinal);
+
+ internal static PoV Create()
+ {
+ var component = VR.Camera.gameObject.GetComponent();
+ if (component != null)
+ {
+ return component;
+ }
+ return VR.Camera.gameObject.AddComponent();
+ }
+ private void Awake()
+ {
+ Instance = this;
+ }
+
+ private void UpdateSettings()
+ {
+ _sync = false;
+ _syncTimestamp = 0f;
+ _smoothDamp = new SmoothDamp();
+ _degPerSec = 30f * KoikatuInterpreter.Settings.RotationMultiplier;
+ _rotDeviationThreshold = KoikatuInterpreter.Settings.RotationDeviationThreshold;
+ _rotDeviationHalf = (int)(_rotDeviationThreshold * 0.4f);
+ _offsetVecEyes = new Vector3(0f, KoikatuInterpreter.Settings.PositionOffsetY, KoikatuInterpreter.Settings.PositionOffsetZ);
+ }
+ private void SetVisibility(ChaControl chara)
+ {
+ if (chara != null) chara.fileStatus.visibleHeadAlways = true;
+ }
+ private void MoveToPos()
+ {
+ var origin = VR.Camera.Origin;
+ if (_newAttachPoint)
+ {
+ if (!IsClimax)
+ {
+ //origin.rotation = _offsetRotNewAttach;
+ origin.position += _targetEyes.position + _offsetVecNewAttach - VR.Camera.Head.position;
+ }
+ }
+ else
+ {
+ if (IsClimax)
+ {
+ if (_rotationRequired)
+ {
+ _rotationRequired = false;
+ _smoothDamp = null;
+ //_synced = false;
+ }
+ }
+ else
+ {
+ var angle = Quaternion.Angle(origin.rotation, _targetEyes.rotation);
+ if (!_rotationRequired)
+ {
+ if (angle > _rotDeviationThreshold)
+ {
+ _sync = false;
+ _syncTimestamp = 0f;
+ _rotationRequired = true;
+ _smoothDamp = new SmoothDamp();
+ }
+ }
+ else
+ {
+ float sDamp;
+ if (angle < _rotDeviationHalf)
+ {
+ sDamp = _smoothDamp.Current;
+ if (angle < 1f) // && sDamp < 0.01f)
+ {
+ if (_syncTimestamp == 0f)
+ {
+ if (Quaternion.Angle(VR.Camera.Head.rotation, _targetEyes.rotation) < 30f)
+ {
+ _syncTimestamp = Time.time + 2f;
+ }
+ }
+ else
+ {
+ if (_syncTimestamp < Time.time)
+ {
+ if (Quaternion.Angle(VR.Camera.Head.rotation, _targetEyes.rotation) < 30f)
+ {
+ _sync = true;
+ _syncTimestamp = 0f;
+ _smoothDamp = null;
+ _rotationRequired = false;
+ _prevFramePos = VR.Camera.Head.position;
+ }
+ else
+ {
+ _syncTimestamp = 0f;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ sDamp = _smoothDamp.Increase();
+ }
+ var moveTowards = Vector3.MoveTowards(VR.Camera.Head.position, GetEyesPosition(), 0.05f);
+ origin.rotation = Quaternion.RotateTowards(origin.rotation, _targetEyes.rotation, Time.deltaTime * _degPerSec * sDamp);
+ origin.position += moveTowards - VR.Camera.Head.position;
+ return;
+ }
+ if (_sync)
+ {
+ var pos = GetEyesPosition();
+ origin.position += (pos - _prevFramePos); // + (Vector3.MoveTowards(VR.Camera.Head.position, pos, 0.01f) - VR.Camera.Head.position);
+ _prevFramePos = pos;
+ }
+ else
+ {
+ // We don't branch here anymore?
+ origin.position += GetEyesPosition() - VR.Camera.Head.position;
+ }
+ }
+ }
+ }
+ public void StartPov()
+ {
+ _active = true;
+ NextChara(keepChara: true);
+ }
+
+ public void OnSpotChange()
+ {
+ StartPov();
+ CameraIsFar(3f);
+ }
+ public void CameraIsFar(float speed = 1f)
+ {
+ _mode = Mode.Move;
+ if (speed != 1f)
+ {
+ StartMoveToHead(speed);
+ }
+ }
+ public void CameraIsFarAndBusy()
+ {
+ CameraIsFar();
+ if (MouthGuide.Instance != null)
+ {
+ MouthGuide.Instance.PauseInteractions = true;
+ }
+ }
+ public void CameraIsNear()
+ {
+ _mode = Mode.Follow;
+ _sync = false;
+ _syncTimestamp = 0f;
+ _rotationRequired = true;
+ _smoothDamp = new SmoothDamp();
+ SetVisibility(_prevTarget);
+ _prevTarget = null;
+ if (_target.sex == 1)
+ {
+ GirlPoV = true;
+ if (MouthGuide.Instance != null)
+ {
+ MouthGuide.Instance.PauseInteractions = true;
+ }
+ }
+ else
+ {
+ GirlPoV = false;
+ if (MouthGuide.Instance != null)
+ {
+ MouthGuide.Instance.PauseInteractions = false;
+ }
+ }
+ }
+
+ private void StartMoveToHead(float speed = 1f)
+ {
+ if (KoikatuInterpreter.Settings.FlyInPov == KoikatuSettings.MovementTypeH.Disabled)
+ {
+ _newAttachPoint = false;
+ CameraIsNear();
+ }
+ else
+ {
+ // Only one mode is currently operational.
+ _trip = new OneWayTrip(Mathf.Min(
+ KoikatuInterpreter.Settings.FlightSpeed * speed / Vector3.Distance(VR.Camera.Head.position, GetEyesPosition()),
+ KoikatuInterpreter.Settings.FlightSpeed * 60f / Quaternion.Angle(VR.Camera.Origin.rotation, _targetEyes.rotation)),
+ _targetEyes.rotation);
+ }
+ }
+ private void MoveToHeadEx()
+ {
+ if (_trip == null)
+ {
+ StartMoveToHead();
+ }
+ else if (_trip.Move(GetEyesPosition()) >= 1f)
+ {
+ CameraIsNear();
+ _newAttachPoint = false;
+ _trip = null;
+ }
+ }
+
+ internal void OnGraspEnd()
+ {
+ if (_active && !_newAttachPoint)
+ {
+ CameraIsFar(0.25f);
+ }
+ }
+
+
+ private int GetCurrentCharaIndex(List _chaControls)
+ {
+ if (_target != null)
+ {
+ for (int i = 0; i < _chaControls.Count; i++)
+ {
+ if (_chaControls[i] == _target)
+ {
+ return i;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private void NextChara(bool keepChara = false)
+ {
+ // As some may add extra characters with kPlug, we look them all up.
+ var charas = FindObjectsOfType()
+ .Where(c => c.objTop.activeSelf && c.visibleAll
+ && c.sex != (KoikatuInterpreter.Settings.PoV == KoikatuSettings.Impersonation.Girls ? 0 : KoikatuInterpreter.Settings.PoV == KoikatuSettings.Impersonation.Boys ? 1 : 2))
+ .ToList();
+
+ if (charas.Count == 0)
+ {
+ Sleep();
+ VRPlugin.Logger.LogWarning("Can't impersonate, no appropriate targets. To extend allowed genders change setting.");
+ return;
+ }
+ var currentCharaIndex = GetCurrentCharaIndex(charas);
+
+ if (keepChara)
+ {
+ _target = charas[currentCharaIndex];
+ }
+ else if (currentCharaIndex == charas.Count - 1)
+ {
+ // No point in switching with only one active character, disable instead.
+
+ _prevTarget = _target;
+ _target = charas[0];
+
+ _mode = Mode.Disable;
+ return;
+ }
+ else
+ {
+ _prevTarget = _target;
+ _target = charas[currentCharaIndex + 1];
+ }
+ if (MouthGuide.Instance != null)
+ {
+ MouthGuide.Instance.OnImpersonation(_target);
+ }
+ _targetEyes = _target.objHeadBone.transform.Find("cf_J_N_FaceRoot/cf_J_FaceRoot/cf_J_FaceBase/cf_J_FaceUp_ty/cf_J_FaceUp_tz");
+ CameraIsFarAndBusy();
+ UpdateSettings();
+ }
+
+ private void NewPosition()
+ {
+ // Most likely a bad idea to kiss/lick when detached from the head but still inheriting all movements.
+ CameraIsNear();
+ _offsetVecNewAttach = VR.Camera.Head.position - _targetEyes.position;
+ }
+
+ internal void OnGripMove(bool press)
+ {
+ //_gripMove = press;
+ if (_active)
+ {
+ if (press)
+ {
+ CameraIsFar();
+ }
+ else if (_newAttachPoint)
+ {
+ NewPosition();
+ }
+ }
+ }
+
+ internal bool OnTouchpad(bool press)
+ {
+ // We call it only in gripMove state.
+ if (press)
+ {
+ if (_active && !_newAttachPoint)
+ {
+ _newAttachPoint = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void Sleep()
+ {
+ _active = false;
+ SetVisibility(_target);
+ _mode = Mode.Disable;
+ _newAttachPoint = false;
+ _forceHideHead = false;
+ _moveTo = null;
+
+ if (MouthGuide.Instance != null)
+ {
+ MouthGuide.Instance.PauseInteractions = false;
+ MouthGuide.Instance.OnUnImpersonation();
+ }
+ }
+
+ private void Disable(bool moveTo)
+ {
+ if (_moveTo == null)
+ {
+ if (!moveTo || _target == null)
+ {
+ Sleep();
+ }
+ else
+ {
+ var target = _target.sex == 1 ? _target : FindObjectsOfType()
+ .Where(c => c.sex == 1 && c.objTop.activeSelf && c.visibleAll)
+ .FirstOrDefault();
+ _moveTo = new MoveToPoi(target != null ? target : _target, Sleep );
+ }
+ }
+ else
+ {
+ _moveTo.Move();
+ }
+ }
+
+ private void HandleDisable(bool moveTo = true)
+ {
+ if (_newAttachPoint)
+ {
+ _newAttachPoint = false;
+ CameraIsFarAndBusy();
+ }
+ else
+ {
+ Disable(moveTo);
+ }
+ }
+
+ internal bool TryDisable(bool moveTo)
+ {
+ if (_active)
+ {
+ if (!moveTo)
+ {
+ Sleep();
+ }
+ else
+ {
+ Disable(moveTo);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void Update()
+ {
+ if (_active)
+ {
+ if (KoikatuInterpreter.SceneInput.IsBusy// || _mouth.IsActive
+#if KK
+ || !Scene.Instance.AddSceneName.Equals("HProc"))
+#else
+ || !Scene.AddSceneName.Equals("HProc"))
+#endif
+ // !Scene.AddSceneName.Equals("HProc")) // SceneApi.GetIsOverlap()) KKS option KK has it broken.
+ {
+ // We don't want pov while kissing/licking or if config/pointmove scene pops up.
+ CameraIsFar();
+ }
+ else
+ {
+ switch (_mode)
+ {
+ case Mode.Disable:
+ HandleDisable();
+ break;
+ case Mode.Follow:
+ MoveToPos();
+ break;
+ case Mode.Move:
+ MoveToHeadEx();
+ break;
+ }
+ }
+ }
+ }
+
+ private void LateUpdate()
+ {
+ if (_active && KoikatuInterpreter.Settings.HideHeadInPOV && _target != null)
+ {
+ HideHeadEx(_target);
+ if (_prevTarget != null)
+ {
+ HideHead(_prevTarget);
+ }
+ }
+ }
+
+ private void HideHeadEx(ChaControl chara)
+ {
+ if (_forceHideHead)
+ {
+ chara.fileStatus.visibleHeadAlways = false;
+ }
+ else
+ {
+ HideHead(chara);
+ }
+ }
+
+ private void HideHead(ChaControl chara)
+ {
+ var head = chara.objHead.transform;
+ var wasVisible = chara.fileStatus.visibleHeadAlways;
+ var headCenter = head.TransformPoint(0, 0.12f, -0.04f);
+ var sqrDistance = (VR.Camera.transform.position - headCenter).sqrMagnitude;
+ var visible = 0.0361f < sqrDistance; // 19 centimeters
+ chara.fileStatus.visibleHeadAlways = visible;
+ if (wasVisible && !visible)
+ {
+ chara.objHead.SetActive(false);
+
+ foreach (var hair in chara.objHair)
+ {
+ hair.SetActive(false);
+ }
+ }
+ }
+
+ internal void TryEnable()
+ {
+ if (KoikatuInterpreter.Settings.PoV != KoikatuSettings.Impersonation.Disabled)
+ {
+ if (_newAttachPoint)
+ {
+ CameraIsFarAndBusy();
+ _newAttachPoint = false;
+ }
+ else if (_active)
+ NextChara();
+ else
+ StartPov();
+ }
+ }
+
+ internal void OnLimbSync(bool start)
+ {
+ _forceHideHead = start;
+ }
+ }
+}
+
diff --git a/MainGameVR/Features/PrivacyScreen.cs b/Shared/Features/PrivacyScreen.cs
similarity index 97%
rename from MainGameVR/Features/PrivacyScreen.cs
rename to Shared/Features/PrivacyScreen.cs
index df64303..c681d33 100644
--- a/MainGameVR/Features/PrivacyScreen.cs
+++ b/Shared/Features/PrivacyScreen.cs
@@ -1,10 +1,10 @@
-using KKS_VR.Settings;
+using KK_VR.Settings;
using UnityEngine;
using UnityEngine.UI;
using VRGIN.Core;
using Object = UnityEngine.Object;
-namespace KKS_VR.Features
+namespace KK_VR.Features
{
///
/// Class that allows the user to hide contents of the desktop mirror screen.
diff --git a/Shared/Features/Undresser.cs b/Shared/Features/Undresser.cs
new file mode 100644
index 0000000..d30efcb
--- /dev/null
+++ b/Shared/Features/Undresser.cs
@@ -0,0 +1,342 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+using VRGIN.Core;
+using HarmonyLib;
+
+using static ChaFileDefine;
+using KK_VR.Fixes;
+using static KK_VR.Features.LoadVoice;
+using KK_VR.Controls;
+using KK_VR.Features;
+using static KK_VR.Trackers.Tracker;
+
+namespace KK_VR.Interactors
+{
+ ///
+ /// Simplified/expanded version from https://github.com/mosirnik/KK_MainGameVR
+ ///
+ static class Undresser
+ {
+ public static bool IsBodyPartClothed(ChaControl chara, Body part)
+ {
+ var array = ConvertToSlot(part);
+ if (array == null) return false;
+ foreach (var item in array)
+ {
+ if (chara.IsClothes(item) && chara.fileStatus.clothesState[item] == 0) return true;
+ }
+ return false;
+ }
+ private static int[] ConvertToSlot(Body part)
+ {
+ return part switch
+ {
+ Body.MuneL or Body.MuneR => [0, 2],
+ Body.UpperBody => [0],
+ Body.LowerBody => [1, 5],
+ Body.ArmL or Body.ArmR => [0, 4],
+ Body.Groin or Body.Asoko => [1, 3, 5],
+ Body.ThighL or Body.ThighR or Body.LegL or Body.LegR or Body.FootL or Body.FootR => [5, 6],
+ _ => null,
+ };
+ }
+ private static Body ConvertToUndress(Body body)
+ {
+ return body switch
+ {
+ Body.Head => Body.None,
+ Body.HandR => Body.HandL,
+ Body.ArmR => Body.ArmL,
+ Body.MuneR => Body.MuneL,
+ Body.Groin => Body.Asoko,
+ Body.ThighR => Body.ThighL,
+ Body.ForearmL => Body.ArmL,
+ Body.ForearmR => Body.ArmL,
+ Body.FootR => Body.FootL,
+ _ => body
+ };
+ }
+ public static bool Undress(Body part, ChaControl chara, bool decrease)
+ {
+ part = ConvertToUndress(part);
+ //if (part == InteractionBodyPart.Crotch && IsWearingSkirt(female))
+ //{
+ // //VRLog.Debug($"WearingSkirt");
+ // // Special case: if the character is wearing a skirt, allow
+ // // directly removing the underwear.
+ // targets = _skirtCrotchTargets;
+ //}
+
+ var targets = decrease ? UndressDic[part] : RedressDic[part];
+
+ foreach (var target in targets)
+ {
+ var slot = target.slot;
+ if (!chara.IsClothes(slot)
+ || (decrease && chara.fileStatus.clothesState[slot] > target.state)
+ || (!decrease && chara.fileStatus.clothesState[slot] <= target.state))
+ {
+ //VRPlugin.Logger.LogDebug($"Undress:Skip[{part}]");
+ continue;
+ }
+ else
+ {
+ //VRPlugin.Logger.LogDebug($"Undress:Valid:Part[{part}]:Slot[{slot}]:State[{target.state}]");
+ }
+ //if (slot > 6)
+ //{
+ // // Target proper shoe slot.
+ // slot = chara.fileStatus.shoesType == 0 ? 7 : 8;
+ //}
+ if (slot == 3 || slot == 5 || slot == 6)
+ {
+ if (decrease)
+ {
+ // Check for pants. If present override pantyhose/socks/panties with them.
+ if (chara.fileStatus.clothesState[1] < (slot == 3 ? 1 : 3) && chara.objClothes[1].GetComponent() == null)
+ {
+ chara.SetClothesStateNext(1);
+ return true;
+ }
+ }
+ else
+ {
+ if (slot != 3)
+ {
+ if (chara.fileStatus.clothesState[3] == 2)
+ {
+ // Is we decided to redress pantyhose/socks with panties hanging on the leg, remove them instead.
+ chara.SetClothesState(3, 3, false);
+ //chara.fileStatus.clothesState[3] = 3;
+ }
+ else if (slot == 5 && chara.fileStatus.clothesState[3] == 1)
+ {
+ // Or put them back on if only shifted and we redress pantyhose.
+ chara.SetClothesState(3, 0, false);
+ //chara.fileStatus.clothesState[3] = 0;
+ }
+ }
+ else
+ {
+ // Put panties on in one go.
+ chara.SetClothesState(3, 0, false);
+ return true;
+ }
+ }
+ }
+ if (decrease)
+ {
+ chara.SetClothesStateNext(slot);
+ PlayVoice((VoiceType)UnityEngine.Random.Range(0, 2), chara);
+ }
+ else
+ {
+ chara.SetClothesStatePrev(slot);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * KKS Slots
+ * 0 - Top
+ * 1 - Bottom
+ * 2 - Bra
+ * 3 - Panties
+ * 4 - gloves
+ * 5 - pantyhose
+ * 6 - Stockings
+ *
+ * 8 - Shoes
+ */
+
+ struct SlotState
+ {
+ public int slot;
+ public int state;
+ }
+ private static readonly Dictionary> UndressDic = new()
+ {
+ // Pairs of clothing slots and their states
+ // We check each, if state is less or equal, jump to the next one, otherwise change state.
+ {
+ Body.Asoko, new List
+ {
+ new() { slot = 1, state = 0 },
+ new SlotState { slot = 5, state = 0 },
+ new SlotState { slot = 3, state = 0 },
+ //new SlotState { slot = 5, state = 1 },
+ new SlotState { slot = 3, state = 1 }
+ }
+ },
+ {
+ Body.LowerBody, new List
+ {
+ new SlotState { slot = 1, state = 0 },
+ new SlotState { slot = 1, state = 1 }
+ }
+ },
+ {
+ Body.UpperBody, new List
+ {
+ new SlotState { slot = 0, state = 0 },
+ new SlotState { slot = 0, state = 1 }
+ }
+ },
+ {
+ Body.ThighL, new List
+ {
+ new SlotState { slot = 5, state = 0 },
+ new SlotState { slot = 6, state = 0 },
+ new SlotState { slot = 1, state = 0 }
+ }
+ },
+ {
+ Body.LegL, new List
+ {
+ new SlotState { slot = 5, state = 0 },
+ new SlotState { slot = 6, state = 0 },
+ new SlotState { slot = 8, state = 0 },
+ new SlotState { slot = 5, state = 1 },
+ new SlotState { slot = 3, state = 2 }
+ }
+ },
+ {
+ Body.LegR, new List
+ {
+ new SlotState { slot = 5, state = 0 },
+ new SlotState { slot = 6, state = 0 },
+ new SlotState { slot = 8, state = 0 },
+ new SlotState { slot = 5, state = 1 },
+ }
+ },
+ {
+ Body.MuneL, new List
+ {
+ new SlotState { slot = 0, state = 0 },
+ new SlotState { slot = 2, state = 0 },
+ new SlotState { slot = 0, state = 1 },
+ new SlotState { slot = 2, state = 1 },
+ }
+ },
+ {
+ Body.ArmL, new List