├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── OpenXR-Runtime-Switcher.sln ├── OpenXR-Runtime-Switcher ├── App.config ├── CustomRuntimeSaveListEntry.cs ├── Form_AddCustomRuntime.Designer.cs ├── Form_AddCustomRuntime.cs ├── Form_AddCustomRuntime.resx ├── ILMerge.props ├── ILMergeOrder.txt ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── OpenXR-Runtime-Switcher.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── NoLogo.png │ ├── Oculus.png │ ├── SteamVR.png │ ├── Varjo.png │ ├── Vive.png │ ├── WMR.png │ └── icon.png ├── RuntimeEntryControl.Designer.cs ├── RuntimeEntryControl.cs ├── RuntimeEntryControl.resx ├── RuntimeManager.cs ├── Runtimes │ ├── IOpenXRRuntime.cs │ ├── Runtime_Custom.cs │ ├── Runtime_Oculus.cs │ ├── Runtime_SteamVR.cs │ ├── Runtime_Varjo.cs │ ├── Runtime_ViveVR.cs │ └── Runtime_WMR.cs ├── StatusTypes.cs ├── app.manifest ├── icon.ico └── packages.config ├── README.md └── docs └── index.html /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: wagi_coding # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ['https://buymeacoff.ee/wagicoding'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 WaGi-Coding aka. Taki7o7 2 | OXR runtime detection helpers credits go mostly to - Copyright (c) 2021 KOGA Mitsuhiro in [OpenXRRuntimeSelector](https://github.com/shiena/OpenXRRuntimeSelector) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32126.315 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenXR-Runtime-Switcher", "OpenXR-Runtime-Switcher\OpenXR-Runtime-Switcher.csproj", "{EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Release|Any CPU = Release|Any CPU 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Debug|x64.ActiveCfg = Debug|x64 19 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Debug|x64.Build.0 = Debug|x64 20 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Release|x64.ActiveCfg = Release|x64 23 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {28D86E52-9C38-4EC6-A313-0EF80E57480E} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | True 15 | 16 | 17 | [] 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/CustomRuntimeSaveListEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace OpenXR_Runtime_Switcher 8 | { 9 | [Serializable] 10 | public struct CustomRuntimeSaveListEntry 11 | { 12 | public string Name { get; set; } 13 | public string JsonPath { get; set; } 14 | public string ImagePath { get; set; } 15 | 16 | public CustomRuntimeSaveListEntry(string name, string jsonPath, string imagePath) 17 | { 18 | Name = name; 19 | JsonPath = jsonPath; 20 | ImagePath = imagePath; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Form_AddCustomRuntime.Designer.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace OpenXR_Runtime_Switcher 3 | { 4 | partial class Form_AddCustomRuntime 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.components = new System.ComponentModel.Container(); 33 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form_AddCustomRuntime)); 34 | this.btnAdd = new System.Windows.Forms.Button(); 35 | this.btnCancel = new System.Windows.Forms.Button(); 36 | this.tbName = new System.Windows.Forms.TextBox(); 37 | this.tbPath = new System.Windows.Forms.TextBox(); 38 | this.lblName = new System.Windows.Forms.Label(); 39 | this.lblPath = new System.Windows.Forms.Label(); 40 | this.btnSearchPath = new System.Windows.Forms.Button(); 41 | this.openFileDialogLogo = new System.Windows.Forms.OpenFileDialog(); 42 | this.openFileDialogJsonPath = new System.Windows.Forms.OpenFileDialog(); 43 | this.tbImagePath = new System.Windows.Forms.TextBox(); 44 | this.lblImagePath = new System.Windows.Forms.Label(); 45 | this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); 46 | this.pictureBoxLogo = new System.Windows.Forms.PictureBox(); 47 | ((System.ComponentModel.ISupportInitialize)(this.pictureBoxLogo)).BeginInit(); 48 | this.SuspendLayout(); 49 | // 50 | // btnAdd 51 | // 52 | this.btnAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 53 | this.btnAdd.BackColor = System.Drawing.Color.Green; 54 | this.btnAdd.Cursor = System.Windows.Forms.Cursors.Hand; 55 | this.btnAdd.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 56 | this.btnAdd.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 57 | this.btnAdd.Location = new System.Drawing.Point(377, 189); 58 | this.btnAdd.Name = "btnAdd"; 59 | this.btnAdd.Size = new System.Drawing.Size(75, 23); 60 | this.btnAdd.TabIndex = 32; 61 | this.btnAdd.Text = "Add"; 62 | this.btnAdd.UseVisualStyleBackColor = false; 63 | this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); 64 | // 65 | // btnCancel 66 | // 67 | this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 68 | this.btnCancel.BackColor = System.Drawing.Color.DarkOrange; 69 | this.btnCancel.Cursor = System.Windows.Forms.Cursors.Hand; 70 | this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 71 | this.btnCancel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 72 | this.btnCancel.Location = new System.Drawing.Point(296, 189); 73 | this.btnCancel.Name = "btnCancel"; 74 | this.btnCancel.Size = new System.Drawing.Size(75, 23); 75 | this.btnCancel.TabIndex = 31; 76 | this.btnCancel.Text = "Cancel"; 77 | this.btnCancel.UseVisualStyleBackColor = false; 78 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 79 | // 80 | // tbName 81 | // 82 | this.tbName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 83 | | System.Windows.Forms.AnchorStyles.Right))); 84 | this.tbName.Location = new System.Drawing.Point(218, 35); 85 | this.tbName.Name = "tbName"; 86 | this.tbName.Size = new System.Drawing.Size(234, 20); 87 | this.tbName.TabIndex = 11; 88 | // 89 | // tbPath 90 | // 91 | this.tbPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 92 | | System.Windows.Forms.AnchorStyles.Right))); 93 | this.tbPath.Location = new System.Drawing.Point(218, 81); 94 | this.tbPath.Name = "tbPath"; 95 | this.tbPath.Size = new System.Drawing.Size(234, 20); 96 | this.tbPath.TabIndex = 21; 97 | // 98 | // lblName 99 | // 100 | this.lblName.AutoSize = true; 101 | this.lblName.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 102 | this.lblName.Location = new System.Drawing.Point(218, 12); 103 | this.lblName.Name = "lblName"; 104 | this.lblName.Size = new System.Drawing.Size(60, 20); 105 | this.lblName.TabIndex = 10; 106 | this.lblName.Text = "Name:"; 107 | // 108 | // lblPath 109 | // 110 | this.lblPath.AutoSize = true; 111 | this.lblPath.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 112 | this.lblPath.Location = new System.Drawing.Point(214, 58); 113 | this.lblPath.Name = "lblPath"; 114 | this.lblPath.Size = new System.Drawing.Size(95, 20); 115 | this.lblPath.TabIndex = 20; 116 | this.lblPath.Text = "Json-Path:"; 117 | // 118 | // btnSearchPath 119 | // 120 | this.btnSearchPath.BackColor = System.Drawing.SystemColors.ControlDark; 121 | this.btnSearchPath.Cursor = System.Windows.Forms.Cursors.Hand; 122 | this.btnSearchPath.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 123 | this.btnSearchPath.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 124 | this.btnSearchPath.Location = new System.Drawing.Point(218, 107); 125 | this.btnSearchPath.Name = "btnSearchPath"; 126 | this.btnSearchPath.Size = new System.Drawing.Size(75, 23); 127 | this.btnSearchPath.TabIndex = 22; 128 | this.btnSearchPath.Text = "Search"; 129 | this.btnSearchPath.UseVisualStyleBackColor = false; 130 | this.btnSearchPath.Click += new System.EventHandler(this.btnSearchPath_Click); 131 | // 132 | // openFileDialogLogo 133 | // 134 | this.openFileDialogLogo.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialogLogo_FileOk); 135 | // 136 | // openFileDialogJsonPath 137 | // 138 | this.openFileDialogJsonPath.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialogJsonPath_FileOk); 139 | // 140 | // tbImagePath 141 | // 142 | this.tbImagePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 143 | | System.Windows.Forms.AnchorStyles.Right))); 144 | this.tbImagePath.Location = new System.Drawing.Point(218, 156); 145 | this.tbImagePath.Name = "tbImagePath"; 146 | this.tbImagePath.Size = new System.Drawing.Size(234, 20); 147 | this.tbImagePath.TabIndex = 58; 148 | this.toolTip1.SetToolTip(this.tbImagePath, "Path of the Image you want to use as Logo\r\nLeave empty to use the default Logo."); 149 | // 150 | // lblImagePath 151 | // 152 | this.lblImagePath.AutoSize = true; 153 | this.lblImagePath.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 154 | this.lblImagePath.Location = new System.Drawing.Point(214, 133); 155 | this.lblImagePath.Name = "lblImagePath"; 156 | this.lblImagePath.Size = new System.Drawing.Size(97, 20); 157 | this.lblImagePath.TabIndex = 57; 158 | this.lblImagePath.Text = "Logo-Path:"; 159 | this.toolTip1.SetToolTip(this.lblImagePath, "Path of the Image you want to use as Logo\r\nLeave empty to use the default Logo."); 160 | // 161 | // pictureBoxLogo 162 | // 163 | this.pictureBoxLogo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 164 | this.pictureBoxLogo.Cursor = System.Windows.Forms.Cursors.Hand; 165 | this.pictureBoxLogo.Image = global::OpenXR_Runtime_Switcher.Properties.Resources.Logo_NoLogo; 166 | this.pictureBoxLogo.Location = new System.Drawing.Point(12, 12); 167 | this.pictureBoxLogo.Name = "pictureBoxLogo"; 168 | this.pictureBoxLogo.Size = new System.Drawing.Size(200, 200); 169 | this.pictureBoxLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 170 | this.pictureBoxLogo.TabIndex = 56; 171 | this.pictureBoxLogo.TabStop = false; 172 | this.pictureBoxLogo.Click += new System.EventHandler(this.pictureBoxLogo_Click); 173 | // 174 | // Form_AddCustomRuntime 175 | // 176 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 177 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 178 | this.BackColor = System.Drawing.SystemColors.ControlDarkDark; 179 | this.ClientSize = new System.Drawing.Size(464, 221); 180 | this.Controls.Add(this.lblImagePath); 181 | this.Controls.Add(this.tbImagePath); 182 | this.Controls.Add(this.btnSearchPath); 183 | this.Controls.Add(this.lblPath); 184 | this.Controls.Add(this.lblName); 185 | this.Controls.Add(this.tbPath); 186 | this.Controls.Add(this.tbName); 187 | this.Controls.Add(this.pictureBoxLogo); 188 | this.Controls.Add(this.btnCancel); 189 | this.Controls.Add(this.btnAdd); 190 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; 191 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 192 | this.MaximumSize = new System.Drawing.Size(999999999, 260); 193 | this.MinimumSize = new System.Drawing.Size(480, 260); 194 | this.Name = "Form_AddCustomRuntime"; 195 | this.Text = "OpenXR Runtime-Switcher | Add Custom Runtime"; 196 | ((System.ComponentModel.ISupportInitialize)(this.pictureBoxLogo)).EndInit(); 197 | this.ResumeLayout(false); 198 | this.PerformLayout(); 199 | 200 | } 201 | 202 | #endregion 203 | 204 | private System.Windows.Forms.Button btnAdd; 205 | private System.Windows.Forms.Button btnCancel; 206 | private System.Windows.Forms.PictureBox pictureBoxLogo; 207 | private System.Windows.Forms.TextBox tbName; 208 | private System.Windows.Forms.TextBox tbPath; 209 | private System.Windows.Forms.Label lblName; 210 | private System.Windows.Forms.Label lblPath; 211 | private System.Windows.Forms.Button btnSearchPath; 212 | private System.Windows.Forms.OpenFileDialog openFileDialogLogo; 213 | private System.Windows.Forms.OpenFileDialog openFileDialogJsonPath; 214 | private System.Windows.Forms.TextBox tbImagePath; 215 | private System.Windows.Forms.Label lblImagePath; 216 | private System.Windows.Forms.ToolTip toolTip1; 217 | } 218 | } -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Form_AddCustomRuntime.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace OpenXR_Runtime_Switcher 13 | { 14 | public partial class Form_AddCustomRuntime : Form 15 | { 16 | MainForm mainForm; 17 | 18 | public CustomRuntimeSaveListEntry EntryToAdd = new CustomRuntimeSaveListEntry("", "", ""); 19 | 20 | 21 | public Form_AddCustomRuntime(MainForm mainForm) 22 | { 23 | InitializeComponent(); 24 | 25 | this.mainForm = mainForm; 26 | } 27 | 28 | private void pictureBoxLogo_Click(object sender, EventArgs e) 29 | { 30 | this.openFileDialogLogo.Filter = "Image Files (*.PNG;*.JPG;*.JPEG)|*PNG;*.JPG;*.JPEG"; 31 | this.openFileDialogLogo.RestoreDirectory = true; 32 | this.openFileDialogLogo.Title = "Open an existing Image"; 33 | var result = openFileDialogLogo.ShowDialog(); 34 | if (result == DialogResult.OK) 35 | { 36 | pictureBoxLogo.Image = Image.FromFile(openFileDialogLogo.FileName); 37 | } 38 | } 39 | 40 | private void btnSearchPath_Click(object sender, EventArgs e) 41 | { 42 | this.openFileDialogJsonPath.Filter = "OpenXR Runtime JSON File (*.JSON;)|*JSON;"; 43 | this.openFileDialogJsonPath.RestoreDirectory = true; 44 | this.openFileDialogJsonPath.Title = "Open an existing Runtime JSON"; 45 | var result = openFileDialogJsonPath.ShowDialog(); 46 | if (result == DialogResult.OK) 47 | { 48 | tbPath.Text = openFileDialogJsonPath.FileName; 49 | } 50 | } 51 | 52 | private void btnCancel_Click(object sender, EventArgs e) 53 | { 54 | this.DialogResult = DialogResult.Cancel; 55 | this.Close(); 56 | } 57 | 58 | private void btnAdd_Click(object sender, EventArgs e) 59 | { 60 | List errorMessages = new List(); 61 | 62 | if (string.IsNullOrWhiteSpace(tbName.Text)) 63 | { 64 | errorMessages.Add("-| The Name cannot be empty."); 65 | } 66 | if (mainForm.rtm.CustomRuntimes.Select(x => x.Name).Contains(tbName.Text.ToLower(), StringComparer.OrdinalIgnoreCase)) 67 | { 68 | errorMessages.Add("-| This Name is already in use by a custom Runtime."); 69 | } 70 | if (!string.IsNullOrWhiteSpace(tbPath.Text)) 71 | { 72 | if (mainForm.rtm.PresetRuntimes.Select(x => x.JsonPath).Contains(tbPath.Text.ToLower(), StringComparer.OrdinalIgnoreCase)) 73 | { 74 | errorMessages.Add("-| This Json Path is already in use by a Preset."); 75 | } 76 | } 77 | else 78 | { 79 | errorMessages.Add("-| Json Path cannot be empty."); 80 | } 81 | if (mainForm.rtm.CustomRuntimes.Select(x => x.JsonPath).Contains(tbPath.Text.ToLower(), StringComparer.OrdinalIgnoreCase)) 82 | { 83 | errorMessages.Add("-| This Json Path is already in use by a custom Runtime."); 84 | } 85 | if (!tbPath.Text.ToLower().EndsWith(".json")) 86 | { 87 | errorMessages.Add("-| This Json path has no \".json\" Extension."); 88 | } 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | if (!File.Exists(tbImagePath.Text)) 99 | { 100 | if (errorMessages.Count != 0) 101 | { 102 | errorMessages.Add("-| Invalid Logo/Logo-Path!"); 103 | } 104 | else 105 | { 106 | if (MessageBox.Show("Invalid Logo/Logo-Path!" + "\n" + "Use default Logo instead?", "Add Custom Runtime", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 107 | { 108 | EntryToAdd.ImagePath = string.Empty; 109 | } 110 | 111 | else 112 | { 113 | return; 114 | } 115 | } 116 | } 117 | 118 | 119 | FileInfo fi = null; 120 | 121 | if (File.Exists(tbImagePath.Text)) 122 | { 123 | fi = new FileInfo(tbImagePath.Text); 124 | string ext = fi.Extension.ToLower(); 125 | if (ext != ".png" && ext != ".jpg" && ext != ".jpeg") 126 | { 127 | if (errorMessages.Count != 0) 128 | { 129 | errorMessages.Add("-| Invalid Logo Extension!"); 130 | } 131 | else 132 | { 133 | if (MessageBox.Show("Invalid Logo Extension!" + "\n" + "Use default Logo instead?", "Add Custom Runtime", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 134 | { 135 | EntryToAdd.ImagePath = string.Empty; 136 | } 137 | else 138 | { 139 | return; 140 | } 141 | } 142 | } 143 | else 144 | { 145 | EntryToAdd.ImagePath = tbImagePath.Text; 146 | } 147 | } 148 | 149 | 150 | 151 | if (errorMessages.Count > 0) 152 | { 153 | MessageBox.Show("Cannot Add Runtime!\n\n\n" + string.Join("\n\n", errorMessages)); 154 | return; 155 | } 156 | 157 | 158 | EntryToAdd.Name = tbName.Text; 159 | EntryToAdd.JsonPath = tbPath.Text; 160 | 161 | this.DialogResult = DialogResult.OK; 162 | this.Close(); 163 | } 164 | 165 | private void openFileDialogLogo_FileOk(object sender, CancelEventArgs e) 166 | { 167 | tbImagePath.Text = openFileDialogLogo.FileName; 168 | } 169 | 170 | private void openFileDialogJsonPath_FileOk(object sender, CancelEventArgs e) 171 | { 172 | tbPath.Text = openFileDialogJsonPath.FileName; 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/ILMerge.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/ILMergeOrder.txt: -------------------------------------------------------------------------------- 1 | # this file contains the partial list of the merged assemblies in the merge order 2 | # you can fill it from the obj\CONFIG\PROJECT.ilmerge generated on every build 3 | # and finetune merge order to your satisfaction 4 | 5 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace OpenXR_Runtime_Switcher 3 | { 4 | partial class MainForm 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.components = new System.ComponentModel.Container(); 33 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); 34 | this.flowLayoutPanelPresets = new System.Windows.Forms.FlowLayoutPanel(); 35 | this.menuStrip1 = new System.Windows.Forms.MenuStrip(); 36 | this.menuToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.WebsiteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.label1 = new System.Windows.Forms.Label(); 39 | this.flowLayoutPanelCustoms = new System.Windows.Forms.FlowLayoutPanel(); 40 | this.btnRefreshAll = new System.Windows.Forms.Button(); 41 | this.label2 = new System.Windows.Forms.Label(); 42 | this.btnAddCustom = new System.Windows.Forms.Button(); 43 | this.btnRemoveCustom = new System.Windows.Forms.Button(); 44 | this.panelSplash = new System.Windows.Forms.Panel(); 45 | this.pictureBox1 = new System.Windows.Forms.PictureBox(); 46 | this.timerSplash = new System.Windows.Forms.Timer(this.components); 47 | this.checkForUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 48 | this.menuStrip1.SuspendLayout(); 49 | this.panelSplash.SuspendLayout(); 50 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); 51 | this.SuspendLayout(); 52 | // 53 | // flowLayoutPanelPresets 54 | // 55 | this.flowLayoutPanelPresets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 56 | | System.Windows.Forms.AnchorStyles.Left))); 57 | this.flowLayoutPanelPresets.AutoScroll = true; 58 | this.flowLayoutPanelPresets.BackColor = System.Drawing.SystemColors.ControlDarkDark; 59 | this.flowLayoutPanelPresets.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 60 | this.flowLayoutPanelPresets.Location = new System.Drawing.Point(2, 27); 61 | this.flowLayoutPanelPresets.Name = "flowLayoutPanelPresets"; 62 | this.flowLayoutPanelPresets.Size = new System.Drawing.Size(375, 427); 63 | this.flowLayoutPanelPresets.TabIndex = 1; 64 | // 65 | // menuStrip1 66 | // 67 | this.menuStrip1.BackColor = System.Drawing.SystemColors.ControlDark; 68 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 69 | this.menuToolStripMenuItem}); 70 | this.menuStrip1.Location = new System.Drawing.Point(0, 0); 71 | this.menuStrip1.Name = "menuStrip1"; 72 | this.menuStrip1.Size = new System.Drawing.Size(763, 24); 73 | this.menuStrip1.TabIndex = 6; 74 | this.menuStrip1.Text = "menuStrip1"; 75 | // 76 | // menuToolStripMenuItem 77 | // 78 | this.menuToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 79 | this.WebsiteToolStripMenuItem, 80 | this.checkForUpdateToolStripMenuItem}); 81 | this.menuToolStripMenuItem.Name = "menuToolStripMenuItem"; 82 | this.menuToolStripMenuItem.Size = new System.Drawing.Size(50, 20); 83 | this.menuToolStripMenuItem.Text = "Menu"; 84 | this.menuToolStripMenuItem.MouseLeave += new System.EventHandler(this.ToolStripMenuItem_MouseLeave); 85 | this.menuToolStripMenuItem.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ToolStripMenuItem_MouseMove); 86 | // 87 | // WebsiteToolStripMenuItem 88 | // 89 | this.WebsiteToolStripMenuItem.Name = "WebsiteToolStripMenuItem"; 90 | this.WebsiteToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 91 | this.WebsiteToolStripMenuItem.Text = "Website"; 92 | this.WebsiteToolStripMenuItem.Click += new System.EventHandler(this.WebsiteStripMenuItem_Click); 93 | this.WebsiteToolStripMenuItem.MouseLeave += new System.EventHandler(this.ToolStripMenuItem_MouseLeave); 94 | this.WebsiteToolStripMenuItem.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ToolStripMenuItem_MouseMove); 95 | // 96 | // label1 97 | // 98 | this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 99 | | System.Windows.Forms.AnchorStyles.Left))); 100 | this.label1.AutoSize = true; 101 | this.label1.Location = new System.Drawing.Point(274, 480); 102 | this.label1.Name = "label1"; 103 | this.label1.Size = new System.Drawing.Size(0, 13); 104 | this.label1.TabIndex = 0; 105 | // 106 | // flowLayoutPanelCustoms 107 | // 108 | this.flowLayoutPanelCustoms.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 109 | | System.Windows.Forms.AnchorStyles.Left))); 110 | this.flowLayoutPanelCustoms.AutoScroll = true; 111 | this.flowLayoutPanelCustoms.BackColor = System.Drawing.SystemColors.ControlDarkDark; 112 | this.flowLayoutPanelCustoms.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 113 | this.flowLayoutPanelCustoms.Location = new System.Drawing.Point(383, 133); 114 | this.flowLayoutPanelCustoms.Name = "flowLayoutPanelCustoms"; 115 | this.flowLayoutPanelCustoms.Size = new System.Drawing.Size(375, 321); 116 | this.flowLayoutPanelCustoms.TabIndex = 7; 117 | this.flowLayoutPanelCustoms.Click += new System.EventHandler(this.MainForm_Click); 118 | // 119 | // btnRefreshAll 120 | // 121 | this.btnRefreshAll.BackColor = System.Drawing.SystemColors.ActiveBorder; 122 | this.btnRefreshAll.Cursor = System.Windows.Forms.Cursors.Hand; 123 | this.btnRefreshAll.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 124 | this.btnRefreshAll.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 125 | this.btnRefreshAll.Location = new System.Drawing.Point(383, 27); 126 | this.btnRefreshAll.Name = "btnRefreshAll"; 127 | this.btnRefreshAll.Size = new System.Drawing.Size(375, 34); 128 | this.btnRefreshAll.TabIndex = 51; 129 | this.btnRefreshAll.Text = "REFRESH ALL"; 130 | this.btnRefreshAll.UseVisualStyleBackColor = false; 131 | this.btnRefreshAll.Click += new System.EventHandler(this.btnRefreshAll_Click); 132 | // 133 | // label2 134 | // 135 | this.label2.AutoSize = true; 136 | this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 137 | this.label2.Location = new System.Drawing.Point(383, 68); 138 | this.label2.Name = "label2"; 139 | this.label2.Size = new System.Drawing.Size(263, 33); 140 | this.label2.TabIndex = 52; 141 | this.label2.Text = "Custom Runtimes"; 142 | this.label2.Click += new System.EventHandler(this.MainForm_Click); 143 | // 144 | // btnAddCustom 145 | // 146 | this.btnAddCustom.BackColor = System.Drawing.Color.Green; 147 | this.btnAddCustom.Cursor = System.Windows.Forms.Cursors.Hand; 148 | this.btnAddCustom.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 149 | this.btnAddCustom.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 150 | this.btnAddCustom.Location = new System.Drawing.Point(383, 104); 151 | this.btnAddCustom.Name = "btnAddCustom"; 152 | this.btnAddCustom.Size = new System.Drawing.Size(75, 23); 153 | this.btnAddCustom.TabIndex = 53; 154 | this.btnAddCustom.Text = "Add"; 155 | this.btnAddCustom.UseVisualStyleBackColor = false; 156 | this.btnAddCustom.Click += new System.EventHandler(this.btnAddCustom_Click); 157 | // 158 | // btnRemoveCustom 159 | // 160 | this.btnRemoveCustom.BackColor = System.Drawing.Color.DarkRed; 161 | this.btnRemoveCustom.Cursor = System.Windows.Forms.Cursors.Hand; 162 | this.btnRemoveCustom.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 163 | this.btnRemoveCustom.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 164 | this.btnRemoveCustom.Location = new System.Drawing.Point(464, 104); 165 | this.btnRemoveCustom.Name = "btnRemoveCustom"; 166 | this.btnRemoveCustom.Size = new System.Drawing.Size(75, 23); 167 | this.btnRemoveCustom.TabIndex = 54; 168 | this.btnRemoveCustom.Text = "Remove"; 169 | this.btnRemoveCustom.UseVisualStyleBackColor = false; 170 | this.btnRemoveCustom.Click += new System.EventHandler(this.btnRemoveCustom_Click); 171 | // 172 | // panelSplash 173 | // 174 | this.panelSplash.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 175 | | System.Windows.Forms.AnchorStyles.Left) 176 | | System.Windows.Forms.AnchorStyles.Right))); 177 | this.panelSplash.Controls.Add(this.pictureBox1); 178 | this.panelSplash.Location = new System.Drawing.Point(0, 0); 179 | this.panelSplash.Name = "panelSplash"; 180 | this.panelSplash.Size = new System.Drawing.Size(763, 466); 181 | this.panelSplash.TabIndex = 56; 182 | // 183 | // pictureBox1 184 | // 185 | this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 186 | | System.Windows.Forms.AnchorStyles.Left) 187 | | System.Windows.Forms.AnchorStyles.Right))); 188 | this.pictureBox1.Image = global::OpenXR_Runtime_Switcher.Properties.Resources.AppLogo; 189 | this.pictureBox1.Location = new System.Drawing.Point(12, 12); 190 | this.pictureBox1.Name = "pictureBox1"; 191 | this.pictureBox1.Size = new System.Drawing.Size(739, 442); 192 | this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 193 | this.pictureBox1.TabIndex = 0; 194 | this.pictureBox1.TabStop = false; 195 | // 196 | // timerSplash 197 | // 198 | this.timerSplash.Enabled = true; 199 | this.timerSplash.Interval = 1000; 200 | this.timerSplash.Tick += new System.EventHandler(this.timerSplash_Tick); 201 | // 202 | // checkForUpdateToolStripMenuItem 203 | // 204 | this.checkForUpdateToolStripMenuItem.Name = "checkForUpdateToolStripMenuItem"; 205 | this.checkForUpdateToolStripMenuItem.Size = new System.Drawing.Size(180, 22); 206 | this.checkForUpdateToolStripMenuItem.Text = "Check for Update"; 207 | this.checkForUpdateToolStripMenuItem.Click += new System.EventHandler(this.checkForUpdateToolStripMenuItem_Click); 208 | this.checkForUpdateToolStripMenuItem.MouseLeave += new System.EventHandler(this.ToolStripMenuItem_MouseLeave); 209 | this.checkForUpdateToolStripMenuItem.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ToolStripMenuItem_MouseMove); 210 | // 211 | // MainForm 212 | // 213 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 214 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 215 | this.BackColor = System.Drawing.SystemColors.ControlDarkDark; 216 | this.ClientSize = new System.Drawing.Size(763, 466); 217 | this.Controls.Add(this.panelSplash); 218 | this.Controls.Add(this.btnRemoveCustom); 219 | this.Controls.Add(this.btnAddCustom); 220 | this.Controls.Add(this.label2); 221 | this.Controls.Add(this.btnRefreshAll); 222 | this.Controls.Add(this.flowLayoutPanelCustoms); 223 | this.Controls.Add(this.label1); 224 | this.Controls.Add(this.flowLayoutPanelPresets); 225 | this.Controls.Add(this.menuStrip1); 226 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 227 | this.MainMenuStrip = this.menuStrip1; 228 | this.MaximumSize = new System.Drawing.Size(779, 99999999); 229 | this.MinimumSize = new System.Drawing.Size(779, 295); 230 | this.Name = "MainForm"; 231 | this.Text = "OpenXR Runtime-Switcher"; 232 | this.Click += new System.EventHandler(this.MainForm_Click); 233 | this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyUp); 234 | this.menuStrip1.ResumeLayout(false); 235 | this.menuStrip1.PerformLayout(); 236 | this.panelSplash.ResumeLayout(false); 237 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); 238 | this.ResumeLayout(false); 239 | this.PerformLayout(); 240 | 241 | } 242 | 243 | #endregion 244 | private System.Windows.Forms.FlowLayoutPanel flowLayoutPanelPresets; 245 | private System.Windows.Forms.MenuStrip menuStrip1; 246 | private System.Windows.Forms.ToolStripMenuItem menuToolStripMenuItem; 247 | private System.Windows.Forms.Button btnRefreshAll; 248 | private System.Windows.Forms.Label label2; 249 | private System.Windows.Forms.Button btnAddCustom; 250 | private System.Windows.Forms.ToolStripMenuItem WebsiteToolStripMenuItem; 251 | public System.Windows.Forms.Label label1; 252 | public System.Windows.Forms.Button btnRemoveCustom; 253 | public System.Windows.Forms.FlowLayoutPanel flowLayoutPanelCustoms; 254 | private System.Windows.Forms.Panel panelSplash; 255 | private System.Windows.Forms.PictureBox pictureBox1; 256 | private System.Windows.Forms.Timer timerSplash; 257 | private System.Windows.Forms.ToolStripMenuItem checkForUpdateToolStripMenuItem; 258 | } 259 | } 260 | 261 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/MainForm.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using OpenXR_Runtime_Switcher.Runtimes; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Data; 7 | using System.Drawing; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using System.Windows.Forms; 13 | using Newtonsoft.Json; 14 | using Newtonsoft.Json.Linq; 15 | using System.Reflection; 16 | using System.Diagnostics; 17 | using System.Net.Http; 18 | 19 | namespace OpenXR_Runtime_Switcher 20 | { 21 | public partial class MainForm : Form 22 | { 23 | private List PresetUCControls = new List(); 24 | private List CustomUCControls = new List(); 25 | 26 | public RuntimeManager rtm; 27 | 28 | public List customRuntimeSaveListEntries = new List(); 29 | 30 | public bool RemoveCustomModeOn = false; 31 | 32 | public MainForm() 33 | { 34 | InitializeComponent(); 35 | 36 | string version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); 37 | this.Text = "OpenXR Runtime-Switcher | v" + TrimTheEnd(version, ".0"); 38 | 39 | Application.EnableVisualStyles(); 40 | 41 | if (Properties.Settings.Default.UpgradeRequired) 42 | { 43 | Properties.Settings.Default.Upgrade(); 44 | Properties.Settings.Default.UpgradeRequired = false; 45 | Properties.Settings.Default.Save(); 46 | } 47 | 48 | 49 | 50 | 51 | // ########### Desirialize Settings ########### 52 | 53 | // Custom Runtimes 54 | customRuntimeSaveListEntries = JsonConvert.DeserializeObject>(Properties.Settings.Default.CustomRuntimes); 55 | 56 | // ############################################ 57 | 58 | 59 | 60 | 61 | rtm = new RuntimeManager(this); 62 | RefreshPanels(); 63 | 64 | 65 | // Fake Label Focus to get rid of initially focusing the first entries path textbox 66 | //this.ActiveControl = label1; 67 | //label1.Focus(); 68 | } 69 | 70 | public static string FirstLetterToUpperCaseOrConvertNullToEmptyString(string s) 71 | { 72 | if (string.IsNullOrEmpty(s)) 73 | return string.Empty; 74 | 75 | char[] a = s.ToCharArray(); 76 | a[0] = char.ToUpper(a[0]); 77 | return new string(a); 78 | } 79 | 80 | public void RefreshPanels() 81 | { 82 | Properties.Settings.Default.Reload(); 83 | customRuntimeSaveListEntries = JsonConvert.DeserializeObject>(Properties.Settings.Default.CustomRuntimes); 84 | 85 | if (rtm != null) 86 | { 87 | rtm.Refresh(); 88 | 89 | // Presets 90 | flowLayoutPanelPresets.Controls.Clear(); 91 | PresetUCControls = new List(); 92 | 93 | foreach (RuntimeEntryControl REC in rtm.GetEntryListPresets()) 94 | { 95 | PresetUCControls.Add(REC); 96 | } 97 | 98 | foreach (RuntimeEntryControl REC in PresetUCControls) 99 | { 100 | flowLayoutPanelPresets.Controls.Add(REC); 101 | } 102 | 103 | 104 | 105 | // Customs 106 | flowLayoutPanelCustoms.Controls.Clear(); 107 | CustomUCControls = new List(); 108 | 109 | foreach (RuntimeEntryControl REC in rtm.GetEntryListCustoms()) 110 | { 111 | CustomUCControls.Add(REC); 112 | } 113 | 114 | foreach (RuntimeEntryControl REC in CustomUCControls) 115 | { 116 | flowLayoutPanelCustoms.Controls.Add(REC); 117 | } 118 | 119 | // Fake Label Focus to get rid of initially focusing the first entries path textbox 120 | this.ActiveControl = label1; 121 | label1.Focus(); 122 | } 123 | } 124 | 125 | public bool SamePaths(string p1, string p2) 126 | { 127 | string path1 = p1; 128 | string path2 = p2; 129 | if (Path.IsPathRooted(path1) && Path.IsPathRooted(path2)) 130 | { 131 | path1 = FirstLetterToUpperCaseOrConvertNullToEmptyString(p1); 132 | path2 = FirstLetterToUpperCaseOrConvertNullToEmptyString(p2); 133 | } 134 | 135 | if (path1 == path2) 136 | { 137 | return true; 138 | } 139 | 140 | return false; 141 | } 142 | 143 | public string TrimTheEnd(string target, string trimString) 144 | { 145 | if (string.IsNullOrEmpty(trimString)) return target; 146 | 147 | string result = target; 148 | if (result.EndsWith(trimString)) 149 | { 150 | result = result.Substring(0, result.Length - trimString.Length); 151 | } 152 | 153 | return result; 154 | } 155 | 156 | private void ToolStripMenuItem_MouseMove(object sender, MouseEventArgs e) 157 | { 158 | this.Cursor = Cursors.Hand; 159 | } 160 | 161 | private void ToolStripMenuItem_MouseLeave(object sender, EventArgs e) 162 | { 163 | this.Cursor = Cursors.Default; 164 | } 165 | 166 | private void btnRefreshAll_Click(object sender, EventArgs e) 167 | { 168 | RefreshPanels(); 169 | } 170 | 171 | private void btnRemoveCustom_Click(object sender, EventArgs e) 172 | { 173 | if (flowLayoutPanelCustoms.Controls.Count < 1) 174 | { 175 | MessageBox.Show("There are no Custom Runtimes in the List to delete one of them."); 176 | return; 177 | } 178 | 179 | RemoveCustomModeOn = !RemoveCustomModeOn; 180 | if (RemoveCustomModeOn) 181 | { 182 | this.KeyPreview = true; 183 | btnRemoveCustom.Text = "Cancel"; 184 | btnRemoveCustom.BackColor = Color.DarkOrange; 185 | } 186 | else 187 | { 188 | this.KeyPreview = false; 189 | btnRemoveCustom.Text = "Remove"; 190 | btnRemoveCustom.BackColor = Color.DarkRed; 191 | } 192 | } 193 | 194 | private void btnAddCustom_Click(object sender, EventArgs e) 195 | { 196 | using (Form_AddCustomRuntime addCustomFrm = new Form_AddCustomRuntime(this)) 197 | { 198 | var result = addCustomFrm.ShowDialog(); 199 | 200 | if (result == DialogResult.OK) 201 | { 202 | customRuntimeSaveListEntries.Add(addCustomFrm.EntryToAdd); 203 | Properties.Settings.Default.CustomRuntimes = JsonConvert.SerializeObject(customRuntimeSaveListEntries); 204 | Properties.Settings.Default.Save(); 205 | RefreshPanels(); 206 | } 207 | } 208 | } 209 | 210 | private void WebsiteStripMenuItem_Click(object sender, EventArgs e) 211 | { 212 | Process.Start("https://wagi-coding.github.io/OpenXR-Runtime-Switcher"); 213 | } 214 | 215 | private void button5_Click(object sender, EventArgs e) 216 | { 217 | Properties.Settings.Default.Reload(); 218 | customRuntimeSaveListEntries = JsonConvert.DeserializeObject>(Properties.Settings.Default.CustomRuntimes); 219 | 220 | foreach (var item in customRuntimeSaveListEntries) 221 | { 222 | MessageBox.Show($"Name: {item.Name}\nJsonPath: {item.JsonPath}\nImagePath: {item.ImagePath}"); 223 | } 224 | } 225 | 226 | private void MainForm_KeyUp(object sender, KeyEventArgs e) 227 | { 228 | if (RemoveCustomModeOn && e.KeyCode == Keys.Escape) 229 | { 230 | RemoveCustomModeOn = false; 231 | btnRemoveCustom.Text = "Remove"; 232 | btnRemoveCustom.BackColor = Color.DarkRed; 233 | } 234 | } 235 | 236 | private void MainForm_Click(object sender, EventArgs e) 237 | { 238 | if (RemoveCustomModeOn) 239 | { 240 | RemoveCustomModeOn = false; 241 | btnRemoveCustom.Text = "Remove"; 242 | btnRemoveCustom.BackColor = Color.DarkRed; 243 | } 244 | 245 | this.ActiveControl = label1; 246 | label1.Focus(); 247 | } 248 | 249 | private void timerSplash_Tick(object sender, EventArgs e) 250 | { 251 | timerSplash.Enabled = false; 252 | this.Controls.Remove(panelSplash); 253 | CheckForUpdate(false); 254 | } 255 | 256 | private void checkForUpdateToolStripMenuItem_Click(object sender, EventArgs e) 257 | { 258 | CheckForUpdate(true); 259 | } 260 | public async void CheckForUpdate(bool showInfoMessages) 261 | { 262 | try 263 | { 264 | long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); 265 | 266 | using (HttpClient client = new HttpClient()) 267 | { 268 | client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); 269 | 270 | client.DefaultRequestHeaders.UserAgent.TryParseAdd("request");//Set the User Agent to "request" 271 | 272 | using (HttpResponseMessage response = client.GetAsync("https://api.github.com/repos/WaGi-Coding/OpenXR-Runtime-Switcher/releases/latest?ts=" + timestamp.ToString()).Result) 273 | { 274 | response.EnsureSuccessStatusCode(); 275 | string responseBody = await response.Content.ReadAsStringAsync(); 276 | 277 | string verStr = JObject.Parse(responseBody)["tag_name"].ToString(); 278 | Version ver = new Version(verStr); 279 | 280 | string appVerStr = Application.ProductVersion; 281 | Version appVer = new Version(appVerStr); 282 | 283 | bool needUpdate = ver.CompareTo(appVer) > 0; 284 | 285 | if (needUpdate) 286 | { 287 | if (MessageBox.Show($"There is an Update available!\n\n\nNew Version: {ver}\n\nYour Version: {appVer}\n\n\nDo you want to visit the Download Page?", "Update available!", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 288 | { 289 | Process.Start("https://github.com/WaGi-Coding/OpenXR-Runtime-Switcher/releases/latest"); 290 | } 291 | else 292 | { 293 | return; 294 | } 295 | } 296 | else 297 | { 298 | if (showInfoMessages) 299 | { 300 | MessageBox.Show("You are using the newest Version!\n\nNo Update needed..."); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | catch (Exception) 307 | { 308 | if (showInfoMessages) 309 | { 310 | MessageBox.Show("Error when checking for Update!"); 311 | } 312 | // Ignore any errors on update check for the "on start update check" 313 | } 314 | 315 | } 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/OpenXR-Runtime-Switcher.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Debug 8 | AnyCPU 9 | {EF8C31E1-DDE3-4DEC-A36D-D9475EA703D4} 10 | WinExe 11 | OpenXR_Runtime_Switcher 12 | OpenXR-Runtime-Switcher 13 | v4.8 14 | 512 15 | true 16 | true 17 | false 18 | 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | true 33 | 34 | 35 | 36 | 37 | x64 38 | true 39 | full 40 | false 41 | bin\Debug\ 42 | DEBUG;TRACE 43 | prompt 44 | 4 45 | false 46 | 47 | 48 | x64 49 | pdbonly 50 | true 51 | bin\Release\ 52 | TRACE 53 | prompt 54 | 4 55 | false 56 | 57 | 58 | true 59 | bin\x64\Debug\ 60 | DEBUG;TRACE 61 | full 62 | x64 63 | 7.3 64 | prompt 65 | 66 | 67 | bin\x64\Release\ 68 | TRACE 69 | true 70 | pdbonly 71 | x64 72 | 7.3 73 | prompt 74 | 75 | 76 | app.manifest 77 | 78 | 79 | icon.ico 80 | 81 | 82 | 83 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | Form 102 | 103 | 104 | Form_AddCustomRuntime.cs 105 | 106 | 107 | 108 | 109 | Form 110 | 111 | 112 | MainForm.cs 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | UserControl 125 | 126 | 127 | RuntimeEntryControl.cs 128 | 129 | 130 | Form_AddCustomRuntime.cs 131 | 132 | 133 | MainForm.cs 134 | 135 | 136 | ResXFileCodeGenerator 137 | Resources.Designer.cs 138 | Designer 139 | 140 | 141 | True 142 | Resources.resx 143 | True 144 | 145 | 146 | RuntimeEntryControl.cs 147 | 148 | 149 | 150 | 151 | 152 | SettingsSingleFileGenerator 153 | Settings.Designer.cs 154 | 155 | 156 | True 157 | Settings.settings 158 | True 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | False 167 | Microsoft .NET Framework 4.8 %28x86 and x64%29 168 | true 169 | 170 | 171 | False 172 | .NET Framework 3.5 SP1 173 | false 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace OpenXR_Runtime_Switcher 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new MainForm()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OpenXR Runtime-Switcher")] 9 | [assembly: AssemblyDescription("OpenXR Runtime-Switcher for Windows")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("WaGi-Coding")] 12 | [assembly: AssemblyProduct("Taki7o7's OpenXR Runtime-Switcher")] 13 | [assembly: AssemblyCopyright("Copyright © WaGi-Coding 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ef8c31e1-dde3-4dec-a36d-d9475ea703d4")] 24 | 25 | [assembly: AssemblyVersion("1.0.4")] 26 | [assembly: AssemblyFileVersion("1.0.4")] 27 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OpenXR_Runtime_Switcher.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenXR_Runtime_Switcher.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap AppLogo { 67 | get { 68 | object obj = ResourceManager.GetObject("AppLogo", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap Logo_NoLogo { 77 | get { 78 | object obj = ResourceManager.GetObject("Logo_NoLogo", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap Logo_Oculus { 87 | get { 88 | object obj = ResourceManager.GetObject("Logo_Oculus", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap Logo_SteamVR { 97 | get { 98 | object obj = ResourceManager.GetObject("Logo_SteamVR", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap Logo_Varjo { 107 | get { 108 | object obj = ResourceManager.GetObject("Logo_Varjo", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// Looks up a localized resource of type System.Drawing.Bitmap. 115 | /// 116 | internal static System.Drawing.Bitmap Logo_Vive { 117 | get { 118 | object obj = ResourceManager.GetObject("Logo_Vive", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | 123 | /// 124 | /// Looks up a localized resource of type System.Drawing.Bitmap. 125 | /// 126 | internal static System.Drawing.Bitmap Logo_WMR { 127 | get { 128 | object obj = ResourceManager.GetObject("Logo_WMR", resourceCulture); 129 | return ((System.Drawing.Bitmap)(obj)); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\NoLogo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\Oculus.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\SteamVR.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resources\Varjo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | 137 | ..\Resources\Vive.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | 140 | ..\Resources\WMR.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OpenXR_Runtime_Switcher.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 29 | public bool UpgradeRequired { 30 | get { 31 | return ((bool)(this["UpgradeRequired"])); 32 | } 33 | set { 34 | this["UpgradeRequired"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("[]")] 41 | public string CustomRuntimes { 42 | get { 43 | return ((string)(this["CustomRuntimes"])); 44 | } 45 | set { 46 | this["CustomRuntimes"] = value; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | True 7 | 8 | 9 | [] 10 | 11 | 12 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/NoLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/NoLogo.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/Oculus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/Oculus.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/SteamVR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/SteamVR.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/Varjo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/Varjo.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/Vive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/Vive.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/WMR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/WMR.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/Resources/icon.png -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/RuntimeEntryControl.Designer.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace OpenXR_Runtime_Switcher 3 | { 4 | partial class RuntimeEntryControl 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Component Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.components = new System.ComponentModel.Container(); 33 | this.lblRuntimeName = new System.Windows.Forms.Label(); 34 | this.tbPath = new System.Windows.Forms.TextBox(); 35 | this.labelPath = new System.Windows.Forms.Label(); 36 | this.btnCopyPath = new System.Windows.Forms.Button(); 37 | this.toolTipUC = new System.Windows.Forms.ToolTip(this.components); 38 | this.btnHandle = new System.Windows.Forms.Button(); 39 | this.pictureBox_RuntimeLogo = new System.Windows.Forms.PictureBox(); 40 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox_RuntimeLogo)).BeginInit(); 41 | this.SuspendLayout(); 42 | // 43 | // lblRuntimeName 44 | // 45 | this.lblRuntimeName.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 46 | this.lblRuntimeName.Location = new System.Drawing.Point(103, 3); 47 | this.lblRuntimeName.Name = "lblRuntimeName"; 48 | this.lblRuntimeName.Size = new System.Drawing.Size(244, 38); 49 | this.lblRuntimeName.TabIndex = 9999; 50 | this.lblRuntimeName.Text = "No Runtime Name Defined for this Entry"; 51 | this.lblRuntimeName.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 52 | this.lblRuntimeName.Click += new System.EventHandler(this.RuntimeEntryControl_Click); 53 | this.lblRuntimeName.MouseLeave += new System.EventHandler(this.RuntimeEntryControl_MouseLeave); 54 | this.lblRuntimeName.MouseMove += new System.Windows.Forms.MouseEventHandler(this.RuntimeEntryControl_MouseMove); 55 | // 56 | // tbPath 57 | // 58 | this.tbPath.Enabled = false; 59 | this.tbPath.Location = new System.Drawing.Point(132, 77); 60 | this.tbPath.Name = "tbPath"; 61 | this.tbPath.ReadOnly = true; 62 | this.tbPath.Size = new System.Drawing.Size(161, 20); 63 | this.tbPath.TabIndex = 2; 64 | this.tbPath.DoubleClick += new System.EventHandler(this.tbPath_DoubleClick); 65 | this.tbPath.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbPath_KeyDown); 66 | // 67 | // labelPath 68 | // 69 | this.labelPath.Location = new System.Drawing.Point(100, 75); 70 | this.labelPath.Name = "labelPath"; 71 | this.labelPath.Size = new System.Drawing.Size(32, 23); 72 | this.labelPath.TabIndex = 9999; 73 | this.labelPath.Text = "Path:"; 74 | this.labelPath.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; 75 | // 76 | // btnCopyPath 77 | // 78 | this.btnCopyPath.Cursor = System.Windows.Forms.Cursors.Hand; 79 | this.btnCopyPath.Enabled = false; 80 | this.btnCopyPath.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 81 | this.btnCopyPath.Font = new System.Drawing.Font("Arial", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 82 | this.btnCopyPath.ImageAlign = System.Drawing.ContentAlignment.TopCenter; 83 | this.btnCopyPath.Location = new System.Drawing.Point(299, 77); 84 | this.btnCopyPath.Name = "btnCopyPath"; 85 | this.btnCopyPath.Size = new System.Drawing.Size(48, 20); 86 | this.btnCopyPath.TabIndex = 3; 87 | this.btnCopyPath.Text = "COPY"; 88 | this.btnCopyPath.TextAlign = System.Drawing.ContentAlignment.TopCenter; 89 | this.toolTipUC.SetToolTip(this.btnCopyPath, "Copy Path to Clipboard"); 90 | this.btnCopyPath.UseMnemonic = false; 91 | this.btnCopyPath.UseVisualStyleBackColor = true; 92 | this.btnCopyPath.Click += new System.EventHandler(this.btnCopyPath_Click); 93 | // 94 | // btnHandle 95 | // 96 | this.btnHandle.BackColor = System.Drawing.Color.DarkRed; 97 | this.btnHandle.Cursor = System.Windows.Forms.Cursors.Hand; 98 | this.btnHandle.Enabled = false; 99 | this.btnHandle.FlatAppearance.BorderSize = 2; 100 | this.btnHandle.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 101 | this.btnHandle.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 102 | this.btnHandle.Location = new System.Drawing.Point(103, 44); 103 | this.btnHandle.Name = "btnHandle"; 104 | this.btnHandle.Size = new System.Drawing.Size(244, 27); 105 | this.btnHandle.TabIndex = 1; 106 | this.btnHandle.Text = "Error in determining the Status"; 107 | this.btnHandle.TextAlign = System.Drawing.ContentAlignment.TopCenter; 108 | this.btnHandle.UseVisualStyleBackColor = false; 109 | this.btnHandle.Click += new System.EventHandler(this.btnHandle_Click); 110 | // 111 | // pictureBox_RuntimeLogo 112 | // 113 | this.pictureBox_RuntimeLogo.Image = global::OpenXR_Runtime_Switcher.Properties.Resources.Logo_NoLogo; 114 | this.pictureBox_RuntimeLogo.Location = new System.Drawing.Point(3, 3); 115 | this.pictureBox_RuntimeLogo.Name = "pictureBox_RuntimeLogo"; 116 | this.pictureBox_RuntimeLogo.Size = new System.Drawing.Size(94, 94); 117 | this.pictureBox_RuntimeLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 118 | this.pictureBox_RuntimeLogo.TabIndex = 0; 119 | this.pictureBox_RuntimeLogo.TabStop = false; 120 | this.pictureBox_RuntimeLogo.Click += new System.EventHandler(this.RuntimeEntryControl_Click); 121 | this.pictureBox_RuntimeLogo.MouseLeave += new System.EventHandler(this.RuntimeEntryControl_MouseLeave); 122 | this.pictureBox_RuntimeLogo.MouseMove += new System.Windows.Forms.MouseEventHandler(this.RuntimeEntryControl_MouseMove); 123 | // 124 | // RuntimeEntryControl 125 | // 126 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 127 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 128 | this.BackColor = System.Drawing.Color.DarkGray; 129 | this.Controls.Add(this.btnHandle); 130 | this.Controls.Add(this.btnCopyPath); 131 | this.Controls.Add(this.labelPath); 132 | this.Controls.Add(this.tbPath); 133 | this.Controls.Add(this.lblRuntimeName); 134 | this.Controls.Add(this.pictureBox_RuntimeLogo); 135 | this.Name = "RuntimeEntryControl"; 136 | this.Size = new System.Drawing.Size(350, 100); 137 | this.Click += new System.EventHandler(this.RuntimeEntryControl_Click); 138 | this.MouseLeave += new System.EventHandler(this.RuntimeEntryControl_MouseLeave); 139 | this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.RuntimeEntryControl_MouseMove); 140 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox_RuntimeLogo)).EndInit(); 141 | this.ResumeLayout(false); 142 | this.PerformLayout(); 143 | 144 | } 145 | 146 | #endregion 147 | 148 | private System.Windows.Forms.PictureBox pictureBox_RuntimeLogo; 149 | private System.Windows.Forms.Label lblRuntimeName; 150 | private System.Windows.Forms.TextBox tbPath; 151 | private System.Windows.Forms.Label labelPath; 152 | private System.Windows.Forms.Button btnCopyPath; 153 | private System.Windows.Forms.ToolTip toolTipUC; 154 | private System.Windows.Forms.Button btnHandle; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/RuntimeEntryControl.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using OpenXR_Runtime_Switcher.Runtimes; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Data; 7 | using System.Drawing; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Forms; 12 | 13 | namespace OpenXR_Runtime_Switcher 14 | { 15 | public partial class RuntimeEntryControl : UserControl 16 | { 17 | public IOpenXRRuntime UCRuntime = null; 18 | private MainForm mainForm = null; 19 | private bool isCustom = false; 20 | 21 | public RuntimeEntryControl() 22 | { 23 | MessageBox.Show("This Component is not meant to be initialized without parameters"); 24 | InitializeComponent(); 25 | 26 | InitializeUC(null); 27 | } 28 | 29 | public RuntimeEntryControl(MainForm mainForm, IOpenXRRuntime runtime, bool isCustom) 30 | { 31 | InitializeComponent(); 32 | 33 | this.mainForm = mainForm; 34 | 35 | UCRuntime = runtime; 36 | 37 | this.isCustom = isCustom; 38 | 39 | InitializeUC(UCRuntime); 40 | 41 | 42 | } 43 | 44 | private void InitializeUC(IOpenXRRuntime runtime) 45 | { 46 | if (runtime == null) 47 | { 48 | pictureBox_RuntimeLogo.Image = Properties.Resources.Logo_NoLogo; 49 | 50 | btnHandle.Text = "Error in determining the Status"; 51 | btnHandle.BackColor = Color.Red; 52 | btnHandle.Enabled = false; 53 | 54 | btnCopyPath.Enabled = false; 55 | tbPath.Enabled = false; 56 | 57 | return; 58 | } 59 | 60 | switch (runtime.Status) 61 | { 62 | case ControlStatusType.NotInstalled: 63 | pictureBox_RuntimeLogo.Image = runtime.Logo; 64 | lblRuntimeName.Text = runtime.Name; 65 | tbPath.Text = runtime.JsonPath; 66 | 67 | btnHandle.Text = "Runtime not installed or found"; 68 | btnHandle.BackColor = Color.DarkRed; 69 | btnHandle.Enabled = false; 70 | 71 | if (isCustom) 72 | { 73 | btnCopyPath.Enabled = true; 74 | tbPath.Enabled = true; 75 | } 76 | else 77 | { 78 | btnCopyPath.Enabled = false; 79 | tbPath.Enabled = false; 80 | } 81 | break; 82 | case ControlStatusType.Installed: 83 | pictureBox_RuntimeLogo.Image = runtime.Logo; 84 | lblRuntimeName.Text = runtime.Name; 85 | tbPath.Text = runtime.JsonPath; 86 | 87 | btnHandle.Text = "Switch to this Runtime"; 88 | btnHandle.BackColor = Color.DarkOrange; 89 | btnHandle.Enabled = true; 90 | 91 | btnCopyPath.Enabled = true; 92 | tbPath.Enabled = true; 93 | break; 94 | case ControlStatusType.Active: 95 | pictureBox_RuntimeLogo.Image = runtime.Logo; 96 | lblRuntimeName.Text = runtime.Name; 97 | tbPath.Text = runtime.JsonPath; 98 | 99 | btnHandle.Text = "This is the ACTIVE Runtime"; 100 | btnHandle.BackColor = Color.Green; 101 | btnHandle.Enabled = false; 102 | 103 | btnCopyPath.Enabled = true; 104 | tbPath.Enabled = true; 105 | break; 106 | default: 107 | pictureBox_RuntimeLogo.Image = runtime.Logo; 108 | lblRuntimeName.Text = "No Name"; 109 | tbPath.Text = String.Empty; 110 | 111 | btnHandle.Text = "Error in determining the Status"; 112 | btnHandle.BackColor = Color.DarkRed; 113 | btnHandle.Enabled = false; 114 | 115 | if (isCustom) 116 | { 117 | btnCopyPath.Enabled = true; 118 | tbPath.Enabled = true; 119 | } 120 | else 121 | { 122 | btnCopyPath.Enabled = false; 123 | tbPath.Enabled = false; 124 | } 125 | break; 126 | } 127 | } 128 | 129 | private void btnCopyPath_Click(object sender, EventArgs e) 130 | { 131 | if (!String.IsNullOrWhiteSpace(tbPath.Text)) 132 | { 133 | Clipboard.SetDataObject(tbPath.Text); 134 | } 135 | } 136 | 137 | private void btnHandle_Click(object sender, EventArgs e) 138 | { 139 | try 140 | { 141 | RuntimeManager.TrySetActiveRuntimeJsonPath(UCRuntime.JsonPath); 142 | this.mainForm.RefreshPanels(); 143 | } 144 | catch (UnauthorizedAccessException) 145 | { 146 | MessageBox.Show("You need to run this Program as Administrator, in order to set a Runtime!"); 147 | return; 148 | } 149 | catch (Exception ex) 150 | { 151 | MessageBox.Show("Error when attempting to edit the Registry:\n" + ex.Message); 152 | } 153 | } 154 | 155 | private void tbPath_KeyDown(object sender, KeyEventArgs e) 156 | { 157 | if (e.Control && e.KeyCode == Keys.A) 158 | { 159 | tbPath.SelectAll(); 160 | } 161 | } 162 | 163 | private void tbPath_DoubleClick(object sender, EventArgs e) 164 | { 165 | tbPath.SelectAll(); 166 | } 167 | 168 | private void RuntimeEntryControl_MouseMove(object sender, MouseEventArgs e) 169 | { 170 | if (isCustom && mainForm.RemoveCustomModeOn && UCRuntime.Status != ControlStatusType.Active) 171 | { 172 | this.BackColor = Color.Red; 173 | Cursor.Current = Cursors.Hand; 174 | } 175 | else 176 | { 177 | this.BackColor = Color.DarkGray; 178 | Cursor.Current = Cursors.Default; 179 | } 180 | } 181 | private void RuntimeEntryControl_MouseLeave(object sender, EventArgs e) 182 | { 183 | if (isCustom) 184 | { 185 | this.BackColor = Color.DarkGray; 186 | Cursor.Current = Cursors.Default; 187 | } 188 | } 189 | 190 | private void RuntimeEntryControl_Click(object sender, EventArgs e) 191 | { 192 | if (isCustom && mainForm.RemoveCustomModeOn && UCRuntime.Status != ControlStatusType.Active) 193 | { 194 | Properties.Settings.Default.Reload(); 195 | mainForm.customRuntimeSaveListEntries = JsonConvert.DeserializeObject>(Properties.Settings.Default.CustomRuntimes); 196 | 197 | var entriesToRemove = mainForm.customRuntimeSaveListEntries.Where(x => x.Name == UCRuntime.Name && x.JsonPath == UCRuntime.JsonPath).ToList(); 198 | 199 | if (entriesToRemove != null && entriesToRemove.Count() == 1) 200 | { 201 | mainForm.customRuntimeSaveListEntries.Remove(entriesToRemove[0]); 202 | 203 | Properties.Settings.Default.CustomRuntimes = JsonConvert.SerializeObject(mainForm.customRuntimeSaveListEntries); 204 | Properties.Settings.Default.Save(); 205 | 206 | Cursor.Current = Cursors.Default; 207 | 208 | mainForm.RemoveCustomModeOn = false; 209 | mainForm.btnRemoveCustom.Text = "Remove"; 210 | mainForm.btnRemoveCustom.BackColor = Color.DarkRed; 211 | 212 | mainForm.RefreshPanels(); 213 | //mainForm.flowLayoutPanelCustoms.Controls.Remove(this); 214 | } 215 | else 216 | { 217 | MessageBox.Show("Error:\nCannot Remove!"); 218 | } 219 | } 220 | 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/RuntimeEntryControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/RuntimeManager.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using OpenXR_Runtime_Switcher.Runtimes; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace OpenXR_Runtime_Switcher 13 | { 14 | public class RuntimeManager 15 | { 16 | private const string OpenXRMajorApiVersion = "1"; 17 | private const string OpenXRKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\" + OpenXRMajorApiVersion; 18 | private const string OpenXRValue = "ActiveRuntime"; 19 | private MainForm MainForm_Ref; 20 | 21 | 22 | // Presets 23 | public List PresetRuntimes; 24 | public List FoundRuntimes; 25 | 26 | // Customs 27 | public List CustomRuntimes; 28 | public List FoundCustomRuntimes; 29 | 30 | 31 | public IOpenXRRuntime ActiveRuntime = null; 32 | 33 | private string activeRuntimePath = String.Empty; 34 | 35 | public RuntimeManager(MainForm mainForm) 36 | { 37 | MainForm_Ref = mainForm; 38 | 39 | Refresh(); 40 | } 41 | 42 | public List GetEntryListPresets() 43 | { 44 | List PresetControlsList = new List(); 45 | 46 | foreach (IOpenXRRuntime runtime in PresetRuntimes) 47 | { 48 | PresetControlsList.Add(new RuntimeEntryControl(MainForm_Ref, runtime, false)); 49 | } 50 | 51 | PresetControlsList = PresetControlsList.OrderBy(x => x.UCRuntime.Status).ThenBy(x => x.UCRuntime.Name).ToList(); 52 | 53 | return PresetControlsList; 54 | } 55 | 56 | public List GetEntryListCustoms() 57 | { 58 | List CustomControlsList = new List(); 59 | 60 | foreach (IOpenXRRuntime runtime in CustomRuntimes) 61 | { 62 | CustomControlsList.Add(new RuntimeEntryControl(MainForm_Ref, runtime, true)); 63 | } 64 | 65 | CustomControlsList = CustomControlsList.OrderBy(x => x.UCRuntime.Status).ThenBy(x => x.UCRuntime.Name).ToList(); 66 | 67 | return CustomControlsList; 68 | } 69 | 70 | public void Refresh() 71 | { 72 | 73 | activeRuntimePath = GetActiveRuntimeJsonPath(); 74 | 75 | 76 | // ############### Presets ############### 77 | 78 | PresetRuntimes = new List 79 | { 80 | new Runtime_WMR(), 81 | new Runtime_SteamVR(), 82 | new Runtime_Oculus(), 83 | new Runtime_ViveVR(), 84 | new Runtime_Varjo(), 85 | }; 86 | 87 | FoundRuntimes = PresetRuntimes 88 | .Select(FindRuntime) 89 | .Where(e => e.result) 90 | .Select(e => e.runtime) 91 | .ToList(); 92 | 93 | // Update UC for all Preset Runtimes 94 | foreach (IOpenXRRuntime runtime in PresetRuntimes) 95 | { 96 | // Update Status 97 | if (FoundRuntimes.Contains(runtime)) 98 | { 99 | if (runtime.JsonPath.ToLower() == activeRuntimePath.ToLower()) 100 | { 101 | runtime.Status = ControlStatusType.Active; 102 | } 103 | else 104 | { 105 | runtime.Status = ControlStatusType.Installed; 106 | } 107 | } 108 | else 109 | { 110 | runtime.Status = ControlStatusType.NotInstalled; 111 | } 112 | } 113 | 114 | 115 | // ############### Customs ############### 116 | CustomRuntimes = new List(); 117 | 118 | foreach (CustomRuntimeSaveListEntry entry in MainForm_Ref.customRuntimeSaveListEntries) 119 | { 120 | Image img; 121 | if (String.IsNullOrWhiteSpace(entry.ImagePath)) 122 | { 123 | img = Properties.Resources.Logo_NoLogo; 124 | } 125 | else 126 | { 127 | try 128 | { 129 | img = Image.FromFile(entry.ImagePath); 130 | } 131 | catch (Exception) 132 | { 133 | img = Properties.Resources.Logo_NoLogo; 134 | } 135 | } 136 | Runtime_Custom cstmRuntime = new Runtime_Custom() { Name=entry.Name, JsonPath=entry.JsonPath, Logo=img, Status=ControlStatusType.NotInstalled }; 137 | CustomRuntimes.Add(cstmRuntime); 138 | } 139 | 140 | FoundCustomRuntimes = CustomRuntimes 141 | .Select(FindRuntime) 142 | .Where(e => e.result) 143 | .Select(e => e.runtime) 144 | .ToList(); 145 | 146 | // Update UC for all Custom Runtimes 147 | foreach (IOpenXRRuntime runtime in CustomRuntimes) 148 | { 149 | // Update Status 150 | if (FoundCustomRuntimes.Contains(runtime)) 151 | { 152 | if (runtime.JsonPath.ToLower() == activeRuntimePath.ToLower()) 153 | { 154 | runtime.Status = ControlStatusType.Active; 155 | } 156 | else 157 | { 158 | runtime.Status = ControlStatusType.Installed; 159 | } 160 | } 161 | else 162 | { 163 | runtime.Status = ControlStatusType.NotInstalled; 164 | } 165 | } 166 | } 167 | 168 | private static (bool result, string path, IOpenXRRuntime runtime) FindRuntime(IOpenXRRuntime e) 169 | { 170 | bool result = e.TryGetJsonPath(out var path); 171 | 172 | return (result, path, e); 173 | } 174 | 175 | public string GetActiveRuntimeJsonPath() 176 | { 177 | var pathValue = Registry.GetValue(OpenXRKey, OpenXRValue, string.Empty); 178 | if (pathValue is string path && !string.IsNullOrWhiteSpace(path)) 179 | { 180 | if (File.Exists(path)) 181 | { 182 | return Path.GetFullPath(path); 183 | } 184 | } 185 | 186 | return String.Empty; 187 | } 188 | 189 | 190 | // Needs Administrator rights! 191 | public static void TrySetActiveRuntimeJsonPath(string jsonPath) 192 | { 193 | Registry.SetValue(OpenXRKey, OpenXRValue, jsonPath, RegistryValueKind.ExpandString); 194 | } 195 | 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/IOpenXRRuntime.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 KOGA Mitsuhiro Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Drawing; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace OpenXR_Runtime_Switcher.Runtimes 13 | { 14 | public interface IOpenXRRuntime 15 | { 16 | string Name { get; set; } 17 | string JsonPath { get; set; } 18 | ControlStatusType? Status { get; set; } 19 | Image Logo { get; set; } 20 | bool TryGetJsonPath(out string jsonPath); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/Runtime_Custom.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Drawing; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Text.RegularExpressions; 9 | using System.Threading.Tasks; 10 | 11 | namespace OpenXR_Runtime_Switcher.Runtimes 12 | { 13 | internal class Runtime_Custom : IOpenXRRuntime 14 | { 15 | private string name = "Custom Runtime"; 16 | private string jsonPath = String.Empty; 17 | private ControlStatusType? status = ControlStatusType.NotInstalled; 18 | private Image logo = Properties.Resources.Logo_NoLogo; 19 | 20 | public string Name 21 | { 22 | get => this.name; 23 | set 24 | { 25 | this.name = value; 26 | } 27 | } 28 | public string JsonPath 29 | { 30 | get => this.jsonPath; 31 | set 32 | { 33 | this.jsonPath = value; 34 | } 35 | } 36 | 37 | public ControlStatusType? Status 38 | { 39 | get => this.status; 40 | set 41 | { 42 | this.status = value; 43 | } 44 | } 45 | 46 | public Image Logo 47 | { 48 | get => this.logo; 49 | set 50 | { 51 | this.logo = value; 52 | } 53 | } 54 | 55 | public bool TryGetJsonPath(out string jsonPath) 56 | { 57 | string path = this.jsonPath; 58 | if (File.Exists(Path.Combine(path))) 59 | { 60 | jsonPath = Path.GetFullPath(path); 61 | JsonPath = jsonPath; 62 | return true; 63 | } 64 | 65 | jsonPath = Path.GetFullPath(path); 66 | return false; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/Runtime_Oculus.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 KOGA Mitsuhiro Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Text.RegularExpressions; 13 | using System.Threading.Tasks; 14 | 15 | namespace OpenXR_Runtime_Switcher.Runtimes 16 | { 17 | internal class Runtime_Oculus : IOpenXRRuntime 18 | { 19 | private string name = "Oculus"; 20 | private string jsonPath = String.Empty; 21 | private ControlStatusType? status = ControlStatusType.NotInstalled; 22 | private Image logo = Properties.Resources.Logo_Oculus; 23 | 24 | 25 | private const string InstallLocKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Oculus"; 26 | private const string InstallLocValue = "InstallLocation"; 27 | private const string JsonName = @"Support\oculus-runtime\oculus_openxr_64.json"; 28 | 29 | public string Name 30 | { 31 | get => name; 32 | set 33 | { 34 | this.name = value; 35 | } 36 | } 37 | public string JsonPath 38 | { 39 | get => this.jsonPath; 40 | set 41 | { 42 | this.jsonPath = value; 43 | } 44 | } 45 | 46 | public ControlStatusType? Status 47 | { 48 | get => this.status; 49 | set 50 | { 51 | this.status = value; 52 | } 53 | } 54 | 55 | public Image Logo 56 | { 57 | get => this.logo; 58 | set 59 | { 60 | this.logo = value; 61 | } 62 | } 63 | 64 | public bool TryGetJsonPath(out string jsonPath) 65 | { 66 | var oculusPathValue = Registry.GetValue(InstallLocKey, InstallLocValue, string.Empty); 67 | if (oculusPathValue is string oculusPath && !string.IsNullOrWhiteSpace(oculusPath)) 68 | { 69 | var path = Path.Combine(oculusPath, JsonName); 70 | if (File.Exists(path)) 71 | { 72 | jsonPath = Path.GetFullPath(path); 73 | JsonPath = jsonPath; 74 | return true; 75 | } 76 | } 77 | 78 | jsonPath = String.Empty; 79 | JsonPath = jsonPath; 80 | return false; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/Runtime_SteamVR.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 KOGA Mitsuhiro Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Text.RegularExpressions; 13 | using System.Threading.Tasks; 14 | 15 | namespace OpenXR_Runtime_Switcher.Runtimes 16 | { 17 | internal class Runtime_SteamVR : IOpenXRRuntime 18 | { 19 | private string name = "SteamVR"; 20 | private string jsonPath = String.Empty; 21 | private ControlStatusType? status = ControlStatusType.NotInstalled; 22 | private Image logo = Properties.Resources.Logo_SteamVR; 23 | 24 | private const string SteamPathKey = @"HKEY_CURRENT_USER\SOFTWARE\Valve\Steam"; 25 | private const string SteamPathValue = "SteamPath"; 26 | private const string LibraryFoldersVdf = "steamapps/libraryfolders.vdf"; 27 | private const string LibraryFoldersKey = "\"LibraryFolders\""; 28 | private const string JsonName = @"steamapps/common/SteamVR/steamxr_win64.json"; 29 | private static readonly Regex RxKeyValue = new Regex(@"^[0-9]+$"); 30 | 31 | 32 | public string Name 33 | { 34 | get => name; 35 | set 36 | { 37 | this.name = value; 38 | } 39 | } 40 | public string JsonPath 41 | { 42 | get => jsonPath; 43 | set 44 | { 45 | this.jsonPath = value; 46 | } 47 | } 48 | 49 | public ControlStatusType? Status 50 | { 51 | get => this.status; 52 | set 53 | { 54 | this.status = value; 55 | } 56 | } 57 | 58 | public Image Logo 59 | { 60 | get => this.logo; 61 | set 62 | { 63 | this.logo = value; 64 | } 65 | } 66 | 67 | public bool TryGetJsonPath(out string jsonPath) 68 | { 69 | jsonPath = String.Empty; 70 | this.jsonPath = jsonPath; 71 | var steamPathValue = Registry.GetValue(SteamPathKey, SteamPathValue, string.Empty); 72 | if (!(steamPathValue is string steamPath)) 73 | { 74 | return false; 75 | } 76 | 77 | if (string.IsNullOrWhiteSpace(steamPath)) 78 | { 79 | return false; 80 | } 81 | 82 | var libraryFolders = Path.Combine(steamPath, LibraryFoldersVdf); 83 | if (!File.Exists(libraryFolders)) 84 | { 85 | return false; 86 | } 87 | 88 | var folders = new List { steamPath }; 89 | using (var sr = new StreamReader(libraryFolders)) 90 | { 91 | var line = sr.ReadLine()?.Trim(); 92 | if (string.Compare(line, LibraryFoldersKey, StringComparison.OrdinalIgnoreCase) != 0) 93 | { 94 | return false; 95 | } 96 | 97 | line = sr.ReadLine()?.Trim(); 98 | if (line != "{") 99 | { 100 | return false; 101 | } 102 | 103 | line = sr.ReadLine()?.Trim(); 104 | while (line != null && line != "{") 105 | { 106 | var m = RxKeyValue.Match(line); 107 | if (m.Success) 108 | { 109 | folders.Add(m.Groups[1].Value.Replace(@"\\", @"\")); 110 | } 111 | 112 | line = sr.ReadLine()?.Trim(); 113 | } 114 | } 115 | 116 | foreach (var folder in folders) 117 | { 118 | var path = Path.Combine(folder, JsonName); 119 | if (File.Exists(path)) 120 | { 121 | jsonPath = Path.GetFullPath(path); 122 | this.jsonPath = jsonPath; 123 | return true; 124 | } 125 | } 126 | 127 | return false; 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/Runtime_Varjo.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 KOGA Mitsuhiro Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Text.RegularExpressions; 13 | using System.Threading.Tasks; 14 | 15 | namespace OpenXR_Runtime_Switcher.Runtimes 16 | { 17 | internal class Runtime_Varjo : IOpenXRRuntime 18 | { 19 | private string name = "Varjo"; 20 | private string jsonPath = String.Empty; 21 | private ControlStatusType? status = ControlStatusType.NotInstalled; 22 | private Image logo = Properties.Resources.Logo_Varjo; 23 | 24 | private const string VarjoRuntimeKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Varjo\Runtime"; 25 | private const string InstallDirKey = "InstallDir"; 26 | private const string JsonName = @"varjo-openxr/VarjoOpenXR.json"; 27 | 28 | 29 | public string Name 30 | { 31 | get => name; 32 | set 33 | { 34 | this.name = value; 35 | } 36 | } 37 | public string JsonPath 38 | { 39 | get => jsonPath; 40 | set 41 | { 42 | this.jsonPath = value; 43 | } 44 | } 45 | 46 | public ControlStatusType? Status 47 | { 48 | get => this.status; 49 | set 50 | { 51 | this.status = value; 52 | } 53 | } 54 | 55 | public Image Logo 56 | { 57 | get => this.logo; 58 | set 59 | { 60 | this.logo = value; 61 | } 62 | } 63 | 64 | public bool TryGetJsonPath(out string jsonPath) 65 | { 66 | jsonPath = String.Empty; 67 | this.jsonPath = jsonPath; 68 | var varjoPathValue = Registry.GetValue(VarjoRuntimeKey, InstallDirKey, string.Empty); 69 | if (!(varjoPathValue is string vivePath)) 70 | { 71 | return false; 72 | } 73 | 74 | if (string.IsNullOrWhiteSpace(vivePath)) 75 | { 76 | return false; 77 | } 78 | 79 | var path = Path.Combine(vivePath, JsonName); 80 | 81 | if (File.Exists(path)) 82 | { 83 | jsonPath = Path.GetFullPath(path); 84 | this.jsonPath = jsonPath; 85 | return true; 86 | } 87 | 88 | return false; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/Runtime_ViveVR.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 KOGA Mitsuhiro Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Text.RegularExpressions; 13 | using System.Threading.Tasks; 14 | 15 | namespace OpenXR_Runtime_Switcher.Runtimes 16 | { 17 | internal class Runtime_ViveVR : IOpenXRRuntime 18 | { 19 | private string name = "ViveVR"; 20 | private string jsonPath = String.Empty; 21 | private ControlStatusType? status = ControlStatusType.NotInstalled; 22 | private Image logo = Properties.Resources.Logo_Vive; 23 | 24 | private const string VivePathKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\HtcVive\Updater"; 25 | private const string AppPathKey = "AppPath"; 26 | private const string JsonName = @"App/ViveVRRuntime/ViveVR_openxr/ViveOpenXR.json"; 27 | 28 | 29 | public string Name 30 | { 31 | get => name; 32 | set 33 | { 34 | this.name = value; 35 | } 36 | } 37 | public string JsonPath 38 | { 39 | get => jsonPath; 40 | set 41 | { 42 | this.jsonPath = value; 43 | } 44 | } 45 | 46 | public ControlStatusType? Status 47 | { 48 | get => this.status; 49 | set 50 | { 51 | this.status = value; 52 | } 53 | } 54 | 55 | public Image Logo 56 | { 57 | get => this.logo; 58 | set 59 | { 60 | this.logo = value; 61 | } 62 | } 63 | 64 | public bool TryGetJsonPath(out string jsonPath) 65 | { 66 | jsonPath = String.Empty; 67 | this.jsonPath = jsonPath; 68 | var vivePathValue = Registry.GetValue(VivePathKey, AppPathKey, string.Empty); 69 | if (!(vivePathValue is string vivePath)) 70 | { 71 | return false; 72 | } 73 | 74 | if (string.IsNullOrWhiteSpace(vivePath)) 75 | { 76 | return false; 77 | } 78 | 79 | var path = Path.Combine(vivePath, JsonName); 80 | 81 | if (File.Exists(path)) 82 | { 83 | jsonPath = Path.GetFullPath(path); 84 | this.jsonPath = jsonPath; 85 | return true; 86 | } 87 | 88 | return false; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/Runtimes/Runtime_WMR.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 KOGA Mitsuhiro Authors. All rights reserved. 2 | // Use of this source code is governed by a MIT-style 3 | // license that can be found in the LICENSE file. 4 | 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Text.RegularExpressions; 13 | using System.Threading.Tasks; 14 | 15 | namespace OpenXR_Runtime_Switcher.Runtimes 16 | { 17 | internal class Runtime_WMR : IOpenXRRuntime 18 | { 19 | private string name = "Windows Mixed Reality"; 20 | private string jsonPath = String.Empty; 21 | private ControlStatusType? status = ControlStatusType.NotInstalled; 22 | private Image logo = Properties.Resources.Logo_WMR; 23 | 24 | 25 | private const string JsonName = "MixedRealityRuntime.json"; 26 | 27 | 28 | public string Name 29 | { 30 | get => name; 31 | set 32 | { 33 | this.name = value; 34 | } 35 | } 36 | public string JsonPath 37 | { 38 | get => jsonPath; 39 | set 40 | { 41 | this.jsonPath = value; 42 | } 43 | } 44 | 45 | public ControlStatusType? Status 46 | { 47 | get => this.status; 48 | set 49 | { 50 | this.status = value; 51 | } 52 | } 53 | 54 | public Image Logo 55 | { 56 | get => this.logo; 57 | set 58 | { 59 | this.logo = value; 60 | } 61 | } 62 | 63 | public bool TryGetJsonPath(out string jsonPath) 64 | { 65 | var systemPath = Environment.GetFolderPath(Environment.SpecialFolder.System); 66 | var path = Path.Combine(systemPath, JsonName); 67 | if (File.Exists(path)) 68 | { 69 | jsonPath = Path.GetFullPath(path); 70 | this.jsonPath = jsonPath; 71 | return true; 72 | } 73 | 74 | jsonPath = String.Empty; 75 | this.jsonPath = jsonPath; 76 | return false; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/StatusTypes.cs: -------------------------------------------------------------------------------- 1 | namespace OpenXR_Runtime_Switcher 2 | { 3 | public enum ControlStatusType 4 | { 5 | Active, 6 | Installed, 7 | NotInstalled, 8 | } 9 | } -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 55 | 63 | 64 | 65 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WaGi-Coding/OpenXR-Runtime-Switcher/50deb940e934b2afcc16694fdbcb96628792a059/OpenXR-Runtime-Switcher/icon.ico -------------------------------------------------------------------------------- /OpenXR-Runtime-Switcher/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenXR Runtime-Switcher 2 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/WaGi-Coding/OpenXR-Runtime-Switcher?label=latest%20release&style=for-the-badge) 3 | ![GitHub all releases](https://img.shields.io/github/downloads/WaGi-Coding/OpenXR-Runtime-Switcher/total?label=Github%20Release%20Downloads&style=for-the-badge) 4 | 5 | ![GitHub Repo stars](https://img.shields.io/github/stars/WaGi-Coding/OpenXR-Runtime-Switcher?style=social) 6 | 7 | 8 |

