Skip to content

Commit

Permalink
feat(ui): inventory overhaul (#3)
Browse files Browse the repository at this point in the history
* feat(ui): attach quest list to hand

* feat(ui): move toolbar, compas and map to hands

* feat(ui): place menus in world

* fix(ui): render inventory menu in correct position

* fix(player): move all hand attach childs to default layer
  • Loading branch information
Xenira committed Dec 5, 2023
1 parent c669795 commit 4c6fdb5
Show file tree
Hide file tree
Showing 22 changed files with 1,170 additions and 711 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true

[*{.cs,.adoc,.sh}]
indent_style = tab
indent_size = 1
tab_width = 2
5 changes: 0 additions & 5 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,7 @@ jobs:
- id: release
uses: google-github-actions/release-please-action@v4
with:
# this assumes that you have created a personal access token
# (PAT) and configured it as a GitHub action secret named
# `MY_RELEASE_PLEASE_TOKEN` (this secret name is not important).
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
# this is a built-in strategy in release-please, see "Action Inputs"
# for more options
release-type: simple
- name: Download release artifact
if: ${{ steps.release.outputs.release_created }}
Expand Down
27 changes: 18 additions & 9 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,38 @@ This will be improved in the future.
While the mod is in a playable state, it is still in early development. Some features are still missing and there are some known issues. Other things might be a little yanky or not work as expected.

=== Working
- :earth_americas: Rendering of the game world with 6DOF Tracking
- :raised_hands: Tracking of the player's head and hands
- :walking: Movement
- :gamepad: Basic controller bindings (Although they might not be optimal)
- :vibration_mode: Controller haptics
- :arrows_counterclockwise: Smooth turning
- Rendering of the game world with 6DOF Tracking
- Tracking of the player's head and hands
- Movement
- Basic controller bindings (Although they might not be optimal)
- Controller haptics
- Smooth turning
- UI

=== Missing
- Gesture support (e.g. Mining using pickaxe motion)
- Comfort options (e.g. Teleportation). Smooth locomotion and turning only for now.
- Model for the player's body. Currently not a priority as this requires IK.
- Default bindings for VR controllers other than the Valve Index Controllers
- Configuration options
- Object outlines. Disabled for now as the shader is broken in VR.
- Finger tracking
- Ability to switch primary hand
- Ability to yeet paladin down the waterfall

=== 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.
- Some UI elements might be outside of the players field of view or scaled incorrectly.
- 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.
- Performance needs improvement

== Q&A
[qanda]
Why is my framerate locked to 60fps?::
The game is locked to x fps 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)
// AI generated below :P::
Why is the mod not open source?::
It is. You are looking at the source right now (duh!).
Why is the mod not on NexusMods?::
I don't like NexusMods. I don't like their ToS and I don't like their mod manager. I don't want to support them.

