@anon74848233 @PimaxUSA is this feature still coming along soon? It’s tiring having to fiddle with settings every time opening a different game.
A button added under each game in pitool with preferences including individual game configuration settings seems like the easiest way to do this.
That has been in the roadmap for a while (and I agree completely it’s among the most important pieces) but we wanted to get the baseline control settings into PiTool first prior to profiles. There are already some structural pieces in there now for that.
We’ll be putting some more info out on this later this month.
@mojojojo do you think we might be able to do something like this via a batch/script file? Replacing Json file of pitool settings, restarting pitool service & Steamvr to push changes to headset?
If possible to have pitool execute batchfiles/scripts.
Creating a backup of the current configuration and keeping one for each game is easy, it’s just making a copy and you’re done.
All that is necessary is having the hmd reload the values via restarting the PiServiceLauncher.
It’s uncertain if the setting files would have to be recreated with PiTool upgrades.
%LOCALAPPDATA%\pimax\runtime\profile.json
But it would be much more preferable for PiTool to keep them in a local database.
There aren’t that many values to keep track of at the moment, so effort for Pimax would be limited.
Optionally saving the SteamVR SS settings would also be cool.
Agreed but this could be a good Diy solution in the meanwhile.
For what it’s worth, here is a crude implementation, totally without warranty and unmaintained.
Backup:
@echo off
xcopy "%LOCALAPPDATA%\pimax\runtime\profile.json" .
Will copy the current profile.json into the folder where the batch file is located.
For the restore scripts, I’d suggest using a folder structure like this:
The leading numbers are optional.
Simple restore:
@echo off
SETLOCAL
SET "profile="
SET srcfile=%profile%\profile.json
IF exist "%srcfile%" (
echo copying "%srcfile%" to "%LOCALAPPDATA%\pimax\runtime"
xcopy /y "%srcfile%" "%LOCALAPPDATA%\pimax\runtime"
PAUSE
) ELSE (
echo ERROR: "%srcfile%" does not exist
)
ENDLOCAL
All that is necessary is to create a batch file for each game and set the “profile” parameter to the directory containing the profile.json e.g.:
SET "profile=01 IL2"
Interactive restore:
@echo off
:while
SETLOCAL
SET "profile="
SET "source="
SET cnt=0
SET /p profile="Enter profile: "
IF "%profile%"=="" (
echo ERROR: please enter a profile
GOTO :while
)
FOR /f "delims=?" %%A IN ('dir /ad /b "*%profile%*"') DO (
SET source=%%A
SET /A cnt=cnt+1
)
SET srcfile=%source%\profile.json
IF "%cnt%"=="1" (
IF exist "%srcfile%" (
echo copying "%srcfile%" to "%LOCALAPPDATA%\pimax\runtime"
xcopy /y "%srcfile%" "%LOCALAPPDATA%\pimax\runtime"
PAUSE
GOTO :end
) ELSE (
echo ERROR: %srcfile% does not exist
)
)
IF "%cnt%"=="0" (
echo ERROR: profile "%profile%" does not exist
)
IF %cnt% gtr 1 (
echo ERROR: profile %profile% is not unique
)
ENDLOCAL
GOTO :while
:end
ENDLOCAL
This will prompt you for a profile and search for it.
All that is necessary now is to restart the PiServiceLauncher, must be run as administrator.
Because backing up of the whole settings file isn’t ideal in general and also not for sharing I’ve put some scripts together to make this more feasible. Configurations for software IPD, lighthouses, etc. aren’t exported so no need to worry about overwriting your personal settings. When importing settings, the current profile.json is only modified, other settings aren’t touched.
The local settings are transformed into performance and color files, it takes a few steps to get the scripts working and it’s nothing like the oculus store but that shouldn’t discourage anyone.
Following folder structure is recommended:
Having the configuration files in the resources folder is necessary.
Configuration Files:
config.json
{
"device": "Pimax P2 5K Formal",
"blacklist": "fov,fov_adjust_degree"
}
device
must be set once with the value found in
%LOCALAPPDATA%\pimax\runtime\profile.json
e.g.: Pimax P2 5K Formal
for 5K+` ,please look it up for 8K or XR
blacklist
: for values you don’t want to import, in my example FOV settings
mapping.json
{
"color": {
"brightness_left": "$device$/color_brightness_0",
"brightness_left_red": "$device$/color_brightness_0_rgb/x",
"brightness_left_green": "$device$/color_brightness_0_rgb/y",
"brightness_left_blue": "$device$/color_brightness_0_rgb/z",
"brightness_right": "$device$/color_brightness_1_rgb",
"brightness_right_red": "$device$/color_brightness_1_rgb/x",
"brightness_right_green": "$device$/color_brightness_1_rgb/y",
"brightness_right_blue": "$device$/color_brightness_1_rgb/z",
"contrast_left": "$device$/color_contrast_0",
"contrast_left_red": "$device$/color_contrast_0_rgb/x",
"contrast_left_green": "$device$/color_contrast_0_rgb/y",
"contrast_left_blue": "$device$/color_contrast_0_rgb/z",
"contrast_right": "$device$/color_contrast_1_rgb",
"contrast_right_red": "$device$/color_contrast_1_rgb/x",
"contrast_right_green": "$device$/color_contrast_1_rgb/y",
"contrast_right_blue": "$device$/color_contrast_1_rgb/z"
},
"performance": {
"render_quality": "pixels_per_display_pixel_rate",
"refresh_rate": "$device$/display_timing_selection",
"fov": "$device$/fov_level",
"fov_adjust_degree": "$device$/fov_outer_adjust_degree",
"parallel_projection_disabled": "steamvr_use_native_fov",
"smart_smoothing": "dbg_asw_enable",
"hidden_area_mask": "dbg_hidden_area_enable",
"foveated_rendering": "enable_foveated_rendering",
"vive_support": "support_vive_only_games"
}
}
Please just copy as is.
Backup Script:
$profilefile = "$env:LOCALAPPDATA\pimax\runtime\profile.json"
$resourcesDir = "resources"
$config = Get-Content "$resourcesDir\config.json" | ConvertFrom-Json
$device = $config."device"
$mapping = Get-Content "$resourcesDir\mapping.json" | ConvertFrom-Json
$pathSettingsHash = @{}
foreach($categoryName in $mapping.psobject.properties.name) {
$category = $mapping.$categoryName
foreach($settingName in $category.psobject.properties.name) {
$path = $category.$settingName -replace '\$device\$', $device
$pathSettingsHash.add($path, $settingName)
}
}
$settingsHash = @{}
function Extract-Settings-From-Profile-Node {
Param ([PSCustomObject]$nodeObj, [string]$path)
$nodeObj.psobject.Properties | ForEach-Object {
$attributePath = $_.Name;
if ($path) {
$attributePath = "$path/$attributePath"
}
if ($_.TypeNameOfValue -eq 'System.Management.Automation.PSCustomObject') {
Extract-Settings-From-Profile-Node -nodeObj ($nodeObj | Select -ExpandProperty $_.Name) -path $attributePath
} elseif ($pathSettingsHash.ContainsKey($attributePath)) {
$settingsHash.Add($pathSettingsHash.$attributePath, $_.Value)
}
}
}
$profileObj = (Get-Content $profilefile) `
-replace '""\s*:','"a":' `
| ConvertFrom-Json
Extract-Settings-From-Profile-Node -nodeObj $profileObj -path $null
foreach($categoryName in $mapping.psobject.properties.name) {
$category = $mapping.$categoryName
$settingsObject = [PSCustomObject]@{}
foreach($settingName in $category.psobject.properties.name) {
if ($settingsHash.ContainsKey($settingName)) {
$settingsObject | Add-Member -MemberType NoteProperty -Name $settingName -Value $settingsHash.$settingName
}
}
$settingsObject | ConvertTo-Json | Set-Content "$categoryName.json"
}
# cmd /c pause | out-null
Save as backup.ps1
and must be executed with right click on file: Run with PowerShell
param (
[string]$dir = ""
)
$resourcesDir = "resources"
$sourceDir = $dir
$profilefile = "$env:LOCALAPPDATA\pimax\runtime\profile.json"
$config = Get-Content "$resourcesDir\config.json" | ConvertFrom-Json
$device = $config.'device'
$blacklistHash = @{}
if (Get-Member -inputobject $config -name 'blacklist' -Membertype NoteProperty) {
$config.'blacklist'.Split(',') | ForEach {
$key = $_.Trim()
if ($key) {
$blacklistHash.Add($key, $true);
}
}
}
$mapping = Get-Content "$resourcesDir\mapping.json" | ConvertFrom-Json
$pathSettingsHash = @{}
$categories = @()
foreach($categoryName in $mapping.psobject.properties.name) {
$category = $mapping.$categoryName
$categories += $categoryName
foreach($settingName in $category.psobject.properties.name) {
$path = $category.$settingName -replace '\$device\$', $device
if (!$blacklistHash.ContainsKey($settingName)) {
$pathSettingsHash.add($settingName, $path)
}
}
}
function Find-Settings-Directory {
Param ([string]$dir)
$count = 0
$resultDir = ""
Get-ChildItem . -Directory -Filter "*$dir*" | ForEach {
$curDir = $_.Name
$categories | Foreach-Object {
$file = "$curDir\$_.json"
if ([System.IO.File]::Exists($file)) {
$resultDir = $curDir
}
}
$count++
}
if ($count -gt 1) {
Write-Host "ERROR: more than one matching directory found"
return ""
} elseif ($count -eq 0) {
Write-Host "ERROR: no matching directory found"
}
return $resultDir
}
while (!$sourceDir) {
$sourceDir = Read-Host -Prompt 'Enter profile'
$sourceDir = $sourceDir.Trim()
$sourceDir = Find-Settings-Directory -dir $sourceDir
}
function Convert-File-To-Profile {
Param ([string]$file, [PSCustomObject]$targetObj)
$hasConvertedProperties = $false
$jsonObj = Get-Content $file | ConvertFrom-Json
$jsonObj.psobject.Properties | ForEach-Object {
$settingName = $_.Name;
if ($pathSettingsHash.ContainsKey($settingName)) {
$path = $pathSettingsHash.$settingName
$settingsBranch = $path.Split('/')
$currentNode = $targetObj
for ($i=0; $i -lt $settingsBranch.Length - 1; $i++) {
$nodeName = $settingsBranch[$i]
if (!(Get-Member -inputobject $currentNode -name $nodeName -Membertype NoteProperty)) {
$newNode = [PSCustomObject]@{}
$currentNode | Add-Member -MemberType NoteProperty -Name $nodeName -Value $newNode
}
$currentNode = $currentNode | Select -ExpandProperty $nodeName
}
$nodeName = $settingsBranch[$settingsBranch.Length - 1]
$currentNode | Add-Member -MemberType NoteProperty -Name $nodeName -Value $_.Value -Force
$hasConvertedProperties = $true
}
}
return $hasConvertedProperties
}
$profileJsonObj = (Get-Content $profilefile) `
-replace '""\s*:','"a":' `
| ConvertFrom-Json
$hasConvertedProperties = $false
$categories | Foreach-Object {
$file = "$sourceDir\$_.json"
if ([System.IO.File]::Exists($file)) {
Write-Host "Reading settings file '$file'"
$hasConvertedProperties = (Convert-File-To-Profile -file $file -targetObj $profileJsonObj) -or $hasConvertedProperties
}
}
if (!$hasConvertedProperties) {
Write-Host "No properties could be read, exiting"
cmd /c pause | out-null
exit
}
($profileJsonObj | ConvertTo-Json) `
-replace '"a"\s*:','"":' `
| Set-Content $profilefile
Write-Host "Profile has been updated"
cmd /c pause | out-null
Save as restore.ps1
and must be executed with right click on file: Run with PowerShell
This will bring up interactive mode and ask you for a directory which contains the exported setting files.
For convenience it also takes a -dir parameter to restore often used settings more quickly by creating a dedicated intermediate script for it.
Example
& .\restore.ps1 -dir "DCS"
Save as anything you like.ps1
and change DCS
to the profile you want to restore, must be executed with right click on file: Run with PowerShell
Restart PiServiceLauncher after restoring settings and you’re done.
Only one of the backup files needs to be present for restoring settings.
Here are example files that the backup script created.
color.json
{
"brightness_left": -0.2,
"brightness_left_red": -0.2,
"brightness_left_green": -0.2,
"brightness_left_blue": -0.2,
"brightness_right_red": -0.2,
"brightness_right_green": -0.2,
"brightness_right_blue": -0.2,
"contrast_left": -0.1000000014901161,
"contrast_left_red": -0.2000000029802322,
"contrast_left_green": -0.2000000029802322,
"contrast_left_blue": -0.2000000029802322,
"contrast_right_red": -0.2000000029802322,
"contrast_right_green": -0.2000000029802322,
"contrast_right_blue": -0.2000000029802322
}
performance.json
{
"render_quality": 1,
"refresh_rate": 0,
"fov": 2,
"fov_adjust_degree": 20,
"parallel_projection_disabled": 1,
"smart_smoothing": 0,
"hidden_area_mask": 1,
"foveated_rendering": 1,
"vive_support": 1
}
Note:
created for PiTool version .129
detailed FFR settings are excluded because I haven’t got access to them
Of course use at your own risk.
Edit:
shortened the restore script
Awesome work! …
Hope it’s swiftly made obsolete by amazing new PiTool features Pimax will add any day now
You’re a HACKER!
Only rewriting configuration files for fun and not much profit in this case