9 | Download 10 |

11 | 12 | --- 13 | 14 |

15 | 16 |

17 | 18 |

19 | Allows you to quickly switch your System Default OpenXR Runtime between existing ones (currently SteamVR, Oculus/Meta, ViveVR, Windows Mixed Reality & Varjo) if installed & custom ones, which you can add manually to the program. 20 |

21 | 22 | 23 |

24 | 25 |

26 | 27 |

28 | 29 |

30 | 31 | 32 |

33 | I've made this because for example SteamVR only gives you the option to set it's Runtime as System Default OXR Runtime via the Developer Tab, when you've a Headset connected to it - which is/was annoying. 34 |

35 | 36 |

37 | Let me know if you find any bugs or if you have any questions. Here in Issues tab, or via Discord: Taki7o7#0860 38 |

39 | 40 |

41 | Also if you want me to add more Runtime "Presets". 42 |

43 | 44 | --- 45 | 46 | ## Additional Info 47 | 48 | - The presets try to automatically detect the programs with a runtime via the registry key, in order to make the detection work with different installation paths. 49 | - The program does not check the validity of a runtimes json file! 50 | - This program only changes the SYSTEM DEFAULT OpenXR Runtime, a Game could internally pick/require a/the non System Default one manually! 51 | - The program needs administrator rights, in order to set the runtime registry key! 52 | - Normally, it should automatically request Admin Rights. I've heard thats not the case for some people, most likely on Windows 11. Make sure it runs as administrator, otherwise you cannot actually switch the runtime (needs permission to edit the registry key for that) 53 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | OpenXR Runtime-Switcher | by WaGi-Coding aka. Taki7o7 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 46 | 47 | 48 | 49 |
50 | 51 | --------------------------------------------------------------------------------