diff --git a/LICENSE b/LICENSE
index 63218ce..3afd917 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2018 Nielk1
+Copyright (c) 2018 John Klein
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/VSCView.sln b/VSCView.sln
new file mode 100644
index 0000000..859fad9
--- /dev/null
+++ b/VSCView.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.16
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSCView", "VSCView\VSCView.csproj", "{E513702D-EF79-4766-AD9D-C2382BD0CEAD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E513702D-EF79-4766-AD9D-C2382BD0CEAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E513702D-EF79-4766-AD9D-C2382BD0CEAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E513702D-EF79-4766-AD9D-C2382BD0CEAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E513702D-EF79-4766-AD9D-C2382BD0CEAD}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DC3B117E-47DB-4553-8101-4ECBC70B1A48}
+ EndGlobalSection
+EndGlobal
diff --git a/VSCView/About.Designer.cs b/VSCView/About.Designer.cs
new file mode 100644
index 0000000..48083e2
--- /dev/null
+++ b/VSCView/About.Designer.cs
@@ -0,0 +1,334 @@
+namespace VSCView
+{
+ partial class About
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(About));
+ this.okButton = new System.Windows.Forms.Button();
+ this.logoPictureBox = new System.Windows.Forms.PictureBox();
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this.labelProductName = new System.Windows.Forms.Label();
+ this.labelVersion = new System.Windows.Forms.Label();
+ this.textBoxDescription = new System.Windows.Forms.TextBox();
+ this.labelCompanyName = new System.Windows.Forms.Label();
+ this.labelCopyright = new System.Windows.Forms.Label();
+ this.tabControl1 = new System.Windows.Forms.TabControl();
+ this.tabPage1 = new System.Windows.Forms.TabPage();
+ this.tabPage2 = new System.Windows.Forms.TabPage();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.tabPage3 = new System.Windows.Forms.TabPage();
+ this.textBox2 = new System.Windows.Forms.TextBox();
+ this.tabPage4 = new System.Windows.Forms.TabPage();
+ this.textBox3 = new System.Windows.Forms.TextBox();
+ ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
+ this.tableLayoutPanel1.SuspendLayout();
+ this.tabControl1.SuspendLayout();
+ this.tabPage1.SuspendLayout();
+ this.tabPage2.SuspendLayout();
+ this.tabPage3.SuspendLayout();
+ this.tabPage4.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // okButton
+ //
+ this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.okButton.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(54)))), ((int)(((byte)(54)))), ((int)(((byte)(54)))));
+ this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.okButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.okButton.Location = new System.Drawing.Point(12, 146);
+ this.okButton.Name = "okButton";
+ this.okButton.Size = new System.Drawing.Size(128, 31);
+ this.okButton.TabIndex = 32;
+ this.okButton.Text = "&OK";
+ //
+ // logoPictureBox
+ //
+ this.logoPictureBox.Image = global::VSCView.Properties.Resources.Nielk1_eyes_128;
+ this.logoPictureBox.Location = new System.Drawing.Point(12, 12);
+ this.logoPictureBox.Name = "logoPictureBox";
+ this.logoPictureBox.Size = new System.Drawing.Size(128, 128);
+ this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.logoPictureBox.TabIndex = 31;
+ this.logoPictureBox.TabStop = false;
+ //
+ // tableLayoutPanel1
+ //
+ this.tableLayoutPanel1.ColumnCount = 1;
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tableLayoutPanel1.Controls.Add(this.labelProductName, 0, 0);
+ this.tableLayoutPanel1.Controls.Add(this.labelVersion, 0, 1);
+ this.tableLayoutPanel1.Controls.Add(this.textBoxDescription, 0, 4);
+ this.tableLayoutPanel1.Controls.Add(this.labelCompanyName, 0, 3);
+ this.tableLayoutPanel1.Controls.Add(this.labelCopyright, 0, 2);
+ this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ this.tableLayoutPanel1.RowCount = 5;
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(572, 136);
+ this.tableLayoutPanel1.TabIndex = 33;
+ //
+ // labelProductName
+ //
+ this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelProductName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.labelProductName.Location = new System.Drawing.Point(0, 0);
+ this.labelProductName.Margin = new System.Windows.Forms.Padding(0);
+ this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelProductName.Name = "labelProductName";
+ this.labelProductName.Size = new System.Drawing.Size(572, 17);
+ this.labelProductName.TabIndex = 19;
+ this.labelProductName.Text = "Product Name";
+ this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelVersion
+ //
+ this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelVersion.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.labelVersion.Location = new System.Drawing.Point(0, 20);
+ this.labelVersion.Margin = new System.Windows.Forms.Padding(0);
+ this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelVersion.Name = "labelVersion";
+ this.labelVersion.Size = new System.Drawing.Size(572, 17);
+ this.labelVersion.TabIndex = 0;
+ this.labelVersion.Text = "Version";
+ this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // textBoxDescription
+ //
+ this.textBoxDescription.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(22)))), ((int)(((byte)(22)))), ((int)(((byte)(22)))));
+ this.textBoxDescription.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBoxDescription.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.textBoxDescription.Location = new System.Drawing.Point(0, 80);
+ this.textBoxDescription.Margin = new System.Windows.Forms.Padding(0);
+ this.textBoxDescription.Multiline = true;
+ this.textBoxDescription.Name = "textBoxDescription";
+ this.textBoxDescription.ReadOnly = true;
+ this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBoxDescription.Size = new System.Drawing.Size(572, 56);
+ this.textBoxDescription.TabIndex = 23;
+ this.textBoxDescription.TabStop = false;
+ this.textBoxDescription.Text = "Description";
+ //
+ // labelCompanyName
+ //
+ this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelCompanyName.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.labelCompanyName.Location = new System.Drawing.Point(0, 60);
+ this.labelCompanyName.Margin = new System.Windows.Forms.Padding(0);
+ this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelCompanyName.Name = "labelCompanyName";
+ this.labelCompanyName.Size = new System.Drawing.Size(572, 17);
+ this.labelCompanyName.TabIndex = 22;
+ this.labelCompanyName.Text = "Company Name";
+ this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelCopyright
+ //
+ this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelCopyright.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.labelCopyright.Location = new System.Drawing.Point(0, 40);
+ this.labelCopyright.Margin = new System.Windows.Forms.Padding(0);
+ this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelCopyright.Name = "labelCopyright";
+ this.labelCopyright.Size = new System.Drawing.Size(572, 17);
+ this.labelCopyright.TabIndex = 21;
+ this.labelCopyright.Text = "Copyright";
+ this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // tabControl1
+ //
+ this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tabControl1.Appearance = System.Windows.Forms.TabAppearance.FlatButtons;
+ this.tabControl1.Controls.Add(this.tabPage1);
+ this.tabControl1.Controls.Add(this.tabPage2);
+ this.tabControl1.Controls.Add(this.tabPage3);
+ this.tabControl1.Controls.Add(this.tabPage4);
+ this.tabControl1.Location = new System.Drawing.Point(146, 12);
+ this.tabControl1.Multiline = true;
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.Padding = new System.Drawing.Point(0, 0);
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size(580, 165);
+ this.tabControl1.TabIndex = 35;
+ //
+ // tabPage1
+ //
+ this.tabPage1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37)))));
+ this.tabPage1.Controls.Add(this.tableLayoutPanel1);
+ this.tabPage1.Location = new System.Drawing.Point(4, 25);
+ this.tabPage1.Margin = new System.Windows.Forms.Padding(0);
+ this.tabPage1.Name = "tabPage1";
+ this.tabPage1.Size = new System.Drawing.Size(572, 136);
+ this.tabPage1.TabIndex = 0;
+ this.tabPage1.Text = "VSCView";
+ //
+ // tabPage2
+ //
+ this.tabPage2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37)))));
+ this.tabPage2.Controls.Add(this.textBox1);
+ this.tabPage2.Location = new System.Drawing.Point(4, 25);
+ this.tabPage2.Margin = new System.Windows.Forms.Padding(0);
+ this.tabPage2.Name = "tabPage2";
+ this.tabPage2.Size = new System.Drawing.Size(422, 136);
+ this.tabPage2.TabIndex = 1;
+ this.tabPage2.Text = "VSCView License";
+ //
+ // textBox1
+ //
+ this.textBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(22)))), ((int)(((byte)(22)))), ((int)(((byte)(22)))));
+ this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBox1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.textBox1.Location = new System.Drawing.Point(0, 0);
+ this.textBox1.Margin = new System.Windows.Forms.Padding(0);
+ this.textBox1.Multiline = true;
+ this.textBox1.Name = "textBox1";
+ this.textBox1.ReadOnly = true;
+ this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBox1.Size = new System.Drawing.Size(422, 136);
+ this.textBox1.TabIndex = 35;
+ this.textBox1.TabStop = false;
+ this.textBox1.Text = resources.GetString("textBox1.Text");
+ //
+ // tabPage3
+ //
+ this.tabPage3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37)))));
+ this.tabPage3.Controls.Add(this.textBox2);
+ this.tabPage3.Location = new System.Drawing.Point(4, 25);
+ this.tabPage3.Margin = new System.Windows.Forms.Padding(0);
+ this.tabPage3.Name = "tabPage3";
+ this.tabPage3.Size = new System.Drawing.Size(422, 136);
+ this.tabPage3.TabIndex = 2;
+ this.tabPage3.Text = "HidLibrary License";
+ //
+ // textBox2
+ //
+ this.textBox2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(22)))), ((int)(((byte)(22)))), ((int)(((byte)(22)))));
+ this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.textBox2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBox2.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.textBox2.Location = new System.Drawing.Point(0, 0);
+ this.textBox2.Margin = new System.Windows.Forms.Padding(0);
+ this.textBox2.Multiline = true;
+ this.textBox2.Name = "textBox2";
+ this.textBox2.ReadOnly = true;
+ this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBox2.Size = new System.Drawing.Size(422, 136);
+ this.textBox2.TabIndex = 36;
+ this.textBox2.TabStop = false;
+ this.textBox2.Text = resources.GetString("textBox2.Text");
+ //
+ // tabPage4
+ //
+ this.tabPage4.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37)))));
+ this.tabPage4.Controls.Add(this.textBox3);
+ this.tabPage4.Location = new System.Drawing.Point(4, 25);
+ this.tabPage4.Margin = new System.Windows.Forms.Padding(0);
+ this.tabPage4.Name = "tabPage4";
+ this.tabPage4.Size = new System.Drawing.Size(422, 136);
+ this.tabPage4.TabIndex = 3;
+ this.tabPage4.Text = "Newtonsoft.Json License";
+ //
+ // textBox3
+ //
+ this.textBox3.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(22)))), ((int)(((byte)(22)))), ((int)(((byte)(22)))));
+ this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.textBox3.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBox3.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(204)))), ((int)(((byte)(204)))));
+ this.textBox3.Location = new System.Drawing.Point(0, 0);
+ this.textBox3.Margin = new System.Windows.Forms.Padding(0);
+ this.textBox3.Multiline = true;
+ this.textBox3.Name = "textBox3";
+ this.textBox3.ReadOnly = true;
+ this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBox3.Size = new System.Drawing.Size(422, 136);
+ this.textBox3.TabIndex = 37;
+ this.textBox3.TabStop = false;
+ this.textBox3.Text = resources.GetString("textBox3.Text");
+ //
+ // About
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(37)))), ((int)(((byte)(37)))), ((int)(((byte)(37)))));
+ this.ClientSize = new System.Drawing.Size(738, 188);
+ this.Controls.Add(this.tabControl1);
+ this.Controls.Add(this.logoPictureBox);
+ this.Controls.Add(this.okButton);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "About";
+ this.Padding = new System.Windows.Forms.Padding(9);
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "About";
+ ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
+ this.tableLayoutPanel1.ResumeLayout(false);
+ this.tableLayoutPanel1.PerformLayout();
+ this.tabControl1.ResumeLayout(false);
+ this.tabPage1.ResumeLayout(false);
+ this.tabPage2.ResumeLayout(false);
+ this.tabPage2.PerformLayout();
+ this.tabPage3.ResumeLayout(false);
+ this.tabPage3.PerformLayout();
+ this.tabPage4.ResumeLayout(false);
+ this.tabPage4.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button okButton;
+ private System.Windows.Forms.PictureBox logoPictureBox;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.Label labelProductName;
+ private System.Windows.Forms.Label labelVersion;
+ private System.Windows.Forms.TextBox textBoxDescription;
+ private System.Windows.Forms.Label labelCompanyName;
+ private System.Windows.Forms.Label labelCopyright;
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage tabPage1;
+ private System.Windows.Forms.TabPage tabPage2;
+ private System.Windows.Forms.TextBox textBox1;
+ private System.Windows.Forms.TabPage tabPage3;
+ private System.Windows.Forms.TextBox textBox2;
+ private System.Windows.Forms.TabPage tabPage4;
+ private System.Windows.Forms.TextBox textBox3;
+ }
+}
diff --git a/VSCView/About.cs b/VSCView/About.cs
new file mode 100644
index 0000000..720e4d8
--- /dev/null
+++ b/VSCView/About.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VSCView
+{
+ partial class About : Form
+ {
+ public About()
+ {
+ InitializeComponent();
+ this.Text = String.Format("About {0}", AssemblyTitle);
+ this.labelProductName.Text = AssemblyProduct;
+ this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
+ this.labelCopyright.Text = AssemblyCopyright;
+ this.labelCompanyName.Text = AssemblyCompany;
+ this.textBoxDescription.Text = AssemblyDescription;
+ }
+
+ #region Assembly Attribute Accessors
+
+ public string AssemblyTitle
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+ if (attributes.Length > 0)
+ {
+ AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
+ if (titleAttribute.Title != "")
+ {
+ return titleAttribute.Title;
+ }
+ }
+ return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
+ }
+ }
+
+ public string AssemblyVersion
+ {
+ get
+ {
+ return Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ }
+ }
+
+ public string AssemblyDescription
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyDescriptionAttribute)attributes[0]).Description;
+ }
+ }
+
+ public string AssemblyProduct
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyProductAttribute)attributes[0]).Product;
+ }
+ }
+
+ public string AssemblyCopyright
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+ }
+ }
+
+ public string AssemblyCompany
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyCompanyAttribute)attributes[0]).Company;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/VSCView/About.resx b/VSCView/About.resx
new file mode 100644
index 0000000..a7bc4a0
--- /dev/null
+++ b/VSCView/About.resx
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ MIT License
+
+Copyright (c) 2018 John Klein
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
+ Copyright (c) 2010 Ultraviolet Catastrophe
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+ The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
\ No newline at end of file
diff --git a/VSCView/App.config b/VSCView/App.config
new file mode 100644
index 0000000..b50c74f
--- /dev/null
+++ b/VSCView/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VSCView/MainForm.Designer.cs b/VSCView/MainForm.Designer.cs
new file mode 100644
index 0000000..a6c878e
--- /dev/null
+++ b/VSCView/MainForm.Designer.cs
@@ -0,0 +1,194 @@
+namespace VSCView
+{
+ partial class MainForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.tmrPaint = new System.Windows.Forms.Timer(this.components);
+ this.cmsMain = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.tsmiTheme = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiController = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this.tsmiReloadThemes = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiReloadControllers = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+ this.tsmiAbout = new System.Windows.Forms.ToolStripMenuItem();
+ this.tsmiExit = new System.Windows.Forms.ToolStripMenuItem();
+ this.lblHint1 = new System.Windows.Forms.Label();
+ this.lblHint2 = new System.Windows.Forms.Label();
+ this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
+ this.tsmiSetBackgroundColor = new System.Windows.Forms.ToolStripMenuItem();
+ this.colorDialog1 = new System.Windows.Forms.ColorDialog();
+ this.cmsMain.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // tmrPaint
+ //
+ this.tmrPaint.Enabled = true;
+ this.tmrPaint.Interval = 15;
+ this.tmrPaint.Tick += new System.EventHandler(this.tmrPaint_Tick);
+ //
+ // cmsMain
+ //
+ this.cmsMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.tsmiTheme,
+ this.tsmiController,
+ this.toolStripSeparator1,
+ this.tsmiReloadThemes,
+ this.tsmiReloadControllers,
+ this.toolStripSeparator2,
+ this.tsmiSetBackgroundColor,
+ this.tsmiAbout,
+ this.toolStripSeparator3,
+ this.tsmiExit});
+ this.cmsMain.Name = "cmsMain";
+ this.cmsMain.Size = new System.Drawing.Size(190, 176);
+ //
+ // tsmiTheme
+ //
+ this.tsmiTheme.Name = "tsmiTheme";
+ this.tsmiTheme.Size = new System.Drawing.Size(189, 22);
+ this.tsmiTheme.Text = "&Theme";
+ //
+ // tsmiController
+ //
+ this.tsmiController.Name = "tsmiController";
+ this.tsmiController.Size = new System.Drawing.Size(189, 22);
+ this.tsmiController.Text = "&Controller";
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(186, 6);
+ //
+ // tsmiReloadThemes
+ //
+ this.tsmiReloadThemes.Name = "tsmiReloadThemes";
+ this.tsmiReloadThemes.Size = new System.Drawing.Size(189, 22);
+ this.tsmiReloadThemes.Text = "Reload Themes";
+ this.tsmiReloadThemes.Click += new System.EventHandler(this.tsmiReloadThemes_Click);
+ //
+ // tsmiReloadControllers
+ //
+ this.tsmiReloadControllers.Name = "tsmiReloadControllers";
+ this.tsmiReloadControllers.Size = new System.Drawing.Size(189, 22);
+ this.tsmiReloadControllers.Text = "Reload Controllers";
+ this.tsmiReloadControllers.Click += new System.EventHandler(this.tsmiReloadControllers_Click);
+ //
+ // toolStripSeparator2
+ //
+ this.toolStripSeparator2.Name = "toolStripSeparator2";
+ this.toolStripSeparator2.Size = new System.Drawing.Size(186, 6);
+ //
+ // tsmiAbout
+ //
+ this.tsmiAbout.Name = "tsmiAbout";
+ this.tsmiAbout.Size = new System.Drawing.Size(189, 22);
+ this.tsmiAbout.Text = "&About";
+ this.tsmiAbout.Click += new System.EventHandler(this.tsmiAbout_Click);
+ //
+ // tsmiExit
+ //
+ this.tsmiExit.Name = "tsmiExit";
+ this.tsmiExit.Size = new System.Drawing.Size(189, 22);
+ this.tsmiExit.Text = "E&xit";
+ this.tsmiExit.Click += new System.EventHandler(this.tsmiExit_Click);
+ //
+ // lblHint1
+ //
+ this.lblHint1.AutoSize = true;
+ this.lblHint1.Location = new System.Drawing.Point(87, 77);
+ this.lblHint1.Name = "lblHint1";
+ this.lblHint1.Size = new System.Drawing.Size(142, 13);
+ this.lblHint1.TabIndex = 1;
+ this.lblHint1.Text = "Right Click for Context Menu";
+ //
+ // lblHint2
+ //
+ this.lblHint2.AutoSize = true;
+ this.lblHint2.Location = new System.Drawing.Point(87, 109);
+ this.lblHint2.Name = "lblHint2";
+ this.lblHint2.Size = new System.Drawing.Size(119, 13);
+ this.lblHint2.TabIndex = 2;
+ this.lblHint2.Text = "Click and Drag to Move";
+ //
+ // toolStripSeparator3
+ //
+ this.toolStripSeparator3.Name = "toolStripSeparator3";
+ this.toolStripSeparator3.Size = new System.Drawing.Size(186, 6);
+ //
+ // tsmiSetBackgroundColor
+ //
+ this.tsmiSetBackgroundColor.Name = "tsmiSetBackgroundColor";
+ this.tsmiSetBackgroundColor.Size = new System.Drawing.Size(189, 22);
+ this.tsmiSetBackgroundColor.Text = "Set Background Color";
+ this.tsmiSetBackgroundColor.Click += new System.EventHandler(this.tsmiSetBackgroundColor_Click);
+ //
+ // colorDialog1
+ //
+ this.colorDialog1.Color = System.Drawing.Color.Lime;
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.Lime;
+ this.ClientSize = new System.Drawing.Size(314, 264);
+ this.ContextMenuStrip = this.cmsMain;
+ this.Controls.Add(this.lblHint2);
+ this.Controls.Add(this.lblHint1);
+ this.DoubleBuffered = true;
+ this.Name = "MainForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+ this.Text = "VSCView";
+ this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseDown);
+ this.cmsMain.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Timer tmrPaint;
+ private System.Windows.Forms.ContextMenuStrip cmsMain;
+ private System.Windows.Forms.ToolStripMenuItem tsmiTheme;
+ private System.Windows.Forms.ToolStripMenuItem tsmiController;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripMenuItem tsmiExit;
+ private System.Windows.Forms.ToolStripMenuItem tsmiReloadThemes;
+ private System.Windows.Forms.ToolStripMenuItem tsmiReloadControllers;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+ private System.Windows.Forms.ToolStripMenuItem tsmiAbout;
+ private System.Windows.Forms.Label lblHint1;
+ private System.Windows.Forms.Label lblHint2;
+ private System.Windows.Forms.ToolStripMenuItem tsmiSetBackgroundColor;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
+ private System.Windows.Forms.ColorDialog colorDialog1;
+ }
+}
\ No newline at end of file
diff --git a/VSCView/MainForm.cs b/VSCView/MainForm.cs
new file mode 100644
index 0000000..362a8d8
--- /dev/null
+++ b/VSCView/MainForm.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VSCView
+{
+ public partial class MainForm : Form
+ {
+ //SteamController[] Controllers;
+ //SteamController.SteamControllerState State;
+
+ ControllerData ControllerData;
+ SteamController ActiveController;
+
+ //short AngularVelocityXMax = 5000;
+ //short AngularVelocityYMax = 5000;
+ //short AngularVelocityZMax = 5000;
+
+ UI ui;
+
+ public MainForm()
+ {
+ this.FormBorderStyle = FormBorderStyle.None;
+ InitializeComponent();
+
+ ControllerData = new ControllerData();
+ //ActiveController.SetController(Controllers[0]);
+
+ //ui = new UI(ActiveController, "default",);
+
+ //this.Width = ui.Width;
+ //this.Height = ui.Height;
+
+ //Controllers = SteamController.GetControllers();
+ //ActiveController.SetController(Controllers[0]);
+ //if (Controllers.Length > 0) Controllers[0].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 0);
+ //if (Controllers.Length > 1) Controllers[1].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 1);
+ //if (Controllers.Length > 2) Controllers[2].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 2);
+ //if (Controllers.Length > 3) Controllers[3].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 3);
+
+ LoadThemes();
+ LoadControllers();
+ }
+
+ private void LoadThemes()
+ {
+ tsmiTheme.DropDownItems.Clear();
+
+ if (!Directory.Exists("themes")) Directory.CreateDirectory("themes");
+ string[] themeParents = Directory.GetDirectories("themes");
+
+ foreach (string themeParent in themeParents)
+ {
+ string ThemeName = Path.GetFileName(themeParent);
+
+ string[] themeFiles = Directory.GetFiles(themeParent, "*.json", SearchOption.TopDirectoryOnly);
+ foreach (string themeFile in themeFiles)
+ {
+ string ThemeFileName = Path.GetFileNameWithoutExtension(themeFile);
+
+ string DisplayName = ThemeName + "/" + ThemeFileName;
+
+ ToolStripItem itm = tsmiTheme.DropDownItems.Add(DisplayName, null, LoadTheme);
+ }
+ }
+ }
+
+ private void LoadControllers()
+ {
+ tsmiController.DropDownItems.Clear();
+
+ SteamController[] Controllers = SteamController.GetControllers();
+
+ foreach (SteamController controller in Controllers)
+ {
+ ToolStripItem itm = tsmiController.DropDownItems.Add(controller.GetDevicePath(), null, LoadController);
+ itm.Tag = controller;
+ }
+ }
+
+ private void LoadController(object sender, EventArgs e)
+ {
+ if (ActiveController != null)
+ {
+ ActiveController.DeInitalize();
+ }
+
+ ToolStripItem item = (ToolStripItem)sender;
+ ActiveController = (SteamController)item.Tag;
+
+ ControllerData.SetController(ActiveController);
+ ActiveController.Initalize();
+ }
+
+ private void LoadTheme(object sender, EventArgs e)
+ {
+ lblHint1.Hide();
+ lblHint2.Hide();
+
+ ToolStripItem item = (ToolStripItem)sender;
+ string displayText = item.Text;
+
+ string[] displayTextParts = displayText.Split(new string[] { "/" }, 2, StringSplitOptions.None);
+
+ string skinJson = File.ReadAllText(Path.Combine("themes", displayTextParts[0], displayTextParts[1] + @".json"));
+
+ ui = new UI(ControllerData, displayTextParts[0], skinJson);
+ this.Width = ui.Width;
+ this.Height = ui.Height;
+ }
+
+ #region Drag Anywhere
+ public const int WM_NCLBUTTONDOWN = 0xA1;
+ public const int HT_CAPTION = 0x2;
+
+ [System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
+ public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+ [System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
+ public static extern bool ReleaseCapture();
+
+ private void MainForm_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Left)
+ {
+ ReleaseCapture();
+ SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
+ }
+ }
+ #endregion Drag Anywhere
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ //DateTime now = DateTime.UtcNow;
+
+ // Call the OnPaint method of the base class.
+ base.OnPaint(e);
+
+ ui?.Paint(e.Graphics);
+
+ //Console.WriteLine((DateTime.UtcNow - now).TotalMilliseconds);
+ }
+
+ private void tmrPaint_Tick(object sender, EventArgs e)
+ {
+ this.Invalidate(); // we can invalidate specific zones
+ this.Update();
+ }
+
+ private void tsmiExit_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void tsmiReloadThemes_Click(object sender, EventArgs e)
+ {
+ LoadThemes();
+ }
+
+ private void tsmiReloadControllers_Click(object sender, EventArgs e)
+ {
+ LoadControllers();
+ }
+
+ private void tsmiAbout_Click(object sender, EventArgs e)
+ {
+ new About().ShowDialog();
+ }
+
+ private void tsmiSetBackgroundColor_Click(object sender, EventArgs e)
+ {
+ if(colorDialog1.ShowDialog() == DialogResult.OK)
+ {
+ this.BackColor = colorDialog1.Color;
+ }
+ }
+ }
+}
diff --git a/VSCView/MainForm.resx b/VSCView/MainForm.resx
new file mode 100644
index 0000000..411f443
--- /dev/null
+++ b/VSCView/MainForm.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 115, 17
+
+
+ 215, 17
+
+
\ No newline at end of file
diff --git a/VSCView/OSD.cs b/VSCView/OSD.cs
new file mode 100644
index 0000000..e2f738c
--- /dev/null
+++ b/VSCView/OSD.cs
@@ -0,0 +1,946 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace VSCView
+{
+ public class UI
+ {
+ public int Height { get; private set; }
+ public int Width { get; private set; }
+
+ private UI_ImageCache cache;
+ private ControllerData data;
+ private List Items;
+
+ public UI(ControllerData data, string themePath, string json)
+ {
+ JObject themeData = JObject.Parse(json);
+ Initalize(data, themePath, themeData);
+ }
+
+ public UI(ControllerData data, string themePath, JObject themeData)
+ {
+ Initalize(data, themePath, themeData);
+ }
+
+ private void Initalize(ControllerData data, string themePath, JObject themeData)
+ {
+ this.data = data;
+ cache = new UI_ImageCache(themePath);
+ Items = new List();
+
+ Height = themeData["height"]?.Value() ?? 100;
+ Width = themeData["width"]?.Value() ?? 100;
+
+ themeData["children"]?.ToList().ForEach(child =>
+ {
+ string uiType = child["type"]?.Value() ?? "";
+
+ switch (uiType)
+ {
+ case "":
+ Items.Add(new UI_Item(data, cache, themePath, (JObject)child));
+ break;
+ case "image":
+ Items.Add(new UI_GraphicalItem(data, cache, themePath, (JObject)child));
+ break;
+ case "showhide":
+ Items.Add(new UL_ShowHide(data, cache, themePath, (JObject)child));
+ break;
+ case "slider":
+ Items.Add(new UL_Slider(data, cache, themePath, (JObject)child));
+ break;
+ case "trailpad":
+ Items.Add(new UL_TrailPad(data, cache, themePath, (JObject)child));
+ break;
+ case "pbar":
+ Items.Add(new UL_PBar(data, cache, themePath, (JObject)child));
+ break;
+ case "basic3d1":
+ Items.Add(new UL_Basic3D1(data, cache, themePath, (JObject)child));
+ break;
+ default:
+ throw new Exception("Unknown UI Widget Type");
+ }
+ });
+ }
+
+ public void Paint(Graphics graphics)
+ {
+ foreach(UI_Item item in Items)
+ {
+ item.Paint(graphics);
+ }
+ }
+ }
+
+ public class ControllerData
+ {
+ SteamController ActiveController;
+
+ public bool GetBasicControl(string inputName)
+ {
+ if (ActiveController == null) return false;
+
+ inputName = inputName.ToLowerInvariant();
+
+ SteamController.SteamControllerState state = ActiveController.GetState();
+
+ switch (inputName)
+ {
+ case "a":
+ return state.Buttons.A;
+ case "b":
+ return state.Buttons.B;
+ case "x":
+ return state.Buttons.X;
+ case "y":
+ return state.Buttons.Y;
+
+ case "leftbumper":
+ case "lb":
+ return state.Buttons.LeftBumper;
+ case "lefttrigger":
+ case "lt":
+ return state.Buttons.LeftTrigger;
+
+ case "rightbumper":
+ case "rb":
+ return state.Buttons.RightBumper;
+ case "righttrigger":
+ case "rt":
+ return state.Buttons.RightTrigger;
+
+ case "leftgrip":
+ case "lg":
+ return state.Buttons.LeftGrip;
+ case "rightgrip":
+ case "rg":
+ return state.Buttons.RightGrip;
+
+ case "start":
+ return state.Buttons.Start;
+ case "steam":
+ return state.Buttons.Steam;
+ case "select":
+ return state.Buttons.Select;
+
+ case "down":
+ return state.Buttons.Down;
+ case "left":
+ return state.Buttons.Left;
+ case "right":
+ return state.Buttons.Right;
+ case "up":
+ return state.Buttons.Up;
+
+ case "stickclick":
+ case "sc":
+ return state.Buttons.StickClick;
+ case "leftpadtouch":
+ case "lpt":
+ return state.Buttons.LeftPadTouch;
+ case "leftpadclick":
+ case "lpc":
+ return state.Buttons.LeftPadClick;
+ case "rightpadtouch":
+ case "rpt":
+ return state.Buttons.RightPadTouch;
+ case "rightpadclick":
+ case "rpc":
+ return state.Buttons.RightPadClick;
+ default:
+ return false;
+ }
+ }
+
+ public Int32 GetAnalogControl(string inputName)
+ {
+ if (ActiveController == null) return 0;
+
+ inputName = inputName.ToLowerInvariant();
+
+ SteamController.SteamControllerState state = ActiveController.GetState();
+
+ switch (inputName)
+ {
+ case "leftpadx": return state.LeftPadX;
+ case "leftpady": return state.LeftPadY;
+
+ case "rightpadx": return state.RightPadX;
+ case "rightpady": return state.RightPadY;
+
+ case "leftstickx": return state.LeftStickX;
+ case "leftsticky": return state.LeftStickY;
+
+ case "lefttrigger": return state.LeftTrigger;
+ case "righttrigger": return state.RightTrigger;
+
+ case "angularvelocityx": return state.AngularVelocityX;
+ case "angularvelocityy": return state.AngularVelocityY;
+ case "angularvelocityz": return state.AngularVelocityZ;
+
+ // consider orientation data here, but it's a quaternion so that's complicated
+
+ default: return 0;
+ }
+ }
+
+ public SteamController.SteamControllerState GetState()
+ {
+ if (ActiveController == null) return null;
+ return ActiveController.GetState();
+ }
+
+ public void SetController(SteamController ActiveController)
+ {
+ this.ActiveController = ActiveController;
+ }
+ }
+
+ public class UI_ImageCache : IDisposable
+ {
+ private string themePath;
+ private Dictionary cache;
+
+ public UI_ImageCache(string themePath)
+ {
+ this.themePath = themePath;
+ this.cache = new Dictionary();
+ }
+
+ private bool disposed = false;
+ ~UI_ImageCache()
+ {
+ Dispose(false);
+ }
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing)
+ {
+ // Free any other managed objects here.
+ //
+ foreach(var key in cache.Keys)
+ {
+ cache[key].Dispose();
+ cache[key] = null;
+ }
+ }
+
+ // Free any unmanaged objects here.
+ //
+ cache = null;
+ disposed = true;
+ }
+
+ public Image GetImage(string Key, Func ImageLoader)
+ {
+ lock(cache)
+ {
+ if (cache.ContainsKey(Key)) return cache[Key];
+ cache[Key] = ImageLoader();
+ return cache[Key];
+ }
+ }
+
+ public Image LoadImage(string name)
+ {
+ // load the image for the active theme
+ string ImagePath = Path.Combine("themes", themePath, name);
+
+ // this will throw an exception if the file or path doesn't exist
+ return Image.FromFile(ImagePath);
+ }
+
+ public static Image SetImageOpacity(Image image, float opacity)
+ {
+ try
+ {
+ //create a Bitmap the size of the image provided
+ Bitmap bmp = new Bitmap(image.Width, image.Height);
+
+ //create a graphics object from the image
+ using (Graphics gfx = Graphics.FromImage(bmp))
+ {
+
+ //create a color matrix object
+ ColorMatrix matrix = new ColorMatrix();
+
+ //set the opacity
+ matrix.Matrix33 = opacity;
+
+ //create image attributes
+ ImageAttributes attributes = new ImageAttributes();
+
+ //set the color(opacity) of the image
+ attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
+
+ //now draw the image
+ gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
+
+ bmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
+ }
+ return bmp;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ }
+
+ }
+
+ public class UI_Item
+ {
+ public float X { get; private set; }
+ public float Y { get; private set; }
+ public float Rot { get; private set; }
+
+ private UI_ImageCache cache;
+ private List Items;
+
+ //public UI_Item(UI_ImageCache cache, string themePath, string json)
+ //{
+ // JObject themeData = JObject.Parse(json);
+ // Initalize(cache, themePath, themeData);
+ //}
+
+ public UI_Item(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ Initalize(data, cache, themePath, themeData);
+ }
+
+ protected virtual void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ this.cache = cache;
+ Items = new List();
+
+ X = themeData["x"]?.Value() ?? 0;
+ Y = themeData["y"]?.Value() ?? 0;
+ Rot = themeData["rot"]?.Value() ?? 0;
+
+ themeData["children"]?.ToList().ForEach(child =>
+ {
+ string uiType = child["type"]?.Value() ?? "";
+
+ switch (uiType)
+ {
+ case "":
+ Items.Add(new UI_Item(data, cache, themePath, (JObject)child));
+ break;
+ case "image":
+ Items.Add(new UI_GraphicalItem(data, cache, themePath, (JObject)child));
+ break;
+ case "showhide":
+ Items.Add(new UL_ShowHide(data, cache, themePath, (JObject)child));
+ break;
+ case "slider":
+ Items.Add(new UL_Slider(data, cache, themePath, (JObject)child));
+ break;
+ case "trailpad":
+ Items.Add(new UL_TrailPad(data, cache, themePath, (JObject)child));
+ break;
+ case "pbar":
+ Items.Add(new UL_PBar(data, cache, themePath, (JObject)child));
+ break;
+ case "basic3d1":
+ Items.Add(new UL_Basic3D1(data, cache, themePath, (JObject)child));
+ break;
+ default:
+ throw new Exception("Unknown UI Widget Type");
+ }
+ });
+ }
+
+ public virtual void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+ graphics.TranslateTransform(X, Y);
+ graphics.RotateTransform(Rot);
+
+ foreach (UI_Item item in Items)
+ {
+ item.Paint(graphics);
+ }
+
+ graphics.Transform = preserve;
+ }
+ }
+
+ public class UI_GraphicalItem : UI_Item
+ {
+ public UI_GraphicalItem(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData) : base(data, cache, themePath, themeData)
+ {
+ }
+
+ public float Height { get; private set; }
+ public float Width { get; private set; }
+ public bool DrawFromCenter { get; private set; }
+
+ protected Image DisplayImage;
+
+ protected override void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ base.Initalize(data, cache, themePath, themeData);
+
+ Height = themeData["height"]?.Value() ?? 0;
+ Width = themeData["width"]?.Value() ?? 0;
+ DrawFromCenter = themeData["center"]?.Value() ?? false;
+
+ string imageName = themeData["image"]?.Value();
+
+ if (!string.IsNullOrWhiteSpace(imageName))
+ {
+ DisplayImage = cache.LoadImage(imageName);
+ }
+ }
+
+ public override void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+ if (DrawFromCenter)
+ graphics.TranslateTransform(-Width / 2, -Height / 2);
+
+ if (DisplayImage != null)
+ {
+ if(DisplayImage != null)
+ graphics.DrawImage(DisplayImage, X, Y, Width, Height);
+ }
+
+ graphics.Transform = preserve;
+
+ //if (DrawFromCenter)
+ // graphics.TranslateTransform(X, Y);
+
+ base.Paint(graphics);
+
+ //graphics.Transform = preserve;
+ }
+ }
+
+ public class UL_ShowHide : UI_Item
+ {
+ public UL_ShowHide(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData) : base(data, cache, themePath, themeData)
+ {
+ }
+
+ private ControllerData data;
+ private string InputName;
+
+ private bool output;
+
+ protected override void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ base.Initalize(data, cache, themePath, themeData);
+ this.data = data;
+
+ output = true;
+
+ InputName = themeData["inputName"]?.Value();
+ output = !(themeData["invert"]?.Value() ?? false);
+ }
+
+ public override void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+
+ if (string.IsNullOrWhiteSpace(InputName))
+ {
+ if (output) base.Paint(graphics);
+ }
+ else if (data.GetBasicControl(InputName))
+ {
+ if (output) base.Paint(graphics);
+ }
+ else
+ {
+ if (!output) base.Paint(graphics);
+ }
+ }
+ }
+
+ public class UL_Slider : UI_Item
+ {
+ public UL_Slider(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData) : base(data, cache, themePath, themeData)
+ {
+ }
+
+ private ControllerData data;
+ protected string AxisNameX;
+ protected string AxisNameY;
+ protected float ScaleFactorX;
+ protected float ScaleFactorY;
+
+ protected override void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ base.Initalize(data, cache, themePath, themeData);
+ this.data = data;
+
+ AxisNameX = themeData["axisNameX"]?.Value();
+ AxisNameY = themeData["axisNameY"]?.Value();
+
+ ScaleFactorX = themeData["scaleFactorX"]?.Value() ?? 0;
+ ScaleFactorY = themeData["scaleFactorY"]?.Value() ?? 0;
+ }
+
+ public override void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+
+ float AnalogX = string.IsNullOrWhiteSpace(AxisNameX) ? 0 : (data.GetAnalogControl(AxisNameX) * ScaleFactorX);
+ float AnalogY = string.IsNullOrWhiteSpace(AxisNameY) ? 0 : (data.GetAnalogControl(AxisNameY) * ScaleFactorY);
+
+ graphics.TranslateTransform(AnalogX, -AnalogY);
+
+ base.Paint(graphics);
+
+ graphics.Transform = preserve;
+ }
+ }
+
+ public class UL_TrailPad : UL_Slider
+ {
+ public UL_TrailPad(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData) : base(data, cache, themePath, themeData)
+ {
+ }
+
+ private ControllerData data;
+ private Image[] ImagePadDecay;
+ private List PadPosHistory;
+ private string InputName;
+
+ protected override void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ base.Initalize(data, cache, themePath, themeData);
+ this.data = data;
+
+ PadPosHistory = new List();
+
+ InputName = themeData["inputName"]?.Value();
+ string imageName = themeData["image"]?.Value();
+ int TrailLength = themeData["length"]?.Value()??0;
+
+ if (!string.IsNullOrWhiteSpace(imageName) && TrailLength > 0)
+ {
+ Image ImagePadDecayBase = cache.LoadImage(imageName);
+ ImagePadDecay = new Image[TrailLength];
+ for (int x = 0; x < ImagePadDecay.Length; x++)
+ {
+ float percent = ((x + 1) * 1.0f / ImagePadDecay.Length);
+
+ ImagePadDecay[x] = cache.GetImage($"{imageName}:{percent}", () => { return UI_ImageCache.SetImageOpacity(ImagePadDecayBase, percent * 0.15f); });
+ }
+ }
+ else
+ {
+ ImagePadDecay = new Image[0];
+ }
+ }
+
+ public override void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+ graphics.TranslateTransform(X, Y);
+
+ bool ControlHot = data.GetBasicControl(InputName);
+
+ PointF? prevCord = null;
+ for (int pointfade = 0; pointfade < PadPosHistory.Count && pointfade < ImagePadDecay.Length; pointfade++)
+ {
+ PointF? cord = PadPosHistory[pointfade];
+ if (cord.HasValue)
+ {
+ float SubPointWidth = ImagePadDecay[pointfade].Width;
+ float SubPointHeight = ImagePadDecay[pointfade].Height;
+
+ float ratio = (pointfade * 1.0f / ImagePadDecay.Length);
+ ratio = ratio * 0.5f + 0.5f;
+ SubPointWidth *= ratio;
+ SubPointHeight *= ratio;
+
+ graphics.DrawImage(ImagePadDecay[pointfade], cord.Value.X - (SubPointWidth / 2.0f), cord.Value.Y - (SubPointHeight / 2.0f), SubPointWidth, SubPointHeight);
+ if (prevCord.HasValue)
+ {
+ // draw extra dots between points we've seen
+ double xVector = cord.Value.X - prevCord.Value.X;
+ double yVector = cord.Value.Y - prevCord.Value.Y;
+
+ double distance = Math.Sqrt(xVector * xVector + yVector * yVector);
+ double subdist = distance * 0.5f;
+
+ if ((int)subdist > 0)
+ {
+ double distBetweenDots = distance / subdist;
+ float SubPoint2Width = ImagePadDecay[pointfade - 1].Width;
+ float SubPoint2Height = ImagePadDecay[pointfade - 1].Height;
+
+ //float ratio = (pointfade * 1.0f / ImagePadDecay.Length);
+ SubPoint2Width *= ratio;
+ SubPoint2Height *= ratio;
+
+ for (int subDistPlot = 0; subDistPlot < subdist; subDistPlot++)
+ {
+ PointF betweenPoint = new PointF(
+ (float)(prevCord.Value.X + xVector * subDistPlot / subdist),
+ (float)(prevCord.Value.Y + yVector * subDistPlot / subdist));
+
+ //Matrix preserve2 = graphics.Transform;
+ //graphics.TranslateTransform(X, Y);
+ graphics.DrawImage(ImagePadDecay[pointfade - 1], betweenPoint.X - (SubPoint2Width / 2.0f), betweenPoint.Y - (SubPoint2Height / 2.0f), SubPoint2Width, SubPoint2Height);
+ //graphics.Transform = preserve2;
+ }
+ }
+ }
+ }
+ prevCord = cord;
+ }
+
+
+ if (PadPosHistory.Count >= ImagePadDecay.Length && PadPosHistory.Count > 0) PadPosHistory.RemoveAt(0);
+
+ float AnalogX = string.IsNullOrWhiteSpace(AxisNameX) ? 0 : (data.GetAnalogControl(AxisNameX) * ScaleFactorX);
+ float AnalogY = string.IsNullOrWhiteSpace(AxisNameY) ? 0 : (data.GetAnalogControl(AxisNameY) * ScaleFactorY);
+
+ if (string.IsNullOrWhiteSpace(InputName) || data.GetBasicControl(InputName))
+ {
+ PointF cord = new PointF(AnalogX,-AnalogY);
+ PadPosHistory.Add(cord);
+ }
+ else
+ {
+ PadPosHistory.Add(null);
+ }
+
+ graphics.Transform = preserve;
+
+ base.Paint(graphics);
+ }
+ }
+
+ public class UL_PBar : UI_Item
+ {
+ public UL_PBar(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData) : base(data, cache, themePath, themeData)
+ {
+ }
+
+ private ControllerData data;
+ protected string AxisName;
+ protected string Direction;
+ protected int Min;
+ protected int Max;
+ protected float Width;
+ protected float Height;
+ protected Color Foreground;
+ protected Color Background;
+
+ protected override void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ base.Initalize(data, cache, themePath, themeData);
+ this.data = data;
+
+ Background = Color.White;
+ Foreground = Color.Black ;
+
+ AxisName = themeData["axisName"]?.Value();
+ Direction = themeData["direction"]?.Value();
+
+ Min = themeData["min"]?.Value() ?? 0;
+ Max = themeData["max"]?.Value() ?? 0;
+ Width = themeData["width"]?.Value() ?? 0;
+ Height = themeData["height"]?.Value() ?? 0;
+
+ string ForegroundCode = themeData["foreground"]?.Value();
+ string BackgroundCode = themeData["background"]?.Value();
+
+ try
+ {
+ Foreground = Color.FromArgb(int.Parse(ForegroundCode, System.Globalization.NumberStyles.HexNumber));
+ }
+ catch { }
+ try
+ {
+ Background = Color.FromArgb(int.Parse(BackgroundCode, System.Globalization.NumberStyles.HexNumber));
+ }
+ catch { }
+ }
+
+ public override void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+
+ float Analog = string.IsNullOrWhiteSpace(AxisName) ? 0 : (data.GetAnalogControl(AxisName));
+ Analog = Math.Max(Math.Min((Analog - Min) / (Max - Min), 1.0f), 0.0f);
+
+ graphics.TranslateTransform(X, Y);
+ graphics.TranslateTransform(-Width / 2, -Height / 2);
+
+ switch (Direction)
+ {
+ case "up":
+ graphics.FillRectangle(new SolidBrush(Background), 0, Height - (Height * Analog), Width, Height * Analog);
+ break;
+ case "down":
+ graphics.FillRectangle(new SolidBrush(Background), 0, 0, Width, Height * Analog);
+ break;
+ case "left":
+ graphics.FillRectangle(new SolidBrush(Background), Width - (Width * Analog), 0, Width * Analog, Height);
+ break;
+ default:
+ graphics.FillRectangle(new SolidBrush(Background), 0, 0, Width * Analog, Height);
+ break;
+ }
+
+ graphics.DrawRectangle(new Pen(Foreground, 2), 0, 0, Width, Height);
+
+ graphics.Transform = preserve;
+
+ base.Paint(graphics);
+ }
+ }
+
+ public class UL_Basic3D1 : UI_Item
+ {
+ public UL_Basic3D1(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData) : base(data, cache, themePath, themeData)
+ {
+ }
+
+ private ControllerData data;
+ private UI_ImageCache cache;
+ protected string DisplayType;
+ protected Image DisplayImage;
+ protected Image ShadowL;
+ protected Image ShadowR;
+ protected Image ShadowU;
+ protected Image ShadowD;
+ protected float Width;
+ protected float Height;
+
+ float TiltTranslateX;
+ float TiltTranslateY;
+
+ string ShadowLName;
+ string ShadowRName;
+ string ShadowUName;
+ string ShadowDName;
+
+ protected override void Initalize(ControllerData data, UI_ImageCache cache, string themePath, JObject themeData)
+ {
+ base.Initalize(data, cache, themePath, themeData);
+ this.data = data;
+ this.cache = cache;
+
+ DisplayType = themeData["mode"]?.Value();
+ string ImageName = themeData["image"]?.Value();
+ ShadowLName = themeData["shadowl"]?.Value();
+ ShadowRName = themeData["shadowr"]?.Value();
+ ShadowUName = themeData["shadowu"]?.Value();
+ ShadowDName = themeData["shadowd"]?.Value();
+
+ if (!string.IsNullOrWhiteSpace(ImageName))
+ DisplayImage = cache.LoadImage(ImageName);
+
+ if (!string.IsNullOrWhiteSpace(ShadowLName))
+ ShadowL = cache.LoadImage(ShadowLName);
+
+ if (!string.IsNullOrWhiteSpace(ShadowRName))
+ ShadowR = cache.LoadImage(ShadowRName);
+
+ if (!string.IsNullOrWhiteSpace(ShadowUName))
+ ShadowU = cache.LoadImage(ShadowUName);
+
+ if (!string.IsNullOrWhiteSpace(ShadowDName))
+ ShadowD = cache.LoadImage(ShadowDName);
+
+ Width = themeData["width"]?.Value() ?? 0;
+ Height = themeData["height"]?.Value() ?? 0;
+
+ TiltTranslateX = themeData["tilttranslatex"]?.Value() ?? 0;
+ TiltTranslateY = themeData["tilttranslatey"]?.Value() ?? 0;
+ }
+
+ public override void Paint(Graphics graphics)
+ {
+ Matrix preserve = graphics.Transform;
+
+ graphics.TranslateTransform(X, Y);
+ //graphics.TranslateTransform(-Width / 2, -Height / 2);
+
+ switch (DisplayType)
+ {
+ case "accel":
+ {
+ SteamController.SteamControllerState State = data.GetState();
+
+ if (State != null)
+ {
+ float TiltFactorX = State.AngularVelocityX * 0.0001f;
+ float TiltFactorY = State.AngularVelocityY * 0.0001f;
+ float rotationAngle = (State.AngularVelocityZ * 0.0001f) * -90;
+ float transformX = 1.0f - Math.Abs(TiltFactorY * 0.5f);
+ float transformY = 1.0f - Math.Abs(TiltFactorX * 0.5f);
+
+ Draw3dAs3d(cache, graphics, DisplayImage, ShadowLName, ShadowL, ShadowRName, ShadowR, ShadowUName, ShadowU, ShadowDName, ShadowD, transformX, transformY, rotationAngle, TiltFactorX, TiltFactorY, Width, Height, TiltTranslateX, TiltTranslateY);
+
+ graphics.ResetTransform();
+ }
+ }
+ break;
+ case "gyro":
+ {
+ SteamController.SteamControllerState State = data.GetState();
+
+ if (State != null)
+ {
+ double qw = (State.OrientationW * 1.0f / 32736);
+ double qx = (State.OrientationX * 1.0f / 32736);
+ double qy = (State.OrientationY * 1.0f / 32736);
+ double qz = (State.OrientationZ * 1.0f / 32736);
+
+ double pitch;
+ double roll;
+ double yaw;
+
+ ToEulerAngles(qw, qy, qz, qx, out pitch, out roll, out yaw);
+
+ {
+ double Yaw = (yaw * 2.0f / Math.PI);
+ double Roll = -(roll * 2.0f / Math.PI);
+ double Pitch = (pitch * 2.0f / Math.PI);
+
+ if (double.IsNaN(Yaw)) Yaw = 0;
+ if (double.IsNaN(Roll)) Roll = 0;
+ if (double.IsNaN(Pitch)) Pitch = 0;
+
+ int SignY = -Math.Sign((2 * mod(Math.Floor((Roll - 1) * 0.5f) + 1, 2)) - 1);
+ float TiltFactorX = (float)((2 * Math.Abs(mod((Pitch - 1) * 0.5f, 2) - 1)) - 1);
+ float TiltFactorY = (float)((2 * Math.Abs(mod((Roll - 1) * 0.5f, 2) - 1)) - 1);
+ float rotationAngle = (float)(Yaw * -90.0f);
+ float transformX = SignY * Math.Max(1.0f - Math.Abs(TiltFactorY), 0.15f);
+ float transformY = Math.Max(1.0f - Math.Abs(TiltFactorX), 0.15f);
+
+ //Console.WriteLine($"{TiltFactorY}\t{Roll}\t{(2 * mod(Math.Floor((Roll - 1) * 0.5f) + 1, 2)) - 1}");
+
+ Draw3dAs3d(cache, graphics, DisplayImage, ShadowLName, ShadowL, ShadowRName, ShadowR, ShadowUName, ShadowU, ShadowDName, ShadowD, transformX, transformY, rotationAngle, TiltFactorX, TiltFactorY, Width, Height, TiltTranslateX, TiltTranslateY);
+
+ graphics.ResetTransform();
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ graphics.Transform = preserve;
+
+ base.Paint(graphics);
+ }
+
+ public static void ToEulerAngles(double QuaternionW, double QuaternionX, double QuaternionY, double QuaternionZ, out double Pitch, out double Roll, out double Yaw)
+ {
+ // Store the Euler angles in radians
+ //Vector3 pitchYawRoll = new Vector3();
+
+ double sqw = QuaternionW * QuaternionW;
+ double sqx = QuaternionX * QuaternionX;
+ double sqy = QuaternionY * QuaternionY;
+ double sqz = QuaternionZ * QuaternionZ;
+
+ // If quaternion is normalised the unit is one, otherwise it is the correction factor
+ double unit = sqx + sqy + sqz + sqw;
+ double test = QuaternionX * QuaternionY + QuaternionZ * QuaternionW;
+
+ if (test > 0.4999f * unit) // 0.4999f OR 0.5f - EPSILON
+ {
+ // Singularity at north pole
+ Yaw = 2f * Math.Atan2(QuaternionX, QuaternionW); // Yaw
+ Pitch = Math.PI * 0.5f; // Pitch
+ Roll = 0f; // Roll
+ return;
+ }
+ else if (test < -0.4999f * unit) // -0.4999f OR -0.5f + EPSILON
+ {
+ // Singularity at south pole
+ Yaw = -2f * Math.Atan2(QuaternionX, QuaternionW); // Yaw
+ Pitch = -Math.PI * 0.5f; // Pitch
+ Roll = 0f; // Roll
+ return;
+ }
+ else
+ {
+ Yaw = Math.Atan2(2f * QuaternionY * QuaternionW - 2f * QuaternionX * QuaternionZ, sqx - sqy - sqz + sqw); // Yaw
+ Pitch = Math.Asin(2f * test / unit); // Pitch
+ Roll = Math.Atan2(2f * QuaternionX * QuaternionW - 2f * QuaternionY * QuaternionZ, -sqx + sqy - sqz + sqw); // Roll
+ }
+ }
+
+ double mod(double x, double m)
+ {
+ return (x % m + m) % m;
+ }
+
+ private void Draw3dAs3d(
+ UI_ImageCache cache, Graphics g,
+ Image image, string ImageGyroLName, Image ImageGyroL, string ImageGyroRName, Image ImageGyroR, string ImageGyroUName, Image ImageGyroU, string ImageGyroDName, Image ImageGyroD,
+ float transformX, float transformY,
+ float rotationAngle,
+ float TiltFactorX, float TiltFactorY,
+ float Width, float Height,
+ float TiltTranslateX, float TiltTranslateY)
+ {
+ // fix flip
+ if (TiltFactorX < -1) TiltFactorX = 2.0f + TiltFactorX;
+ if (TiltFactorX > 1) TiltFactorX = 2.0f - TiltFactorX;
+ if (TiltFactorY < -1) TiltFactorY = 2.0f + TiltFactorY;
+ if (TiltFactorY > 1) TiltFactorY = 2.0f - TiltFactorY;
+
+ PointF location = new PointF((TiltFactorY * -TiltTranslateX) - (Width / 2), (TiltFactorX * TiltTranslateY) - (Height / 2));
+
+ g.RotateTransform(rotationAngle);
+ g.ScaleTransform(transformX, transformY);
+
+ g.DrawImage(image, location.X, location.Y, Width, Height);
+
+ if (Math.Abs(TiltFactorX) > 0)
+ {
+ if (Math.Sign(TiltFactorX) > 0) {
+ float percent = TiltFactorX * 2;// * 0.15f;
+ g.DrawImage(cache.GetImage($"{ImageGyroDName}:{percent}", () => { return UI_ImageCache.SetImageOpacity(ImageGyroD, percent); }), location.X, location.Y, Width, Height);
+ }
+ if (Math.Sign(TiltFactorX) < 0) {
+ float percent = -TiltFactorX * 2;// * 0.15f;
+ g.DrawImage(cache.GetImage($"{ImageGyroUName}:{percent}", () => { return UI_ImageCache.SetImageOpacity(ImageGyroU, percent); }), location.X, location.Y, Width, Height);
+ }
+ }
+
+ if (Math.Abs(TiltFactorY) > 0)
+ {
+ if (Math.Sign(TiltFactorY) > 0) {
+ float percent = TiltFactorY * 2;// * 0.15f;
+ g.DrawImage(cache.GetImage($"{ImageGyroLName}:{percent}", () => { return UI_ImageCache.SetImageOpacity(ImageGyroL, percent); }), location.X, location.Y, Width, Height);
+ }
+ if (Math.Sign(TiltFactorY) < 0) {
+ float percent = -TiltFactorY * 2;// * 0.15f;
+ g.DrawImage(cache.GetImage($"{ImageGyroRName}:{percent}", () => { return UI_ImageCache.SetImageOpacity(ImageGyroR, percent); }), location.X, location.Y, Width, Height);
+ }
+ }
+ }
+
+ }
+}
diff --git a/VSCView/ProcForm.Designer.cs b/VSCView/ProcForm.Designer.cs
new file mode 100644
index 0000000..c5c4879
--- /dev/null
+++ b/VSCView/ProcForm.Designer.cs
@@ -0,0 +1,124 @@
+namespace VSCView
+{
+ partial class ProcForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.txtTemp1 = new System.Windows.Forms.TextBox();
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this.txtTemp2 = new System.Windows.Forms.TextBox();
+ this.txtTemp3 = new System.Windows.Forms.TextBox();
+ this.txtTemp4 = new System.Windows.Forms.TextBox();
+ this.tableLayoutPanel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // txtTemp1
+ //
+ this.txtTemp1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTemp1.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtTemp1.Location = new System.Drawing.Point(3, 3);
+ this.txtTemp1.Multiline = true;
+ this.txtTemp1.Name = "txtTemp1";
+ this.txtTemp1.ReadOnly = true;
+ this.txtTemp1.Size = new System.Drawing.Size(229, 647);
+ this.txtTemp1.TabIndex = 0;
+ //
+ // tableLayoutPanel1
+ //
+ this.tableLayoutPanel1.ColumnCount = 4;
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F));
+ this.tableLayoutPanel1.Controls.Add(this.txtTemp4, 3, 0);
+ this.tableLayoutPanel1.Controls.Add(this.txtTemp3, 2, 0);
+ this.tableLayoutPanel1.Controls.Add(this.txtTemp2, 1, 0);
+ this.tableLayoutPanel1.Controls.Add(this.txtTemp1, 0, 0);
+ this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ this.tableLayoutPanel1.RowCount = 1;
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(940, 637);
+ this.tableLayoutPanel1.TabIndex = 1;
+ //
+ // txtTemp2
+ //
+ this.txtTemp2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTemp2.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtTemp2.Location = new System.Drawing.Point(238, 3);
+ this.txtTemp2.Multiline = true;
+ this.txtTemp2.Name = "txtTemp2";
+ this.txtTemp2.ReadOnly = true;
+ this.txtTemp2.Size = new System.Drawing.Size(229, 647);
+ this.txtTemp2.TabIndex = 1;
+ //
+ // txtTemp3
+ //
+ this.txtTemp3.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTemp3.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtTemp3.Location = new System.Drawing.Point(473, 3);
+ this.txtTemp3.Multiline = true;
+ this.txtTemp3.Name = "txtTemp3";
+ this.txtTemp3.ReadOnly = true;
+ this.txtTemp3.Size = new System.Drawing.Size(229, 647);
+ this.txtTemp3.TabIndex = 2;
+ //
+ // txtTemp4
+ //
+ this.txtTemp4.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.txtTemp4.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtTemp4.Location = new System.Drawing.Point(708, 3);
+ this.txtTemp4.Multiline = true;
+ this.txtTemp4.Name = "txtTemp4";
+ this.txtTemp4.ReadOnly = true;
+ this.txtTemp4.Size = new System.Drawing.Size(229, 647);
+ this.txtTemp4.TabIndex = 3;
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(940, 637);
+ this.Controls.Add(this.tableLayoutPanel1);
+ this.Name = "MainForm";
+ this.Text = "MainForm";
+ this.tableLayoutPanel1.ResumeLayout(false);
+ this.tableLayoutPanel1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtTemp1;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.TextBox txtTemp4;
+ private System.Windows.Forms.TextBox txtTemp3;
+ private System.Windows.Forms.TextBox txtTemp2;
+ }
+}
\ No newline at end of file
diff --git a/VSCView/ProcForm.cs b/VSCView/ProcForm.cs
new file mode 100644
index 0000000..c42bd56
--- /dev/null
+++ b/VSCView/ProcForm.cs
@@ -0,0 +1,109 @@
+using HidLibrary;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VSCView
+{
+ public partial class ProcForm : Form
+ {
+ SteamController[] Controllers;
+ TextBox[] txtTemp;
+
+ public ProcForm()
+ {
+ InitializeComponent();
+
+ SetDoubleBuffered(txtTemp1);
+ SetDoubleBuffered(txtTemp2);
+ SetDoubleBuffered(txtTemp3);
+ SetDoubleBuffered(txtTemp4);
+ txtTemp = new TextBox[] { txtTemp1, txtTemp2, txtTemp3, txtTemp4 }; ;
+
+ Controllers = SteamController.GetControllers();
+
+ //Controllers[0].StateUpdated += MainForm_StateUpdated;
+ if (Controllers.Length > 0) Controllers[0].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 0);
+ if (Controllers.Length > 1) Controllers[1].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 1);
+ if (Controllers.Length > 2) Controllers[2].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 2);
+ if (Controllers.Length > 3) Controllers[3].StateUpdated += (object sender, SteamController.SteamControllerState e) => MainForm_StateUpdated(sender, e, 3);
+ }
+
+ public static void SetDoubleBuffered(System.Windows.Forms.Control c)
+ {
+ //Taxes: Remote Desktop Connection and painting
+ //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
+ if (System.Windows.Forms.SystemInformation.TerminalServerSession)
+ return;
+
+ System.Reflection.PropertyInfo aProp =
+ typeof(System.Windows.Forms.Control).GetProperty(
+ "DoubleBuffered",
+ System.Reflection.BindingFlags.NonPublic |
+ System.Reflection.BindingFlags.Instance);
+
+ aProp.SetValue(c, true, null);
+ }
+
+ private void MainForm_StateUpdated(object sender, SteamController.SteamControllerState e, int index)
+ {
+ txtTemp1.Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ txtTemp[index].Text =
+ $"Buttons.A = {e.Buttons.A}\r\n" +
+ $"Buttons.B = {e.Buttons.B}\r\n" +
+ $"Buttons.X = {e.Buttons.X}\r\n" +
+ $"Buttons.Y = {e.Buttons.Y}\r\n" +
+ "\r\n" +
+ $"Buttons.LeftBumper = {e.Buttons.LeftBumper}\r\n" +
+ $"Buttons.LeftTrigger = {e.Buttons.LeftTrigger}\r\n" +
+ $"Buttons.LeftGrip = {e.Buttons.LeftGrip}\r\n" +
+ "\r\n" +
+ $"Buttons.RightBumper = {e.Buttons.RightBumper}\r\n" +
+ $"Buttons.RightTrigger = {e.Buttons.RightTrigger}\r\n" +
+ $"Buttons.RightGrip = {e.Buttons.RightGrip}\r\n" +
+ "\r\n" +
+ $"Buttons.CenterRight = {e.Buttons.Start}\r\n" +
+ $"Buttons.Center = {e.Buttons.Steam}\r\n" +
+ $"Buttons.CenterLeft = {e.Buttons.Select}\r\n" +
+ "\r\n" +
+ $"Buttons.Up = {e.Buttons.Up}\r\n" +
+ $"Buttons.Down = {e.Buttons.Down}\r\n" +
+ $"Buttons.Left = {e.Buttons.Left}\r\n" +
+ $"Buttons.Right = {e.Buttons.Right}\r\n" +
+ "\r\n" +
+ $"Buttons.ThumbStick = {e.Buttons.StickClick}\r\n" +
+ $"Buttons.LeftPadTouch = {e.Buttons.LeftPadTouch}\r\n" +
+ $"Buttons.LeftPadPress = {e.Buttons.LeftPadClick}\r\n" +
+ $"Buttons.RightPadTouch = {e.Buttons.RightPadTouch}\r\n" +
+ $"Buttons.RightPadPress = {e.Buttons.RightPadClick}\r\n" +
+ "\r\n" +
+ $"LeftTrigger = {e.LeftTrigger}\r\n" +
+ $"RightTrigger = {e.RightTrigger}\r\n" +
+ "\r\n" +
+ $"LeftStickX = {e.LeftStickX}\r\n" +
+ $"LeftStickY = {e.LeftStickY}\r\n" +
+ $"LeftPadX = {e.LeftPadX}\r\n" +
+ $"LeftPadY = {e.LeftPadY}\r\n" +
+ $"RightPadX = {e.RightPadX}\r\n" +
+ $"RightPadY = {e.RightPadY}\r\n" +
+ "\r\n" +
+ $"AngularVelocityX = {e.AngularVelocityX}\r\n" +
+ $"AngularVelocityY = {e.AngularVelocityY}\r\n" +
+ $"AngularVelocityZ = {e.AngularVelocityZ}\r\n" +
+ $"OrientationW = {e.OrientationW}\r\n" +
+ $"OrientationX = {e.OrientationX}\r\n" +
+ $"OrientationY = {e.OrientationY}\r\n" +
+ $"OrientationZ = {e.OrientationZ}\r\n";
+ });
+ }
+ }
+}
diff --git a/VSCView/ProcForm.resx b/VSCView/ProcForm.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/VSCView/ProcForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/VSCView/Program.cs b/VSCView/Program.cs
new file mode 100644
index 0000000..fc81073
--- /dev/null
+++ b/VSCView/Program.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VSCView
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main(string[] args)
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ if (args.Length == 0 || args[0] == @"-1")
+ {
+ Application.Run(new MainForm());
+ }
+ else if (args[0] == @"-2")
+ {
+ Application.Run(new ProcForm());
+ }
+ else if (args[0] == @"-3")
+ {
+ Application.Run(new RawForm());
+ }
+ else
+ {
+ Application.Run(new MainForm());
+ }
+ }
+ }
+}
diff --git a/VSCView/Properties/AssemblyInfo.cs b/VSCView/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9091b58
--- /dev/null
+++ b/VSCView/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("VSCView")]
+[assembly: AssemblyDescription("This application allows the viewing of raw Steam Controller input for use in on screen displays for videos and streams.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Nielk1")]
+[assembly: AssemblyProduct("VSCView")]
+[assembly: AssemblyCopyright("John Klein © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e513702d-ef79-4766-ad9d-c2382bd0cead")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.2.0.3")]
+[assembly: AssemblyFileVersion("0.2.0.3")]
diff --git a/VSCView/Properties/Resources.Designer.cs b/VSCView/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..0531561
--- /dev/null
+++ b/VSCView/Properties/Resources.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace VSCView.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VSCView.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap Nielk1_eyes_128 {
+ get {
+ object obj = ResourceManager.GetObject("Nielk1_eyes_128", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/VSCView/Properties/Resources.resx b/VSCView/Properties/Resources.resx
new file mode 100644
index 0000000..ee6e547
--- /dev/null
+++ b/VSCView/Properties/Resources.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\Nielk1_eyes_128.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/VSCView/Properties/Settings.Designer.cs b/VSCView/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..6531372
--- /dev/null
+++ b/VSCView/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace VSCView.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/VSCView/Properties/Settings.settings b/VSCView/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/VSCView/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/VSCView/RawForm.Designer.cs b/VSCView/RawForm.Designer.cs
new file mode 100644
index 0000000..b43c0dd
--- /dev/null
+++ b/VSCView/RawForm.Designer.cs
@@ -0,0 +1,128 @@
+namespace VSCView
+{
+ partial class RawForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RawForm));
+ this.txtUpdate = new System.Windows.Forms.TextBox();
+ this.txtDevicePath = new System.Windows.Forms.TextBox();
+ this.txtDescription = new System.Windows.Forms.TextBox();
+ this.txtBattery = new System.Windows.Forms.TextBox();
+ this.txtConnection = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // txtUpdate
+ //
+ this.txtUpdate.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtUpdate.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtUpdate.Location = new System.Drawing.Point(12, 60);
+ this.txtUpdate.Multiline = true;
+ this.txtUpdate.Name = "txtUpdate";
+ this.txtUpdate.ReadOnly = true;
+ this.txtUpdate.Size = new System.Drawing.Size(738, 840);
+ this.txtUpdate.TabIndex = 0;
+ this.txtUpdate.Text = resources.GetString("txtUpdate.Text");
+ //
+ // txtDevicePath
+ //
+ this.txtDevicePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtDevicePath.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtDevicePath.Location = new System.Drawing.Point(12, 8);
+ this.txtDevicePath.Name = "txtDevicePath";
+ this.txtDevicePath.ReadOnly = true;
+ this.txtDevicePath.Size = new System.Drawing.Size(738, 20);
+ this.txtDevicePath.TabIndex = 1;
+ //
+ // txtDescription
+ //
+ this.txtDescription.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtDescription.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtDescription.Location = new System.Drawing.Point(12, 34);
+ this.txtDescription.Name = "txtDescription";
+ this.txtDescription.ReadOnly = true;
+ this.txtDescription.Size = new System.Drawing.Size(738, 20);
+ this.txtDescription.TabIndex = 2;
+ //
+ // txtBattery
+ //
+ this.txtBattery.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtBattery.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtBattery.Location = new System.Drawing.Point(12, 1024);
+ this.txtBattery.Multiline = true;
+ this.txtBattery.Name = "txtBattery";
+ this.txtBattery.ReadOnly = true;
+ this.txtBattery.Size = new System.Drawing.Size(738, 166);
+ this.txtBattery.TabIndex = 3;
+ this.txtBattery.Text = "00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00";
+ //
+ // txtConnection
+ //
+ this.txtConnection.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.txtConnection.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.txtConnection.Location = new System.Drawing.Point(12, 906);
+ this.txtConnection.Multiline = true;
+ this.txtConnection.Name = "txtConnection";
+ this.txtConnection.ReadOnly = true;
+ this.txtConnection.Size = new System.Drawing.Size(738, 112);
+ this.txtConnection.TabIndex = 4;
+ this.txtConnection.Text = "00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00\r\n00";
+ //
+ // RawForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.AutoScroll = true;
+ this.ClientSize = new System.Drawing.Size(811, 298);
+ this.Controls.Add(this.txtConnection);
+ this.Controls.Add(this.txtBattery);
+ this.Controls.Add(this.txtDescription);
+ this.Controls.Add(this.txtDevicePath);
+ this.Controls.Add(this.txtUpdate);
+ this.Name = "RawForm";
+ this.Text = "Form1";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox txtUpdate;
+ private System.Windows.Forms.TextBox txtDevicePath;
+ private System.Windows.Forms.TextBox txtDescription;
+ private System.Windows.Forms.TextBox txtBattery;
+ private System.Windows.Forms.TextBox txtConnection;
+ }
+}
+
diff --git a/VSCView/RawForm.cs b/VSCView/RawForm.cs
new file mode 100644
index 0000000..d018b3c
--- /dev/null
+++ b/VSCView/RawForm.cs
@@ -0,0 +1,405 @@
+using HidLibrary;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace VSCView
+{
+ public partial class RawForm : Form
+ {
+ private const int VendorId = 10462;
+ private static int ProductIdWireless = 4418;
+ private static int ProductIdWired = 1102;
+ private static bool _attached;
+
+ //private Int16 MaxVal = 0;
+
+ public RawForm()
+ {
+ InitializeComponent();
+ SetDoubleBuffered(txtUpdate);
+ }
+
+ public static void SetDoubleBuffered(System.Windows.Forms.Control c)
+ {
+ //Taxes: Remote Desktop Connection and painting
+ //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
+ if (System.Windows.Forms.SystemInformation.TerminalServerSession)
+ return;
+
+ System.Reflection.PropertyInfo aProp =
+ typeof(System.Windows.Forms.Control).GetProperty(
+ "DoubleBuffered",
+ System.Reflection.BindingFlags.NonPublic |
+ System.Reflection.BindingFlags.Instance);
+
+ aProp.SetValue(c, true, null);
+ }
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ GetHidDevice();
+ }
+
+ private void GetHidDevice()
+ {
+ List _devices = HidDevices.Enumerate(VendorId, ProductIdWireless, ProductIdWired).ToList();
+
+ foreach(HidDevice _device in _devices)
+ {
+ if (_device != null)
+ {
+ // found
+
+ // \\?\hid#vid_28de&pid_1142&mi_00&col01#8&d70e632&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} HID Keyboard Device
+ // \\?\hid#vid_28de&pid_1142&mi_00&col02#8&d70e632&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030} HID-compliant mouse
+ // \\?\hid#vid_28de&pid_1142&mi_01#8&314823f4&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} HID-compliant device
+ // \\?\hid#vid_28de&pid_1142&mi_02#8&198497af&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} HID-compliant device
+ // \\?\hid#vid_28de&pid_1142&mi_03#8&1c10b6a&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} HID-compliant device
+ // \\?\hid#vid_28de&pid_1142&mi_04#8&279758bf&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} HID-compliant device
+
+ int index = -1;
+ Match m = Regex.Match(_device.DevicePath, "&mi_([0-9]{2})");
+ if (!m.Success) continue;
+ index = int.Parse(m.Groups[1].Value) - 1;
+ if (index < 0) continue;
+
+ _device.OpenDevice();
+ //_device.OpenDevice(DeviceMode.NonOverlapped, DeviceMode.NonOverlapped, ShareMode.ShareRead);
+
+ Console.WriteLine(_device.DevicePath + "\t" + _device.Description);
+
+ byte[] featureData;
+ _device.ReadFeatureData(out featureData);
+ byte[] manufacturer;
+ _device.ReadManufacturer(out manufacturer);
+ byte[] productData;
+ _device.ReadProduct(out productData);
+ byte[] serialNumber;
+ _device.ReadSerialNumber(out serialNumber);
+
+ _device.Inserted += () => DeviceAttachedHandler(_device);
+ _device.Removed += () => DeviceRemovedHandler(_device);
+
+ _device.MonitorDeviceEvents = true;
+
+ _device.ReadReport((_data) => OnReport(_device, _data));
+ //_device.Read((_data) => OnRead(_device, _data));
+ }
+ else
+ {
+ // not found
+ }
+ }
+ }
+
+ /*private static void OnRead(HidDevice _device, HidDeviceData data)
+ {
+ if (_attached == false) { return; }
+
+ //if (data.Data.Length >= 4)
+ {
+ var message = MessageFactory.CreateMessage(ProductId, data.Data);
+ }
+
+ _device.Read((_data) => OnRead(_device, _data));
+ }*/
+
+ private void OnReport(HidDevice _device, HidReport report)
+ {
+ if (_attached == false) { return; }
+
+ //if (report.Data.Length == 64)
+ {
+ txtDevicePath.Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ txtDevicePath.Text = _device.DevicePath;
+ });
+
+ txtDescription.Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ txtDescription.Text = _device.Description;
+ });
+
+ byte EventType = report.Data[2];
+
+ string[] NiceOutputText = BitConverter.ToString(report.Data).Split('-');
+
+ switch (EventType)
+ {
+ case 0x00:
+ {
+
+ }
+ //_device.ReadReport((data) => OnReport(_device, data));
+ break;
+
+ case 0x01:
+ {
+ NiceOutputText[0] += " -------- Always 01?";
+ NiceOutputText[1] += " -------- Always 00?";
+ NiceOutputText[2] += " -------- Event Type";
+ NiceOutputText[3] += " -------- 3C?";
+
+ NiceOutputText[4] += " -------- Packet Index: " + BitConverter.ToUInt32(report.Data, 4);
+ NiceOutputText[5] += " ^^^^^^^^";
+ NiceOutputText[6] += " ^^^^^^^^";
+ NiceOutputText[7] += " ^^^^^^^^";
+
+ NiceOutputText[8] += " " + Convert.ToString(report.Data[8], 2).PadLeft(8, '0');
+ NiceOutputText[8] += (report.Data[8] & 128) == 128 ? " ↓A↓" : " ↑A↑";
+ NiceOutputText[8] += (report.Data[8] & 64) == 64 ? " ↓X↓" : " ↑X↑";
+ NiceOutputText[8] += (report.Data[8] & 32) == 32 ? " ↓B↓" : " ↑B↑";
+ NiceOutputText[8] += (report.Data[8] & 16) == 16 ? " ↓Y↓" : " ↑Y↑";
+ NiceOutputText[8] += (report.Data[8] & 8) == 8 ? " ↓LB↓" : " ↑LB↑";
+ NiceOutputText[8] += (report.Data[8] & 4) == 4 ? " ↓RB↓" : " ↑RB↑";
+ NiceOutputText[8] += (report.Data[8] & 2) == 2 ? " ↓LT↓" : " ↑LT↑";
+ NiceOutputText[8] += (report.Data[8] & 1) == 1 ? " ↓RT↓" : " ↑RT↑";
+
+ NiceOutputText[9] += " " + Convert.ToString(report.Data[9], 2).PadLeft(8, '0');
+ NiceOutputText[9] += (report.Data[9] & 128) == 128 ? " ↓L-Grip↓" : " ↑L-Grip↑";
+ NiceOutputText[9] += (report.Data[9] & 64) == 64 ? " ↓SteamR↓" : " ↑SteamR↑";
+ NiceOutputText[9] += (report.Data[9] & 32) == 32 ? " ↓Steam↓" : " ↑Steam↑";
+ NiceOutputText[9] += (report.Data[9] & 16) == 16 ? " ↓SteamL↓" : " ↑SteamL↑";
+ NiceOutputText[9] += (report.Data[9] & 8) == 8 ? " ↓Down↓" : " ↑Down↑";
+ NiceOutputText[9] += (report.Data[9] & 4) == 4 ? " ↓Left↓" : " ↑Left↑";
+ NiceOutputText[9] += (report.Data[9] & 2) == 2 ? " ↓Right↓" : " ↑Right↑";
+ NiceOutputText[9] += (report.Data[9] & 1) == 1 ? " ↓Up↓" : " ↑Up↑";
+
+ bool LeftAnalogMultiplexMode = (report.Data[10] & 128) == 128;
+ bool LeftPadTouch = (report.Data[10] & 8) == 8;
+
+ NiceOutputText[10] += " " + Convert.ToString(report.Data[10], 2).PadLeft(8, '0');
+ NiceOutputText[10] += LeftAnalogMultiplexMode ? " !MULTIPLEX!" : " ";
+ NiceOutputText[10] += (report.Data[10] & 64) == 64 ? " ↓ThumbStick↓" : " ↑ThumbStick↑";
+ NiceOutputText[10] += (report.Data[10] & 32) == 32 ? " ↓-↓" : " ↑-↑";
+ NiceOutputText[10] += (report.Data[10] & 16) == 16 ? " ↓R-Pad Touch↓" : " ↑R-Pad Touch↑";
+ NiceOutputText[10] += LeftPadTouch ? " ↓L-Pad Touch↓" : " ↑L-Pad Touch↑";
+ NiceOutputText[10] += (report.Data[10] & 4) == 4 ? " ↓R-Pad Press↓" : " ↑R-Pad Press↑";
+ NiceOutputText[10] += (report.Data[10] & 2) == 2 ? " ↓?ThumbStick OR L-Pad Press?↓" : " ↑?ThumbStick OR L-Pad Press?↑";
+ NiceOutputText[10] += (report.Data[10] & 1) == 1 ? " ↓R-Grip↓" : " ↑R-Grip↑";
+
+ NiceOutputText[11] += " -------- LT: " + report.Data[11].ToString().PadLeft(3);
+ NiceOutputText[12] += " -------- RT: " + report.Data[12].ToString().PadLeft(3);
+
+ string LeftPadX = " ";
+ string LeftPadY = " ";
+ string LeftStickX = string.Empty;
+ string LeftStickY = string.Empty;
+
+ if (LeftAnalogMultiplexMode)
+ {
+ if (LeftPadTouch)
+ {
+ LeftPadX = BitConverter.ToInt16(report.Data, 16).ToString().PadLeft(6);
+ LeftPadY = BitConverter.ToInt16(report.Data, 18).ToString().PadLeft(6);
+ }
+ else
+ {
+ LeftStickX = BitConverter.ToInt16(report.Data, 16).ToString().PadLeft(6);
+ LeftStickY = BitConverter.ToInt16(report.Data, 18).ToString().PadLeft(6);
+ }
+ }
+ else if (LeftPadTouch)
+ {
+ LeftPadX = BitConverter.ToInt16(report.Data, 16).ToString().PadLeft(6);
+ LeftPadY = BitConverter.ToInt16(report.Data, 18).ToString().PadLeft(6);
+ }
+ else
+ {
+ LeftStickX = BitConverter.ToInt16(report.Data, 16).ToString().PadLeft(6);
+ LeftStickY = BitConverter.ToInt16(report.Data, 18).ToString().PadLeft(6);
+ }
+
+ NiceOutputText[16] += " -------- Left Pad X: " + LeftPadX + " ThumbStick X: " + LeftStickX;
+ NiceOutputText[17] += " ^^^^^^^^";
+ NiceOutputText[18] += " -------- Left Pad Y: " + LeftPadY + " ThumbStick Y: " + LeftStickY;
+ NiceOutputText[19] += " ^^^^^^^^";
+
+ NiceOutputText[20] += " -------- Right Pad X: " + BitConverter.ToInt16(report.Data, 20);
+ NiceOutputText[21] += " ^^^^^^^^";
+ NiceOutputText[22] += " -------- Right Pad Y: " + BitConverter.ToInt16(report.Data, 22);
+ NiceOutputText[23] += " ^^^^^^^^";
+
+ //NiceOutputText[28] += " -------- Acceleration X: " + BitConverter.ToInt16(report.Data, 28);
+ //NiceOutputText[29] += " ^^^^^^^^";
+ //NiceOutputText[30] += " -------- Acceleration Y: " + BitConverter.ToInt16(report.Data, 30);
+ //NiceOutputText[31] += " ^^^^^^^^";
+ //NiceOutputText[32] += " -------- Acceleration Z: " + BitConverter.ToInt16(report.Data, 32);
+ //NiceOutputText[33] += " ^^^^^^^^";
+ NiceOutputText[34] += " -------- AngularVelocity X: " + BitConverter.ToInt16(report.Data, 34);
+ NiceOutputText[35] += " ^^^^^^^^";
+ NiceOutputText[36] += " -------- AngularVelocity Y: " + BitConverter.ToInt16(report.Data, 36);
+ NiceOutputText[37] += " ^^^^^^^^";
+ NiceOutputText[38] += " -------- AngularVelocity Z: " + BitConverter.ToInt16(report.Data, 38);
+ NiceOutputText[39] += " ^^^^^^^^";
+
+ float qw = (BitConverter.ToInt16(report.Data, 40) * 1.0f / 32736);
+ float qx = (BitConverter.ToInt16(report.Data, 42) * 1.0f / 32736);
+ float qy = (BitConverter.ToInt16(report.Data, 44) * 1.0f / 32736);
+ float qz = (BitConverter.ToInt16(report.Data, 46) * 1.0f / 32736);
+
+ double roll;
+ double pitch;
+ double yaw;
+
+ // roll (x-axis rotation)
+ double sinr = +2.0 * (qw * qx + qy * qz);
+ double cosr = +1.0 - 2.0 * (qx * qx + qy * qy);
+ roll = Math.Atan2(sinr, cosr);
+
+ // pitch (y-axis rotation)
+ double sinp = +2.0 * (qw * qy - qz * qx);
+ if (Math.Abs(sinp) >= 1)
+ pitch = Math.Abs(Math.PI / 2) * Math.Sign(sinp); // use 90 degrees if out of range
+ else
+ pitch = Math.Asin(sinp);
+
+ // yaw (z-axis rotation)
+ double siny = +2.0 * (qw * qz + qx * qy);
+ double cosy = +1.0 - 2.0 * (qy * qy + qz * qz);
+ yaw = Math.Atan2(siny, cosy);
+
+ Console.WriteLine($"{(roll / 2 / Math.PI).ToString("0.###")},{(pitch / 2 / Math.PI).ToString("0.###")},{(yaw / 2 / Math.PI).ToString("0.###")}");
+
+ NiceOutputText[40] += " -------- Orientation W: " + BitConverter.ToInt16(report.Data, 40) + " " + (BitConverter.ToInt16(report.Data, 40) * 1.0f / 32736).ToString("0.###");
+ NiceOutputText[41] += " ^^^^^^^^";
+ NiceOutputText[42] += " -------- Orientation X: " + BitConverter.ToInt16(report.Data, 42) + " " + (BitConverter.ToInt16(report.Data, 42) * 1.0f / 32736).ToString("0.###");
+ NiceOutputText[43] += " ^^^^^^^^";
+ NiceOutputText[44] += " -------- Orientation Y: " + BitConverter.ToInt16(report.Data, 44) + " " + (BitConverter.ToInt16(report.Data, 44) * 1.0f / 32736).ToString("0.###");
+ NiceOutputText[45] += " ^^^^^^^^";
+ NiceOutputText[46] += " -------- Orientation Z: " + BitConverter.ToInt16(report.Data, 46) + " " + (BitConverter.ToInt16(report.Data, 46) * 1.0f / 32736).ToString("0.###");
+ NiceOutputText[47] += " ^^^^^^^^";
+
+ /*MaxVal = Math.Max(
+ Math.Max(
+ Math.Abs(BitConverter.ToInt16(report.Data, 40)),
+ Math.Max(
+ Math.Abs(BitConverter.ToInt16(report.Data, 42)),
+ Math.Max(
+ Math.Abs(BitConverter.ToInt16(report.Data, 44)),
+ Math.Abs(BitConverter.ToInt16(report.Data, 46))
+ )
+ )
+ ), MaxVal);
+
+ Console.WriteLine(MaxVal);*/
+
+ txtUpdate.Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ txtUpdate.Text = string.Join("\r\n", NiceOutputText);
+ });
+ }
+ //_device.ReadReport((data) => OnReport(_device, data));
+ _device.ReadReport((data) => OnReport(_device, data));
+ break;
+
+ case 0x03:
+ {
+ NiceOutputText[0] += " -------- Always 01?";
+ NiceOutputText[1] += " -------- Always 00?";
+ NiceOutputText[2] += " -------- Event Type";
+ NiceOutputText[3] += " -------- 01?";
+
+ // Connection detail. 0x01 for disconnect, 0x02 for connect, 0x03 for pairing request.
+ NiceOutputText[4] += " -------- Connection Detail: " + report.Data[4];
+
+ if (report.Data[4] == 0x01)
+ {
+ byte[] tmpBytes = new byte[4];
+ tmpBytes[1] = report.Data[5];
+ tmpBytes[2] = report.Data[6];
+ tmpBytes[3] = report.Data[7];
+
+ NiceOutputText[5] += " -------- Packet Index: " + BitConverter.ToUInt32(tmpBytes, 0);
+ NiceOutputText[6] += " ^^^^^^^^";
+ NiceOutputText[7] += " ^^^^^^^^";
+ }
+
+ // only works if controller is configured to send this data
+
+ // millivolts
+ NiceOutputText[8] += " -------- Battery Voltage: " + BitConverter.ToUInt16(report.Data, 8);
+ NiceOutputText[9] += " ^^^^^^^^";
+
+ NiceOutputText[10] += " -------- Unknown, stuck at 100%: " + BitConverter.ToUInt16(report.Data, 10);
+ NiceOutputText[11] += " ^^^^^^^^";
+
+ txtConnection.Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ txtConnection.Text = string.Join("\r\n", NiceOutputText);
+ });
+ }
+ _device.ReadReport((data) => OnReport(_device, data));
+ break;
+
+ case 0x04:
+ {
+ NiceOutputText[0] += " -------- Always 01?";
+ NiceOutputText[1] += " -------- Always 00?";
+ NiceOutputText[2] += " -------- Event Type";
+ NiceOutputText[3] += " -------- 0B?";
+
+ NiceOutputText[4] += " -------- Packet Index: " + BitConverter.ToUInt32(report.Data, 4);
+ NiceOutputText[5] += " ^^^^^^^^";
+ NiceOutputText[6] += " ^^^^^^^^";
+ NiceOutputText[7] += " ^^^^^^^^";
+
+ // only works if controller is configured to send this data
+
+ // millivolts
+ NiceOutputText[8] += " -------- Battery Voltage: " + BitConverter.ToUInt16(report.Data, 8);
+ NiceOutputText[9] += " ^^^^^^^^";
+
+ NiceOutputText[10] += " -------- Unknown, stuck at 100%: " + BitConverter.ToUInt16(report.Data, 10);
+ NiceOutputText[11] += " ^^^^^^^^";
+
+ txtBattery.Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ txtBattery.Text = string.Join("\r\n", NiceOutputText);
+ });
+ }
+ _device.ReadReport((data) => OnReport(_device, data));
+ break;
+
+ default:
+ {
+ Console.WriteLine("Unknown Packet Type " + EventType);
+ }
+ _device.ReadReport((data) => OnReport(_device, data));
+ break;
+ }
+
+ //var message = MessageFactory.CreateMessage(ProductId, report.Data);
+
+ //_device.ReadReport((data) => OnReport(_device, data));
+ }
+ }
+
+ private void DeviceAttachedHandler(HidDevice _device)
+ {
+ _attached = true;
+ Console.WriteLine("Gamepad attached.");
+ _device.ReadReport((_data) => OnReport(_device, _data));
+ //_device.Read((_data) => OnRead(_device, _data));
+ }
+
+ private void DeviceRemovedHandler(HidDevice _device)
+ {
+ _attached = false;
+ Console.WriteLine("Gamepad removed.");
+ }
+ }
+}
diff --git a/VSCView/RawForm.resx b/VSCView/RawForm.resx
new file mode 100644
index 0000000..07855bc
--- /dev/null
+++ b/VSCView/RawForm.resx
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+
+
\ No newline at end of file
diff --git a/VSCView/Resources/Nielk1_eyes_128.png b/VSCView/Resources/Nielk1_eyes_128.png
new file mode 100644
index 0000000..746ece5
Binary files /dev/null and b/VSCView/Resources/Nielk1_eyes_128.png differ
diff --git a/VSCView/SteamController.cs b/VSCView/SteamController.cs
new file mode 100644
index 0000000..f95062b
--- /dev/null
+++ b/VSCView/SteamController.cs
@@ -0,0 +1,441 @@
+using HidLibrary;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace VSCView
+{
+ public class SteamController
+ {
+ private const int VendorId = 0x28DE; // 10462
+ private const int ProductIdWireless = 0x1142; // 4418;
+ private const int ProductIdWired = 0x1102; // 4354
+
+ private bool _attached = false;
+ private HidDevice _device;
+
+ public enum VSCEventType
+ {
+ CONTROL_UPDATE = 0x01,
+ CONNECTION_DETAIL = 0x03,
+ BATTERY_UPDATE = 0x04,
+ }
+
+ public enum ConnectionState
+ {
+ DISCONNECT = 0x01,
+ CONNECT = 0x02,
+ PAIRING = 0x03,
+ }
+
+ public class SteamControllerButtons : ICloneable
+ {
+ public bool A { get; set; }
+ public bool B { get; set; }
+ public bool X { get; set; }
+ public bool Y { get; set; }
+
+ public bool LeftBumper { get; set; }
+ public bool LeftTrigger { get; set; }
+
+ public bool RightBumper { get; set; }
+ public bool RightTrigger { get; set; }
+
+ public bool LeftGrip { get; set; }
+ public bool RightGrip { get; set; }
+
+ public bool Start { get; set; }
+ public bool Steam { get; set; }
+ public bool Select { get; set; }
+
+ public bool Down { get; set; }
+ public bool Left { get; set; }
+ public bool Right { get; set; }
+ public bool Up { get; set; }
+
+ public bool StickClick { get; set; }
+ public bool LeftPadTouch { get; set; }
+ public bool LeftPadClick { get; set; }
+ public bool RightPadTouch { get; set; }
+ public bool RightPadClick { get; set; }
+
+ public object Clone()
+ {
+ SteamControllerButtons buttons = new SteamControllerButtons();
+
+ buttons.A = A;
+ buttons.B = B;
+ buttons.X = X;
+ buttons.Y = Y;
+
+ buttons.LeftBumper = LeftBumper;
+ buttons.LeftTrigger = LeftTrigger;
+
+ buttons.RightBumper = RightBumper;
+ buttons.RightTrigger = RightTrigger;
+
+ buttons.LeftGrip = LeftGrip;
+ buttons.RightGrip = RightGrip;
+
+ buttons.Start = Start;
+ buttons.Steam = Steam;
+ buttons.Select = Select;
+
+ buttons.Down = Down;
+ buttons.Left = Left;
+ buttons.Right = Right;
+ buttons.Up = Up;
+
+ buttons.StickClick = StickClick;
+ buttons.LeftPadTouch = LeftPadTouch;
+ buttons.LeftPadClick = LeftPadClick;
+ buttons.RightPadTouch = RightPadTouch;
+ buttons.RightPadClick = RightPadClick;
+
+ return buttons;
+ }
+ }
+
+ public class SteamControllerState
+ {
+ public SteamControllerButtons Buttons;
+
+ public byte LeftTrigger { get; set; }
+ public byte RightTrigger { get; set; }
+
+ public Int32 LeftStickX { get; set; }
+ public Int32 LeftStickY { get; set; }
+ public Int32 LeftPadX { get; set; }
+ public Int32 LeftPadY { get; set; }
+ public Int32 RightPadX { get; set; }
+ public Int32 RightPadY { get; set; }
+
+ public Int16 AngularVelocityX { get; set; }
+ public Int16 AngularVelocityY { get; set; }
+ public Int16 AngularVelocityZ { get; set; }
+ public Int16 OrientationW { get; set; }
+ public Int16 OrientationX { get; set; }
+ public Int16 OrientationY { get; set; }
+ public Int16 OrientationZ { get; set; }
+ }
+
+ SteamControllerButtons Buttons { get; set; }
+
+ byte LeftTrigger { get; set; }
+ byte RightTrigger { get; set; }
+
+ Int32 LeftStickX { get; set; }
+ Int32 LeftStickY { get; set; }
+ Int32 LeftPadX { get; set; }
+ Int32 LeftPadY { get; set; }
+ Int32 RightPadX { get; set; }
+ Int32 RightPadY { get; set; }
+
+ Int16 AngularVelocityX { get; set; }
+ Int16 AngularVelocityY { get; set; }
+ Int16 AngularVelocityZ { get; set; }
+ Int16 OrientationW { get; set; }
+ Int16 OrientationX { get; set; }
+ Int16 OrientationY { get; set; }
+ Int16 OrientationZ { get; set; }
+
+ bool Initalized;
+
+ public delegate void StateUpdatedEventHandler(object sender, SteamControllerState e);
+ public event StateUpdatedEventHandler StateUpdated;
+ protected virtual void OnStateUpdated(SteamControllerState e)
+ {
+ StateUpdated?.Invoke(this, e);
+ }
+
+ object controllerStateLock = new object();
+
+ public SteamController(HidDevice device)
+ {
+ Buttons = new SteamControllerButtons();
+
+ _device = device;
+
+ Initalized = false;
+ }
+
+ public void Initalize()
+ {
+ if (Initalized) return;
+
+ //_device.OpenDevice();
+
+ _device.Inserted += DeviceAttachedHandler;
+ _device.Removed += DeviceRemovedHandler;
+
+ _device.MonitorDeviceEvents = true;
+
+ _device.ReadReport(OnReport);
+
+ Initalized = true;
+ }
+
+ public void DeInitalize()
+ {
+ if (!Initalized) return;
+
+ _device.Inserted -= DeviceAttachedHandler;
+ _device.Removed -= DeviceRemovedHandler;
+
+ _device.MonitorDeviceEvents = false;
+
+ Initalized = false;
+ }
+
+ public string GetDevicePath()
+ {
+ return _device.DevicePath;
+ }
+
+ public SteamControllerState GetState()
+ {
+ lock (controllerStateLock)
+ {
+ SteamControllerState state = new SteamControllerState();
+ state.Buttons = (SteamControllerButtons)Buttons.Clone();
+
+ state.LeftTrigger = LeftTrigger;
+ state.RightTrigger = RightTrigger;
+
+ state.LeftStickX = LeftStickX;
+ state.LeftStickY = LeftStickY;
+ state.LeftPadX = LeftPadX;
+ state.LeftPadY = LeftPadY;
+ state.RightPadX = RightPadX;
+ state.RightPadY = RightPadY;
+
+ state.AngularVelocityX = AngularVelocityX;
+ state.AngularVelocityY = AngularVelocityY;
+ state.AngularVelocityZ = AngularVelocityZ;
+ state.OrientationW = OrientationW;
+ state.OrientationX = OrientationX;
+ state.OrientationY = OrientationY;
+ state.OrientationZ = OrientationZ;
+
+ return state;
+ }
+ }
+
+ public static SteamController[] GetControllers()
+ {
+ List _devices = HidDevices.Enumerate(VendorId, ProductIdWireless, ProductIdWired).ToList();
+ //Dictionary HidDeviceList = new Dictionary();
+
+ List HidDeviceList = new List();
+
+ // we should never have holes, this entire dictionary is just because I don't know if I can trust the order I get the HID devices
+ foreach (HidDevice _device in _devices)
+ {
+ if (_device != null)
+ {
+ int index = -1;
+ Match m = Regex.Match(_device.DevicePath, "&mi_([0-9]{2})");
+ if (!m.Success) continue;
+ index = int.Parse(m.Groups[1].Value) - 1;
+ if (index < 0) continue;
+
+ //HidDeviceList.Add(index, _device);
+ HidDeviceList.Add(_device);
+ }
+ }
+
+ //SteamController[] Controllers = new SteamController[HidDeviceList.Count];
+ //for (int idx = 0; idx < HidDeviceList.Count; idx++)
+ //{
+ // if (!HidDeviceList.ContainsKey(idx)) continue;
+ //
+ // Controllers[idx] = new SteamController(HidDeviceList[idx]);
+ //}
+ //
+ //return Controllers;
+
+ return HidDeviceList.Select(dr => new SteamController(dr)).ToArray();
+ }
+
+ private void OnReport(HidReport report)
+ {
+ if (!Initalized) return;
+
+ lock (controllerStateLock)
+ {
+ //SteamControllerState OldState = GetState();
+
+ if (_attached == false) { return; }
+
+ byte Unknown1 = report.Data[0]; // always 0x01?
+ byte Unknown2 = report.Data[1]; // always 0x00?
+ VSCEventType EventType = (VSCEventType)report.Data[2];
+
+ switch (EventType)
+ {
+ case 0: // not sure what this is but wired controllers do it
+ break;
+ case VSCEventType.CONTROL_UPDATE:
+ {
+ //report.Data[3] // 0x3C?
+
+ UInt32 PacketIndex = BitConverter.ToUInt32(report.Data, 4);
+
+ Buttons.A = (report.Data[8] & 128) == 128;
+ Buttons.X = (report.Data[8] & 64) == 64;
+ Buttons.B = (report.Data[8] & 32) == 32;
+ Buttons.Y = (report.Data[8] & 16) == 16;
+ Buttons.LeftBumper = (report.Data[8] & 8) == 8;
+ Buttons.RightBumper = (report.Data[8] & 4) == 4;
+ Buttons.LeftTrigger = (report.Data[8] & 2) == 2;
+ Buttons.RightTrigger = (report.Data[8] & 1) == 1;
+
+ Buttons.LeftGrip = (report.Data[9] & 128) == 128;
+ Buttons.Start = (report.Data[9] & 64) == 64;
+ Buttons.Steam = (report.Data[9] & 32) == 32;
+ Buttons.Select = (report.Data[9] & 16) == 16;
+
+ Buttons.Down = (report.Data[9] & 8) == 8;
+ Buttons.Left = (report.Data[9] & 4) == 4;
+ Buttons.Right = (report.Data[9] & 2) == 2;
+ Buttons.Up = (report.Data[9] & 1) == 1;
+
+ bool LeftAnalogMultiplexMode = (report.Data[10] & 128) == 128;
+ Buttons.StickClick = (report.Data[10] & 64) == 64;
+ bool Unknown = (report.Data[10] & 32) == 32; // what is this?
+ Buttons.RightPadTouch = (report.Data[10] & 16) == 16;
+ bool LeftPadTouch = (report.Data[10] & 8) == 8;
+ Buttons.RightPadClick = (report.Data[10] & 4) == 4;
+ bool ThumbOrLeftPadPress = (report.Data[10] & 2) == 2; // what is this even for?
+ Buttons.RightGrip = (report.Data[10] & 1) == 1;
+
+ LeftTrigger = report.Data[11];
+ RightTrigger = report.Data[12];
+
+ if (LeftAnalogMultiplexMode)
+ {
+ if (LeftPadTouch)
+ {
+ Buttons.LeftPadTouch = true;
+ Buttons.LeftPadClick = ThumbOrLeftPadPress;
+ LeftPadX = BitConverter.ToInt16(report.Data, 16);
+ LeftPadY = BitConverter.ToInt16(report.Data, 18);
+ }
+ else
+ {
+ LeftStickX = BitConverter.ToInt16(report.Data, 16);
+ LeftStickY = BitConverter.ToInt16(report.Data, 18);
+ }
+ }
+ else
+ {
+ if (LeftPadTouch)
+ {
+ Buttons.LeftPadTouch = true;
+ LeftPadX = BitConverter.ToInt16(report.Data, 16);
+ LeftPadY = BitConverter.ToInt16(report.Data, 18);
+ }
+ else
+ {
+ Buttons.LeftPadTouch = false;
+ LeftStickX = BitConverter.ToInt16(report.Data, 16);
+ LeftStickY = BitConverter.ToInt16(report.Data, 18);
+ LeftPadX = 0;
+ LeftPadY = 0;
+ }
+
+ Buttons.LeftPadClick = ThumbOrLeftPadPress && !Buttons.StickClick;
+ }
+
+ RightPadX = BitConverter.ToInt16(report.Data, 20);
+ RightPadY = BitConverter.ToInt16(report.Data, 22);
+
+ /*
+ //NiceOutputText[28] += " -------- Acceleration X: " + BitConverter.ToInt16(report.Data, 28);
+ //NiceOutputText[29] += " ^^^^^^^^";
+ //NiceOutputText[30] += " -------- Acceleration Y: " + BitConverter.ToInt16(report.Data, 30);
+ //NiceOutputText[31] += " ^^^^^^^^";
+ //NiceOutputText[32] += " -------- Acceleration Z: " + BitConverter.ToInt16(report.Data, 32);
+ //NiceOutputText[33] += " ^^^^^^^^";
+ */
+ AngularVelocityX = BitConverter.ToInt16(report.Data, 34);
+ AngularVelocityY = BitConverter.ToInt16(report.Data, 36);
+ AngularVelocityZ = BitConverter.ToInt16(report.Data, 38);
+ OrientationW = BitConverter.ToInt16(report.Data, 40);
+ OrientationX = BitConverter.ToInt16(report.Data, 42);
+ OrientationY = BitConverter.ToInt16(report.Data, 44);
+ OrientationZ = BitConverter.ToInt16(report.Data, 46);
+ }
+ break;
+
+ case VSCEventType.CONNECTION_DETAIL:
+ {
+ //report.Data[3] // 0x01?
+
+ // Connection detail. 0x01 for disconnect, 0x02 for connect, 0x03 for pairing request.
+ ConnectionState ConnectionStateV = (ConnectionState)report.Data[4];
+
+ if (report.Data[4] == 0x01)
+ {
+ byte[] tmpBytes = new byte[4];
+ tmpBytes[1] = report.Data[5];
+ tmpBytes[2] = report.Data[6];
+ tmpBytes[3] = report.Data[7];
+
+ //BitConverter.ToUInt32(tmpBytes, 0); // Timestamp
+ }
+ }
+ break;
+
+ case VSCEventType.BATTERY_UPDATE:
+ {
+ //report.Data[3] // 0x0B?
+
+ UInt32 PacketIndex = BitConverter.ToUInt32(report.Data, 4);
+
+ // only works if controller is configured to send this data
+
+ // millivolts
+ UInt16 BatteryVoltage = BitConverter.ToUInt16(report.Data, 8);
+ //BitConverter.ToUInt16(report.Data, 10); // UNKNOWN, stuck at 100
+ }
+ break;
+
+ default:
+ {
+ Console.WriteLine("Unknown Packet Type " + EventType);
+ }
+ break;
+ }
+
+ SteamControllerState NewState = GetState();
+ OnStateUpdated(NewState);
+
+ _device.ReadReport(OnReport);
+ }
+ }
+
+ private void DeviceAttachedHandler()
+ {
+ lock (controllerStateLock)
+ {
+ _attached = true;
+ Console.WriteLine("VSC Address Attached");
+ _device.ReadReport(OnReport);
+ }
+ }
+
+ private void DeviceRemovedHandler()
+ {
+ lock (controllerStateLock)
+ {
+ _attached = false;
+ Console.WriteLine("VSC Address Removed");
+ }
+ }
+ }
+}
diff --git a/VSCView/VSCView.csproj b/VSCView/VSCView.csproj
new file mode 100644
index 0000000..04da5d8
--- /dev/null
+++ b/VSCView/VSCView.csproj
@@ -0,0 +1,181 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E513702D-EF79-4766-AD9D-C2382BD0CEAD}
+ WinExe
+ VSCView
+ VSCView
+ v4.6.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+ true
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\hidlibrary.3.2.46.0\lib\HidLibrary.dll
+
+
+ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ About.cs
+
+
+ Form
+
+
+ MainForm.cs
+
+
+
+ Form
+
+
+ ProcForm.cs
+
+
+
+ Form
+
+
+ RawForm.cs
+
+
+
+
+ About.cs
+
+
+ MainForm.cs
+
+
+ RawForm.cs
+
+
+ ProcForm.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
\ No newline at end of file
diff --git a/VSCView/licenses/HidLibrary.txt b/VSCView/licenses/HidLibrary.txt
new file mode 100644
index 0000000..7d5d651
--- /dev/null
+++ b/VSCView/licenses/HidLibrary.txt
@@ -0,0 +1,18 @@
+Copyright (c) 2010 Ultraviolet Catastrophe
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/VSCView/licenses/Newtonsoft.Json.txt b/VSCView/licenses/Newtonsoft.Json.txt
new file mode 100644
index 0000000..0fecee7
--- /dev/null
+++ b/VSCView/licenses/Newtonsoft.Json.txt
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/VSCView/licenses/VCSView.txt b/VSCView/licenses/VCSView.txt
new file mode 100644
index 0000000..3afd917
--- /dev/null
+++ b/VSCView/licenses/VCSView.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 John Klein
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/VSCView/packages.config b/VSCView/packages.config
new file mode 100644
index 0000000..2726fbe
--- /dev/null
+++ b/VSCView/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/VSCView/themes/default/all.json b/VSCView/themes/default/all.json
new file mode 100644
index 0000000..5df4044
--- /dev/null
+++ b/VSCView/themes/default/all.json
@@ -0,0 +1,160 @@
+{
+ "width": 629,
+ "height": 774,
+ "children": [
+ {
+ "type":"image",
+ "image":"base.png",
+ "x":314.5,
+ "y":302.5,
+ "width":629,
+ "height":605,
+ "center":true,
+ "children": [
+ {
+ "x":74,
+ "y":67,
+ "children": [
+ { "type":"showhide", "inputName":"a", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y": 35, "width":36, "height":36, "center":true } ] },
+ { "type":"showhide", "inputName":"b", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 35, "y": 0, "width":36, "height":36, "center":true } ] },
+ { "type":"showhide", "inputName":"x", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x":-35, "y": 0, "width":36, "height":36, "center":true } ] },
+ { "type":"showhide", "inputName":"y", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y":-35, "width":36, "height":36, "center":true } ] }
+ ]
+ },
+
+ { "type":"showhide", "inputName":"stickclick", "invert":false, "children": [ { "type":"image", "image":"btn-stick.png", "x": -73, "y": 67, "width":105, "height":105, "center":true } ] },
+ {
+ "type":"slider",
+ "x": -72,
+ "y": 67,
+ "axisNameX":"leftstickx",
+ "axisNameY":"leftsticky",
+ "scaleFactorX": 0.0005,
+ "scaleFactorY": 0.0005,
+ "children": [
+ { "type":"image", "image":"stick.png", "x": 0, "y": 0, "width":69, "height":70, "center":true }
+ ]
+ },
+ {
+ "x":0,
+ "y":-29,
+ "children": [
+ { "type":"showhide", "inputName":"steam" , "invert":false, "children": [ { "type":"image", "image":"btn-home.png", "x": 0, "y": -8, "width":51, "height":51, "center":true } ] },
+ { "type":"showhide", "inputName":"start" , "invert":false, "children": [ { "type":"image", "image":"btn-sub.png" , "x": 52, "y": 0, "width":38, "height":22, "center":true } ] },
+ { "type":"showhide", "inputName":"select", "invert":false, "children": [ { "type":"image", "image":"btn-sub.png" , "x": -52, "y": 0, "width":38, "height":22, "center":true } ] }
+ ]
+ },
+ {
+ "x":0,
+ "y":-235,
+ "children": [
+ { "type":"showhide", "inputName":"lg", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": -75, "y": 0, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"lt", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": -163, "y": 48, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"lb", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": -163, "y": -28, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"rg", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": 75, "y": 0, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"rt", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": 163, "y": 48, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"rb", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": 163, "y": -28, "width":50, "height":50, "center":true } ] }
+ ]
+ },
+
+ { "type":"showhide", "inputName":"rightpadclick", "invert":false, "children": [ { "type":"image", "image":"btn-haptic.png", "x": 171, "y": -23, "width":156, "height":160, "center":true } ] },
+ {
+ "x": 171,
+ "y": -23,
+ "rot":-15,
+ "children": [
+ {
+ "type":"trailpad",
+ "inputName":"rightpadtouch",
+ "x": 0,
+ "y": 0,
+ "axisNameX":"rightpadx",
+ "axisNameY":"rightpady",
+ "scaleFactorX": 0.0022,
+ "scaleFactorY": 0.0022,
+ "image":"padheat.png",
+ "length":60,
+ "width":36,
+ "height":36,
+ "children": [
+ { "type":"showhide", "inputName":"rightpadtouch", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y": 0, "width":36, "height":36, "center":true } ] }
+ ]
+ }
+ ]
+ },
+
+ { "type":"showhide", "inputName":"leftpadclick" , "invert":false, "children": [ { "type":"image", "image":"btn-haptic.png", "x": -171, "y": -23, "width":156, "height":160, "center":true } ] },
+ {
+ "x": -171,
+ "y": -23,
+ "rot": 15,
+ "children": [
+ {
+ "type":"trailpad",
+ "inputName":"leftpadtouch",
+ "x": 0,
+ "y": 0,
+ "axisNameX":"leftpadx",
+ "axisNameY":"leftpady",
+ "scaleFactorX": 0.0022,
+ "scaleFactorY": 0.0022,
+ "image":"padheat.png",
+ "length":60,
+ "width":36,
+ "height":36,
+ "children": [
+ { "type":"showhide", "inputName":"leftpadtouch", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y": 0, "width":36, "height":36, "center":true } ] }
+ ]
+ }
+ ]
+ },
+
+ {
+ "x":0,
+ "y":-170,
+ "children": [
+ { "type":"pbar", "axisName":"lefttrigger" , "background":"ff007894", "foreground":"ff00d2f8", "x": -65, "y": 0, "width":120, "height":15, "min":0, "max":255, "direction": "right" },
+ { "type":"pbar", "axisName":"righttrigger", "background":"ff007894", "foreground":"ff00d2f8", "x": 65, "y": 0, "width":120, "height":15, "min":0, "max":255, "direction": "left" }
+ ]
+ },
+
+ {
+ "x":0,
+ "y":370,
+ "children": [
+ {
+ "type":"basic3d1",
+ "x": 165,
+ "y": 0,
+ "width":103,
+ "height":77,
+ "mode": "accel",
+ "image":"gyro.png",
+ "shadowl":"gyro_l.png",
+ "shadowr":"gyro_r.png",
+ "shadowu":"gyro_u.png",
+ "shadowd":"gyro_d.png",
+ "tilttranslatex":55,
+ "tilttranslatey":40
+ },
+ {
+ "type":"basic3d1",
+ "x": -165,
+ "y": 0,
+ "width":103,
+ "height":77,
+ "mode": "gyro",
+ "image":"gyro.png",
+ "shadowl":"gyro_l.png",
+ "shadowr":"gyro_r.png",
+ "shadowu":"gyro_u.png",
+ "shadowd":"gyro_d.png",
+ "tilttranslatex":55,
+ "tilttranslatey":40
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/VSCView/themes/default/base.png b/VSCView/themes/default/base.png
new file mode 100644
index 0000000..7de0a62
Binary files /dev/null and b/VSCView/themes/default/base.png differ
diff --git a/VSCView/themes/default/btn-face.png b/VSCView/themes/default/btn-face.png
new file mode 100644
index 0000000..9d87693
Binary files /dev/null and b/VSCView/themes/default/btn-face.png differ
diff --git a/VSCView/themes/default/btn-haptic.png b/VSCView/themes/default/btn-haptic.png
new file mode 100644
index 0000000..62c6fd3
Binary files /dev/null and b/VSCView/themes/default/btn-haptic.png differ
diff --git a/VSCView/themes/default/btn-home.png b/VSCView/themes/default/btn-home.png
new file mode 100644
index 0000000..28ae679
Binary files /dev/null and b/VSCView/themes/default/btn-home.png differ
diff --git a/VSCView/themes/default/btn-stick.png b/VSCView/themes/default/btn-stick.png
new file mode 100644
index 0000000..2999fa7
Binary files /dev/null and b/VSCView/themes/default/btn-stick.png differ
diff --git a/VSCView/themes/default/btn-sub.png b/VSCView/themes/default/btn-sub.png
new file mode 100644
index 0000000..8ac314d
Binary files /dev/null and b/VSCView/themes/default/btn-sub.png differ
diff --git a/VSCView/themes/default/btn-trigger.png b/VSCView/themes/default/btn-trigger.png
new file mode 100644
index 0000000..25e7ad1
Binary files /dev/null and b/VSCView/themes/default/btn-trigger.png differ
diff --git a/VSCView/themes/default/gyro.png b/VSCView/themes/default/gyro.png
new file mode 100644
index 0000000..f29dece
Binary files /dev/null and b/VSCView/themes/default/gyro.png differ
diff --git a/VSCView/themes/default/gyro_d.png b/VSCView/themes/default/gyro_d.png
new file mode 100644
index 0000000..cc61b82
Binary files /dev/null and b/VSCView/themes/default/gyro_d.png differ
diff --git a/VSCView/themes/default/gyro_l.png b/VSCView/themes/default/gyro_l.png
new file mode 100644
index 0000000..a449329
Binary files /dev/null and b/VSCView/themes/default/gyro_l.png differ
diff --git a/VSCView/themes/default/gyro_r.png b/VSCView/themes/default/gyro_r.png
new file mode 100644
index 0000000..4b9a01e
Binary files /dev/null and b/VSCView/themes/default/gyro_r.png differ
diff --git a/VSCView/themes/default/gyro_u.png b/VSCView/themes/default/gyro_u.png
new file mode 100644
index 0000000..6a0082f
Binary files /dev/null and b/VSCView/themes/default/gyro_u.png differ
diff --git a/VSCView/themes/default/nogyro.json b/VSCView/themes/default/nogyro.json
new file mode 100644
index 0000000..7a1c909
--- /dev/null
+++ b/VSCView/themes/default/nogyro.json
@@ -0,0 +1,123 @@
+{
+ "width": 629,
+ "height": 605,
+ "children": [
+ {
+ "type":"image",
+ "image":"base.png",
+ "x":314.5,
+ "y":302.5,
+ "width":629,
+ "height":605,
+ "center":true,
+ "children": [
+ {
+ "x":74,
+ "y":67,
+ "children": [
+ { "type":"showhide", "inputName":"a", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y": 35, "width":36, "height":36, "center":true } ] },
+ { "type":"showhide", "inputName":"b", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 35, "y": 0, "width":36, "height":36, "center":true } ] },
+ { "type":"showhide", "inputName":"x", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x":-35, "y": 0, "width":36, "height":36, "center":true } ] },
+ { "type":"showhide", "inputName":"y", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y":-35, "width":36, "height":36, "center":true } ] }
+ ]
+ },
+
+ { "type":"showhide", "inputName":"stickclick", "invert":false, "children": [ { "type":"image", "image":"btn-stick.png", "x": -73, "y": 67, "width":105, "height":105, "center":true } ] },
+ {
+ "type":"slider",
+ "x": -72,
+ "y": 67,
+ "axisNameX":"leftstickx",
+ "axisNameY":"leftsticky",
+ "scaleFactorX": 0.0005,
+ "scaleFactorY": 0.0005,
+ "children": [
+ { "type":"image", "image":"stick.png", "x": 0, "y": 0, "width":69, "height":70, "center":true }
+ ]
+ },
+ {
+ "x":0,
+ "y":-29,
+ "children": [
+ { "type":"showhide", "inputName":"steam" , "invert":false, "children": [ { "type":"image", "image":"btn-home.png", "x": 0, "y": -8, "width":51, "height":51, "center":true } ] },
+ { "type":"showhide", "inputName":"start" , "invert":false, "children": [ { "type":"image", "image":"btn-sub.png" , "x": 52, "y": 0, "width":38, "height":22, "center":true } ] },
+ { "type":"showhide", "inputName":"select", "invert":false, "children": [ { "type":"image", "image":"btn-sub.png" , "x": -52, "y": 0, "width":38, "height":22, "center":true } ] }
+ ]
+ },
+ {
+ "x":0,
+ "y":-235,
+ "children": [
+ { "type":"showhide", "inputName":"lg", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": -75, "y": 0, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"lt", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": -163, "y": 48, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"lb", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": -163, "y": -28, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"rg", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": 75, "y": 0, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"rt", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": 163, "y": 48, "width":50, "height":50, "center":true } ] },
+ { "type":"showhide", "inputName":"rb", "invert":false, "children": [ { "type":"image", "image":"btn-trigger.png" , "x": 163, "y": -28, "width":50, "height":50, "center":true } ] }
+ ]
+ },
+
+ { "type":"showhide", "inputName":"rightpadclick", "invert":false, "children": [ { "type":"image", "image":"btn-haptic.png", "x": 171, "y": -23, "width":156, "height":160, "center":true } ] },
+ {
+ "x": 171,
+ "y": -23,
+ "rot":-15,
+ "children": [
+ {
+ "type":"trailpad",
+ "inputName":"rightpadtouch",
+ "x": 0,
+ "y": 0,
+ "axisNameX":"rightpadx",
+ "axisNameY":"rightpady",
+ "scaleFactorX": 0.0022,
+ "scaleFactorY": 0.0022,
+ "image":"padheat.png",
+ "length":60,
+ "width":36,
+ "height":36,
+ "children": [
+ { "type":"showhide", "inputName":"rightpadtouch", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y": 0, "width":36, "height":36, "center":true } ] }
+ ]
+ }
+ ]
+ },
+
+ { "type":"showhide", "inputName":"leftpadclick" , "invert":false, "children": [ { "type":"image", "image":"btn-haptic.png", "x": -171, "y": -23, "width":156, "height":160, "center":true } ] },
+ {
+ "x": -171,
+ "y": -23,
+ "rot": 15,
+ "children": [
+ {
+ "type":"trailpad",
+ "inputName":"leftpadtouch",
+ "x": 0,
+ "y": 0,
+ "axisNameX":"leftpadx",
+ "axisNameY":"leftpady",
+ "scaleFactorX": 0.0022,
+ "scaleFactorY": 0.0022,
+ "image":"padheat.png",
+ "length":60,
+ "width":36,
+ "height":36,
+ "children": [
+ { "type":"showhide", "inputName":"leftpadtouch", "invert":false, "children": [ { "type":"image", "image":"btn-face.png", "x": 0, "y": 0, "width":36, "height":36, "center":true } ] }
+ ]
+ }
+ ]
+ },
+
+ {
+ "x":0,
+ "y":-170,
+ "children": [
+ { "type":"pbar", "axisName":"lefttrigger" , "background":"ff007894", "foreground":"ff00d2f8", "x": -65, "y": 0, "width":120, "height":15, "min":0, "max":255, "direction": "right" },
+ { "type":"pbar", "axisName":"righttrigger", "background":"ff007894", "foreground":"ff00d2f8", "x": 65, "y": 0, "width":120, "height":15, "min":0, "max":255, "direction": "left" }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/VSCView/themes/default/padheat.png b/VSCView/themes/default/padheat.png
new file mode 100644
index 0000000..492086e
Binary files /dev/null and b/VSCView/themes/default/padheat.png differ
diff --git a/VSCView/themes/default/stick.png b/VSCView/themes/default/stick.png
new file mode 100644
index 0000000..454c72d
Binary files /dev/null and b/VSCView/themes/default/stick.png differ