Generalized overlay locations.

Added controller as a location, and made GUI to configure it.
Fixed "Hide overlay when window not found" functionality.
Added scrolling for WindowOverlay and MonitorOverlay.
This commit is contained in:
jrhodnik 2019-06-02 16:54:01 -04:00
parent 5713d22935
commit 7226c724d7
11 changed files with 237 additions and 69 deletions

View File

@ -8,6 +8,8 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VRDash.Overlay;
using VRDash.Overlay.Config;
namespace VRDash
{
@ -82,7 +84,22 @@ namespace VRDash
{
public static ILog GetLogger(this object instance)
{
if (typeof(IOverlay).IsAssignableFrom(instance.GetType()))
{
IOverlay overlay = (IOverlay)instance;
return GetLogger(instance, overlay);
}
return LogManager.GetLogger(instance.GetType());
}
public static ILog GetLogger(this object instance, IOverlay overlay)
{
return LogManager.GetLogger($"{instance.GetType()} [{overlay.OverlayConfig.Name}]");
}
public static ILog GetLogger(this object instance, IOverlayConfig overlayConfig)
{
return LogManager.GetLogger($"{instance.GetType()} [{overlayConfig.Name}]");
}
}
}

View File

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VRDash"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
Title="VRDash" Height="700" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />

View File

@ -14,7 +14,7 @@ namespace VRDash.Overlay.Config.OverlayLocation
[OverlayLocationInfo("Controller", typeof(ControllerLocationEditor))]
public class ControllerLocation : IOverlayLocation
{
public ControllerHand Controller { get; private set; } = ControllerHand.Left;
public ControllerHand Controller { get; set; } = ControllerHand.Left;
[JsonIgnore]
public Matrix3x4 Location { get; private set; } = new Matrix3x4(new Vector4(1, 0, 0, 0),
@ -76,7 +76,7 @@ namespace VRDash.Overlay.Config.OverlayLocation
//Location = Matrix3x4.Add(Matrix3x4.CreateFromQuaternion(quat), Location);
//Location = Matrix3x4.Add(Matrix3x4.CreateScale(ScaleX, ScaleY, ScaleZ), Location);
if (m_Overlay.OverlayHandle == OpenVR.k_ulOverlayHandleInvalid || m_ControllerIndex == OpenVR.k_unTrackedDeviceIndexInvalid) { return; }
//Index changed, need to update the overlay
if (controllerIndex != m_ControllerIndex)
@ -89,11 +89,11 @@ namespace VRDash.Overlay.Config.OverlayLocation
if (err != EVROverlayError.None)
{
this.GetLogger().Warn($"[{m_Overlay.OverlayConfig.Name}] Error setting tracked device relative to {Controller} hand: {err}");
this.GetLogger(m_Overlay).Warn($"Error setting tracked device relative to {Controller} hand: {err}");
}
else
{
this.GetLogger().Info($"[{m_Overlay.OverlayConfig.Name}] Controller index updated.");
this.GetLogger(m_Overlay).Info($"Controller index updated.");
}
}
else
@ -105,7 +105,7 @@ namespace VRDash.Overlay.Config.OverlayLocation
if (err != EVROverlayError.None)
{
this.GetLogger().Warn($"[{m_Overlay.OverlayConfig.Name}] Error setting tracked device relative to {Controller} hand: {err}");
this.GetLogger(m_Overlay).Warn($"Error updating tracked device relative to {Controller} hand: {err}");
}
}

View File

@ -128,6 +128,8 @@ namespace VRDash.Overlay
m_OverlayHandle = overlayHandles.OverlayHandle;
m_ThumbnailIcon = overlayHandles.ThumbnailHandle;
overlay.SetOverlayFlag(m_OverlayHandle, VROverlayFlags.SendVRDiscreteScrollEvents, true);
var tempError = OpenVR.Overlay.ShowOverlay(m_OverlayHandle);
//EVROverlayError err = overlay.CreateDashboardOverlay(Config.Key, Config.Name, ref m_OverlayHandle, ref m_ThumbnailIcon);
@ -224,7 +226,7 @@ namespace VRDash.Overlay
if (!succ)
{
this.GetLogger().Warn($"[{Config.Name}] SetCursorPos failed.");
this.GetLogger().Warn($"SetCursorPos failed.");
}
break;
@ -356,6 +358,13 @@ namespace VRDash.Overlay
break;
}
}
break;
}
case EVREventType.VREvent_ScrollDiscrete:
{
var scrollAmount = vrEvent.data.scroll.ydelta;
User32.mouse_event(User32.MouseEventFlags.MOUSEEVENTF_WHEEL, 0, 0, (uint)(scrollAmount * 100), UIntPtr.Zero);
break;
}
}
@ -400,13 +409,13 @@ namespace VRDash.Overlay
}
else
{
this.GetLogger().Warn($"[{Config.Name}] Error getting coords to draw cursor.");
this.GetLogger().Warn($"Error getting coords to draw cursor.");
}
}
else
{
string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
this.GetLogger().Warn($"[{Config.Name}] Error getting cursor info: {errorMessage}");
this.GetLogger().Warn($"Error getting cursor info: {errorMessage}");
}
#endregion
@ -447,7 +456,7 @@ namespace VRDash.Overlay
HmdVector2_t vecWindowSize = new HmdVector2_t() { v0 = data.Width, v1 = data.Height };
OpenVR.Overlay.SetOverlayMouseScale(m_OverlayHandle, ref vecWindowSize);
this.GetLogger().Info($"[{Config.Name}] Monitor resized, texture updated.");
this.GetLogger().Info($"Monitor resized, texture updated.");
}

