From a45f6166adbee753ccad3b1086d6aadbfd3e2b83 Mon Sep 17 00:00:00 2001 From: tony246642 Date: Tue, 7 May 2024 00:57:09 +0800 Subject: [PATCH 1/2] VR POV v1.0 --- KoikatuVR/Interpreters/HSceneInterpreter.cs | 3 + KoikatuVR/KoikatuSettings.cs | 2 + KoikatuVR/KoikatuVR.csproj | 1 + KoikatuVR/POV.cs | 260 ++++++++++++++++++++ KoikatuVR/SettingsManager.cs | 28 +++ 5 files changed, 294 insertions(+) create mode 100644 KoikatuVR/POV.cs diff --git a/KoikatuVR/Interpreters/HSceneInterpreter.cs b/KoikatuVR/Interpreters/HSceneInterpreter.cs index 838af32..cfc68e1 100644 --- a/KoikatuVR/Interpreters/HSceneInterpreter.cs +++ b/KoikatuVR/Interpreters/HSceneInterpreter.cs @@ -10,6 +10,7 @@ class HSceneInterpreter : SceneInterpreter bool _active; HSceneProc _proc; Caress.VRMouth _vrMouth; + POV _pov; public override void OnStart() { @@ -32,6 +33,7 @@ public override void OnUpdate() Manager.Scene.GetRootComponent("HProc") is HSceneProc proc && proc.enabled) { + _pov = VR.Camera.gameObject.AddComponent(); _vrMouth = VR.Camera.gameObject.AddComponent(); AddControllerComponent(); _proc = proc; @@ -43,6 +45,7 @@ private void Deactivate() { if (_active) { + GameObject.Destroy(_pov); GameObject.Destroy(_vrMouth); DestroyControllerComponent(); _proc = null; diff --git a/KoikatuVR/KoikatuSettings.cs b/KoikatuVR/KoikatuSettings.cs index 87134ae..19fc2e0 100644 --- a/KoikatuVR/KoikatuSettings.cs +++ b/KoikatuVR/KoikatuSettings.cs @@ -73,6 +73,8 @@ public bool UseLegacyInputSimulator set { _UseLegacyInputSimulator = value; TriggerPropertyChanged("UseLegacyInputSimulator"); } } private bool _UseLegacyInputSimulator; + public bool EnablePOV { get { return _EnablePOV; } set { _EnablePOV = value; TriggerPropertyChanged("EnablePOV"); } } + private bool _EnablePOV = true; } public class KeySet diff --git a/KoikatuVR/KoikatuVR.csproj b/KoikatuVR/KoikatuVR.csproj index 5727905..3ef476f 100644 --- a/KoikatuVR/KoikatuVR.csproj +++ b/KoikatuVR/KoikatuVR.csproj @@ -126,6 +126,7 @@ + diff --git a/KoikatuVR/POV.cs b/KoikatuVR/POV.cs new file mode 100644 index 0000000..8ed2c4b --- /dev/null +++ b/KoikatuVR/POV.cs @@ -0,0 +1,260 @@ +using KoikatuVR.Caress; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using VRGIN.Core; +using VRGIN.Helpers; + + +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 KoikatuVR +{ + public class POV : ProtectedBehaviour + { + + private ChaControl _currentTarget; + + private POV_MODE _povMode; + + private bool _active; + + private KoikatuSettings _settings; + + private Quaternion _tmp_head_y; // for POV_MODE.EYE + + protected override void OnAwake() + { + base.OnAwake(); + // HScene Init + _currentTarget = 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.Debug("Creating eyes", new object[0]); + 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", new object[0]); + } + return transform; + } + private int getCurrChaIdx(ChaControl[] targets) + { + if(_currentTarget) + { + for(int i = 0; i < targets.Length; i++) + { + if(ChaControl.ReferenceEquals(targets[i], _currentTarget) && _currentTarget.sex != 1) + { + return i; + } + } + } + // cannot find last pov character (initialize / deleted) + return targets.Length - 1; + } + + // set _currentTarget + 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; + } + _currentTarget = targets[currentTargetIndex]; + + if (_currentTarget) + { + if (_currentTarget.sex != 1) // 1 is female, only choose male as target + { + if (_povMode == POV_MODE.EYE || _povMode == POV_MODE.HEAD || _povMode == POV_MODE.TELEPORT) + { + SetCameraToCharEye(_currentTarget); + + 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 + _currentTarget = 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 (_currentTarget) + { + switch (_povMode) + { + case POV_MODE.EYE: + MoveToPositionEx(GetEyes(_currentTarget).position, GetEyes(_currentTarget).rotation); + break; + + case POV_MODE.HEAD: + VRManager.Instance.Mode.MoveToPosition(GetEyes(_currentTarget).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.IsDown()) + { + if (_povMode == POV_MODE.EYE) {resetRotationXZ();} + _povMode = (POV_MODE)(((int)(_povMode + 1)) % (int)(POV_MODE.TOTAL)); + } + + // When left hand controller is Hand Tool and visible, Press VR Trigger button to set _active + if ((!_active) && VR.Mode.Left.ToolIndex == 2 && VR.Mode.Left.ActiveTool.isActiveAndEnabled) + { + var device = SteamVR_Controller.Input((int)VR.Mode.Left.Tracking.index); + if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) + { + _active = true; + initPOVTarget(); + return; + } + } + // When right hand controller is Hand Tool and visible, Press VR Trigger button to set _active + else if ((!_active) && VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled) + { + var device = SteamVR_Controller.Input((int)VR.Mode.Right.Tracking.index); + if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) + { + _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) + { + // Press VR Trigger button to change target POV character + if (VR.Mode.Left.ToolIndex == 2 && VR.Mode.Left.ActiveTool.isActiveAndEnabled) + { + var device = SteamVR_Controller.Input((int)VR.Mode.Left.Tracking.index); + if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) {SwitchToNextChar();} + } + else if (VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled) + { + var device = SteamVR_Controller.Input((int)VR.Mode.Right.Tracking.index); + if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) {SwitchToNextChar();} + } + } + + + setPOV(); + } + } +} diff --git a/KoikatuVR/SettingsManager.cs b/KoikatuVR/SettingsManager.cs index 24849f5..faacb35 100644 --- a/KoikatuVR/SettingsManager.cs +++ b/KoikatuVR/SettingsManager.cs @@ -5,6 +5,7 @@ using BepInEx.Configuration; using System.ComponentModel; using VRGIN.Core; +using UnityEngine; namespace KoikatuVR { @@ -175,6 +176,8 @@ void updateKeySets() keySetsConfig = new KeySetsConfig(config, updateKeySets); updateKeySets(); + POVConfig pOVConfig = new POVConfig(config, settings); + // Fixed settings settings.ApplyEffects = false; // We manage effects ourselves. @@ -292,4 +295,29 @@ public KeySet CurrentKeySet() } } + + public class POVConfig + { + private const string sectionPOV = "4. POV between characters (Hand Tool in free H)"; + public static ConfigEntry switchPOVModeKey { get; private set; } + + 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", new KeyboardShortcut(KeyCode.Y), + new ConfigDescription( + "Use VR Trigger Button to switch POV between characters. Three Modes:\r\n1: Camera is fixed at character's eye.\r\n2: Camera moves when character's head moves.\r\n3: Camera doesn't move when character's head moves (jump to character).", + null, + new ConfigurationManagerAttributes { Order = -1 })); + } + private static void Tie(ConfigEntry entry, Action set) + { + set(entry.Value); + entry.SettingChanged += (_, _1) => set(entry.Value); + } + + } } From e550b06ef54cef659a1e970cf80686d8befa7602 Mon Sep 17 00:00:00 2001 From: tony246642 Date: Wed, 19 Jun 2024 04:01:00 +0800 Subject: [PATCH 2/2] VR POV v1.1 --- KoikatuVR/POV.cs | 83 ++++++++++----- KoikatuVR/SettingsManager.cs | 197 ++++++++++++++++++++++++++++++++++- KoikatuVR/VRMale.cs | 4 +- 3 files changed, 254 insertions(+), 30 deletions(-) diff --git a/KoikatuVR/POV.cs b/KoikatuVR/POV.cs index 8ed2c4b..b3ec46f 100644 --- a/KoikatuVR/POV.cs +++ b/KoikatuVR/POV.cs @@ -32,6 +32,9 @@ public class POV : ProtectedBehaviour private Quaternion _tmp_head_y; // for POV_MODE.EYE + private SteamVR_Controller.Device L_device; + private SteamVR_Controller.Device R_device; + protected override void OnAwake() { base.OnAwake(); @@ -45,6 +48,10 @@ protected override void OnAwake() _settings = VR.Context.Settings as KoikatuSettings; _tmp_head_y = Quaternion.identity; + + L_device = SteamVR_Controller.Input((int)VR.Mode.Left.Tracking.index); + + R_device = SteamVR_Controller.Input((int)VR.Mode.Right.Tracking.index); } private void SetCameraToCharEye(ChaControl target) @@ -106,7 +113,8 @@ private int getCurrChaIdx(ChaControl[] targets) { for(int i = 0; i < targets.Length; i++) { - if(ChaControl.ReferenceEquals(targets[i], _currentTarget) && _currentTarget.sex != 1) + if(ChaControl.ReferenceEquals(targets[i], _currentTarget) && + ((_currentTarget.sex == (int)POVConfig.targetGender.Value) || (POVConfig.targetGender.Value == POVConfig.Gender.All))) { return i; } @@ -131,7 +139,7 @@ private void nextChar(ChaControl[] targets, int currentTargetIndex, bool keep_ch if (_currentTarget) { - if (_currentTarget.sex != 1) // 1 is female, only choose male as target + if ((POVConfig.targetGender.Value == POVConfig.Gender.All) || (_currentTarget.sex == (int)POVConfig.targetGender.Value)) // 1 is female { if (_povMode == POV_MODE.EYE || _povMode == POV_MODE.HEAD || _povMode == POV_MODE.TELEPORT) { @@ -201,32 +209,49 @@ 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.IsDown()) + 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 (L_device.GetPressDown(button_id) || R_device.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)); } - // When left hand controller is Hand Tool and visible, Press VR Trigger button to set _active - if ((!_active) && VR.Mode.Left.ToolIndex == 2 && VR.Mode.Left.ActiveTool.isActiveAndEnabled) + if (!_active) // Activate POV under Hand Tool if user press VR Trigger button / Key { - var device = SteamVR_Controller.Input((int)VR.Mode.Left.Tracking.index); - if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) + if (POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_TRIGGER || POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_BUTTON2) // Use VR button { - _active = true; - initPOVTarget(); - return; + 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 && L_device.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 && R_device.GetPressDown(button_id)) + { + _active = true; + initPOVTarget(); + return; + } } - } - // When right hand controller is Hand Tool and visible, Press VR Trigger button to set _active - else if ((!_active) && VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled) - { - var device = SteamVR_Controller.Input((int)VR.Mode.Right.Tracking.index); - if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) + else // Use Keyboard Key { - _active = true; - initPOVTarget(); - return; + 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 @@ -240,16 +265,22 @@ protected override void OnUpdate() if (_active) { - // Press VR Trigger button to change target POV character - if (VR.Mode.Left.ToolIndex == 2 && VR.Mode.Left.ActiveTool.isActiveAndEnabled) + if (POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_TRIGGER || POVConfig.POVKey.Value == POVConfig.POVKeyList.VR_BUTTON2) // Use VR button { - var device = SteamVR_Controller.Input((int)VR.Mode.Left.Tracking.index); - if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) {SwitchToNextChar();} + 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 && L_device.GetPressDown(button_id)) + { + SwitchToNextChar(); + } + else if (VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled && R_device.GetPressDown(button_id)) + { + SwitchToNextChar(); + } } - else if (VR.Mode.Right.ToolIndex == 2 && VR.Mode.Right.ActiveTool.isActiveAndEnabled) + else // Use Keyboard Key { - var device = SteamVR_Controller.Input((int)VR.Mode.Right.Tracking.index); - if (device.GetPressDown(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger)) {SwitchToNextChar();} + if (Input.GetKeyDown((KeyCode)POVConfig.POVKey.Value)) {SwitchToNextChar();} } } diff --git a/KoikatuVR/SettingsManager.cs b/KoikatuVR/SettingsManager.cs index faacb35..26ccbb3 100644 --- a/KoikatuVR/SettingsManager.cs +++ b/KoikatuVR/SettingsManager.cs @@ -299,19 +299,210 @@ public KeySet CurrentKeySet() 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 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", new KeyboardShortcut(KeyCode.Y), + switchPOVModeKey = config.Bind(sectionPOV, "Switch POV Mode (1~3)", POVKeyList.Y, new ConfigDescription( - "Use VR Trigger Button to switch POV between characters. Three Modes:\r\n1: Camera is fixed at character's eye.\r\n2: Camera moves when character's head moves.\r\n3: Camera doesn't move when character's head moves (jump to character).", + "Use VR Button/Key to switch POV between characters. Three Modes:\r\n1: Camera is fixed at character's eye.\r\n2: Camera moves when character's head moves. (Default)\r\n3: 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 setting to switch the POV camera between target characters.", + null, + new ConfigurationManagerAttributes { Order = -2 })); + + targetGender = config.Bind(sectionPOV, "Target", Gender.Male, + new ConfigDescription( + "The Gender of the POV targets.", + null, + new ConfigurationManagerAttributes { Order = -3 })); } private static void Tie(ConfigEntry entry, Action set) { diff --git a/KoikatuVR/VRMale.cs b/KoikatuVR/VRMale.cs index 546b622..00d0f68 100644 --- a/KoikatuVR/VRMale.cs +++ b/KoikatuVR/VRMale.cs @@ -61,7 +61,9 @@ class ChaControlPatches [HarmonyPostfix] static void PostInitialize(ChaControl __instance) { - if (__instance.sex == 0) + 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)) { __instance.GetOrAddComponent(); }