Skip to content

Commit

Permalink
fix(input): build and remove target bound to hand (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xenira committed Dec 10, 2023
1 parent 2639dff commit 4420a46
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 119 deletions.
8 changes: 6 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,18 @@ While the mod is in a playable state, it is still in early development. Some fea
- Finger tracking
- Ability to switch primary hand
- Ability to yeet paladin down the waterfall
- Hand crank using uhhhhh... hands?
- Hotbar reassignment

=== Known Issues
- The players position is not synced correctly with the game when using roomscale. The characters position is in the center of the playspace. This might cause issues with collisions and other things.
- The players position is not synced correctly with the game when using roomscale. The characters position is in the center of the playspace. This might cause issues with collisions and other things. Also map shows the player looking in the wrong direction.
- Button prompts are not for VR controllers.
- Haptics are played on both controllers by the game. One improvement would be to play them on the hand that is actually holding the tool.
- Use and interact buttons are mapped to the same button. This might cause issues when interacting with objects.
- The manual crank button is not mapped to a button on the controller.
- Building and erasing uses head rotation instead of hand rotation for targeting.
- Machine info not visible when targeting with hand.
- Crafting queue not visible.
- The game is locked to 60fps when running in windowed mode. This is based on the refresh rate of your monitor. To unlock the framerate, switch to fullscreen mode. (For now)

=== Cool stuff to try
- Enable ik (The game ships with `FinalIK` so it should be possible. Probably just not networked yet.)
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ cd ..

# Copy the mod dll to the mods folder
echo "Copying the mod dll to the mods folder..."
cp ./plugin/bin/Debug/netstandard2.1/techtonica_vr.dll /c/Program\ Files\ \(x86\)/Steam/steamapps/common/Techtonica/BepInEx/plugins/techtonica_vr.dll
cp ./plugin/bin/Debug/netstandard2.1/techtonica_vr.dll /c/Program\ Files\ \(x86\)/Steam/steamapps/common/Techtonica/BepInEx/plugins/techtonica_vr.*

# Copy the vr dlls to the game folder
echo "Copying the vr dlls to the game folder..."
Expand Down
Binary file modified libs/Managed/SteamVR_Actions.dll
Binary file not shown.
12 changes: 11 additions & 1 deletion libs/StreamingAssets/SteamVR/actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@
"name": "/actions/default/in/ToggleErase",
"type": "boolean"
},
{
"name": "/actions/default/in/Use",
"type": "boolean"
},
{
"name": "/actions/default/in/UIShortcut2",
"type": "boolean"
},
{
"name": "/actions/default/out/Haptic",
"type": "vibration"
Expand Down Expand Up @@ -266,7 +274,9 @@
"/actions/default/in/ToggleMenu": "ToggleMenu",
"/actions/default/in/UISubmit": "UI Submit",
"/actions/default/in/UICancel": "UI Cancel",
"/actions/default/in/ToggleErase": "Toggle Erase"
"/actions/default/in/ToggleErase": "Toggle Erase",
"/actions/default/in/Use": "Use",
"/actions/default/in/UIShortcut2": "Crank"
}
]
}
21 changes: 17 additions & 4 deletions libs/StreamingAssets/SteamVR/bindings_knuckles.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"action_manifest_version" : 0,
"alias_info" : {},
"app_key" : "application.generated.unity.unity.exe",
"app_key" : "system.generated.unity.exe",
"bindings" : {
"/actions/buggy" : {
"chords" : [],
Expand Down Expand Up @@ -64,7 +64,7 @@
{
"inputs" : {
"click" : {
"output" : "/actions/default/in/interact"
"output" : "/actions/default/in/use"
}
},
"mode" : "button",
Expand All @@ -86,13 +86,14 @@
{
"inputs" : {
"grab" : {
"output" : "/actions/default/in/grabgrip"
"output" : "/actions/default/in/interact"
}
},
"mode" : "grab",
"parameters" : {
"force_hold_threshold" : "0.02",
"force_release_threshold" : "0.01"
"force_release_threshold" : "0.01",
"value_hold_threshold" : "1.05"
},
"path" : "/user/hand/right/input/grip"
},
Expand Down Expand Up @@ -304,6 +305,18 @@
},
"mode" : "button",
"path" : "/user/hand/left/input/b"
},
{
"inputs" : {
"grab" : {
"output" : "/actions/default/in/uishortcut2"
}
},
"mode" : "grab",
"parameters" : {
"value_hold_threshold" : "1.1"
},
"path" : "/user/hand/right/input/grip"
}
]
},
Expand Down
163 changes: 163 additions & 0 deletions plugin/src/camera/patch/builder_raycast_patch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using Plugin.Input;
using UnityEngine;