View File

@ -103,18 +103,18 @@ namespace VRDash.Overlay
{
m_Destroyed = true;
destroyInternal();
}
private void destroyInternal()
{
if (!m_Created) { return; }
m_Created = false;
//Signal render thread to exit
m_Running = false;
//Wait for render thread to exit
m_EventPumpTask.Wait();
}
private void destroyInternal()
{
if (!m_Created) { return; }
m_Created = false;
var err = OpenVR.Overlay.DestroyOverlay(m_OverlayHandle);
@ -133,10 +133,10 @@ namespace VRDash.Overlay
DateTime lastClick = DateTime.MinValue;
Config.Initialize(this);
overlay.SetOverlayFlag(m_OverlayHandle, VROverlayFlags.SendVRDiscreteScrollEvents, true);
#region Rendering setup
//Partially taken from here: https://stackoverflow.com/questions/6812068/c-sharp-which-is-the-fastest-way-to-take-a-screen-shot
@ -176,7 +176,7 @@ namespace VRDash.Overlay
if (IsCreated())
{
destroyInternal();
this.GetLogger().Info($"Destroyed {Config.Key} because it's window does not exist.");
this.GetLogger().Info($"Destroyed overlay because it's window does not exist.");
}
Thread.Sleep(100);
@ -185,18 +185,11 @@ namespace VRDash.Overlay
else if(Config.Selector.WindowExists() && !m_Created && !m_Destroyed)
{
createInternal();
this.GetLogger().Info($"Instantiated overlay because window became available.");
}
}
//This technically should never happen, buuuut...
IntPtr windowHandle = IntPtr.Zero;
try
{
windowHandle = Config.Selector.GetWindowHandle();
}
catch (WindowNotFoundException)
{
}
var windowHandle = Config.Selector.GetWindowHandle();
//Update the SteamVR dash name if necessary, only once a second.
if (Config.Selector.WindowExists() && Config.UpdateDashboardName && DateTime.Now.Subtract(lastNameCheck).TotalMilliseconds >= 1000)
@ -272,7 +265,7 @@ namespace VRDash.Overlay
if (!succ)
{
this.GetLogger().Warn($"[{Config.Name}] ClientToScreen failed.");
this.GetLogger().Warn($"ClientToScreen failed.");
}
@ -280,7 +273,7 @@ namespace VRDash.Overlay
if (!succ)
{
this.GetLogger().Warn($"[{Config.Name}] SetCursorPos failed.");
this.GetLogger().Warn($"SetCursorPos failed.");
}
}
break;
@ -418,6 +411,13 @@ namespace VRDash.Overlay
break;
}
}
break;
}
case EVREventType.VREvent_ScrollDiscrete:
{
var scrollAmount = vrEvent.data.scroll.ydelta;
User32.mouse_event(User32.MouseEventFlags.MOUSEEVENTF_WHEEL, 0, 0, (uint)(scrollAmount * 100), UIntPtr.Zero);
break;
}
}
@ -467,13 +467,13 @@ namespace VRDash.Overlay
}
else
{
this.GetLogger().Warn($"[{Config.Name}] Error getting coords to draw cursor.");
this.GetLogger().Warn($"Error getting coords to draw cursor.");
}
}
else
{
string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
this.GetLogger().Warn($"[{Config.Name}] Error getting cursor info: {errorMessage}");
this.GetLogger().Warn($"Error getting cursor info: {errorMessage}");
}
#endregion
@ -514,7 +514,7 @@ namespace VRDash.Overlay
HmdVector2_t vecWindowSize = new HmdVector2_t() { v0 = data.Width, v1 = data.Height };
OpenVR.Overlay.SetOverlayMouseScale(m_OverlayHandle, ref vecWindowSize);
this.GetLogger().Info($"[{Config.Name}] Window resized, texture updated.");
this.GetLogger().Info($"Window resized, texture updated.");
}
@ -596,8 +596,15 @@ namespace VRDash.Overlay
if (DateTime.Now.Subtract(lastFps).TotalMilliseconds > 1000)
{
//Console.WriteLine($"{frames} fps.");
if (Config.Selector.WindowExists())
{
CurrentFPS = frames;
}
else
{
CurrentFPS = 0;
}
frames = 0;
lastFps = DateTime.Now;
}

