From de29e50cfb3e7dd5564dfd22730bd666dd708fe6 Mon Sep 17 00:00:00 2001 From: Don Pulsipher Date: Tue, 10 Mar 2026 14:31:11 -0700 Subject: [PATCH 1/2] Use screen resolution for VR render texture instead of fixed asset size The bundled RenderTexture asset has a fixed resolution which causes blurry rendering at higher display resolutions. Create a new RenderTexture at Screen.width x Screen.height using the asset as a format template, so the UI renders at native resolution. Co-Authored-By: Claude Opus 4.6 --- DFUVR/sTx.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/DFUVR/sTx.cs b/DFUVR/sTx.cs index 41ee69c..240963f 100644 --- a/DFUVR/sTx.cs +++ b/DFUVR/sTx.cs @@ -15,17 +15,20 @@ void Start() Plugin.LoggerInstance.LogInfo("!"); string assetBundlePath = Path.Combine(Paths.PluginPath, "AssetBundles", "assetbundle1"); - AssetBundle assetBundle = AssetBundle.LoadFromFile(assetBundlePath); - RenderTexture rT = assetBundle.LoadAsset("Rtxt"); - + assetBundle.Unload(false); + // Create a render texture at the actual screen resolution + // using the asset bundle one as a format template + RenderTexture screenRT = new RenderTexture(Screen.width, Screen.height, rT.depth, rT.format); + screenRT.filterMode = rT.filterMode; + screenRT.antiAliasing = rT.antiAliasing; + screenRT.Create(); + Plugin.LoggerInstance.LogInfo($"Created RT at {Screen.width}x{Screen.height} (screen res)"); - assetBundle.Unload(false); - sTxx = rT;//Resources.Load("Rtxt"); + sTxx = screenRT; Plugin.LoggerInstance.LogInfo(sTxx); - } public IEnumerator UICal() { From 814330a5f9e51955bf912337ed337662a42068f6 Mon Sep 17 00:00:00 2001 From: Don Pulsipher Date: Tue, 10 Mar 2026 14:31:55 -0700 Subject: [PATCH 2/2] Replace uWindowCapture with direct render-to-texture and physics raycast uWindowCapture relies on Windows APIs that don't work under Proton/Wine. Replace it with: - Direct DaggerfallUI render-to-texture on the VR UI quad - Physics raycast for laser pointer interaction instead of uWindowCapture raycasts - DaggerfallUI.CustomMousePosition for hover tracking - Cleaned up commented-out debug code in SPC.cs This enables the VR UI to work on Linux via Proton. Co-Authored-By: Claude Opus 4.6 --- DFUVR/DFUVR.csproj | 4 +- DFUVR/SPC.cs | 178 +++++++++++++++++---------------------------- DFUVR/SpawnUI.cs | 32 ++++++-- 3 files changed, 93 insertions(+), 121 deletions(-) diff --git a/DFUVR/DFUVR.csproj b/DFUVR/DFUVR.csproj index d84be7d..4e8d560 100644 --- a/DFUVR/DFUVR.csproj +++ b/DFUVR/DFUVR.csproj @@ -96,9 +96,7 @@ False ..\dependencies\Windows\x64\DaggerfallUnity_Data\Managed\UnityEngine.XRModule.dll - - ..\dependencies\Windows\x64\DaggerfallUnity_Data\Managed\uWindowCapture.Runtime.dll - + diff --git a/DFUVR/SPC.cs b/DFUVR/SPC.cs index a6cf3e9..a4eecf9 100644 --- a/DFUVR/SPC.cs +++ b/DFUVR/SPC.cs @@ -1,9 +1,9 @@ -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; +using DaggerfallWorkshop.Game; using UnityEngine; using UnityEngine.SpatialTracking; using UnityEngine.UI; using UnityEngine.XR; -using uWindowCapture; namespace DFUVR { @@ -24,8 +24,6 @@ public class SPC : MonoBehaviour private bool isClicking = false; - private UwcWindowTexture wTexture; - [DllImport("user32.dll")] private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo); @@ -42,13 +40,12 @@ public void Initialize(LineRenderer line, GraphicRaycaster graphicRaycaster, Tra { if (Var.isFirst) { - wTexture = GameObject.Find("VRUI").GetComponent(); - wTexture.type = WindowTextureType.Window; - wTexture.partialWindowTitle = "Daggerfall"; + // Use physics raycast for main menu UI (no uWindowCapture) + windowHeight = Var.windowHeight; + windowWidth = Var.windowWidth; } else { - //wTexture = GameObject.Find("VRUI").GetComponent(); windowHeight = Var.windowHeight; windowWidth = Var.windowWidth; } @@ -61,36 +58,6 @@ public void Initialize(LineRenderer line, GraphicRaycaster graphicRaycaster, Tra void Update() { - //foreach (KeyCode kcode in Enum.GetValues(typeof(KeyCode))) - //{ - // if (Input.GetKey(kcode)) - // Plugin.LoggerInstance.LogInfo("KeyCode down: " + kcode); - //} - //float input = Input.GetAxis("Axis" + Var.debugInt2); - - //Plugin.LoggerInstance.LogInfo("Input:" + input); - //Plugin.LoggerInstance.LogInfo("Axis:" + Var.debugInt2); - //Debug.Log(Var.heightOffset); - - //if (Input.GetKeyDown(Var.acceptButton)) { Var.debugInt2 += 1; } - //Plugin.LoggerInstance.LogInfo(wTexture); - //DaggerfallUI daggerfallUI = GameObject.Find("DaggerfallUI").GetComponent(); - //FieldInfo directionField = AccessTools.Field(typeof(DaggerfallUI), "customRenderTarget"); - //Plugin.LoggerInstance.LogInfo(directionField.GetValue(daggerfallUI)); - //if (Input.GetKeyDown(KeyCode.K)) - //{ - // Plugin.LoggerInstance.LogInfo("Pressed"); - // StartCoroutine(SpawnUI.Calibrate()); - //} - //wTexture = GameObject.Find("VRUI").GetComponent(); - //if (wTexture != null) - //{ - // windowPosX = wTexture.window.x; - // windowPosY = wTexture.window.y; - // windowWidth = wTexture.window.width; - // windowHeight = wTexture.window.height; - // Plugin.LoggerInstance.LogInfo(windowWidth+", "+windowHeight); - //} TriggerProvider.CheckPressedRight(); bool clicked = Input.GetKeyDown(Var.acceptButton) || TriggerProvider.pressedDone; @@ -107,67 +74,38 @@ void Update() if (!Var.fStartMenu) { - if (!Var.isCalibrated) - { - if (clicked) - { - var result = UwcWindowTexture.RayCast(lineStart, trackedPoseDriver.transform.forward, raycastDistance, -1); - if (result.hit) - { - //uWindowCapture really needs a proper documentation. I wish I knew sooner that it had a precise raycast function built in before making one myself... - //windowCoord = result.windowCoord; - Vector2 desktopCoord = result.desktopCoord; - SetCursorPos((int)desktopCoord.x, (int)desktopCoord.y); - mouse_event(MOUSEEVENTF_LEFTDOWN, (uint)desktopCoord.x, (uint)desktopCoord.y, 0, 0); - mouse_event(MOUSEEVENTF_LEFTUP, (uint)desktopCoord.x, (uint)desktopCoord.y, 0, 0); - } - } - } - else + // Continuously update DaggerfallUI mouse position from laser pointer + RaycastHit vruiHit; + bool hitVRUI = false; + RaycastHit[] hits = Physics.RaycastAll(lineStart, trackedPoseDriver.transform.forward, raycastDistance); + + foreach (var hit in hits) { - //RaycastHit hit; - - //if (Physics.Raycast(lineStart, trackedPoseDriver.transform.forward, out hit, raycastDistance)) - //{ - // if (hit.collider.gameObject.name == "VRUI") - // { - // if (Input.GetKeyDown(Var.acceptButton)) - // { - // Plugin.LoggerInstance.LogInfo("Raycast Hit: " + hit.point); - // SimulateMouseClick(hit.point); - // } - // } - // if (Input.GetKeyDown(Var.acceptButton)) - // { - // if (hit.collider.gameObject.name != "VRUI") - // { Plugin.LoggerInstance.LogInfo("Hit " + hit.collider.gameObject.name); } - // } - //} - RaycastHit[] hits = Physics.RaycastAll(lineStart, trackedPoseDriver.transform.forward, raycastDistance); - - foreach (var hit in hits) + if (hit.collider.gameObject.name == "VRUI") { - Plugin.LoggerInstance.LogInfo("clicked"); - if (hit.collider.gameObject.name == "VRUI") + vruiHit = hit; + hitVRUI = true; + UpdateVRMousePosition(hit.point); + + if (clicked) { - Plugin.LoggerInstance.LogInfo("Raycast Hit: " + hit.point); SimulateMouseClick(hit.point); - break; } - - if (Input.GetKeyDown(Var.acceptButton) || Var.rTriggerDone || Var.lTriggerDone) - hit.collider.gameObject.GetComponent