namespace TechtonicaVR.VRCamera.Patch;

[HarmonyPatch]
public class BuilderRaycastPatch
{
static MethodInfo raycastMethod = typeof(Physics).GetMethod(nameof(Physics.Raycast), [typeof(Vector3), typeof(Vector3), typeof(RaycastHit).MakeByRefType(), typeof(float), typeof(int), typeof(QueryTriggerInteraction)]);
static MethodInfo vectorMultiplyMethod = typeof(Vector3).GetMethod("op_Multiply", [typeof(Vector3), typeof(float)]);
static MethodInfo vectorAddMethod = typeof(Vector3).GetMethod("op_Addition", [typeof(Vector3), typeof(Vector3)]);

static MethodInfo raycastPatchMethod = typeof(BuilderRaycastPatch).GetMethod(nameof(PatchedRaycast));
static MethodInfo vectorMultiplyPatchMethod = typeof(BuilderRaycastPatch).GetMethod(nameof(PatchedVectorMultiply));
static MethodInfo vectorAddPatchMethod = typeof(BuilderRaycastPatch).GetMethod(nameof(PatchedVectorAdd));

[HarmonyPatch(typeof(PlayerBuilder), nameof(PlayerBuilder.cameraOrigin), MethodType.Getter)]
[HarmonyPrefix]
public static bool cameraOriginPrefix(PlayerBuilder __instance, ref Vector3 __result)
{
if (SteamVRInputMapper.rightHandObject == null)
{
return true;
}

__result = SteamVRInputMapper.rightHandObject.transform.position;
return false;
}

[HarmonyPatch(typeof(PlayerBuilder), nameof(PlayerBuilder.cameraDirection), MethodType.Getter)]
[HarmonyPrefix]
public static bool cameraDirectionPrefix(PlayerBuilder __instance, ref Vector3 __result)
{
if (SteamVRInputMapper.rightHandObject == null)
{
return true;
}

__result = -SteamVRInputMapper.rightHandObject.transform.up;
return false;
}

[HarmonyPatch(typeof(PlayerBuilder), nameof(PlayerBuilder.DeconstructionUpdate))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> DeconstructionUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
{
var patchCnt = 0;
foreach (var instruction in instructions)
{
if (instruction.Calls(raycastMethod))
{
yield return new CodeInstruction(OpCodes.Call, raycastPatchMethod);
patchCnt++;
}
else
{
yield return instruction;
}
}

if (patchCnt != 3)
{
Plugin.Logger.LogError("Failed to patch PlayerBuilder.DeconstructionUpdate");
}
}

[HarmonyPatch(typeof(PlayerBuilder), nameof(PlayerBuilder.FreeformUpdatePlacement))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> FreeformUpdatePlacementTranspiler(IEnumerable<CodeInstruction> instructions)
{
var patchCnt = 0;
foreach (var instruction in instructions)
{
if (instruction.Calls(vectorMultiplyMethod))
{
yield return new CodeInstruction(OpCodes.Call, vectorMultiplyPatchMethod);
patchCnt++;
}
else if (instruction.Calls(vectorAddMethod))
{
yield return new CodeInstruction(OpCodes.Call, vectorAddPatchMethod);
patchCnt++;
}
else
{
yield return instruction;
}
}

if (patchCnt != 2)
{
Plugin.Logger.LogError("Failed to patch PlayerBuilder.FreeformUpdatePlacement");
}
}

[HarmonyPatch(typeof(PlayerBuilder), nameof(PlayerBuilder.HasTargetDeconstructable))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> HasTargetDeconstructableUpdateTranspiler(IEnumerable<CodeInstruction> instructions)
{
var patchCnt = 0;
foreach (var instruction in instructions)
{
if (instruction.Calls(raycastMethod))
{
yield return new CodeInstruction(OpCodes.Call, raycastPatchMethod);
patchCnt++;
}
else
{
yield return instruction;
}
}

if (patchCnt != 1)
{
Plugin.Logger.LogError("Failed to patch PlayerBuilder.HasTargetDeconstructable");
}
}

[HarmonyPatch(typeof(PlayerBuilder), nameof(PlayerBuilder.CheckTargetLogisticsObject))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> CheckTargetLogisticsObjectTranspiler(IEnumerable<CodeInstruction> instructions)
{
var patchCnt = 0;
foreach (var instruction in instructions)
{
if (instruction.Calls(raycastMethod))
{
yield return new CodeInstruction(OpCodes.Call, raycastPatchMethod);
patchCnt++;
}
else
{
yield return instruction;
}
}

if (patchCnt != 1)
{
Plugin.Logger.LogError("Failed to patch PlayerBuilder.CheckTargetLogisticsObject");
}
}

public static bool PatchedRaycast(Vector3 _origin, Vector3 _direction, out RaycastHit hitInfo, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction)
{
return Physics.Raycast(SteamVRInputMapper.rightHandObject.transform.position, -SteamVRInputMapper.rightHandObject.transform.up, out hitInfo, maxDistance, layerMask, queryTriggerInteraction);
}

public static Vector3 PatchedVectorMultiply(Vector3 _vector, float multiplier)
{
return -SteamVRInputMapper.rightHandObject.transform.up * multiplier;
}

public static Vector3 PatchedVectorAdd(Vector3 vector, Vector3 _add)
{
return vector + SteamVRInputMapper.rightHandObject.transform.position;
}

}
78 changes: 78 additions & 0 deletions plugin/src/camera/patch/builder_reassemble_patch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using Plugin.Input;
using UnityEngine;

namespace TechtonicaVR.VRCamera.Patch;

[HarmonyPatch]
public class BuilderReassemblePatch
{
private static MethodInfo getTransformMethod = typeof(Component).GetMethod("get_transform");
private static MethodInfo getForwardMethod = typeof(Transform).GetMethod("get_forward");

private static MethodInfo getTransformPatchMethod = typeof(BuilderReassemblePatch).GetMethod(nameof(patchedGetTransform));
private static MethodInfo getForwardPatchMethod = typeof(BuilderReassemblePatch).GetMethod(nameof(PatchedGetForward));

[HarmonyPatch(typeof(FloorBuilder), nameof(FloorBuilder.Reassemble))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> ReassembleTranspiler(IEnumerable<CodeInstruction> instructions)
{
return reassemblePatch(instructions);
}

[HarmonyPatch(typeof(ResearchCoreBuilder), nameof(ResearchCoreBuilder.Reassemble))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> ResearchCoreReassembleTranspiler(IEnumerable<CodeInstruction> instructions)
{
return reassemblePatch(instructions);
}

[HarmonyPatch(typeof(StairsBuilder), nameof(StairsBuilder.Reassemble))]
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> StairsBuilderTranspiler(IEnumerable<CodeInstruction> instructions)
{
return reassemblePatch(instructions);
}

private static IEnumerable<CodeInstruction> reassemblePatch(IEnumerable<CodeInstruction> instructions)
{
var patchCnt = 0;
foreach (var instruction in instructions)
{
if (instruction.Calls(getTransformMethod))
{
yield return new CodeInstruction(OpCodes.Pop);
yield return new CodeInstruction(OpCodes.Call, getTransformPatchMethod);
patchCnt++;
}
else if (instruction.Calls(getForwardMethod))
{
yield return new CodeInstruction(OpCodes.Pop);
yield return new CodeInstruction(OpCodes.Call, getForwardPatchMethod);
patchCnt++;
}
else
{
yield return instruction;
}
}

if (patchCnt != 12)
{
Plugin.Logger.LogError($"ReassembleTranspiler: Patch count mismatch: {patchCnt} != 12");
}
}

public static Transform patchedGetTransform()
{
return SteamVRInputMapper.rightHandObject.transform;
}

public static Vector3 PatchedGetForward()
{
return -SteamVRInputMapper.rightHandObject.transform.up;
}
}
3 changes: 2 additions & 1 deletion plugin/src/input/input_patches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,9 @@ private static Button MapButtonState(int actionId)
{
case RewiredConsts.Action.Jump:
return SteamVRInputMapper.Jump;
case RewiredConsts.Action.Interact:
case RewiredConsts.Action.Use:
return SteamVRInputMapper.Use;
case RewiredConsts.Action.Interact:
case RewiredConsts.Action.MouseLeftClick:
return SteamVRInputMapper.Interact;
case RewiredConsts.Action.Sprint:
Expand Down
Loading

0 comments on commit 4420a46

Please sign in to comment.