View File

@ -15,7 +15,7 @@
<Grid Grid.Row="0" Margin="5,5,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="104"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>

View File

@ -11,25 +11,68 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Location.PosX}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Location.PosY}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding Location.PosZ}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" >
<TextBlock Margin="0,0,5,0" HorizontalAlignment="Center" VerticalAlignment="Center">Controller:</TextBlock>
<ComboBox x:Name="cbController" Margin="0,0,5,0" SelectedItem="{Binding Location.Controller}" />
</DockPanel>
<TextBox Grid.Row="1" Grid.Column="0" Text="{Binding Location.RotP}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Location.RotY}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Location.RotR}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center">Position:</TextBlock>
<DockPanel Grid.Row="1" Grid.Column="1" >
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">X:</TextBlock>
<TextBox Text="{Binding Location.PosX}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="1" Grid.Column="2" >
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">Y:</TextBlock>
<TextBox Text="{Binding Location.PosY}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="1" Grid.Column="3">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">Z:</TextBlock>
<TextBox Text="{Binding Location.PosZ}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<TextBox Grid.Row="2" Grid.Column="0" Text="{Binding Location.ScaleX}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Location.ScaleY}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBox Grid.Row="2" Grid.Column="2" Text="{Binding Location.ScaleZ}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged"/>
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center">Rotation:</TextBlock>
<DockPanel Grid.Row="2" Grid.Column="1">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">P:</TextBlock>
<TextBox Text="{Binding Location.RotP}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="2" Grid.Column="2">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">Y:</TextBlock>
<TextBox Text="{Binding Location.RotY}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="2" Grid.Column="3">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">R:</TextBlock>
<TextBox Text="{Binding Location.RotR}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center">Scale:</TextBlock>
<DockPanel Grid.Row="3" Grid.Column="1">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">X:</TextBlock>
<TextBox Text="{Binding Location.ScaleX}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="3" Grid.Column="2">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">Y:</TextBlock>
<TextBox Text="{Binding Location.ScaleY}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="3" Grid.Column="3">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">Z:</TextBlock>
<TextBox Text="{Binding Location.ScaleZ}" Margin="5,5,5,5" TextChanged="TextBox_TextChanged" MinWidth="30"/>
</DockPanel>
<DockPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="4">
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Margin="5,0,0,0">Preset: </TextBlock>
<ComboBox x:Name="cbPresets" Margin="5,0,0,0" SelectionChanged="cbPresets_SelectionChanged"/>
</DockPanel>
</Grid>
</UserControl>

View File

@ -22,16 +22,79 @@ namespace VRDash.UI.LocationEditors
public partial class ControllerLocationEditor : UserControl
{
public ControllerLocation Location { get; set; } = null;
public Preset[] Presets = { new Preset() {Description = "Default" }, new Preset() { Description = "Behind Controller", PosY = -0.1f, RotP = -90, RotY = 180 } };
public ControllerLocationEditor(ControllerLocation loction)
{
Location = loction;
InitializeComponent();
DataContext = this;
cbController.ItemsSource = Enum.GetValues(typeof(ControllerLocation.ControllerHand));
cbPresets.ItemsSource = Presets;
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Location.ResetCheckTimer();
}
public class Preset
{
public string Description { get; set; }
public float PosX { get; set; } = 0;
public float PosY { get; set; } = 0;
public float PosZ { get; set; } = 0;
public float RotP { get; set; } = 0;
public float RotY { get; set; } = 0;
public float RotR { get; set; } = 0;
public float ScaleX { get; set; } = 1;
public float ScaleY { get; set; } = 1;
public float ScaleZ { get; set; } = 1;
public override string ToString()
{
return Description;
}
}
private void cbPresets_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Preset preset = (Preset)cbPresets.SelectedItem;
Location.PosX = preset.PosX;
Location.PosY = preset.PosY;
Location.PosZ = preset.PosZ;
Location.RotP = preset.RotP;
Location.RotY = preset.RotY;
Location.RotR = preset.RotR;
Location.ScaleX = preset.ScaleX;
Location.ScaleY = preset.ScaleY;
Location.ScaleZ = preset.ScaleZ;
Panel container = (Panel)this.Content;
UIElementCollection children = container.Children;
List<FrameworkElement> lstElement = children.Cast<FrameworkElement>().ToList();
var lstControl = lstElement.OfType<Control>();
foreach(var control in children)
{
if (control.GetType() == typeof(DockPanel))
{
var dockPanel = (DockPanel)control;
foreach (var dcChild in dockPanel.Children)
{
if(dcChild.GetType() == typeof(TextBox))
{
var tb = (TextBox)dcChild;
tb.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
}
}
}
}
}
}
}