=== Cool stuff to try
- Enable ik (The game ships with `FinalIK` so it should be possible. Probably just not networked yet.)
Expand Down
3 changes: 0 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,3 @@ echo "Copying the assets to the game folder..."
rm -rf /c/Program\ Files\ \(x86\)/Steam/steamapps/common/Techtonica/BepInEx/plugins/techtonica_vr/assets
mkdir -p /c/Program\ Files\ \(x86\)/Steam/steamapps/common/Techtonica/BepInEx/plugins/techtonica_vr/assets
cp -r ./unity/AssetBundles/StandaloneWindows/* /c/Program\ Files\ \(x86\)/Steam/steamapps/common/Techtonica/BepInEx/plugins/techtonica_vr/assets

echo "Done!"
read -p "Press enter to continue"
266 changes: 108 additions & 158 deletions plugin/src/camera/camera_manager.cs
Original file line number Diff line number Diff line change
@@ -1,170 +1,120 @@
using System.Collections;
using FluffyUnderware.DevTools.Extensions;
using HarmonyLib;
using Plugin.Input;
using Rewired;
using TechtonicaVR.Assets;
using TechtonicaVR.Debug;
using UnityEngine;
using Valve.Newtonsoft.Json.Linq;
using Valve.VR;

namespace TechtonicaVR.VRCamera;
public class VRCameraManager : MonoBehaviour
{
public Transform vrRoot;
public SteamVR_CameraHelper cameraHelperPrefab;

private SteamVR_CameraHelper cameraHelper;

public static Camera mainCamera;

public static VRCameraManager Create()
{
var instance = new GameObject(nameof(VRCameraManager)).AddComponent<VRCameraManager>();
// DontDestroyOnLoad(instance.gameObject);

return instance;
}

private void Awake()
{
// DontDestroyOnLoad(gameObject);
}

private void Start()
{
DontDestroyOnLoad(gameObject);
}

private void OnDestory()
{
Plugin.Logger.LogInfo("Destroying vr camera manager...");
}

private void OnEnable()
{
Plugin.Logger.LogInfo("Enabling vr camera manager...");
// DontDestroyOnLoad(gameObject);
}

private void OnDisable()
{
Plugin.Logger.LogInfo("Disabling vr camera manager...");
}

private void Update()
{
if (Camera.main == null)
{
return;
}

if (Camera.main != mainCamera)
{
mainCamera = Camera.main;
SetupCamera();
}

// Set the camera's field of view to match the SteamVR camera's field of view
// mainCamera.fieldOfView = SteamVR.instance.fieldOfView;
// mainCamera.stereoTargetEye = StereoTargetEyeMask.Left;
// mainCamera.projectionMatrix = mainCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
// mainCamera.targetTexture = Plugin.MyDisplay.GetRenderTextureForRenderPass(0);

// secondCamera.fieldOfView = SteamVR.instance.fieldOfView;
// secondCamera.stereoTargetEye = StereoTargetEyeMask.Right;
// secondCamera.projectionMatrix = secondCamera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
// secondCamera.targetTexture = Plugin.MyDisplay.GetRenderTextureForRenderPass(1);
}

private void SetupCamera()
{
Plugin.Logger.LogInfo("Setting up camera...");
// Matrix4x4 leftEyeProjectionMatrix = Plugin.MyDisplay.GetStereoProjectionMatrix(0);
// Matrix4x4 rightEyeProjectionMatrix = Plugin.MyDisplay.GetStereoProjectionMatrix(1);

mainCamera.gameObject.AddComponent<SteamVR_Camera>();
mainCamera.gameObject.AddComponent<SteamVR_TrackedObject>();
mainCamera.gameObject.AddComponent<TechMainCamera>();
HmdMatrix44_t leftEyeMatrix = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Left, mainCamera.nearClipPlane, mainCamera.farClipPlane);
HmdMatrix44_t rightEyeMatrix = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Right, mainCamera.nearClipPlane, mainCamera.farClipPlane);

if (PlayerFirstPersonController.instance != null)
{
vrRoot = PlayerFirstPersonController.instance.transform;


mainCamera.transform.parent = vrRoot;
foreach (var a in ReInput.mapping.Actions)
{
Plugin.Logger.LogInfo("Action: " + a.name);
Plugin.Logger.LogInfo(" id: " + a.id);
}

StartCoroutine(PatchCoroutine());
SpawnHands(vrRoot);
}

FindObjectsOfType<Headlamp>().ForEach(h => h.transform.parent = mainCamera.transform);

// mainCamera.SetStereoProjectionMatrix(Camera.StereoscopicEye.Left, HmdMatrix44ToMatrix4x4(leftEyeMatrix));

// secondCamera = new GameObject("VRCam").AddComponent<Camera>();
// secondCamera.gameObject.AddComponent<SteamVR_CameraHelper>();
// secondCamera.CopyFrom(mainCamera);
// secondCamera.transform.parent = mainCamera.transform.parent;
// secondCamera.SetStereoProjectionMatrix(Camera.StereoscopicEye.Right, HmdMatrix44ToMatrix4x4(rightEyeMatrix));
// secondCamera.enabled = true;
}

IEnumerator PatchCoroutine()
{
yield return new WaitForSeconds(1);

MainGamePatch.Create();
yield break;
}

private void SpawnHands(Transform vrRoot)
{
SteamVRInputMapper.rightHandObject = new GameObject("RightHand");
SteamVRInputMapper.rightHandObject.transform.parent = vrRoot;
var rightHandModel = GameObject.Instantiate(AssetLoader.RightHandBase, Vector3.zero, Quaternion.identity, SteamVRInputMapper.rightHandObject.transform);
rightHandModel.transform.localPosition = new Vector3(0, 0.01f, -0.09f);
rightHandModel.transform.localRotation = Quaternion.Euler(358.4256f, 103.2413f, 240.2217f);
// rightHandModel.GetComponent<Renderer>().enabled = true;

SteamVRInputMapper.leftHandObject = new GameObject("LeftHand");
SteamVRInputMapper.leftHandObject.transform.parent = vrRoot;
var leftHandModel = GameObject.Instantiate(AssetLoader.LeftHandBase, Vector3.zero, Quaternion.identity, SteamVRInputMapper.leftHandObject.transform);
leftHandModel.transform.localPosition = new Vector3(0, 0.01f, -0.09f);
leftHandModel.transform.localRotation = Quaternion.Euler(335.2912f, 256.7355f, 116.7813f);

// leftHandModel.GetComponent<Renderer>().enabled = true;
}


public static Matrix4x4 HmdMatrix44ToMatrix4x4(HmdMatrix44_t hmdMatrix)
{
Matrix4x4 matrix = new Matrix4x4();

matrix[0, 0] = hmdMatrix.m0;
matrix[0, 1] = hmdMatrix.m1;
matrix[0, 2] = hmdMatrix.m2;
matrix[0, 3] = hmdMatrix.m3;
matrix[1, 0] = hmdMatrix.m4;
matrix[1, 1] = hmdMatrix.m5;
matrix[1, 2] = hmdMatrix.m6;
matrix[1, 3] = hmdMatrix.m7;
matrix[2, 0] = hmdMatrix.m8;
matrix[2, 1] = hmdMatrix.m9;
matrix[2, 2] = hmdMatrix.m10;
matrix[2, 3] = hmdMatrix.m11;
matrix[3, 0] = hmdMatrix.m12;
matrix[3, 1] = hmdMatrix.m13;
matrix[3, 2] = hmdMatrix.m14;
matrix[3, 3] = hmdMatrix.m15;

return matrix;
}
public Transform vrRoot;
public SteamVR_CameraHelper cameraHelperPrefab;

private SteamVR_CameraHelper cameraHelper;

Check warning on line 16 in plugin/src/camera/camera_manager.cs

View workflow job for this annotation

GitHub Actions / build

The field 'VRCameraManager.cameraHelper' is never used

Check warning on line 16 in plugin/src/camera/camera_manager.cs

View workflow job for this annotation

GitHub Actions / build

The field 'VRCameraManager.cameraHelper' is never used

public static Camera mainCamera;

public static VRCameraManager Create()
{
var instance = new GameObject(nameof(VRCameraManager)).AddComponent<VRCameraManager>();

return instance;
}

private void Start()
{
DontDestroyOnLoad(gameObject);
}

private void OnDestory()
{
Plugin.Logger.LogInfo("Destroying vr camera manager...");
}

private void OnEnable()
{
Plugin.Logger.LogInfo("Enabling vr camera manager...");
}

private void OnDisable()
{
Plugin.Logger.LogInfo("Disabling vr camera manager...");
}

private void Update()
{
if (Camera.main == null)
{
return;
}

if (Camera.main != mainCamera)
{
mainCamera = Camera.main;
SetupCamera();
}
}

private void SetupCamera()
{
Plugin.Logger.LogInfo("Setting up camera...");

mainCamera.gameObject.AddComponent<SteamVR_Camera>();
mainCamera.gameObject.AddComponent<SteamVR_TrackedObject>();
mainCamera.gameObject.AddComponent<TechMainCamera>();
HmdMatrix44_t leftEyeMatrix = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Left, mainCamera.nearClipPlane, mainCamera.farClipPlane);
HmdMatrix44_t rightEyeMatrix = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Right, mainCamera.nearClipPlane, mainCamera.farClipPlane);

if (PlayerFirstPersonController.instance != null)
{
vrRoot = PlayerFirstPersonController.instance.transform;


mainCamera.transform.parent = vrRoot;
foreach (var a in ReInput.mapping.Actions)
{
Plugin.Logger.LogInfo("Action: " + a.name);
Plugin.Logger.LogInfo(" id: " + a.id);
}

StartCoroutine(PatchCoroutine());
SpawnHands(vrRoot);
}

FindObjectsOfType<Headlamp>().ForEach(h => h.transform.parent = mainCamera.transform);
}

IEnumerator PatchCoroutine()
{
yield return new WaitForSeconds(1);

MainGamePatch.Create();
yield break;
}

private void SpawnHands(Transform vrRoot)
{
var rightHandObject = new GameObject("RightHand");
rightHandObject.AddComponent<Gizmo>();

rightHandObject.transform.parent = vrRoot;
var rightHandModel = GameObject.Instantiate(AssetLoader.RightHandBase, Vector3.zero, Quaternion.identity, rightHandObject.transform);
rightHandModel.transform.localPosition = new Vector3(0, 0.01f, -0.09f);
rightHandModel.transform.localRotation = Quaternion.Euler(358.4256f, 103.2413f, 240.2217f);

SteamVRInputMapper.rightHandObject = rightHandObject;

var leftHandObject = new GameObject("LeftHand");
leftHandObject.AddComponent<Gizmo>();

leftHandObject.transform.parent = vrRoot;
var leftHandModel = GameObject.Instantiate(AssetLoader.LeftHandBase, Vector3.zero, Quaternion.identity, leftHandObject.transform);
leftHandModel.transform.localPosition = new Vector3(0, 0.01f, -0.09f);
leftHandModel.transform.localRotation = Quaternion.Euler(335.2912f, 256.7355f, 116.7813f);

SteamVRInputMapper.leftHandObject = leftHandObject;
}
}
Loading

0 comments on commit 4c6fdb5

Please sign in to comment.