mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-06 22:46:06 +02:00
v2019.08.19
This commit is contained in:
+25
-12
@@ -6,13 +6,14 @@
|
|||||||
using CefSharp;
|
using CefSharp;
|
||||||
using CefSharp.OffScreen;
|
using CefSharp.OffScreen;
|
||||||
using SharpDX.Direct3D11;
|
using SharpDX.Direct3D11;
|
||||||
using System;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
{
|
{
|
||||||
public class Browser : ChromiumWebBrowser
|
public class Browser : ChromiumWebBrowser
|
||||||
{
|
{
|
||||||
|
private readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||||
private Texture2D m_Texture;
|
private Texture2D m_Texture;
|
||||||
|
|
||||||
public Browser(Texture2D texture, string address)
|
public Browser(Texture2D texture, string address)
|
||||||
@@ -24,38 +25,46 @@ namespace VRCX
|
|||||||
m_Texture = texture;
|
m_Texture = texture;
|
||||||
Size = new Size(texture.Description.Width, texture.Description.Height);
|
Size = new Size(texture.Description.Width, texture.Description.Height);
|
||||||
RenderHandler.Dispose();
|
RenderHandler.Dispose();
|
||||||
RenderHandler = new RenderHandler(this);
|
RenderHandler = new RenderHandler(this, m_Lock);
|
||||||
var options = new BindingOptions()
|
var options = new BindingOptions()
|
||||||
{
|
{
|
||||||
CamelCaseJavascriptNames = false
|
CamelCaseJavascriptNames = false
|
||||||
};
|
};
|
||||||
JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
||||||
JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
||||||
|
JavascriptObjectRepository.Register("SQLite", new SQLite(), true, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void Dispose()
|
||||||
|
{
|
||||||
|
RenderHandler.Dispose();
|
||||||
|
RenderHandler = null;
|
||||||
|
base.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
{
|
{
|
||||||
var handler = (RenderHandler)RenderHandler;
|
m_Lock.EnterReadLock();
|
||||||
lock (handler.BufferLock)
|
try
|
||||||
{
|
{
|
||||||
if (handler.Buffer.IsAllocated)
|
var H = (RenderHandler)RenderHandler;
|
||||||
|
if (H.Buffer.IsAllocated)
|
||||||
{
|
{
|
||||||
var context = m_Texture.Device.ImmediateContext;
|
var context = m_Texture.Device.ImmediateContext;
|
||||||
var box = context.MapSubresource(m_Texture, 0, MapMode.WriteDiscard, MapFlags.None);
|
var box = context.MapSubresource(m_Texture, 0, MapMode.WriteDiscard, MapFlags.None);
|
||||||
if (box.DataPointer != IntPtr.Zero)
|
if (box.IsEmpty)
|
||||||
{
|
{
|
||||||
var width = handler.Width;
|
if (box.RowPitch == H.Width * 4)
|
||||||
var height = handler.Height;
|
|
||||||
if (box.RowPitch == width * 4)
|
|
||||||
{
|
{
|
||||||
WinApi.CopyMemory(box.DataPointer, handler.Buffer.AddrOfPinnedObject(), (uint)handler.BufferSize);
|
WinApi.CopyMemory(box.DataPointer, H.Buffer.AddrOfPinnedObject(), (uint)H.BufferSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var dest = box.DataPointer;
|
var dest = box.DataPointer;
|
||||||
var src = handler.Buffer.AddrOfPinnedObject();
|
var src = H.Buffer.AddrOfPinnedObject();
|
||||||
var pitch = box.RowPitch;
|
var pitch = box.RowPitch;
|
||||||
var length = width * 4;
|
var length = H.Width * 4;
|
||||||
|
var height = H.Height;
|
||||||
for (var i = 0; i < height; ++i)
|
for (var i = 0; i < height; ++i)
|
||||||
{
|
{
|
||||||
WinApi.CopyMemory(dest, src, (uint)length);
|
WinApi.CopyMemory(dest, src, (uint)length);
|
||||||
@@ -67,6 +76,10 @@ namespace VRCX
|
|||||||
context.UnmapSubresource(m_Texture, 0);
|
context.UnmapSubresource(m_Texture, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+17
-29
@@ -13,36 +13,32 @@ namespace VRCX
|
|||||||
public static float CpuUsage { get; private set; }
|
public static float CpuUsage { get; private set; }
|
||||||
private static Thread m_Thread;
|
private static Thread m_Thread;
|
||||||
|
|
||||||
public static void Start()
|
public static void Init()
|
||||||
{
|
|
||||||
if (m_Thread == null)
|
|
||||||
{
|
{
|
||||||
m_Thread = new Thread(() =>
|
m_Thread = new Thread(() =>
|
||||||
{
|
{
|
||||||
PerformanceCounter cpuCounter = null;
|
PerformanceCounter counter = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cpuCounter = new PerformanceCounter("Processor Information", "% Processor Utility", "_Total", true);
|
counter = new PerformanceCounter("Processor Information", "% Processor Utility", "_Total", true);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (cpuCounter == null)
|
if (counter == null)
|
||||||
{
|
{
|
||||||
cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
|
counter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
if (counter != null)
|
||||||
|
{
|
||||||
while (m_Thread != null)
|
while (m_Thread != null)
|
||||||
{
|
{
|
||||||
if (cpuCounter != null)
|
|
||||||
{
|
|
||||||
CpuUsage = cpuCounter.NextValue();
|
|
||||||
}
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
@@ -51,31 +47,23 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
// ThreadInterruptedException
|
// ThreadInterruptedException
|
||||||
}
|
}
|
||||||
|
CpuUsage = counter.NextValue();
|
||||||
}
|
}
|
||||||
if (cpuCounter != null)
|
counter.Dispose();
|
||||||
|
}
|
||||||
|
})
|
||||||
{
|
{
|
||||||
cpuCounter.Dispose();
|
IsBackground = true
|
||||||
}
|
};
|
||||||
});
|
|
||||||
m_Thread.Start();
|
m_Thread.Start();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void Stop()
|
public static void Exit()
|
||||||
{
|
|
||||||
var thread = m_Thread;
|
|
||||||
if (thread != null)
|
|
||||||
{
|
{
|
||||||
|
var T = m_Thread;
|
||||||
m_Thread = null;
|
m_Thread = null;
|
||||||
try
|
T.Interrupt();
|
||||||
{
|
T.Join();
|
||||||
thread.Interrupt();
|
|
||||||
thread.Join();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+74
-17
@@ -4,39 +4,81 @@
|
|||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
{
|
{
|
||||||
public class Discord
|
public class Discord
|
||||||
{
|
{
|
||||||
private static RichPresence m_Presence = new RichPresence();
|
private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||||
private static DiscordRpcClient m_Client;
|
private static readonly RichPresence m_Presence = new RichPresence();
|
||||||
|
private static Thread m_Thread;
|
||||||
private static bool m_Active;
|
private static bool m_Active;
|
||||||
|
|
||||||
public static void Update()
|
public static void Init()
|
||||||
{
|
{
|
||||||
if (m_Client != null)
|
m_Thread = new Thread(() =>
|
||||||
{
|
{
|
||||||
m_Client.Invoke();
|
DiscordRpcClient client = null;
|
||||||
|
while (m_Thread != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ThreadInterruptedException
|
||||||
|
}
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
m_Lock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.SetPresence(m_Presence);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitReadLock();
|
||||||
|
}
|
||||||
|
client.Invoke();
|
||||||
}
|
}
|
||||||
if (m_Active)
|
if (m_Active)
|
||||||
{
|
{
|
||||||
if (m_Client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
m_Client = new DiscordRpcClient("525953831020920832");
|
client = new DiscordRpcClient("525953831020920832");
|
||||||
m_Client.Initialize();
|
if (!client.Initialize())
|
||||||
}
|
|
||||||
lock (m_Presence)
|
|
||||||
{
|
{
|
||||||
m_Client.SetPresence(m_Presence);
|
client.Dispose();
|
||||||
|
client = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_Client != null)
|
}
|
||||||
|
else if (client != null)
|
||||||
{
|
{
|
||||||
m_Client.Dispose();
|
client.Dispose();
|
||||||
m_Client = null;
|
client = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (client != null)
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
IsBackground = true
|
||||||
|
};
|
||||||
|
m_Thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exit()
|
||||||
|
{
|
||||||
|
var T = m_Thread;
|
||||||
|
m_Thread = null;
|
||||||
|
T.Interrupt();
|
||||||
|
T.Join();
|
||||||
|
}
|
||||||
|
|
||||||
public void SetActive(bool active)
|
public void SetActive(bool active)
|
||||||
{
|
{
|
||||||
@@ -45,16 +87,22 @@ namespace VRCX
|
|||||||
|
|
||||||
public void SetText(string details, string state)
|
public void SetText(string details, string state)
|
||||||
{
|
{
|
||||||
lock (m_Presence)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
m_Presence.Details = details;
|
m_Presence.Details = details;
|
||||||
m_Presence.State = state;
|
m_Presence.State = state;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAssets(string largeKey, string largeText, string smallKey, string smallText)
|
public void SetAssets(string largeKey, string largeText, string smallKey, string smallText)
|
||||||
{
|
{
|
||||||
lock (m_Presence)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(largeKey) &&
|
if (string.IsNullOrEmpty(largeKey) &&
|
||||||
string.IsNullOrEmpty(smallKey))
|
string.IsNullOrEmpty(smallKey))
|
||||||
@@ -73,6 +121,10 @@ namespace VRCX
|
|||||||
m_Presence.Assets.SmallImageText = smallText;
|
m_Presence.Assets.SmallImageText = smallText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSB Sucks
|
// JSB Sucks
|
||||||
@@ -83,7 +135,8 @@ namespace VRCX
|
|||||||
|
|
||||||
public static void SetTimestamps(ulong startUnixMilliseconds, ulong endUnixMilliseconds)
|
public static void SetTimestamps(ulong startUnixMilliseconds, ulong endUnixMilliseconds)
|
||||||
{
|
{
|
||||||
lock (m_Presence)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (startUnixMilliseconds == 0)
|
if (startUnixMilliseconds == 0)
|
||||||
{
|
{
|
||||||
@@ -106,6 +159,10 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+191
-150
@@ -5,208 +5,249 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
{
|
{
|
||||||
public class VRCX_LogWatcher
|
public class LogWatcherFile
|
||||||
{
|
{
|
||||||
|
public long Length;
|
||||||
|
public long Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogWatcher
|
||||||
|
{
|
||||||
|
private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||||
private static List<string[]> m_GameLog = new List<string[]>();
|
private static List<string[]> m_GameLog = new List<string[]>();
|
||||||
private static Thread m_Thread;
|
private static Thread m_Thread;
|
||||||
private static bool m_Reset;
|
private static bool m_Reset;
|
||||||
|
|
||||||
public static void Start()
|
// NOTE
|
||||||
{
|
// FileSystemWatcher() is unreliable
|
||||||
if (m_Thread == null)
|
|
||||||
|
public static void Init()
|
||||||
{
|
{
|
||||||
m_Thread = new Thread(() =>
|
m_Thread = new Thread(() =>
|
||||||
{
|
{
|
||||||
var lastPosition = 0L;
|
var D = new Dictionary<string, LogWatcherFile>();
|
||||||
var firstLine = string.Empty;
|
var di = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"Low\VRChat\VRChat");
|
||||||
while (m_Thread != null)
|
while (m_Thread != null)
|
||||||
{
|
{
|
||||||
if (m_Reset)
|
|
||||||
{
|
|
||||||
m_Reset = false;
|
|
||||||
firstLine = string.Empty;
|
|
||||||
lastPosition = 0;
|
|
||||||
}
|
|
||||||
var info = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"Low\VRChat\VRChat");
|
|
||||||
if (info != null &&
|
|
||||||
info.Exists)
|
|
||||||
{
|
|
||||||
var files = info.GetFiles("output_log_*.txt", SearchOption.TopDirectoryOnly);
|
|
||||||
if (files != null &&
|
|
||||||
files.Length >= 1)
|
|
||||||
{
|
|
||||||
Array.Sort(files, (A, B) => B.LastWriteTime.CompareTo(A.LastWriteTime));
|
|
||||||
if (firstLine == string.Empty)
|
|
||||||
{
|
|
||||||
for (var i = files.Length - 1; i >= 1; --i)
|
|
||||||
{
|
|
||||||
using (var stream = files[i].Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
|
||||||
{
|
|
||||||
var line = string.Empty;
|
|
||||||
while ((line = reader.ReadLine()) != null)
|
|
||||||
{
|
|
||||||
if (line.Length > 32 &&
|
|
||||||
line[31] == '-')
|
|
||||||
{
|
|
||||||
ParseLine(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
using (var stream = files[0].Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
|
||||||
{
|
|
||||||
var line = reader.ReadLine();
|
|
||||||
if (line != null)
|
|
||||||
{
|
|
||||||
if (string.Equals(firstLine, line))
|
|
||||||
{
|
|
||||||
stream.Position = lastPosition;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
firstLine = line;
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
lastPosition = stream.Position;
|
|
||||||
ParseLine(line);
|
|
||||||
}
|
|
||||||
while ((line = reader.ReadLine()) != null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ThreadInterruptedException
|
// ThreadInterruptedException
|
||||||
}
|
}
|
||||||
}
|
if (m_Reset)
|
||||||
});
|
|
||||||
m_Thread.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Stop()
|
|
||||||
{
|
{
|
||||||
var thread = m_Thread;
|
m_Reset = false;
|
||||||
if (thread != null)
|
D.Clear();
|
||||||
{
|
m_Lock.EnterWriteLock();
|
||||||
m_Thread = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
thread.Interrupt();
|
m_GameLog.Clear();
|
||||||
thread.Join();
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var S = new HashSet<string>(D.Keys);
|
||||||
|
di.Refresh();
|
||||||
|
if (di.Exists)
|
||||||
|
{
|
||||||
|
var files = di.GetFiles("output_log_*.txt", SearchOption.TopDirectoryOnly);
|
||||||
|
Array.Sort(files, (A, B) => A.CreationTime.CompareTo(B.CreationTime));
|
||||||
|
var bias = DateTime.Now.AddMinutes(-5d);
|
||||||
|
foreach (var fi in files)
|
||||||
|
{
|
||||||
|
if (bias.CompareTo(fi.LastWriteTime) <= 0)
|
||||||
|
{
|
||||||
|
fi.Refresh();
|
||||||
|
}
|
||||||
|
if (D.TryGetValue(fi.Name, out LogWatcherFile F))
|
||||||
|
{
|
||||||
|
S.Remove(fi.Name);
|
||||||
|
if (F.Length == fi.Length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
F = new LogWatcherFile();
|
||||||
|
D.Add(fi.Name, F);
|
||||||
|
}
|
||||||
|
F.Length = fi.Length;
|
||||||
|
Parse(fi, ref F.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var key in S)
|
||||||
|
{
|
||||||
|
D.Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
IsBackground = true
|
||||||
|
};
|
||||||
|
m_Thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exit()
|
||||||
|
{
|
||||||
|
var T = m_Thread;
|
||||||
|
m_Thread = null;
|
||||||
|
T.Interrupt();
|
||||||
|
T.Join();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Parse(FileInfo info, ref long position)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var stream = info.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||||
|
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
stream.Position = position;
|
||||||
|
var s = string.Empty;
|
||||||
|
while ((s = reader.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
if (s.Length > 35)
|
||||||
|
{
|
||||||
|
var c = s[35];
|
||||||
|
if (c == 'R')
|
||||||
|
{
|
||||||
|
// 2019.07.31 22:26:24 Log - [RoomManager] Joining wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd:6974~private(usr_4f76a584-9d4b-46f6-8209-8305eb683661)~nonce(0000000000000000000000000000000000000000000000000000000000000000)
|
||||||
|
// 2019.07.31 22:26:24 Log - [RoomManager] Joining or Creating Room: VRChat Home
|
||||||
|
if (s.Length > 56 &&
|
||||||
|
string.Compare(s, 34, "[RoomManager] Joining ", 0, "[RoomManager] Joining ".Length, StringComparison.Ordinal) == 0 &&
|
||||||
|
string.Compare(s, 56, "or ", 0, "or ".Length, StringComparison.Ordinal) != 0)
|
||||||
|
{
|
||||||
|
var item = new[]
|
||||||
|
{
|
||||||
|
ConvertLogTimeToISO8601(s),
|
||||||
|
"Location",
|
||||||
|
s.Substring(56)
|
||||||
|
};
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_GameLog.Add(item);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == 'N')
|
||||||
|
{
|
||||||
|
// 2019.07.31 22:41:18 Log - [NetworkManager] OnPlayerJoined pypy
|
||||||
|
if (s.Length > 66 &&
|
||||||
|
string.Compare(s, 34, "[NetworkManager] OnPlayerJoined ", 0, "[NetworkManager] OnPlayerJoined ".Length, StringComparison.Ordinal) == 0)
|
||||||
|
{
|
||||||
|
var item = new[]
|
||||||
|
{
|
||||||
|
ConvertLogTimeToISO8601(s),
|
||||||
|
"OnPlayerJoined",
|
||||||
|
s.Substring(66)
|
||||||
|
};
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_GameLog.Add(item);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2019.07.31 22:29:31 Log - [NetworkManager] OnPlayerLeft pypy
|
||||||
|
else if (s.Length > 64 &&
|
||||||
|
string.Compare(s, 34, "[NetworkManager] OnPlayerLeft ", 0, "[NetworkManager] OnPlayerLeft ".Length, StringComparison.Ordinal) == 0)
|
||||||
|
{
|
||||||
|
var item = new[]
|
||||||
|
{
|
||||||
|
ConvertLogTimeToISO8601(s),
|
||||||
|
"OnPlayerLeft",
|
||||||
|
s.Substring(64)
|
||||||
|
};
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_GameLog.Add(item);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
position = stream.Position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static string ConvertLogTimeToISO8601(string s)
|
private static string ConvertLogTimeToISO8601(string s)
|
||||||
{
|
{
|
||||||
// 2019.07.31 22:26:24
|
// 2019.07.31 22:26:24
|
||||||
var dt = new DateTime(
|
if (!DateTime.TryParseExact(s.Substring(0, 19),
|
||||||
int.Parse(s.Substring(0, 4)),
|
"yyyy.MM.dd HH:mm:ss",
|
||||||
int.Parse(s.Substring(5, 2)),
|
CultureInfo.InvariantCulture,
|
||||||
int.Parse(s.Substring(8, 2)),
|
DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal,
|
||||||
int.Parse(s.Substring(11, 2)),
|
out DateTime dt))
|
||||||
int.Parse(s.Substring(14, 2)),
|
{
|
||||||
int.Parse(s.Substring(17, 2)),
|
dt = DateTime.UtcNow;
|
||||||
DateTimeKind.Local
|
}
|
||||||
).ToUniversalTime();
|
|
||||||
return $"{dt:yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'}";
|
return $"{dt:yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ParseLine(string line)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 2019.07.31 22:26:24 Log - [RoomManager] Joining wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd:6974~private(usr_4f76a584-9d4b-46f6-8209-8305eb683661)~nonce(0000000000000000000000000000000000000000000000000000000000000000)
|
|
||||||
// 2019.07.31 22:26:24 Log - [RoomManager] Joining or Creating Room: VRChat Home
|
|
||||||
if (string.Compare(line, 34, "[RoomManager] Joining ", 0, "[RoomManager] Joining ".Length) == 0 &&
|
|
||||||
string.Compare(line, 56, "or ", 0, "or ".Length) != 0)
|
|
||||||
{
|
|
||||||
lock (m_GameLog)
|
|
||||||
{
|
|
||||||
m_GameLog.Add(new[]
|
|
||||||
{
|
|
||||||
ConvertLogTimeToISO8601(line),
|
|
||||||
"Location",
|
|
||||||
line.Substring(56)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 2019.07.31 22:41:18 Log - [NetworkManager] OnPlayerJoined pypy
|
|
||||||
else if (string.Compare(line, 34, "[NetworkManager] OnPlayerJoined ", 0, "[NetworkManager] OnPlayerJoined ".Length) == 0)
|
|
||||||
{
|
|
||||||
lock (m_GameLog)
|
|
||||||
{
|
|
||||||
m_GameLog.Add(new[]
|
|
||||||
{
|
|
||||||
ConvertLogTimeToISO8601(line),
|
|
||||||
"OnPlayerJoined",
|
|
||||||
line.Substring(66)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 2019.07.31 22:29:31 Log - [NetworkManager] OnPlayerLeft pypy
|
|
||||||
else if (string.Compare(line, 34, "[NetworkManager] OnPlayerLeft ", 0, "[NetworkManager] OnPlayerLeft ".Length) == 0)
|
|
||||||
{
|
|
||||||
lock (m_GameLog)
|
|
||||||
{
|
|
||||||
m_GameLog.Add(new[]
|
|
||||||
{
|
|
||||||
ConvertLogTimeToISO8601(line),
|
|
||||||
"OnPlayerLeft",
|
|
||||||
line.Substring(64)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
lock (m_GameLog)
|
if (m_Thread != null)
|
||||||
{
|
{
|
||||||
m_Reset = true;
|
m_Reset = true;
|
||||||
m_GameLog.Clear();
|
|
||||||
}
|
|
||||||
m_Thread.Interrupt();
|
m_Thread.Interrupt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string[][] GetLogs()
|
public string[][] Get()
|
||||||
{
|
{
|
||||||
lock (m_GameLog)
|
m_Lock.EnterUpgradeableReadLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
if (m_Reset ||
|
||||||
|
m_GameLog.Count == 0)
|
||||||
|
{
|
||||||
|
return new string[][] { };
|
||||||
|
}
|
||||||
var array = m_GameLog.ToArray();
|
var array = m_GameLog.ToArray();
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
m_GameLog.Clear();
|
m_GameLog.Clear();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
}
|
finally
|
||||||
|
|
||||||
public bool HasLog()
|
|
||||||
{
|
{
|
||||||
lock (m_GameLog)
|
m_Lock.ExitUpgradeableReadLock();
|
||||||
{
|
|
||||||
return m_GameLog.Count > 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
-10
@@ -33,16 +33,8 @@ namespace VRCX
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.components = new System.ComponentModel.Container();
|
|
||||||
this.timer = new System.Windows.Forms.Timer(this.components);
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// timer
|
|
||||||
//
|
|
||||||
this.timer.Enabled = true;
|
|
||||||
this.timer.Interval = 1000;
|
|
||||||
this.timer.Tick += new System.EventHandler(this.timer_Tick);
|
|
||||||
//
|
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
||||||
@@ -56,7 +48,5 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.Timer timer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-6
@@ -43,7 +43,8 @@ namespace VRCX
|
|||||||
};
|
};
|
||||||
Browser.JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
Browser.JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
||||||
Browser.JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
Browser.JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
||||||
Browser.JavascriptObjectRepository.Register("LogWatcher", new VRCX_LogWatcher(), true, options);
|
Browser.JavascriptObjectRepository.Register("SQLite", new SQLite(), true, options);
|
||||||
|
Browser.JavascriptObjectRepository.Register("LogWatcher", new LogWatcher(), true, options);
|
||||||
Browser.JavascriptObjectRepository.Register("Discord", new Discord(), true, options);
|
Browser.JavascriptObjectRepository.Register("Discord", new Discord(), true, options);
|
||||||
Browser.IsBrowserInitializedChanged += (A, B) =>
|
Browser.IsBrowserInitializedChanged += (A, B) =>
|
||||||
{
|
{
|
||||||
@@ -51,10 +52,5 @@ namespace VRCX
|
|||||||
};
|
};
|
||||||
Controls.Add(Browser);
|
Controls.Add(Browser);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void timer_Tick(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
Discord.Update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,4 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>17, 17</value>
|
|
||||||
</metadata>
|
|
||||||
</root>
|
</root>
|
||||||
+10
-6
@@ -53,15 +53,19 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
CpuMonitor.Start();
|
|
||||||
VRCXStorage.Load();
|
VRCXStorage.Load();
|
||||||
VRCXVR.Setup();
|
SQLite.Init();
|
||||||
VRCX_LogWatcher.Start();
|
CpuMonitor.Init();
|
||||||
|
Discord.Init();
|
||||||
|
LogWatcher.Init();
|
||||||
|
VRCXVR.Init();
|
||||||
Application.Run(new MainForm());
|
Application.Run(new MainForm());
|
||||||
VRCX_LogWatcher.Stop();
|
VRCXVR.Exit();
|
||||||
VRCXVR.Stop();
|
LogWatcher.Exit();
|
||||||
|
Discord.Exit();
|
||||||
|
CpuMonitor.Exit();
|
||||||
|
SQLite.Exit();
|
||||||
VRCXStorage.Save();
|
VRCXStorage.Save();
|
||||||
CpuMonitor.Stop();
|
|
||||||
Cef.Shutdown();
|
Cef.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-4
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
using CefSharp;
|
using CefSharp;
|
||||||
using CefSharp.Enums;
|
using CefSharp.Enums;
|
||||||
using CefSharp.OffScreen;
|
using CefSharp.OffScreen;
|
||||||
@@ -15,26 +16,32 @@ namespace VRCX
|
|||||||
public class RenderHandler : IRenderHandler
|
public class RenderHandler : IRenderHandler
|
||||||
{
|
{
|
||||||
private ChromiumWebBrowser m_Browser;
|
private ChromiumWebBrowser m_Browser;
|
||||||
public readonly object BufferLock = new object();
|
private ReaderWriterLockSlim m_Lock;
|
||||||
public int BufferSize { get; private set; }
|
public int BufferSize { get; private set; }
|
||||||
public GCHandle Buffer { get; private set; }
|
public GCHandle Buffer { get; private set; }
|
||||||
public int Width { get; private set; }
|
public int Width { get; private set; }
|
||||||
public int Height { get; private set; }
|
public int Height { get; private set; }
|
||||||
|
|
||||||
public RenderHandler(ChromiumWebBrowser browser)
|
public RenderHandler(ChromiumWebBrowser browser, ReaderWriterLockSlim @lock)
|
||||||
{
|
{
|
||||||
m_Browser = browser;
|
m_Browser = browser;
|
||||||
|
m_Lock = @lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
lock (BufferLock)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (Buffer.IsAllocated)
|
if (Buffer.IsAllocated)
|
||||||
{
|
{
|
||||||
Buffer.Free();
|
Buffer.Free();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
m_Browser = null;
|
m_Browser = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,11 +71,15 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
if (type == PaintElementType.View)
|
if (type == PaintElementType.View)
|
||||||
{
|
{
|
||||||
lock (BufferLock)
|
m_Lock.EnterUpgradeableReadLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if (!Buffer.IsAllocated ||
|
if (!Buffer.IsAllocated ||
|
||||||
width != Width ||
|
width != Width ||
|
||||||
height != Height)
|
height != Height)
|
||||||
|
{
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = height;
|
Height = height;
|
||||||
@@ -79,8 +90,17 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
Buffer = GCHandle.Alloc(new byte[BufferSize], GCHandleType.Pinned);
|
Buffer = GCHandle.Alloc(new byte[BufferSize], GCHandleType.Pinned);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
WinApi.CopyMemory(Buffer.AddrOfPinnedObject(), buffer, (uint)BufferSize);
|
WinApi.CopyMemory(Buffer.AddrOfPinnedObject(), buffer, (uint)BufferSize);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitUpgradeableReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
using CefSharp;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SQLite;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace VRCX
|
||||||
|
{
|
||||||
|
public class SQLite
|
||||||
|
{
|
||||||
|
private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||||
|
private static SQLiteConnection m_Connection;
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
m_Connection = new SQLiteConnection($"Data Source={Application.StartupPath}/VRCX.sqlite;Version=3");
|
||||||
|
m_Connection.Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exit()
|
||||||
|
{
|
||||||
|
m_Connection.Close();
|
||||||
|
m_Connection.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(string sql, IDictionary<string, object> param = null)
|
||||||
|
{
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_Connection.State != ConnectionState.Open)
|
||||||
|
{
|
||||||
|
m_Connection.Close();
|
||||||
|
m_Connection.Open();
|
||||||
|
}
|
||||||
|
using (var C = new SQLiteCommand(sql, m_Connection))
|
||||||
|
{
|
||||||
|
if (param != null)
|
||||||
|
{
|
||||||
|
foreach (var prop in param)
|
||||||
|
{
|
||||||
|
C.Parameters.Add(new SQLiteParameter("@" + prop.Key, prop.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
C.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExecuteQuery(IJavascriptCallback callback, string sql, IDictionary<string, object> param = null)
|
||||||
|
{
|
||||||
|
m_Lock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_Connection.State != ConnectionState.Open)
|
||||||
|
{
|
||||||
|
m_Connection.Close();
|
||||||
|
m_Connection.Open();
|
||||||
|
}
|
||||||
|
using (var C = new SQLiteCommand(sql, m_Connection))
|
||||||
|
{
|
||||||
|
if (param != null)
|
||||||
|
{
|
||||||
|
foreach (var prop in param)
|
||||||
|
{
|
||||||
|
C.Parameters.Add(new SQLiteParameter("@" + prop.Key, prop.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var R = C.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (R.Read())
|
||||||
|
{
|
||||||
|
var row = new object[R.FieldCount];
|
||||||
|
R.GetValues(row);
|
||||||
|
callback.ExecuteAsync(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,12 +69,12 @@ namespace VRCX
|
|||||||
|
|
||||||
public void StartVR()
|
public void StartVR()
|
||||||
{
|
{
|
||||||
VRCXVR.Start();
|
VRCXVR.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopVR()
|
public void StopVR()
|
||||||
{
|
{
|
||||||
VRCXVR.Stop();
|
VRCXVR.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshVR()
|
public void RefreshVR()
|
||||||
|
|||||||
@@ -110,6 +110,9 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Data.SQLite, Version=1.0.111.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
|
||||||
|
<HintPath>packages\System.Data.SQLite.Core.1.0.111.0\lib\net451\System.Data.SQLite.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@@ -125,6 +128,7 @@
|
|||||||
<Compile Include="CpuMonitor.cs" />
|
<Compile Include="CpuMonitor.cs" />
|
||||||
<Compile Include="Browser.cs" />
|
<Compile Include="Browser.cs" />
|
||||||
<Compile Include="RenderHandler.cs" />
|
<Compile Include="RenderHandler.cs" />
|
||||||
|
<Compile Include="SQLite.cs" />
|
||||||
<Compile Include="VRForm.cs">
|
<Compile Include="VRForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -204,8 +208,10 @@
|
|||||||
<Error Condition="!Exists('packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets'))" />
|
<Error Condition="!Exists('packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets'))" />
|
||||||
<Error Condition="!Exists('packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.props'))" />
|
<Error Condition="!Exists('packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.props'))" />
|
||||||
<Error Condition="!Exists('packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets'))" />
|
<Error Condition="!Exists('packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets'))" />
|
||||||
|
<Error Condition="!Exists('packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
<Import Project="packages\CefSharp.Common.73.1.130\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.73.1.130\build\CefSharp.Common.targets')" />
|
<Import Project="packages\CefSharp.Common.73.1.130\build\CefSharp.Common.targets" Condition="Exists('packages\CefSharp.Common.73.1.130\build\CefSharp.Common.targets')" />
|
||||||
<Import Project="packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets')" />
|
<Import Project="packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets" Condition="Exists('packages\CefSharp.WinForms.73.1.130\build\CefSharp.WinForms.targets')" />
|
||||||
<Import Project="packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets" Condition="Exists('packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets')" />
|
<Import Project="packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets" Condition="Exists('packages\CefSharp.OffScreen.73.1.130\build\CefSharp.OffScreen.targets')" />
|
||||||
|
<Import Project="packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets" Condition="Exists('packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets')" />
|
||||||
</Project>
|
</Project>
|
||||||
+59
-16
@@ -4,71 +4,114 @@
|
|||||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace VRCX
|
namespace VRCX
|
||||||
{
|
{
|
||||||
public class VRCXStorage
|
public class VRCXStorage
|
||||||
{
|
{
|
||||||
|
private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||||
private static Dictionary<string, string> m_Storage = new Dictionary<string, string>();
|
private static Dictionary<string, string> m_Storage = new Dictionary<string, string>();
|
||||||
private static bool m_Dirty;
|
private static bool m_Dirty;
|
||||||
|
|
||||||
public static void Load()
|
public static void Load()
|
||||||
|
{
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
JsonSerializer.Deserialize(Application.StartupPath + "/VRCX.json", ref m_Storage);
|
JsonSerializer.Deserialize(Application.StartupPath + "/VRCX.json", ref m_Storage);
|
||||||
|
m_Dirty = false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Save()
|
public static void Save()
|
||||||
|
{
|
||||||
|
m_Lock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_Dirty)
|
||||||
{
|
{
|
||||||
JsonSerializer.Serialize(Application.StartupPath + "/VRCX.json", m_Storage);
|
JsonSerializer.Serialize(Application.StartupPath + "/VRCX.json", m_Storage);
|
||||||
|
m_Dirty = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void Clear()
|
finally
|
||||||
{
|
{
|
||||||
lock (m_Storage)
|
m_Lock.ExitReadLock();
|
||||||
{
|
|
||||||
m_Dirty = true;
|
|
||||||
m_Storage.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flush()
|
public void Flush()
|
||||||
{
|
{
|
||||||
lock (m_Storage)
|
|
||||||
{
|
|
||||||
if (m_Dirty)
|
|
||||||
{
|
|
||||||
m_Dirty = false;
|
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_Storage.Count > 0)
|
||||||
|
{
|
||||||
|
m_Dirty = true;
|
||||||
|
}
|
||||||
|
m_Storage.Clear();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(string key)
|
public bool Remove(string key)
|
||||||
{
|
{
|
||||||
lock (m_Storage)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = m_Storage.Remove(key);
|
||||||
|
if (result)
|
||||||
{
|
{
|
||||||
m_Dirty = true;
|
m_Dirty = true;
|
||||||
return m_Storage.Remove(key);
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Get(string key)
|
public string Get(string key)
|
||||||
{
|
{
|
||||||
lock (m_Storage)
|
m_Lock.EnterReadLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return m_Storage.TryGetValue(key, out string value)
|
return m_Storage.TryGetValue(key, out string value)
|
||||||
? value
|
? value
|
||||||
: string.Empty;
|
: string.Empty;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(string key, string value)
|
public void Set(string key, string value)
|
||||||
{
|
{
|
||||||
lock (m_Storage)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
m_Dirty = true;
|
|
||||||
m_Storage[key] = value;
|
m_Storage[key] = value;
|
||||||
|
m_Dirty = true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
public static class VRCXVR
|
public static class VRCXVR
|
||||||
{
|
{
|
||||||
private static readonly object m_LockObject = new object();
|
private static readonly ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
|
||||||
private static List<string[]> m_Devices = new List<string[]>();
|
private static List<string[]> m_Devices = new List<string[]>();
|
||||||
private static Thread m_Thread;
|
private static Thread m_Thread;
|
||||||
private static Device m_Device;
|
private static Device m_Device;
|
||||||
@@ -29,6 +29,7 @@ namespace VRCX
|
|||||||
private static Texture2D m_Texture2;
|
private static Texture2D m_Texture2;
|
||||||
private static Browser m_Browser1;
|
private static Browser m_Browser1;
|
||||||
private static Browser m_Browser2;
|
private static Browser m_Browser2;
|
||||||
|
private static bool m_Active;
|
||||||
private static float[] m_Rotation = { 0f, 0f, 0f };
|
private static float[] m_Rotation = { 0f, 0f, 0f };
|
||||||
private static float[] m_Translation = { 0f, 0f, 0f };
|
private static float[] m_Translation = { 0f, 0f, 0f };
|
||||||
private static float[] m_L_Translation = { -7f / 100f, -5f / 100f, 6f / 100f };
|
private static float[] m_L_Translation = { -7f / 100f, -5f / 100f, 6f / 100f };
|
||||||
@@ -38,7 +39,7 @@ namespace VRCX
|
|||||||
|
|
||||||
// NOTE
|
// NOTE
|
||||||
// 메모리 릭 때문에 미리 생성해놓고 계속 사용함
|
// 메모리 릭 때문에 미리 생성해놓고 계속 사용함
|
||||||
public static void Setup()
|
public static void Init()
|
||||||
{
|
{
|
||||||
m_Device = new Device(DriverType.Hardware, DeviceCreationFlags.SingleThreaded | DeviceCreationFlags.BgraSupport);
|
m_Device = new Device(DriverType.Hardware, DeviceCreationFlags.SingleThreaded | DeviceCreationFlags.BgraSupport);
|
||||||
m_Texture1 = new Texture2D(m_Device, new Texture2DDescription()
|
m_Texture1 = new Texture2D(m_Device, new Texture2DDescription()
|
||||||
@@ -67,39 +68,140 @@ namespace VRCX
|
|||||||
});
|
});
|
||||||
m_Browser1 = new Browser(m_Texture1, Application.StartupPath + "/html/vr.html?1");
|
m_Browser1 = new Browser(m_Texture1, Application.StartupPath + "/html/vr.html?1");
|
||||||
m_Browser2 = new Browser(m_Texture2, Application.StartupPath + "/html/vr.html?2");
|
m_Browser2 = new Browser(m_Texture2, Application.StartupPath + "/html/vr.html?2");
|
||||||
}
|
m_Thread = new Thread(() =>
|
||||||
|
|
||||||
public static void Start()
|
|
||||||
{
|
{
|
||||||
lock (m_LockObject)
|
var active = false;
|
||||||
|
var e = new VREvent_t();
|
||||||
|
var nextInit = DateTime.MinValue;
|
||||||
|
var nextDeviceUpdate = DateTime.MinValue;
|
||||||
|
var nextOverlay = DateTime.MinValue;
|
||||||
|
var overlayIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
||||||
|
var overlayVisible1 = false;
|
||||||
|
var overlayVisible2 = false;
|
||||||
|
var dashboardHandle = 0UL;
|
||||||
|
var overlayHandle1 = 0UL;
|
||||||
|
var overlayHandle2 = 0UL;
|
||||||
|
while (m_Thread != null)
|
||||||
{
|
{
|
||||||
if (m_Thread == null)
|
|
||||||
{
|
|
||||||
m_Thread = new Thread(ThreadProc);
|
|
||||||
m_Thread.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Stop()
|
|
||||||
{
|
|
||||||
lock (m_LockObject)
|
|
||||||
{
|
|
||||||
var thread = m_Thread;
|
|
||||||
if (thread != null)
|
|
||||||
{
|
|
||||||
m_Thread = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
thread.Interrupt();
|
Thread.Sleep(10);
|
||||||
thread.Join();
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
// ThreadInterruptedException
|
||||||
|
}
|
||||||
|
if (m_Active)
|
||||||
|
{
|
||||||
|
m_Browser1.Render();
|
||||||
|
m_Browser2.Render();
|
||||||
|
var system = OpenVR.System;
|
||||||
|
if (system == null)
|
||||||
|
{
|
||||||
|
if (DateTime.Now.CompareTo(nextInit) <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var _err = EVRInitError.None;
|
||||||
|
system = OpenVR.Init(ref _err, EVRApplicationType.VRApplication_Overlay);
|
||||||
|
nextInit = DateTime.Now.AddSeconds(5);
|
||||||
|
if (system == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
active = true;
|
||||||
|
}
|
||||||
|
while (system.PollNextEvent(ref e, (uint)Marshal.SizeOf(e)))
|
||||||
|
{
|
||||||
|
var type = (EVREventType)e.eventType;
|
||||||
|
if (type == EVREventType.VREvent_Quit)
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
OpenVR.Shutdown();
|
||||||
|
nextInit = DateTime.Now.AddSeconds(10);
|
||||||
|
system = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (system != null)
|
||||||
|
{
|
||||||
|
if (DateTime.Now.CompareTo(nextDeviceUpdate) >= 0)
|
||||||
|
{
|
||||||
|
overlayIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
||||||
|
UpdateDevices(system, ref overlayIndex);
|
||||||
|
if (overlayIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
||||||
|
{
|
||||||
|
nextOverlay = DateTime.Now.AddSeconds(10);
|
||||||
|
}
|
||||||
|
nextDeviceUpdate = DateTime.Now.AddSeconds(0.1);
|
||||||
|
}
|
||||||
|
var overlay = OpenVR.Overlay;
|
||||||
|
if (overlay != null)
|
||||||
|
{
|
||||||
|
var dashboardVisible = overlay.IsDashboardVisible();
|
||||||
|
var err = ProcessDashboard(overlay, ref dashboardHandle, dashboardVisible);
|
||||||
|
if (err != EVROverlayError.None &&
|
||||||
|
dashboardHandle != 0)
|
||||||
|
{
|
||||||
|
overlay.DestroyOverlay(dashboardHandle);
|
||||||
|
dashboardHandle = 0;
|
||||||
|
}
|
||||||
|
err = ProcessOverlay1(overlay, ref overlayHandle1, ref overlayVisible1, dashboardVisible, overlayIndex, nextOverlay);
|
||||||
|
if (err != EVROverlayError.None &&
|
||||||
|
overlayHandle1 != 0)
|
||||||
|
{
|
||||||
|
overlay.DestroyOverlay(overlayHandle1);
|
||||||
|
overlayHandle1 = 0;
|
||||||
|
}
|
||||||
|
err = ProcessOverlay2(overlay, ref overlayHandle2, ref overlayVisible2, dashboardVisible);
|
||||||
|
if (err != EVROverlayError.None &&
|
||||||
|
overlayHandle2 != 0)
|
||||||
|
{
|
||||||
|
overlay.DestroyOverlay(overlayHandle2);
|
||||||
|
overlayHandle2 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (active)
|
||||||
|
{
|
||||||
|
active = false;
|
||||||
|
OpenVR.Shutdown();
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Devices.Clear();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
IsBackground = true
|
||||||
|
};
|
||||||
|
m_Thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exit()
|
||||||
|
{
|
||||||
|
var T = m_Thread;
|
||||||
|
m_Thread = null;
|
||||||
|
T.Interrupt();
|
||||||
|
T.Join();
|
||||||
|
m_Browser2.Dispose();
|
||||||
|
m_Browser1.Dispose();
|
||||||
|
m_Texture2.Dispose();
|
||||||
|
m_Texture1.Dispose();
|
||||||
|
m_Device.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetActive(bool active)
|
||||||
|
{
|
||||||
|
m_Active = active;
|
||||||
|
}
|
||||||
|
|
||||||
public static void Refresh()
|
public static void Refresh()
|
||||||
{
|
{
|
||||||
@@ -109,17 +211,28 @@ namespace VRCX
|
|||||||
|
|
||||||
public static string[][] GetDevices()
|
public static string[][] GetDevices()
|
||||||
{
|
{
|
||||||
lock (m_Devices)
|
m_Lock.EnterReadLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return m_Devices.ToArray();
|
return m_Devices.ToArray();
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateDevices(CVRSystem system, ref uint trackingIndex)
|
private static void UpdateDevices(CVRSystem system, ref uint overlayIndex)
|
||||||
{
|
{
|
||||||
lock (m_Devices)
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
m_Devices.Clear();
|
m_Devices.Clear();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
|
}
|
||||||
var sb = new StringBuilder(256);
|
var sb = new StringBuilder(256);
|
||||||
var state = new VRControllerState_t();
|
var state = new VRControllerState_t();
|
||||||
for (var i = 0u; i < OpenVR.k_unMaxTrackedDeviceCount; ++i)
|
for (var i = 0u; i < OpenVR.k_unMaxTrackedDeviceCount; ++i)
|
||||||
@@ -158,7 +271,7 @@ namespace VRCX
|
|||||||
Array.Copy(m_R_Translation, m_Translation, 3);
|
Array.Copy(m_R_Translation, m_Translation, 3);
|
||||||
Array.Copy(m_R_Rotation, m_Rotation, 3);
|
Array.Copy(m_R_Rotation, m_Rotation, 3);
|
||||||
}
|
}
|
||||||
trackingIndex = i;
|
overlayIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var type = string.Empty;
|
var type = string.Empty;
|
||||||
@@ -181,14 +294,22 @@ namespace VRCX
|
|||||||
{
|
{
|
||||||
type = "tracker";
|
type = "tracker";
|
||||||
}
|
}
|
||||||
m_Devices.Add(new[]
|
var item = new[]
|
||||||
{
|
{
|
||||||
type,
|
type,
|
||||||
system.IsTrackedDeviceConnected(i)
|
system.IsTrackedDeviceConnected(i)
|
||||||
? "connected"
|
? "connected"
|
||||||
: "disconnected",
|
: "disconnected",
|
||||||
(batteryPercentage * 100).ToString()
|
(batteryPercentage * 100).ToString()
|
||||||
});
|
};
|
||||||
|
m_Lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Devices.Add(item);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_Lock.ExitWriteLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +388,7 @@ namespace VRCX
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EVROverlayError ProcessOverlay1(CVROverlay overlay, ref ulong overlayHandle, ref bool overlayVisible, bool dashboardVisible, uint trackingIndex, DateTime nextRender)
|
private static EVROverlayError ProcessOverlay1(CVROverlay overlay, ref ulong overlayHandle, ref bool overlayVisible, bool dashboardVisible, uint overlayIndex, DateTime nextOverlay)
|
||||||
{
|
{
|
||||||
var err = EVROverlayError.None;
|
var err = EVROverlayError.None;
|
||||||
|
|
||||||
@@ -304,7 +425,7 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackingIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
if (overlayIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
||||||
{
|
{
|
||||||
// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices
|
// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices
|
||||||
// Scaling-Rotation-Translation
|
// Scaling-Rotation-Translation
|
||||||
@@ -328,7 +449,7 @@ namespace VRCX
|
|||||||
m10 = m.M33,
|
m10 = m.M33,
|
||||||
m11 = m.M43,
|
m11 = m.M43,
|
||||||
};
|
};
|
||||||
err = overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, trackingIndex, ref hm34);
|
err = overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, overlayIndex, ref hm34);
|
||||||
if (err != EVROverlayError.None)
|
if (err != EVROverlayError.None)
|
||||||
{
|
{
|
||||||
return err;
|
return err;
|
||||||
@@ -336,7 +457,7 @@ namespace VRCX
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dashboardVisible &&
|
if (!dashboardVisible &&
|
||||||
DateTime.Now.CompareTo(nextRender) <= 0)
|
DateTime.Now.CompareTo(nextOverlay) <= 0)
|
||||||
{
|
{
|
||||||
var texture = new Texture_t
|
var texture = new Texture_t
|
||||||
{
|
{
|
||||||
@@ -462,123 +583,5 @@ namespace VRCX
|
|||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ThreadProc()
|
|
||||||
{
|
|
||||||
var e = new VREvent_t();
|
|
||||||
var nextOpenVRInit = DateTime.MinValue;
|
|
||||||
var nextDeviceInfoUpdate = DateTime.MinValue;
|
|
||||||
var nextRender = DateTime.MinValue;
|
|
||||||
var trackingIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
|
||||||
var overlayVisible1 = false;
|
|
||||||
var overlayVisible2 = false;
|
|
||||||
var dashboardHandle = 0UL;
|
|
||||||
var overlayHandle1 = 0UL;
|
|
||||||
var overlayHandle2 = 0UL;
|
|
||||||
|
|
||||||
while (m_Thread != null)
|
|
||||||
{
|
|
||||||
m_Browser1.Render();
|
|
||||||
m_Browser2.Render();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.Sleep(10);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ThreadInterruptedException
|
|
||||||
}
|
|
||||||
|
|
||||||
var system = OpenVR.System;
|
|
||||||
|
|
||||||
if (system == null)
|
|
||||||
{
|
|
||||||
if (DateTime.Now.CompareTo(nextOpenVRInit) < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var _err = EVRInitError.None;
|
|
||||||
system = OpenVR.Init(ref _err, EVRApplicationType.VRApplication_Overlay);
|
|
||||||
nextOpenVRInit = DateTime.Now.AddSeconds(5);
|
|
||||||
if (system == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (system.PollNextEvent(ref e, (uint)Marshal.SizeOf(e)))
|
|
||||||
{
|
|
||||||
var type = (EVREventType)e.eventType;
|
|
||||||
if (type == EVREventType.VREvent_Quit)
|
|
||||||
{
|
|
||||||
OpenVR.Shutdown();
|
|
||||||
// VRChat이 실행 중일 때만 켜는 옵션이 생겨서 시간을 줄임
|
|
||||||
nextOpenVRInit = DateTime.Now.AddSeconds(10);
|
|
||||||
system = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (system == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DateTime.Now.CompareTo(nextDeviceInfoUpdate) >= 0)
|
|
||||||
{
|
|
||||||
trackingIndex = OpenVR.k_unTrackedDeviceIndexInvalid;
|
|
||||||
UpdateDevices(system, ref trackingIndex);
|
|
||||||
if (trackingIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
|
|
||||||
{
|
|
||||||
nextRender = DateTime.Now.AddSeconds(10);
|
|
||||||
}
|
|
||||||
nextDeviceInfoUpdate = DateTime.Now.AddSeconds(0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var overlay = OpenVR.Overlay;
|
|
||||||
|
|
||||||
if (overlay == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dashboardVisible = overlay.IsDashboardVisible();
|
|
||||||
|
|
||||||
var err = ProcessDashboard(overlay, ref dashboardHandle, dashboardVisible);
|
|
||||||
|
|
||||||
if (err != EVROverlayError.None &&
|
|
||||||
dashboardHandle != 0)
|
|
||||||
{
|
|
||||||
overlay.DestroyOverlay(dashboardHandle);
|
|
||||||
dashboardHandle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ProcessOverlay1(overlay, ref overlayHandle1, ref overlayVisible1, dashboardVisible, trackingIndex, nextRender);
|
|
||||||
|
|
||||||
if (err != EVROverlayError.None &&
|
|
||||||
overlayHandle1 != 0)
|
|
||||||
{
|
|
||||||
overlay.DestroyOverlay(overlayHandle1);
|
|
||||||
overlayHandle1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ProcessOverlay2(overlay, ref overlayHandle2, ref overlayVisible2, dashboardVisible);
|
|
||||||
|
|
||||||
if (err != EVROverlayError.None &&
|
|
||||||
overlayHandle2 != 0)
|
|
||||||
{
|
|
||||||
overlay.DestroyOverlay(overlayHandle2);
|
|
||||||
overlayHandle2 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (m_Devices)
|
|
||||||
{
|
|
||||||
m_Devices.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenVR.Shutdown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,8 +44,10 @@ namespace VRCX
|
|||||||
};
|
};
|
||||||
Browser1.JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
Browser1.JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
||||||
Browser1.JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
Browser1.JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
||||||
|
Browser1.JavascriptObjectRepository.Register("SQLite", new SQLite(), true, options);
|
||||||
Browser2.JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
Browser2.JavascriptObjectRepository.Register("VRCX", new VRCX(), true, options);
|
||||||
Browser2.JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
Browser2.JavascriptObjectRepository.Register("VRCXStorage", new VRCXStorage(), false, options);
|
||||||
|
Browser2.JavascriptObjectRepository.Register("SQLite", new SQLite(), true, options);
|
||||||
Browser1.IsBrowserInitializedChanged += (A, B) =>
|
Browser1.IsBrowserInitializedChanged += (A, B) =>
|
||||||
{
|
{
|
||||||
// Browser1.ShowDevTools();
|
// Browser1.ShowDevTools();
|
||||||
@@ -60,9 +62,9 @@ namespace VRCX
|
|||||||
|
|
||||||
private void button_refresh_Click(object sender, System.EventArgs e)
|
private void button_refresh_Click(object sender, System.EventArgs e)
|
||||||
{
|
{
|
||||||
VRCXVR.Refresh();
|
|
||||||
Browser1.ExecuteScriptAsync("location.reload()");
|
Browser1.ExecuteScriptAsync("location.reload()");
|
||||||
Browser2.ExecuteScriptAsync("location.reload()");
|
Browser2.ExecuteScriptAsync("location.reload()");
|
||||||
|
VRCXVR.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void button_devtools_Click(object sender, System.EventArgs e)
|
private void button_devtools_Click(object sender, System.EventArgs e)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ module.exports = {
|
|||||||
'CefSharp': 'readonly',
|
'CefSharp': 'readonly',
|
||||||
'VRCX': 'readonly',
|
'VRCX': 'readonly',
|
||||||
'VRCXStorage': 'readonly',
|
'VRCXStorage': 'readonly',
|
||||||
|
'SQLite': 'readonly',
|
||||||
'LogWatcher': 'readonly',
|
'LogWatcher': 'readonly',
|
||||||
'Discord': 'readonly',
|
'Discord': 'readonly',
|
||||||
'Noty': 'readonly',
|
'Noty': 'readonly',
|
||||||
|
|||||||
+6
-7
@@ -7,6 +7,7 @@ if (window.CefSharp) {
|
|||||||
Promise.all([
|
Promise.all([
|
||||||
CefSharp.BindObjectAsync('VRCX'),
|
CefSharp.BindObjectAsync('VRCX'),
|
||||||
CefSharp.BindObjectAsync('VRCXStorage'),
|
CefSharp.BindObjectAsync('VRCXStorage'),
|
||||||
|
CefSharp.BindObjectAsync('SQLite'),
|
||||||
CefSharp.BindObjectAsync('LogWatcher'),
|
CefSharp.BindObjectAsync('LogWatcher'),
|
||||||
CefSharp.BindObjectAsync('Discord')
|
CefSharp.BindObjectAsync('Discord')
|
||||||
]).catch(() => {
|
]).catch(() => {
|
||||||
@@ -3490,6 +3491,8 @@ if (window.CefSharp) {
|
|||||||
var ref;
|
var ref;
|
||||||
var i;
|
var i;
|
||||||
var j;
|
var j;
|
||||||
|
// FIXME
|
||||||
|
// 여러 개 켠다면 gameLogTable의 데이터가 시간순이 아닐 수도 있음
|
||||||
i = this.gameLogTable.data.length;
|
i = this.gameLogTable.data.length;
|
||||||
j = 0;
|
j = 0;
|
||||||
while (j < 25) {
|
while (j < 25) {
|
||||||
@@ -4460,9 +4463,8 @@ if (window.CefSharp) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$app.methods.refreshGameLog = function () {
|
$app.methods.refreshGameLog = function () {
|
||||||
LogWatcher.HasLog().then((result) => {
|
LogWatcher.Get().then((logs) => {
|
||||||
if (result) {
|
if (logs.length) {
|
||||||
LogWatcher.GetLogs().then((logs) => {
|
|
||||||
logs.forEach((log) => {
|
logs.forEach((log) => {
|
||||||
var ctx = {
|
var ctx = {
|
||||||
created_at: log[0],
|
created_at: log[0],
|
||||||
@@ -4475,16 +4477,13 @@ if (window.CefSharp) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.sweepGameLog();
|
this.sweepGameLog();
|
||||||
this.updateSharedFeed();
|
|
||||||
// sweepGameLog로 기록이 삭제되면
|
// sweepGameLog로 기록이 삭제되면
|
||||||
// 아무 것도 없는데 알림이 떠서 이상함
|
// 아무 것도 없는데 알림이 떠서 이상함
|
||||||
if (this.gameLogTable.length) {
|
if (this.gameLogTable.length) {
|
||||||
this.notifyMenu('gameLog');
|
this.notifyMenu('gameLog');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.updateSharedFeed();
|
|
||||||
}
|
}
|
||||||
|
this.updateSharedFeed();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -6,7 +6,8 @@
|
|||||||
if (window.CefSharp) {
|
if (window.CefSharp) {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
CefSharp.BindObjectAsync('VRCX'),
|
CefSharp.BindObjectAsync('VRCX'),
|
||||||
CefSharp.BindObjectAsync('VRCXStorage')
|
CefSharp.BindObjectAsync('VRCXStorage'),
|
||||||
|
CefSharp.BindObjectAsync('SQLite')
|
||||||
]).catch(() => {
|
]).catch(() => {
|
||||||
location = 'https://github.com/pypy-vrc/vrcx';
|
location = 'https://github.com/pypy-vrc/vrcx';
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
|||||||
@@ -14,4 +14,5 @@
|
|||||||
<package id="SharpDX.Direct3D11" version="4.2.0" targetFramework="net452" />
|
<package id="SharpDX.Direct3D11" version="4.2.0" targetFramework="net452" />
|
||||||
<package id="SharpDX.DXGI" version="4.2.0" targetFramework="net452" />
|
<package id="SharpDX.DXGI" version="4.2.0" targetFramework="net452" />
|
||||||
<package id="SharpDX.Mathematics" version="4.2.0" targetFramework="net452" />
|
<package id="SharpDX.Mathematics" version="4.2.0" targetFramework="net452" />
|
||||||
|
<package id="System.Data.SQLite.Core" version="1.0.111.0" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
||||||
Reference in New Issue
Block a user