View File

@ -8,8 +8,8 @@
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
@ -17,12 +17,16 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<Border x:Name="bdrLocationEditor" Grid.Row="0" Grid.ColumnSpan="3"/>
<Border x:Name="bdrContent" Grid.Row="1" Grid.ColumnSpan="3"/>
<Border x:Name="bdrContent" Grid.Row="0" Grid.ColumnSpan="3"/>
<GroupBox Header="Location Settings" Grid.Row="1" Grid.ColumnSpan="3" HorizontalAlignment="Left" Margin="0,5,0,5">
<Border x:Name="bdrLocationEditor" HorizontalAlignment="Center" VerticalAlignment="Center" />
</GroupBox>
<TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center">Overlay Width:</TextBlock>
<Slider x:Name="slWidth" Maximum="10" Grid.Row="2" Grid.Column="1" Value="{Binding OverlayWidth}" VerticalAlignment="Center" Margin="5,0,5,0"/>
<TextBox x:Name="tbWidth" Grid.Row="2" Grid.Column="2" PreviewTextInput="tbWidth_PreviewTextInput" PreviewKeyDown="tbWidth_PreviewKeyDown" Text="{Binding OverlayWidth}"/>
</Grid>
</UserControl>

View File

@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using VRDash.Utilities;
namespace VRDash.WindowSelectors
@ -38,18 +39,40 @@ namespace VRDash.WindowSelectors
}
Process[] m_Processes = null;
public Process[] GetProcesses()
{
if(m_Processes == null)
{
m_Processes = Process.GetProcessesByName(ProcessName);
RefreshProcesses();
}
return m_Processes;
}
private void RefreshProcesses()
{
m_Processes = Process.GetProcessesByName(ProcessName);
}
DateTime m_LastCheck = DateTime.MinValue;
bool isRefreshing = false;
public Process GetProcess()
{
if(m_Processes != null && DateTime.Now.Subtract(m_LastCheck).TotalSeconds > 10)
{
if (!isRefreshing)
{
Task.Factory.StartNew(() =>
{
isRefreshing = true;
RefreshProcesses();
isRefreshing = false;
m_LastCheck = DateTime.Now;
});
}
}
var procs = GetProcesses();
if (procs.Count() <= 0)
@ -58,6 +81,7 @@ namespace VRDash.WindowSelectors
}
return procs.First();
}
public IntPtr GetWindowHandle()
{
return GetProcess().MainWindowHandle;
@ -75,14 +99,7 @@ namespace VRDash.WindowSelectors
public bool WindowExists()
{
try
{
return User32.IsWindow(GetWindowHandle());
}
catch
{
return false;
}
return WindowInfo.GetWindowList().Any(x => x.hWnd == GetWindowHandle());
}
}
}

View File

@ -2,6 +2,7 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using VRDash.Utilities;
namespace VRDash.WindowSelectors
@ -12,6 +13,8 @@ namespace VRDash.WindowSelectors
public bool RefreshOnGet { get; set; } = false;
public string TitleFilter { get; set; } = "";
public TitleSearchType SearchType { get; set; } = TitleSearchType.Contains;
DateTime m_LastCheck = DateTime.MinValue;
bool isRefreshing = false;
[JsonIgnore]
public WindowInfo Window
@ -25,6 +28,20 @@ namespace VRDash.WindowSelectors
}
else
{
//Auto refreshing. Might be better to not do this in the getter, but whatever.
if(DateTime.Now.Subtract(m_LastCheck).TotalSeconds > 10)
{
if (!isRefreshing)
{
Task.Factory.StartNew(() =>
{
isRefreshing = true;
m_Window = GetWindowUsingFilter();
m_LastCheck = DateTime.Now;
isRefreshing = false;
});
}
}
if (m_Window == null)
{
m_Window = GetWindowUsingFilter();
@ -94,15 +111,6 @@ namespace VRDash.WindowSelectors
public bool WindowExists()
{
//try
//{
// var window = Window;
//}
//catch (WindowNotFoundException)
//{
// return false;
//}
//return true;
if(Window == null)
{
return false;