Merge pull request #12 from OpenVR-Advanced-Settings/formatting

Implement clang-format and format entire src directory
This commit is contained in:
username223
2018-12-28 20:54:03 +01:00
committed by GitHub
51 changed files with 10944 additions and 6957 deletions
+2
View File
@@ -7,6 +7,7 @@ environment:
JOM_LOC: '"C:\Qt\Tools\QtCreator\bin\jom.exe"' JOM_LOC: '"C:\Qt\Tools\QtCreator\bin\jom.exe"'
NSIS_LOC: '"C:\Program Files (x86)\NSIS\"' NSIS_LOC: '"C:\Program Files (x86)\NSIS\"'
ZIP_LOC: 7z ZIP_LOC: 7z
CLANG_FORMAT_LOC: '"C:\Program Files\LLVM\bin\clang-format.exe"'
COMPILER: msvc COMPILER: msvc
VSVER: 14 VSVER: 14
@@ -17,6 +18,7 @@ init:
- set TAG_NAME=%APPVEYOR_REPO_TAG_NAME% - set TAG_NAME=%APPVEYOR_REPO_TAG_NAME%
build_script: build_script:
- python ./build_scripts/run-clang-format.py ./src -r --clang-format-executable %CLANG_FORMAT_LOC% --color always
- call "build_windows.cmd" - call "build_windows.cmd"
artifacts: artifacts:
+105
View File
@@ -0,0 +1,105 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 1
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 2
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4
IndentWrappedFunctionNames: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: true
SpacesInParentheses: true
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
...
+1
View File
@@ -10,6 +10,7 @@ install:
- sudo apt-get install build-essential qtbase5-dev qttools5-dev qtdeclarative5-dev qtmultimedia5-dev qt5-default qttools5-dev-tools - sudo apt-get install build-essential qtbase5-dev qttools5-dev qtdeclarative5-dev qtmultimedia5-dev qt5-default qttools5-dev-tools
script: script:
- python ./build_scripts/run-clang-format.py ./src -r --color always
- mkdir build && cd build - mkdir build && cd build
- qmake .. - qmake ..
- make - make
+6 -2
View File
@@ -1,5 +1,7 @@
![language](https://img.shields.io/badge/Language-C%2B%2B11%2C%20QML-green.svg) ![dependencies](https://img.shields.io/badge/Dependencies-OpenVR%2C%20Qt5-green.svg)
![language](https://img.shields.io/badge/Language-C%2B%2B11%2C%20QML-green.svg) ![dependencies](https://img.shields.io/badge/Dependencies-OpenVR%2C%20Qt5-green.svg) ![license_gpl3](https://img.shields.io/badge/License-GPL%203.0-green.svg) [![Build status](https://ci.appveyor.com/api/projects/status/8oivf5xws6vsq2x3/branch/master?svg=true)](https://ci.appveyor.com/project/icewind1991/openvr-advancedsettings/branch/master) ![license_gpl3](https://img.shields.io/badge/License-GPL%203.0-green.svg)
[![Build status](https://ci.appveyor.com/api/projects/status/8oivf5xws6vsq2x3/branch/master?svg=true)](https://ci.appveyor.com/project/icewind1991/openvr-advancedsettings/branch/master)
[![Build Status](https://travis-ci.org/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings.svg?branch=master)](https://travis-ci.org/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings)
> * [Features](#features) > * [Features](#features)
> * [Usage](#usage) > * [Usage](#usage)
@@ -272,6 +274,8 @@ Full build instructions can be found [here](docs/building_for_windows.md).
If you want to run Advanced Settings on linux you can build it yourself using `qmake` and `make` or using Qt Creator, you'll have to copy the `res` folder from the `src` folder into folder that contains the binary If you want to run Advanced Settings on linux you can build it yourself using `qmake` and `make` or using Qt Creator, you'll have to copy the `res` folder from the `src` folder into folder that contains the binary
and copy `third-party/openvr/lib/linux64/libopenvr_api.so` into your systems library path. and copy `third-party/openvr/lib/linux64/libopenvr_api.so` into your systems library path.
If you want to contribute changes running `clang-format` is necessary. More details are in the [CONTRIBUTING.md](docs/CONTRIBUTING.md) file.
<a name="notes"></a> <a name="notes"></a>
# Notes: # Notes:
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
clang-format --version
if [ $? -eq 0 ]; then
echo "Clang-format found."
build_path="`dirname \"$0\"`"
project_path=$build_path/../..
find $project_path/src/ -regex '.*\.\(cpp\|h\)' -exec clang-format -style=file -i {} \; -exec echo "Iteration 1: {}" \;
find $project_path/src/ -regex '.*\.\(cpp\|h\)' -exec clang-format -style=file -i {} \; -exec echo "Iteration 2: {}" \;
echo "DONE"
else
echo "Could not find clang-format."
fi
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
clang-format --version;
if [ $? -eq 0 ]; then
echo "Clang-format found."
build_path="`dirname \"$0\"`"
project_path=$build_path/../..
python $project_path/build_scripts/run-clang-format.py $project_path/src -r --color always;
if [ $? -eq 0 ]; then
echo "FORMATTED CORRECTLY."
else
echo "NOT FORMATTED CORRECTLY."
fi
else
echo "Could not find clang-format."
fi
+325
View File
@@ -0,0 +1,325 @@
#!/usr/bin/env python
"""A wrapper script around clang-format, suitable for linting multiple files
and to use for continuous integration.
This is an alternative API for the clang-format command line.
It runs over multiple files and directories in parallel.
A diff output is produced and a sensible exit code is returned.
"""
from __future__ import print_function, unicode_literals
import argparse
import codecs
import difflib
import fnmatch
import io
import multiprocessing
import os
import signal
import subprocess
import sys
import traceback
from functools import partial
DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx'
class ExitStatus:
SUCCESS = 0
DIFF = 1
TROUBLE = 2
def list_files(files, recursive=False, extensions=None, exclude=None):
if extensions is None:
extensions = []
if exclude is None:
exclude = []
out = []
for file in files:
if recursive and os.path.isdir(file):
for dirpath, dnames, fnames in os.walk(file):
fpaths = [os.path.join(dirpath, fname) for fname in fnames]
for pattern in exclude:
# os.walk() supports trimming down the dnames list
# by modifying it in-place,
# to avoid unnecessary directory listings.
dnames[:] = [
x for x in dnames
if
not fnmatch.fnmatch(os.path.join(dirpath, x), pattern)
]
fpaths = [
x for x in fpaths if not fnmatch.fnmatch(x, pattern)
]
for f in fpaths:
ext = os.path.splitext(f)[1][1:]
if ext in extensions:
out.append(f)
else:
out.append(file)
return out
def make_diff(file, original, reformatted):
return list(
difflib.unified_diff(
original,
reformatted,
fromfile='{}\t(original)'.format(file),
tofile='{}\t(reformatted)'.format(file),
n=3))
class DiffError(Exception):
def __init__(self, message, errs=None):
super(DiffError, self).__init__(message)
self.errs = errs or []
class UnexpectedError(Exception):
def __init__(self, message, exc=None):
super(UnexpectedError, self).__init__(message)
self.formatted_traceback = traceback.format_exc()
self.exc = exc
def run_clang_format_diff_wrapper(args, file):
try:
ret = run_clang_format_diff(args, file)
return ret
except DiffError:
raise
except Exception as e:
raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__,
e), e)
def run_clang_format_diff(args, file):
try:
with io.open(file, 'r', encoding='utf-8') as f:
original = f.readlines()
except IOError as exc:
raise DiffError(str(exc))
invocation = [args.clang_format_executable, file]
# Use of utf-8 to decode the process output.
#
# Hopefully, this is the correct thing to do.
#
# It's done due to the following assumptions (which may be incorrect):
# - clang-format will returns the bytes read from the files as-is,
# without conversion, and it is already assumed that the files use utf-8.
# - if the diagnostics were internationalized, they would use utf-8:
# > Adding Translations to Clang
# >
# > Not possible yet!
# > Diagnostic strings should be written in UTF-8,
# > the client can translate to the relevant code page if needed.
# > Each translation completely replaces the format string
# > for the diagnostic.
# > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation
#
# It's not pretty, due to Python 2 & 3 compatibility.
encoding_py3 = {}
if sys.version_info[0] >= 3:
encoding_py3['encoding'] = 'utf-8'
try:
proc = subprocess.Popen(
invocation,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
**encoding_py3)
except OSError as exc:
raise DiffError(str(exc))
proc_stdout = proc.stdout
proc_stderr = proc.stderr
if sys.version_info[0] < 3:
# make the pipes compatible with Python 3,
# reading lines should output unicode
encoding = 'utf-8'
proc_stdout = codecs.getreader(encoding)(proc_stdout)
proc_stderr = codecs.getreader(encoding)(proc_stderr)
# hopefully the stderr pipe won't get full and block the process
outs = list(proc_stdout.readlines())
errs = list(proc_stderr.readlines())
proc.wait()
if proc.returncode:
raise DiffError("clang-format exited with status {}: '{}'".format(
proc.returncode, file), errs)
return make_diff(file, original, outs), errs
def bold_red(s):
return '\x1b[1m\x1b[31m' + s + '\x1b[0m'
def colorize(diff_lines):
def bold(s):
return '\x1b[1m' + s + '\x1b[0m'
def cyan(s):
return '\x1b[36m' + s + '\x1b[0m'
def green(s):
return '\x1b[32m' + s + '\x1b[0m'
def red(s):
return '\x1b[31m' + s + '\x1b[0m'
for line in diff_lines:
if line[:4] in ['--- ', '+++ ']:
yield bold(line)
elif line.startswith('@@ '):
yield cyan(line)
elif line.startswith('+'):
yield green(line)
elif line.startswith('-'):
yield red(line)
else:
yield line
def print_diff(diff_lines, use_color):
if use_color:
diff_lines = colorize(diff_lines)
if sys.version_info[0] < 3:
sys.stdout.writelines((l.encode('utf-8') for l in diff_lines))
else:
sys.stdout.writelines(diff_lines)
def print_trouble(prog, message, use_colors):
error_text = 'error:'
if use_colors:
error_text = bold_red(error_text)
print("{}: {} {}".format(prog, error_text, message), file=sys.stderr)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'--clang-format-executable',
metavar='EXECUTABLE',
help='path to the clang-format executable',
default='clang-format')
parser.add_argument(
'--extensions',
help='comma separated list of file extensions (default: {})'.format(
DEFAULT_EXTENSIONS),
default=DEFAULT_EXTENSIONS)
parser.add_argument(
'-r',
'--recursive',
action='store_true',
help='run recursively over directories')
parser.add_argument('files', metavar='file', nargs='+')
parser.add_argument(
'-q',
'--quiet',
action='store_true')
parser.add_argument(
'-j',
metavar='N',
type=int,
default=0,
help='run N clang-format jobs in parallel'
' (default number of cpus + 1)')
parser.add_argument(
'--color',
default='auto',
choices=['auto', 'always', 'never'],
help='show colored diff (default: auto)')
parser.add_argument(
'-e',
'--exclude',
metavar='PATTERN',
action='append',
default=[],
help='exclude paths matching the given glob-like pattern(s)'
' from recursive search')
args = parser.parse_args()
# use default signal handling, like diff return SIGINT value on ^C
# https://bugs.python.org/issue14229#msg156446
signal.signal(signal.SIGINT, signal.SIG_DFL)
try:
signal.SIGPIPE
except AttributeError:
# compatibility, SIGPIPE does not exist on Windows
pass
else:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
colored_stdout = False
colored_stderr = False
if args.color == 'always':
colored_stdout = True
colored_stderr = True
elif args.color == 'auto':
colored_stdout = sys.stdout.isatty()
colored_stderr = sys.stderr.isatty()
retcode = ExitStatus.SUCCESS
files = list_files(
args.files,
recursive=args.recursive,
exclude=args.exclude,
extensions=args.extensions.split(','))
if not files:
return
njobs = args.j
if njobs == 0:
njobs = multiprocessing.cpu_count() + 1
njobs = min(len(files), njobs)
if njobs == 1:
# execute directly instead of in a pool,
# less overhead, simpler stacktraces
it = (run_clang_format_diff_wrapper(args, file) for file in files)
pool = None
else:
pool = multiprocessing.Pool(njobs)
it = pool.imap_unordered(
partial(run_clang_format_diff_wrapper, args), files)
while True:
try:
outs, errs = next(it)
except StopIteration:
break
except DiffError as e:
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
retcode = ExitStatus.TROUBLE
sys.stderr.writelines(e.errs)
except UnexpectedError as e:
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
sys.stderr.write(e.formatted_traceback)
retcode = ExitStatus.TROUBLE
# stop at the first unexpected error,
# something could be very wrong,
# don't process all files unnecessarily
if pool:
pool.terminate()
break
else:
sys.stderr.writelines(errs)
if outs == []:
continue
if not args.quiet:
print_diff(outs, use_color=colored_stdout)
if retcode == ExitStatus.SUCCESS:
retcode = ExitStatus.DIFF
return retcode
if __name__ == '__main__':
sys.exit(main())
+60
View File
@@ -0,0 +1,60 @@
@echo off
REM Echo off to avoid spam.
REM Non zero is failure, 0 is success.
SET exit_code_success=0
SET exit_code_failure_build_apps=1
SET exit_code_failure_build_locations=2
REM Used for echos.
SET current_activity=FORMAT
REM If scripts are chain called the original dirs should not be overwritten.
IF NOT DEFINED original_dir (
SET original_dir=%CD%
)
IF NOT DEFINED project_dir (
REM Arg 0 (called %0) is the full path to the file.
REM https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call#batch-parameters
REM As per above link, %~dp0 expands the zeroth arg to a drive letter and path only.
REM Project dir is up two dirs from the file.
SET project_dir=%~dp0\..\..\
)
ECHO %current_activity%: Testing if clang-format can be located:
IF NOT DEFINED CLANG_FORMAT_LOC (
ECHO %current_activity%: CLANG_FORMAT_LOC not defined. Using default value.
SET CLANG_FORMAT_LOC="C:\Program Files\LLVM\bin\clang-format.exe"
)
ECHO %current_activity%: CLANG_FORMAT_LOC set to '%CLANG_FORMAT_LOC%'.
REM EXIST won't find items in the PATH. WHERE will.
SET CLANG_FORMAT_VALID=0
IF EXIST %CLANG_FORMAT_LOC% SET CLANG_FORMAT_VALID=1
IF %CLANG_FORMAT_VALID% EQU 0 (
WHERE /Q %CLANG_FORMAT_LOC%
IF NOT ERRORLEVEL 1 SET CLANG_FORMAT_VALID=1
)
IF %CLANG_FORMAT_VALID% EQU 1 (
ECHO %current_activity%: CLANG_FORMAT_LOC exists.
) ELSE (
ECHO %current_activity%: CLANG_FORMAT_LOC directory does not exist. Exiting.
EXIT /B %exit_code_failure_build_locations%
)
ECHO %current_activity%: Clang-format located.
%CLANG_FORMAT_LOC% --version
REM First iteration.
FOR /R %project_dir%\src\ %%F IN (*.cpp *.h) DO (%CLANG_FORMAT_LOC% --style=file -i %%F & ECHO Iteration 1. %%F)
REM Clang-format is sometimes indecisive about which exact rules to apply,
REM leading to differences between first and second iteration.
REM Do it twice, just to be sure.
FOR /R %project_dir%\src\ %%F IN (*.cpp *.h) DO (%CLANG_FORMAT_LOC% --style=file -i %%F & ECHO Iteration 2. %%F)
ECHO %current_activity%: %current_activity% DONE.
+40
View File
@@ -0,0 +1,40 @@
@echo off
REM Arg 0 (called %0) is the full path to the file.
REM https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call#batch-parameters
REM As per above link, %~dp0 expands the zeroth arg to a drive letter and path only.
REM Project dir is up two dirs from the file.
SET project_dir=%~dp0\..\..\
ECHO %current_activity%: Testing if clang-format can be located:
IF NOT DEFINED CLANG_FORMAT_LOC (
ECHO %current_activity%: CLANG_FORMAT_LOC not defined. Using default value.
SET CLANG_FORMAT_LOC="C:\Program Files\LLVM\bin\clang-format.exe"
)
ECHO %current_activity%: CLANG_FORMAT_LOC set to '%CLANG_FORMAT_LOC%'.
REM EXIST won't find items in the PATH. WHERE will.
SET CLANG_FORMAT_VALID=0
IF EXIST %CLANG_FORMAT_LOC% SET CLANG_FORMAT_VALID=1
IF %CLANG_FORMAT_VALID% EQU 0 (
WHERE /Q %CLANG_FORMAT_LOC%
IF NOT ERRORLEVEL 1 SET CLANG_FORMAT_VALID=1
)
IF %CLANG_FORMAT_VALID% EQU 1 (
ECHO %current_activity%: CLANG_FORMAT_LOC exists.
) ELSE (
ECHO %current_activity%: CLANG_FORMAT_LOC directory does not exist. Exiting.
EXIT /B %exit_code_failure_build_locations%
)
ECHO %current_activity%: Clang-format located.
%CLANG_FORMAT_LOC% --version
python %project_dir%/build_scripts/run-clang-format.py %project_dir%/src -r --color never --clang-format-executable %CLANG_FORMAT_LOC%
IF NOT ERRORLEVEL 1 (
ECHO FORMATTED CORRECTLY.
) ELSE (
ECHO NOT FORMATTED CORRECTLY.
)
+49
View File
@@ -0,0 +1,49 @@
<a name="top"></a>
# How to contribute to OpenVR Advanced Settings
> * [You found a bug or have a suggestion for improvement](#bug_improvement)
> * [You wrote a patch](#patch)
> * [Building](#building)
> * [Formatting](#formatting)
> * [Style guide](#style)
<a name="bug_improvement"></a>
## You found a bug or have a suggestion for improvement
First, look through the [issues page](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings/issues) and see if there are any open issues relevant to yours. If there are, describe your issue in detail and why you think it's relevant to the already open issue.
If there aren't any open issues relevant to yours, create a new issue and give as much detail as possible.
For bug reports include what you expect to happen, what happened, version number of the application, operating system, SteamVR version number (if possible) and any other information you find relevant.
For improvement requests include what you're expecting to do, why you want the feature this way, the problem that you're solving and any other information that you find relevant.
Include logs if possible. Logs can be found in `%APPDATA%\matzman666\OpenVRAdvancedSettings\AdvancedSettings.log` on Windows.
<a name="patch"></a>
## You want to submit changes
<a name="building"></a>
### Building
If you haven't already, read the instructions for how to build on [Windows](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings/tree/master#building_on_windows) or [Linux](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings/tree/master#building_on_linux). Your patch must build on all platforms without errors (warnings are treated as errors). Notice that different compilers have different warning messages, being able to successfully compile on one does not mean that all of them will pass. The pull request will be built on both Windows (msvc) and Linux (gcc and clang) CI servers.
<a name="formatting"></a>
### Formatting
This project uses `clang-format` (part of the [LLVM collection](https://releases.llvm.org/download.html)) on all `*.cpp`and `*.h` files in the `src` directory, using the supplied `.clang-format` file in the root of the repository. Correct formatting is checked by the CI servers.
The `.\build_scripts\win\format.cmd` (for Windows) and `./build_scripts/linux/format` (for Linux) scripts will automatically run `clang-format` on all required files.
The Windows script requires that either your `clang-format.exe` is in `C:\Program Files\LLVM\bin\clang-format.exe` or the `CLANG_FORMAT_LOC` environment variable is set to the location of the `.exe`.
The Linux script requires that `clang-format` is in your `path`.
There are `clang-format` plugins for many IDEs, including [Qt Creator](https://doc.qt.io/qtcreator/creator-beautifier.html) and [Visual Studio](https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat).
To verify that your patch has been formatted correctly, run `.\build_scripts\win\verify_formatting.cmd` on Windows or `./build_scripts/linux/verify_formatting` on Linux. If there are formatting changes needed the script will output a diff showing which changes are needed, otherwise it will output `FORMATTED CORRECTLY.`. The verification script requires `python` in the `path` for Linux and Windows. On Windows the verification script will either use the `CLANG_FORMAT_LOC` environment variable or the default location.
<a name="style"></a>
### Style guide
Currently, there are no directives for style other than `clang-format`.
+19 -5
View File
@@ -4,6 +4,7 @@
> * [Requirements](#requirements) > * [Requirements](#requirements)
> * [Locations and Environment Variables](#locs_and_envs) > * [Locations and Environment Variables](#locs_and_envs)
> * [Building](#features) > * [Building](#features)
> * [Contributing](#contributing)
> * [Using with QtCreator](#qt_creator) > * [Using with QtCreator](#qt_creator)
> * [Using with Visual Studio](#visual_studio) > * [Using with Visual Studio](#visual_studio)
@@ -12,12 +13,18 @@
For compiling: For compiling:
1. Microsoft Visual Studio (tested on 2017 Community) 1. [Microsoft Visual Studio](https://visualstudio.microsoft.com/downloads/) (tested on 2017 Community)
2. Qt Framework (tested on 5.10 and 5.11) 2. [Qt Framework](https://www.qt.io/download) version later than 5.6 (tested on 5.10 and 5.11)
For pushing changes to the repo:
1. [Python 3](https://www.python.org/downloads/) (must be in `PATH` environment variable)
2. Clang format. Part of the [LLVM collection](https://releases.llvm.org/download.html).
Additionally, for fully building portable and installer release versions: Additionally, for fully building portable and installer release versions:
3. 7zip 3. [7zip](https://www.7-zip.org/download.html)
4. Nullsoft Scriptable Install System (NSIS) 4. [Nullsoft Scriptable Install System (NSIS)](https://sourceforge.net/projects/nsis/)
<a name="locs_and_envs"></a> <a name="locs_and_envs"></a>
## Locations and Environment Variables ## Locations and Environment Variables
@@ -28,9 +35,10 @@ The following environmental variables are relevant for building the project.
| -------------------- | ------------- | | -------------------- | ------------- |
| `QT_LOC` | Path to your Qt `\bin\` folder. | | `QT_LOC` | Path to your Qt `\bin\` folder. |
| `VS_LOC` | Path to your Visual Studio `vcvarsall.bat` file. | | `VS_LOC` | Path to your Visual Studio `vcvarsall.bat` file. |
| `JOM_LOC` | Path to an `.exe` of `jom.exe`. Usually installed with Qt. `jom` is a wrapper around `nmake` allowing more threads to be used. It is not required, but using `nmake`is slower. If `JOM_LOC` isn't defined, or the `.exe` can't be found `nmake` will be used by default. | | `JOM_LOC` | Path to an `.exe` of `jom.exe`. Usually installed with Qt. `jom` is a wrapper around `nmake` allowing more threads to be used. It is not required, but using `nmake`is slower. If `JOM_LOC` isn't defined, or the `.exe` can't be found `nmake` will be used by default. To force using `nmake`, set `JOM_LOC` to a non-valid path like `1`. |
| `ZIP_LOC` | Path to your 7zip `.exe`. Both portable and installer will work. | | `ZIP_LOC` | Path to your 7zip `.exe`. Both portable and installer will work. |
| `NSIS_LOC` | Path to your installation of NSIS containing the `makensis` file. Both portable and installer will work. | | `NSIS_LOC` | Path to your installation of NSIS containing the `makensis` file. Both portable and installer will work. |
| `CLANG_FORMAT_LOC` | Path to your `clang-format.exe`. Not necessary for building, but necessary for pushing changes to the repo. |
If an environment variable isn't set a default value will be provided. The default values are shown in the table below. If an environment variable isn't set a default value will be provided. The default values are shown in the table below.
@@ -41,6 +49,7 @@ If an environment variable isn't set a default value will be provided. The defau
| `JOM_LOC` | `"C:\Qt\Tools\QtCreator\bin\jom.exe"`| | `JOM_LOC` | `"C:\Qt\Tools\QtCreator\bin\jom.exe"`|
| `ZIP_LOC` | `"C:\Program Files\7-Zip\7z.exe"` | | `ZIP_LOC` | `"C:\Program Files\7-Zip\7z.exe"` |
| `NSIS_LOC` | `"C:\Program Files (x86)\NSIS\"` | | `NSIS_LOC` | `"C:\Program Files (x86)\NSIS\"` |
| `CLANG_FORMAT_LOC` | `"C:\Program Files\LLVM\bin\clang-format.exe"` |
Additionally, these optional environment variables are supported. Additionally, these optional environment variables are supported.
@@ -58,6 +67,11 @@ The `.dll` files necessary for a release build differ from those needed by a deb
With the programs above installed and environment variables set, go into the root folder of the repository and run `build_windows.cmd`. Compiled binaries along with everything needed to run portable will output to `.\bin\win64\AdvancedSettings\`. With the programs above installed and environment variables set, go into the root folder of the repository and run `build_windows.cmd`. Compiled binaries along with everything needed to run portable will output to `.\bin\win64\AdvancedSettings\`.
<a name="contributing"></a>
## Contributing
For full details, see [CONTRIBUTING.md](CONTRIBUTING.md).
<a name="qt_creator"></a> <a name="qt_creator"></a>
## Using with QtCreator ## Using with QtCreator
+10 -10
View File
@@ -2,15 +2,15 @@
// easylogging includes // easylogging includes
#ifndef _DEBUG #ifndef _DEBUG
#define _DEBUG # define _DEBUG
#define ELPP_THREAD_SAFE # define ELPP_THREAD_SAFE
#define ELPP_QT_LOGGING # define ELPP_QT_LOGGING
#define ELPP_NO_DEFAULT_LOG_FILE # define ELPP_NO_DEFAULT_LOG_FILE
#include <easylogging++.h> # include <easylogging++.h>
#undef _DEBUG # undef _DEBUG
#else #else
#define ELPP_THREAD_SAFE # define ELPP_THREAD_SAFE
#define ELPP_QT_LOGGING # define ELPP_QT_LOGGING
#define ELPP_NO_DEFAULT_LOG_FILE # define ELPP_NO_DEFAULT_LOG_FILE
#include <easylogging++.h> # include <easylogging++.h>
#endif #endif
+333 -199
View File
@@ -12,248 +12,382 @@
INITIALIZE_EASYLOGGINGPP INITIALIZE_EASYLOGGINGPP
void myQtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { void myQtMessageHandler( QtMsgType type,
QByteArray localMsg = msg.toLocal8Bit(); const QMessageLogContext& context,
switch (type) { const QString& msg )
case QtDebugMsg: {
LOG(DEBUG) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; QByteArray localMsg = msg.toLocal8Bit();
break; switch ( type )
case QtInfoMsg: {
LOG(INFO) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; case QtDebugMsg:
break; LOG( DEBUG ) << localMsg.constData() << " (" << context.file << ":"
case QtWarningMsg: << context.line << ")";
LOG(WARNING) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; break;
break; case QtInfoMsg:
case QtCriticalMsg: LOG( INFO ) << localMsg.constData() << " (" << context.file << ":"
LOG(ERROR) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; << context.line << ")";
break; break;
case QtFatalMsg: case QtWarningMsg:
LOG(FATAL) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; LOG( WARNING ) << localMsg.constData() << " (" << context.file << ":"
break; << context.line << ")";
} break;
case QtCriticalMsg:
LOG( ERROR ) << localMsg.constData() << " (" << context.file << ":"
<< context.line << ")";
break;
case QtFatalMsg:
LOG( FATAL ) << localMsg.constData() << " (" << context.file << ":"
<< context.line << ")";
break;
}
} }
void installManifest(bool cleaninstall = false) { void installManifest( bool cleaninstall = false )
auto manifestQPath = QDir::cleanPath(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("manifest.vrmanifest")); {
if (QFile::exists(manifestQPath)) { auto manifestQPath
bool alreadyInstalled = false; = QDir::cleanPath( QDir( QCoreApplication::applicationDirPath() )
if (vr::VRApplications()->IsApplicationInstalled(advsettings::OverlayController::applicationKey)) { .absoluteFilePath( "manifest.vrmanifest" ) );
if (cleaninstall) { if ( QFile::exists( manifestQPath ) )
char buffer[1024]; {
auto appError = vr::VRApplicationError_None; bool alreadyInstalled = false;
vr::VRApplications()->GetApplicationPropertyString(advsettings::OverlayController::applicationKey, vr::VRApplicationProperty_WorkingDirectory_String, buffer, 1024, &appError); if ( vr::VRApplications()->IsApplicationInstalled(
if (appError == vr::VRApplicationError_None) { advsettings::OverlayController::applicationKey ) )
auto oldManifestQPath = QDir::cleanPath(QDir(buffer).absoluteFilePath("manifest.vrmanifest")); {
if (oldManifestQPath.compare(manifestQPath, Qt::CaseInsensitive) != 0) { if ( cleaninstall )
vr::VRApplications()->RemoveApplicationManifest(QDir::toNativeSeparators(oldManifestQPath).toStdString().c_str()); {
} else { char buffer[1024];
alreadyInstalled = true; auto appError = vr::VRApplicationError_None;
} vr::VRApplications()->GetApplicationPropertyString(
} advsettings::OverlayController::applicationKey,
} else { vr::VRApplicationProperty_WorkingDirectory_String,
alreadyInstalled = true; buffer,
} 1024,
} &appError );
auto apperror = vr::VRApplications()->AddApplicationManifest(QDir::toNativeSeparators(manifestQPath).toStdString().c_str()); if ( appError == vr::VRApplicationError_None )
if (apperror != vr::VRApplicationError_None) { {
throw std::runtime_error(std::string("Could not add application manifest: ") + std::string(vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror))); auto oldManifestQPath
} else if (!alreadyInstalled || cleaninstall) { = QDir::cleanPath( QDir( buffer ).absoluteFilePath(
auto app_error = vr::VRApplications()->SetApplicationAutoLaunch(advsettings::OverlayController::applicationKey, true); "manifest.vrmanifest" ) );
if (app_error != vr::VRApplicationError_None) { if ( oldManifestQPath.compare( manifestQPath,
throw std::runtime_error(std::string("Could not set auto start: ") + std::string(vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror))); Qt::CaseInsensitive )
} != 0 )
} {
} else { vr::VRApplications()->RemoveApplicationManifest(
throw std::runtime_error(std::string("Could not find application manifest: ") + manifestQPath.toStdString()); QDir::toNativeSeparators( oldManifestQPath )
} .toStdString()
} .c_str() );
}
void removeManifest() { else
auto manifestQPath = QDir::cleanPath(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("manifest.vrmanifest")); {
if (QFile::exists(manifestQPath)) { alreadyInstalled = true;
if (vr::VRApplications()->IsApplicationInstalled(advsettings::OverlayController::applicationKey)) { }
vr::VRApplications()->RemoveApplicationManifest(QDir::toNativeSeparators(manifestQPath).toStdString().c_str()); }
}
} else {
throw std::runtime_error(std::string("Could not find application manifest: ") + manifestQPath.toStdString());
}
}
class MyQApplication : public QApplication {
public:
using QApplication::QApplication;
virtual bool notify(QObject * receiver, QEvent * event) override {
try {
return QApplication::notify(receiver, event);
} catch (std::exception& e) {
LOG(ERROR) << "Exception thrown from an event handler: " << e.what();
}
return false;
}
};
namespace argument {
// Checks whether a specific string was passed as a launch argument.
bool CheckCommandLineArgument(int argc, char *argv[], const std::string parameter) {
// The old way was one giant loop that tested every single parameter.
// Having an individual loop for all args most likely has a very small performance
// penalty compared to the original solution,
// but the gains in readability and ease of extension of not having a hundred line+ for loop are worth it.
for (int i = 0; i < argc; i++) {
if (std::string(argv[i]) == parameter) {
return true;
} }
else
{
alreadyInstalled = true;
}
}
auto apperror = vr::VRApplications()->AddApplicationManifest(
QDir::toNativeSeparators( manifestQPath ).toStdString().c_str() );
if ( apperror != vr::VRApplicationError_None )
{
throw std::runtime_error(
std::string( "Could not add application manifest: " )
+ std::string(
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
apperror ) ) );
}
else if ( !alreadyInstalled || cleaninstall )
{
auto app_error = vr::VRApplications()->SetApplicationAutoLaunch(
advsettings::OverlayController::applicationKey, true );
if ( app_error != vr::VRApplicationError_None )
{
throw std::runtime_error(
std::string( "Could not set auto start: " )
+ std::string( vr::VRApplications()
->GetApplicationsErrorNameFromEnum(
apperror ) ) );
}
}
}
else
{
throw std::runtime_error(
std::string( "Could not find application manifest: " )
+ manifestQPath.toStdString() );
}
}
void removeManifest()
{
auto manifestQPath
= QDir::cleanPath( QDir( QCoreApplication::applicationDirPath() )
.absoluteFilePath( "manifest.vrmanifest" ) );
if ( QFile::exists( manifestQPath ) )
{
if ( vr::VRApplications()->IsApplicationInstalled(
advsettings::OverlayController::applicationKey ) )
{
vr::VRApplications()->RemoveApplicationManifest(
QDir::toNativeSeparators( manifestQPath )
.toStdString()
.c_str() );
}
}
else
{
throw std::runtime_error(
std::string( "Could not find application manifest: " )
+ manifestQPath.toStdString() );
}
}
class MyQApplication : public QApplication
{
public:
using QApplication::QApplication;
virtual bool notify( QObject* receiver, QEvent* event ) override
{
try
{
return QApplication::notify( receiver, event );
}
catch ( std::exception& e )
{
LOG( ERROR ) << "Exception thrown from an event handler: "
<< e.what();
} }
return false; return false;
} }
};
constexpr auto DESKTOP_MODE = "-desktop"; namespace argument
constexpr auto NO_SOUND = "-nosound"; {
constexpr auto NO_MANIFEST = "-nomanifest"; // Checks whether a specific string was passed as a launch argument.
constexpr auto INSTALL_MANIFEST= "-installmanifest"; bool CheckCommandLineArgument( int argc,
constexpr auto REMOVE_MANIFEST= "-removemanifest"; char* argv[],
const std::string parameter )
{
// The old way was one giant loop that tested every single parameter.
// Having an individual loop for all args most likely has a very small
// performance penalty compared to the original solution, but the gains in
// readability and ease of extension of not having a hundred line+ for loop
// are worth it.
for ( int i = 0; i < argc; i++ )
{
if ( std::string( argv[i] ) == parameter )
{
return true;
}
}
return false;
} }
enum ReturnErrorCode { constexpr auto DESKTOP_MODE = "-desktop";
constexpr auto NO_SOUND = "-nosound";
constexpr auto NO_MANIFEST = "-nomanifest";
constexpr auto INSTALL_MANIFEST = "-installmanifest";
constexpr auto REMOVE_MANIFEST = "-removemanifest";
} // namespace argument
enum ReturnErrorCode
{
SUCCESS = 0, SUCCESS = 0,
GENERAL_FAILURE = -1, GENERAL_FAILURE = -1,
OPENVR_INIT_ERROR = -2, OPENVR_INIT_ERROR = -2,
}; };
int main(int argc, char *argv[]) { int main( int argc, char* argv[] )
{
const char* logConfigFileName = "logging.conf"; const char* logConfigFileName = "logging.conf";
const char* logConfigDefault = const char* logConfigDefault
"* GLOBAL:\n" = "* GLOBAL:\n"
" FORMAT = \"[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg\"\n" " FORMAT = \"[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg\"\n"
" FILENAME = \"AdvancedSettings.log\"\n" " FILENAME = \"AdvancedSettings.log\"\n"
" ENABLED = true\n" " ENABLED = true\n"
" TO_FILE = true\n" " TO_FILE = true\n"
" TO_STANDARD_OUTPUT = true\n" " TO_STANDARD_OUTPUT = true\n"
" MAX_LOG_FILE_SIZE = 2097152 ## 2MB\n" " MAX_LOG_FILE_SIZE = 2097152 ## 2MB\n"
"* TRACE:\n" "* TRACE:\n"
" ENABLED = false\n" " ENABLED = false\n"
"* DEBUG:\n" "* DEBUG:\n"
" ENABLED = false\n"; " ENABLED = false\n";
const bool desktop_mode = argument::CheckCommandLineArgument(argc, argv, argument::DESKTOP_MODE); const bool desktop_mode = argument::CheckCommandLineArgument(
const bool no_sound = argument::CheckCommandLineArgument(argc, argv, argument::NO_SOUND); argc, argv, argument::DESKTOP_MODE );
const bool no_manifest = argument::CheckCommandLineArgument(argc, argv, argument::NO_MANIFEST); const bool no_sound
const bool install_manifest = argument::CheckCommandLineArgument(argc, argv, argument::INSTALL_MANIFEST); = argument::CheckCommandLineArgument( argc, argv, argument::NO_SOUND );
const bool remove_manifest = argument::CheckCommandLineArgument(argc, argv, argument::REMOVE_MANIFEST); const bool no_manifest = argument::CheckCommandLineArgument(
argc, argv, argument::NO_MANIFEST );
const bool install_manifest = argument::CheckCommandLineArgument(
argc, argv, argument::INSTALL_MANIFEST );
const bool remove_manifest = argument::CheckCommandLineArgument(
argc, argv, argument::REMOVE_MANIFEST );
if (install_manifest || remove_manifest) { if ( install_manifest || remove_manifest )
{
int exit_code = ReturnErrorCode::SUCCESS; int exit_code = ReturnErrorCode::SUCCESS;
QCoreApplication coreApp(argc, argv); QCoreApplication coreApp( argc, argv );
auto openvr_init_status = vr::VRInitError_None; auto openvr_init_status = vr::VRInitError_None;
vr::VR_Init(&openvr_init_status, vr::VRApplication_Utility); vr::VR_Init( &openvr_init_status, vr::VRApplication_Utility );
if (openvr_init_status == vr::VRInitError_None) { if ( openvr_init_status == vr::VRInitError_None )
try { {
if (install_manifest) { try
installManifest(true); {
if ( install_manifest )
{
installManifest( true );
} }
else if (remove_manifest) { else if ( remove_manifest )
{
removeManifest(); removeManifest();
} }
} }
catch (std::exception& e) { catch ( std::exception& e )
{
exit_code = ReturnErrorCode::GENERAL_FAILURE; exit_code = ReturnErrorCode::GENERAL_FAILURE;
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
} }
} }
else { else
{
exit_code = ReturnErrorCode::OPENVR_INIT_ERROR; exit_code = ReturnErrorCode::OPENVR_INIT_ERROR;
std::cerr << std::string("Failed to initialize OpenVR: " + std::string(vr::VR_GetVRInitErrorAsEnglishDescription(openvr_init_status))) << std::endl; std::cerr << std::string(
"Failed to initialize OpenVR: "
+ std::string(
vr::VR_GetVRInitErrorAsEnglishDescription(
openvr_init_status ) ) )
<< std::endl;
} }
vr::VR_Shutdown(); vr::VR_Shutdown();
exit(exit_code); exit( exit_code );
} }
try { try
MyQApplication a(argc, argv); {
a.setOrganizationName("matzman666"); MyQApplication a( argc, argv );
a.setApplicationName("OpenVRAdvancedSettings"); a.setOrganizationName( "matzman666" );
a.setApplicationDisplayName(advsettings::OverlayController::applicationName); a.setApplicationName( "OpenVRAdvancedSettings" );
a.setApplicationVersion(advsettings::OverlayController::applicationVersionString); a.setApplicationDisplayName(
advsettings::OverlayController::applicationName );
a.setApplicationVersion(
advsettings::OverlayController::applicationVersionString );
qInstallMessageHandler(myQtMessageHandler); qInstallMessageHandler( myQtMessageHandler );
// Configure logger // Configure logger
QString logFilePath; QString logFilePath;
START_EASYLOGGINGPP(argc, argv); START_EASYLOGGINGPP( argc, argv );
el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog); el::Loggers::addFlag(
auto logconfigfile = QFileInfo(logConfigFileName).absoluteFilePath(); el::LoggingFlag::DisableApplicationAbortOnFatalLog );
el::Configurations conf; auto logconfigfile = QFileInfo( logConfigFileName ).absoluteFilePath();
if (QFile::exists(logconfigfile)) { el::Configurations conf;
conf.parseFromFile(logconfigfile.toStdString()); if ( QFile::exists( logconfigfile ) )
} else { {
conf.parseFromText(logConfigDefault); conf.parseFromFile( logconfigfile.toStdString() );
} }
if (!conf.get(el::Level::Global, el::ConfigurationType::Filename)) { else
logFilePath = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).absoluteFilePath("AdvancedSettings.log"); {
conf.set(el::Level::Global, el::ConfigurationType::Filename, QDir::toNativeSeparators(logFilePath).toStdString()); conf.parseFromText( logConfigDefault );
} }
conf.setRemainingToDefault(); if ( !conf.get( el::Level::Global, el::ConfigurationType::Filename ) )
el::Loggers::reconfigureAllLoggers(conf); {
LOG(INFO) << "Application started (Version " << advsettings::OverlayController::applicationVersionString << ")"; logFilePath = QDir( QStandardPaths::writableLocation(
LOG(INFO) << "Log Config: " << QDir::toNativeSeparators(logconfigfile).toStdString(); QStandardPaths::AppDataLocation ) )
if (!logFilePath.isEmpty()) { .absoluteFilePath( "AdvancedSettings.log" );
LOG(INFO) << "Log File: " << logFilePath; conf.set( el::Level::Global,
} el::ConfigurationType::Filename,
QDir::toNativeSeparators( logFilePath ).toStdString() );
}
conf.setRemainingToDefault();
el::Loggers::reconfigureAllLoggers( conf );
LOG( INFO ) << "Application started (Version "
<< advsettings::OverlayController::applicationVersionString
<< ")";
LOG( INFO ) << "Log Config: "
<< QDir::toNativeSeparators( logconfigfile ).toStdString();
if ( !logFilePath.isEmpty() )
{
LOG( INFO ) << "Log File: " << logFilePath;
}
if (desktop_mode) { if ( desktop_mode )
LOG(INFO) << "Desktop mode enabled."; {
} LOG( INFO ) << "Desktop mode enabled.";
if (no_sound) { }
LOG(INFO) << "Sound effects disabled."; if ( no_sound )
} {
if (no_manifest) { LOG( INFO ) << "Sound effects disabled.";
LOG(INFO) << "vrmanifest disabled."; }
} if ( no_manifest )
{
LOG( INFO ) << "vrmanifest disabled.";
}
QSettings appSettings(QSettings::IniFormat, QSettings::UserScope, a.organizationName(), a.applicationName()); QSettings appSettings( QSettings::IniFormat,
advsettings::OverlayController::setAppSettings(&appSettings); QSettings::UserScope,
LOG(INFO) << "Settings File: " << appSettings.fileName().toStdString(); a.organizationName(),
a.applicationName() );
advsettings::OverlayController::setAppSettings( &appSettings );
LOG( INFO ) << "Settings File: "
<< appSettings.fileName().toStdString();
QQmlEngine qmlEngine; QQmlEngine qmlEngine;
advsettings::OverlayController* controller = advsettings::OverlayController::createInstance(desktop_mode, no_sound); advsettings::OverlayController* controller
controller->Init(&qmlEngine); = advsettings::OverlayController::createInstance( desktop_mode,
no_sound );
controller->Init( &qmlEngine );
QQmlComponent component(&qmlEngine, QUrl::fromLocalFile("res/qml/mainwidget.qml")); QQmlComponent component(
auto errors = component.errors(); &qmlEngine, QUrl::fromLocalFile( "res/qml/mainwidget.qml" ) );
for (auto& e : errors) { auto errors = component.errors();
LOG(ERROR) << "QML Error: " << e.toString().toStdString() << std::endl; for ( auto& e : errors )
} {
auto quickObj = component.create(); LOG( ERROR ) << "QML Error: " << e.toString().toStdString()
controller->SetWidget(qobject_cast<QQuickItem*>(quickObj), advsettings::OverlayController::applicationName, advsettings::OverlayController::applicationKey); << std::endl;
}
auto quickObj = component.create();
controller->SetWidget( qobject_cast<QQuickItem*>( quickObj ),
advsettings::OverlayController::applicationName,
advsettings::OverlayController::applicationKey );
if (!desktop_mode && !no_manifest) { if ( !desktop_mode && !no_manifest )
try { {
installManifest(); try
} catch (std::exception& e) { {
LOG(ERROR) << e.what(); installManifest();
} }
} catch ( std::exception& e )
{
LOG( ERROR ) << e.what();
}
}
if (desktop_mode) { if ( desktop_mode )
auto m_pWindow = new QQuickWindow(); {
qobject_cast<QQuickItem*>(quickObj)->setParentItem(m_pWindow->contentItem()); auto m_pWindow = new QQuickWindow();
m_pWindow->setGeometry(0, 0, qobject_cast<QQuickItem*>(quickObj)->width(), qobject_cast<QQuickItem*>(quickObj)->height()); qobject_cast<QQuickItem*>( quickObj )
m_pWindow->show(); ->setParentItem( m_pWindow->contentItem() );
} m_pWindow->setGeometry(
0,
0,
qobject_cast<QQuickItem*>( quickObj )->width(),
qobject_cast<QQuickItem*>( quickObj )->height() );
m_pWindow->show();
}
return a.exec(); return a.exec();
}
} catch (const std::exception& e) { catch ( const std::exception& e )
LOG(FATAL) << e.what(); {
return ReturnErrorCode::GENERAL_FAILURE; LOG( FATAL ) << e.what();
} return ReturnErrorCode::GENERAL_FAILURE;
}
} }
+956 -568
View File
File diff suppressed because it is too large Load Diff
+122 -85
View File
@@ -3,7 +3,8 @@
#include <openvr.h> #include <openvr.h>
#include <QtCore/QtCore> #include <QtCore/QtCore>
// because of incompatibilities with QtOpenGL and GLEW we need to cherry pick includes // because of incompatibilities with QtOpenGL and GLEW we need to cherry pick
// includes
#include <QVector2D> #include <QVector2D>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QVector> #include <QVector>
@@ -35,130 +36,166 @@
#include "tabcontrollers/UtilitiesTabController.h" #include "tabcontrollers/UtilitiesTabController.h"
#include "tabcontrollers/AccessibilityTabController.h" #include "tabcontrollers/AccessibilityTabController.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class OverlayController : public QObject { class OverlayController : public QObject
Q_OBJECT {
Q_PROPERTY(bool desktopMode READ isDesktopMode) Q_OBJECT
Q_PROPERTY( bool desktopMode READ isDesktopMode )
public: public:
static constexpr const char* applicationKey = "matzman666.AdvancedSettings"; static constexpr const char* applicationKey = "matzman666.AdvancedSettings";
static constexpr const char* applicationName = "Advanced Settings"; static constexpr const char* applicationName = "Advanced Settings";
static constexpr const char* applicationVersionString = "v2.5"; static constexpr const char* applicationVersionString = "v2.5";
private: private:
vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid; vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid;
vr::VROverlayHandle_t m_ulOverlayThumbnailHandle = vr::k_ulOverlayHandleInvalid; vr::VROverlayHandle_t m_ulOverlayThumbnailHandle
= vr::k_ulOverlayHandleInvalid;
std::unique_ptr<QQuickRenderControl> m_pRenderControl; std::unique_ptr<QQuickRenderControl> m_pRenderControl;
std::unique_ptr<QQuickWindow> m_pWindow; std::unique_ptr<QQuickWindow> m_pWindow;
std::unique_ptr<QOpenGLFramebufferObject> m_pFbo; std::unique_ptr<QOpenGLFramebufferObject> m_pFbo;
std::unique_ptr<QOpenGLContext> m_pOpenGLContext; std::unique_ptr<QOpenGLContext> m_pOpenGLContext;
std::unique_ptr<QOffscreenSurface> m_pOffscreenSurface; std::unique_ptr<QOffscreenSurface> m_pOffscreenSurface;
std::unique_ptr<QTimer> m_pPumpEventsTimer; std::unique_ptr<QTimer> m_pPumpEventsTimer;
std::unique_ptr<QTimer> m_pRenderTimer; std::unique_ptr<QTimer> m_pRenderTimer;
bool dashboardVisible = false; bool dashboardVisible = false;
QPoint m_ptLastMouse; QPoint m_ptLastMouse;
Qt::MouseButtons m_lastMouseButtons = 0; Qt::MouseButtons m_lastMouseButtons = 0;
bool desktopMode; bool desktopMode;
bool noSound; bool noSound;
QUrl m_runtimePathUrl; QUrl m_runtimePathUrl;
utils::ChaperoneUtils m_chaperoneUtils; utils::ChaperoneUtils m_chaperoneUtils;
QSoundEffect activationSoundEffect; QSoundEffect activationSoundEffect;
QSoundEffect focusChangedSoundEffect; QSoundEffect focusChangedSoundEffect;
QSoundEffect alarm01SoundEffect; QSoundEffect alarm01SoundEffect;
public: // I know it's an ugly hack to make them public to enable external access, but I am too lazy to implement getters. public: // I know it's an ugly hack to make them public to enable external
SteamVRTabController steamVRTabController; // access, but I am too lazy to implement getters.
ChaperoneTabController chaperoneTabController; SteamVRTabController steamVRTabController;
MoveCenterTabController moveCenterTabController; ChaperoneTabController chaperoneTabController;
FixFloorTabController fixFloorTabController; MoveCenterTabController moveCenterTabController;
AudioTabController audioTabController; FixFloorTabController fixFloorTabController;
StatisticsTabController statisticsTabController; AudioTabController audioTabController;
SettingsTabController settingsTabController; StatisticsTabController statisticsTabController;
ReviveTabController reviveTabController; SettingsTabController settingsTabController;
UtilitiesTabController utilitiesTabController; ReviveTabController reviveTabController;
AccessibilityTabController accessibilityTabController; UtilitiesTabController utilitiesTabController;
AccessibilityTabController accessibilityTabController;
private: private:
OverlayController(bool desktopMode, bool noSound) : QObject(), desktopMode(desktopMode), noSound(noSound) {} OverlayController( bool desktopMode, bool noSound )
QPoint getMousePositionForEvent(vr::VREvent_Mouse_t mouse); : QObject(), desktopMode( desktopMode ), noSound( noSound )
{
}
QPoint getMousePositionForEvent( vr::VREvent_Mouse_t mouse );
public: public:
virtual ~OverlayController(); virtual ~OverlayController();
void Init(QQmlEngine* qmlEngine); void Init( QQmlEngine* qmlEngine );
void Shutdown(); void Shutdown();
bool isDashboardVisible() { bool isDashboardVisible()
return dashboardVisible; {
} return dashboardVisible;
}
void SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key = ""); void SetWidget( QQuickItem* quickItem,
const std::string& name,
const std::string& key = "" );
void AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds = true, bool commit = true); void AddOffsetToUniverseCenter( vr::ETrackingUniverseOrigin universe,
void AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, float offset[3], bool adjustBounds = true, bool commit = true); unsigned axisId,
void RotateUniverseCenter(vr::ETrackingUniverseOrigin universe, float yAngle, bool adjustBounds = true, bool commit = true); // around y axis float offset,
void AddOffsetToCollisionBounds(unsigned axisId, float offset, bool commit = true); bool adjustBounds = true,
void AddOffsetToCollisionBounds(float offset[3], bool commit = true); bool commit = true );
void RotateCollisionBounds(float angle, bool commit = true); // around y axis void AddOffsetToUniverseCenter( vr::ETrackingUniverseOrigin universe,
float offset[3],
bool adjustBounds = true,
bool commit = true );
void RotateUniverseCenter( vr::ETrackingUniverseOrigin universe,
float yAngle,
bool adjustBounds = true,
bool commit = true ); // around y axis
void AddOffsetToCollisionBounds( unsigned axisId,
float offset,
bool commit = true );
void AddOffsetToCollisionBounds( float offset[3], bool commit = true );
void RotateCollisionBounds( float angle,
bool commit = true ); // around y axis
bool isDesktopMode() { return desktopMode; }; bool isDesktopMode()
{
return desktopMode;
};
utils::ChaperoneUtils& chaperoneUtils() noexcept { return m_chaperoneUtils; } utils::ChaperoneUtils& chaperoneUtils() noexcept
{
return m_chaperoneUtils;
}
Q_INVOKABLE QString getVersionString(); Q_INVOKABLE QString getVersionString();
Q_INVOKABLE QUrl getVRRuntimePathUrl(); Q_INVOKABLE QUrl getVRRuntimePathUrl();
Q_INVOKABLE bool soundDisabled(); Q_INVOKABLE bool soundDisabled();
const vr::VROverlayHandle_t& overlayHandle(); const vr::VROverlayHandle_t& overlayHandle();
const vr::VROverlayHandle_t& overlayThumbnailHandle(); const vr::VROverlayHandle_t& overlayThumbnailHandle();
bool pollNextEvent(vr::VROverlayHandle_t ulOverlayHandle, vr::VREvent_t* pEvent); bool pollNextEvent( vr::VROverlayHandle_t ulOverlayHandle,
vr::VREvent_t* pEvent );
public slots: public slots:
void renderOverlay(); void renderOverlay();
void OnRenderRequest(); void OnRenderRequest();
void OnTimeoutPumpEvents(); void OnTimeoutPumpEvents();
void showKeyboard(QString existingText, unsigned long userValue = 0); void showKeyboard( QString existingText, unsigned long userValue = 0 );
void playActivationSound(); void playActivationSound();
void playFocusChangedSound(); void playFocusChangedSound();
void playAlarm01Sound(bool loop = false); void playAlarm01Sound( bool loop = false );
void setAlarm01SoundVolume(float vol); void setAlarm01SoundVolume( float vol );
void cancelAlarm01Sound(); void cancelAlarm01Sound();
signals: signals:
void keyBoardInputSignal(QString input, unsigned long userValue = 0); void keyBoardInputSignal( QString input, unsigned long userValue = 0 );
private: private:
static QSettings* _appSettings; static QSettings* _appSettings;
static std::unique_ptr<OverlayController> singleton; static std::unique_ptr<OverlayController> singleton;
public: public:
static OverlayController* getInstance() { static OverlayController* getInstance()
return singleton.get(); {
} return singleton.get();
}
static OverlayController* createInstance(bool desktopMode, bool noSound) { static OverlayController* createInstance( bool desktopMode, bool noSound )
singleton.reset(new advsettings::OverlayController(desktopMode, noSound)); {
return singleton.get(); singleton.reset(
} new advsettings::OverlayController( desktopMode, noSound ) );
return singleton.get();
}
static QSettings* appSettings() { return _appSettings; } static QSettings* appSettings()
{
return _appSettings;
}
static void setAppSettings(QSettings* settings) { _appSettings = settings; } static void setAppSettings( QSettings* settings )
{
_appSettings = settings;
}
}; };
} // namespace advsettings } // namespace advsettings
+104 -69
View File
@@ -3,95 +3,130 @@
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
void AccessibilityTabController::initStage1()
{
setTrackingUniverse( vr::VRCompositor()->GetTrackingSpace() );
auto settings = OverlayController::appSettings();
settings->beginGroup( getSettingsName() );
auto value = settings->value( "heightOffset", m_heightOffset );
settings->endGroup();
if ( value.isValid() && !value.isNull() )
{
m_heightOffset = value.toFloat();
emit heightOffsetChanged( m_heightOffset );
}
void AccessibilityTabController::initStage1() { reloadPttConfig();
setTrackingUniverse(vr::VRCompositor()->GetTrackingSpace());
auto settings = OverlayController::appSettings();
settings->beginGroup(getSettingsName());
auto value = settings->value("heightOffset", m_heightOffset);
settings->endGroup();
if (value.isValid() && !value.isNull()) {
m_heightOffset = value.toFloat();
emit heightOffsetChanged(m_heightOffset);
}
reloadPttConfig();
} }
void AccessibilityTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { void AccessibilityTabController::initStage2( OverlayController* var_parent,
this->parent = var_parent; QQuickWindow* var_widget )
this->widget = var_widget; {
this->parent = var_parent;
this->widget = var_widget;
} }
void AccessibilityTabController::setTrackingUniverse(int value) { void AccessibilityTabController::setTrackingUniverse( int value )
if (m_trackingUniverse != value) { {
reset(); if ( m_trackingUniverse != value )
m_trackingUniverse = value; {
} reset();
m_trackingUniverse = value;
}
} }
float AccessibilityTabController::heightOffset() const { float AccessibilityTabController::heightOffset() const
return m_heightOffset; {
return m_heightOffset;
} }
void AccessibilityTabController::setHeightOffset(float value, bool notify) { void AccessibilityTabController::setHeightOffset( float value, bool notify )
if (std::abs(m_heightOffset - value) > 0.001) { {
modHeightOffset(value - m_heightOffset, notify); if ( std::abs( m_heightOffset - value ) > 0.001 )
} {
modHeightOffset( value - m_heightOffset, notify );
}
} }
void AccessibilityTabController::modHeightOffset(float value, bool notify) { void AccessibilityTabController::modHeightOffset( float value, bool notify )
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, -value, false); {
m_heightOffset += value; parent->AddOffsetToUniverseCenter(
auto settings = OverlayController::appSettings(); ( vr::TrackingUniverseOrigin ) m_trackingUniverse, 1, -value, false );
settings->beginGroup(getSettingsName()); m_heightOffset += value;
settings->setValue("heightOffset", m_heightOffset); auto settings = OverlayController::appSettings();
settings->endGroup(); settings->beginGroup( getSettingsName() );
settings->sync(); settings->setValue( "heightOffset", m_heightOffset );
if (notify) { settings->endGroup();
emit heightOffsetChanged(m_heightOffset); settings->sync();
} if ( notify )
{
emit heightOffsetChanged( m_heightOffset );
}
} }
void AccessibilityTabController::onPttStart()
void AccessibilityTabController::onPttStart() { {
m_toggleHeightOffset = m_heightOffset; m_toggleHeightOffset = m_heightOffset;
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, m_toggleHeightOffset, false); parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
1,
m_toggleHeightOffset,
false );
} }
void AccessibilityTabController::onPttStop() { void AccessibilityTabController::onPttStop()
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, -m_toggleHeightOffset, false); {
parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
1,
-m_toggleHeightOffset,
false );
} }
void AccessibilityTabController::onPttDisabled() { void AccessibilityTabController::onPttDisabled()
if (pttActive()) { {
stopPtt(); if ( pttActive() )
} {
m_toggleHeightOffset = 0; stopPtt();
}
m_toggleHeightOffset = 0;
} }
void AccessibilityTabController::reset() { void AccessibilityTabController::reset()
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex); {
vr::VRChaperoneSetup()->RevertWorkingCopy(); std::lock_guard<std::recursive_mutex> lock( eventLoopMutex );
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, m_heightOffset, false, false); vr::VRChaperoneSetup()->RevertWorkingCopy();
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live); parent->AddOffsetToUniverseCenter(
m_heightOffset = 0.0f; ( vr::TrackingUniverseOrigin ) m_trackingUniverse,
emit heightOffsetChanged(m_heightOffset); 1,
m_heightOffset,
false,
false );
vr::VRChaperoneSetup()->CommitWorkingCopy( vr::EChaperoneConfigFile_Live );
m_heightOffset = 0.0f;
emit heightOffsetChanged( m_heightOffset );
} }
void AccessibilityTabController::eventLoopTick(vr::ETrackingUniverseOrigin universe) { void AccessibilityTabController::eventLoopTick(
if (!eventLoopMutex.try_lock()) { vr::ETrackingUniverseOrigin universe )
return; {
} if ( !eventLoopMutex.try_lock() )
if (settingsUpdateCounter >= 50) { {
setTrackingUniverse((int)universe); return;
settingsUpdateCounter = 0; }
} else { if ( settingsUpdateCounter >= 50 )
settingsUpdateCounter++; {
} setTrackingUniverse( ( int ) universe );
checkPttStatus(); settingsUpdateCounter = 0;
eventLoopMutex.unlock(); }
else
{
settingsUpdateCounter++;
}
checkPttStatus();
eventLoopMutex.unlock();
} }
} // namespace advconfig } // namespace advsettings
+29 -25
View File
@@ -5,46 +5,50 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
class AccessibilityTabController : public PttController
class AccessibilityTabController : public PttController { {
Q_OBJECT Q_OBJECT
Q_PROPERTY(float heightOffset READ heightOffset WRITE setHeightOffset NOTIFY heightOffsetChanged) Q_PROPERTY( float heightOffset READ heightOffset WRITE setHeightOffset
NOTIFY heightOffsetChanged )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
int m_trackingUniverse = (int)vr::TrackingUniverseStanding; int m_trackingUniverse = ( int ) vr::TrackingUniverseStanding;
float m_heightOffset = 0.0f; float m_heightOffset = 0.0f;
float m_toggleHeightOffset = 0.0f; float m_toggleHeightOffset = 0.0f;
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
QString getSettingsName() override { return "accessibilitySettings"; } QString getSettingsName() override
void onPttStart() override; {
void onPttStop() override; return "accessibilitySettings";
void onPttDisabled() override; }
void onPttStart() override;
void onPttStop() override;
void onPttDisabled() override;
public: public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(vr::ETrackingUniverseOrigin universe); void eventLoopTick( vr::ETrackingUniverseOrigin universe );
float heightOffset() const; float heightOffset() const;
public slots: public slots:
void setTrackingUniverse(int value); void setTrackingUniverse( int value );
void setHeightOffset(float value, bool notify = true); void setHeightOffset( float value, bool notify = true );
void modHeightOffset(float value, bool notify = true); void modHeightOffset( float value, bool notify = true );
void reset(); void reset();
signals: signals:
void heightOffsetChanged(float value); void heightOffsetChanged( float value );
}; };
} // namespace advsettings } // namespace advsettings
+30 -27
View File
@@ -4,42 +4,45 @@
#include <vector> #include <vector>
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class AudioTabController; class AudioTabController;
class AudioManager class AudioManager
{ {
public: public:
virtual ~AudioManager() {}; virtual ~AudioManager(){};
virtual void init(AudioTabController* controller) = 0; virtual void init( AudioTabController* controller ) = 0;
virtual void setPlaybackDevice(const std::string& id, bool notify = true) = 0; virtual void setPlaybackDevice( const std::string& id, bool notify = true )
virtual std::string getPlaybackDevName() = 0; = 0;
virtual std::string getPlaybackDevId() = 0; virtual std::string getPlaybackDevName() = 0;
virtual std::string getPlaybackDevId() = 0;
virtual void setMirrorDevice(const std::string& id, bool notify = true) = 0; virtual void setMirrorDevice( const std::string& id, bool notify = true )
virtual bool isMirrorValid() = 0; = 0;
virtual std::string getMirrorDevName() = 0; virtual bool isMirrorValid() = 0;
virtual std::string getMirrorDevId() = 0; virtual std::string getMirrorDevName() = 0;
virtual float getMirrorVolume() = 0; virtual std::string getMirrorDevId() = 0;
virtual bool setMirrorVolume(float value) = 0; virtual float getMirrorVolume() = 0;
virtual bool getMirrorMuted() = 0; virtual bool setMirrorVolume( float value ) = 0;
virtual bool setMirrorMuted(bool value) = 0; virtual bool getMirrorMuted() = 0;
virtual bool setMirrorMuted( bool value ) = 0;
virtual void setMicDevice(const std::string& id, bool notify = true) = 0; virtual void setMicDevice( const std::string& id, bool notify = true ) = 0;
virtual bool isMicValid() = 0; virtual bool isMicValid() = 0;
virtual std::string getMicDevName() = 0; virtual std::string getMicDevName() = 0;
virtual std::string getMicDevId() = 0; virtual std::string getMicDevId() = 0;
virtual float getMicVolume() = 0; virtual float getMicVolume() = 0;
virtual bool setMicVolume(float value) = 0; virtual bool setMicVolume( float value ) = 0;
virtual bool getMicMuted() = 0; virtual bool getMicMuted() = 0;
virtual bool setMicMuted(bool value) = 0; virtual bool setMicMuted( bool value ) = 0;
virtual std::vector<std::pair<std::string, std::string>> getRecordingDevices() = 0; virtual std::vector<std::pair<std::string, std::string>>
virtual std::vector<std::pair<std::string, std::string>> getPlaybackDevices() = 0; getRecordingDevices() = 0;
virtual std::vector<std::pair<std::string, std::string>>
getPlaybackDevices() = 0;
}; };
} } // namespace advsettings
File diff suppressed because it is too large Load Diff
+139 -122
View File
@@ -8,160 +8,177 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration
class OverlayController;
// forward declaration struct AudioProfile
class OverlayController; {
std::string profileName;
std::string playbackName;
std::string mirrorName;
std::string micName;
float mirrorVol = 0.0;
float micVol = 0.0;
bool micMute = false;
bool mirrorMute = false;
};
struct AudioProfile { class AudioTabController : public PttController
std::string profileName; {
std::string playbackName; Q_OBJECT
std::string mirrorName; Q_PROPERTY( int playbackDeviceIndex READ playbackDeviceIndex WRITE
std::string micName; setPlaybackDeviceIndex NOTIFY playbackDeviceIndexChanged )
float mirrorVol = 0.0; Q_PROPERTY( int mirrorDeviceIndex READ mirrorDeviceIndex WRITE
float micVol = 0.0; setMirrorDeviceIndex NOTIFY mirrorDeviceIndexChanged )
bool micMute = false; // Q_PROPERTY(bool mirrorPresent READ mirrorPresent NOTIFY
bool mirrorMute = false; // mirrorPresentChanged) Q_PROPERTY(QString mirrorDevName READ mirrorDevName
}; // NOTIFY mirrorDevNameChanged)
Q_PROPERTY( float mirrorVolume READ mirrorVolume WRITE setMirrorVolume
NOTIFY mirrorVolumeChanged )
Q_PROPERTY( bool mirrorMuted READ mirrorMuted WRITE setMirrorMuted NOTIFY
mirrorMutedChanged )
Q_PROPERTY( int micDeviceIndex READ micDeviceIndex WRITE setMicDeviceIndex
NOTIFY micDeviceIndexChanged )
// Q_PROPERTY(bool micPresent READ micPresent NOTIFY micPresentChanged)
// Q_PROPERTY(QString micDevName READ micDevName NOTIFY micDevNameChanged)
Q_PROPERTY( float micVolume READ micVolume WRITE setMicVolume NOTIFY
micVolumeChanged )
Q_PROPERTY(
bool micMuted READ micMuted WRITE setMicMuted NOTIFY micMutedChanged )
Q_PROPERTY( bool micProximitySensorCanMute READ micProximitySensorCanMute
WRITE setMicProximitySensorCanMute NOTIFY
micProximitySensorCanMuteChanged )
Q_PROPERTY( bool micReversePtt READ micReversePtt WRITE setMicReversePtt
NOTIFY micReversePttChanged )
private:
OverlayController* parent;
QQuickWindow* widget;
class AudioTabController : public PttController { vr::VROverlayHandle_t m_ulNotificationOverlayHandle
Q_OBJECT = vr::k_ulOverlayHandleInvalid;
Q_PROPERTY(int playbackDeviceIndex READ playbackDeviceIndex WRITE setPlaybackDeviceIndex NOTIFY playbackDeviceIndexChanged)
Q_PROPERTY(int mirrorDeviceIndex READ mirrorDeviceIndex WRITE setMirrorDeviceIndex NOTIFY mirrorDeviceIndexChanged)
//Q_PROPERTY(bool mirrorPresent READ mirrorPresent NOTIFY mirrorPresentChanged)
//Q_PROPERTY(QString mirrorDevName READ mirrorDevName NOTIFY mirrorDevNameChanged)
Q_PROPERTY(float mirrorVolume READ mirrorVolume WRITE setMirrorVolume NOTIFY mirrorVolumeChanged)
Q_PROPERTY(bool mirrorMuted READ mirrorMuted WRITE setMirrorMuted NOTIFY mirrorMutedChanged)
Q_PROPERTY(int micDeviceIndex READ micDeviceIndex WRITE setMicDeviceIndex NOTIFY micDeviceIndexChanged)
//Q_PROPERTY(bool micPresent READ micPresent NOTIFY micPresentChanged)
//Q_PROPERTY(QString micDevName READ micDevName NOTIFY micDevNameChanged)
Q_PROPERTY(float micVolume READ micVolume WRITE setMicVolume NOTIFY micVolumeChanged)
Q_PROPERTY(bool micMuted READ micMuted WRITE setMicMuted NOTIFY micMutedChanged)
Q_PROPERTY(bool micProximitySensorCanMute READ micProximitySensorCanMute WRITE setMicProximitySensorCanMute NOTIFY micProximitySensorCanMuteChanged)
Q_PROPERTY(bool micReversePtt READ micReversePtt WRITE setMicReversePtt NOTIFY micReversePttChanged)
private: int m_playbackDeviceIndex = -1;
OverlayController* parent;
QQuickWindow* widget;
vr::VROverlayHandle_t m_ulNotificationOverlayHandle = vr::k_ulOverlayHandleInvalid; int m_mirrorDeviceIndex = -1;
float m_mirrorVolume = 1.0;
bool m_mirrorMuted = false;
int m_playbackDeviceIndex = -1; int m_recordingDeviceIndex = -1;
float m_micVolume = 1.0;
bool m_micMuted = false;
bool m_micProximitySensorCanMute = false;
bool m_micReversePtt = false;
int m_mirrorDeviceIndex = -1; unsigned settingsUpdateCounter = 0;
float m_mirrorVolume = 1.0;
bool m_mirrorMuted = false;
int m_recordingDeviceIndex = -1; std::unique_ptr<AudioManager> audioManager;
float m_micVolume = 1.0; std::vector<std::pair<std::string, std::string>> m_recordingDevices;
bool m_micMuted = false; std::vector<std::pair<std::string, std::string>> m_playbackDevices;
bool m_micProximitySensorCanMute = false; std::string lastMirrorDevId;
bool m_micReversePtt = false;
unsigned settingsUpdateCounter = 0; QString getSettingsName() override
{
return "audioSettings";
}
// QString getSettingsNameAudio() override { return "audioSettingsTest"; }
void onPttStart() override;
void onPttStop() override;
void onPttEnabled() override;
void onPttDisabled() override;
bool pttChangeValid() override;
virtual vr::VROverlayHandle_t getNotificationOverlayHandle() override
{
return m_ulNotificationOverlayHandle;
}
std::unique_ptr<AudioManager> audioManager; void findPlaybackDeviceIndex( std::string id, bool notify = true );
std::vector<std::pair<std::string, std::string>> m_recordingDevices; void findMirrorDeviceIndex( std::string id, bool notify = true );
std::vector<std::pair<std::string, std::string>> m_playbackDevices; void findMicDeviceIndex( std::string id, bool notify = true );
std::string lastMirrorDevId;
QString getSettingsName() override { return "audioSettings"; } int getPlaybackIndex( std::string str );
//QString getSettingsNameAudio() override { return "audioSettingsTest"; } int getRecordingIndex( std::string str );
void onPttStart() override; int getMirrorIndex( std::string str );
void onPttStop() override; // void setPlaybackDeviceControl(int index, bool notify = true);
void onPttEnabled() override;
void onPttDisabled() override;
bool pttChangeValid() override;
virtual vr::VROverlayHandle_t getNotificationOverlayHandle() override { return m_ulNotificationOverlayHandle; }
void findPlaybackDeviceIndex(std::string id, bool notify = true); std::vector<AudioProfile> audioProfiles;
void findMirrorDeviceIndex(std::string id, bool notify = true); // std::recursive_mutex eventLoopMutexAudio;
void findMicDeviceIndex(std::string id, bool notify = true);
int getPlaybackIndex(std::string str); public:
int getRecordingIndex(std::string str); void initStage1();
int getMirrorIndex(std::string str); void initStage2( OverlayController* parent, QQuickWindow* widget );
//void setPlaybackDeviceControl(int index, bool notify = true);
std::vector<AudioProfile> audioProfiles; void reloadAudioSettings();
//std::recursive_mutex eventLoopMutexAudio; void saveAudioSettings();
public: void eventLoopTick();
int playbackDeviceIndex() const;
void initStage1(); int mirrorDeviceIndex() const;
void initStage2(OverlayController* parent, QQuickWindow* widget); float mirrorVolume() const;
bool mirrorMuted() const;
void reloadAudioSettings(); int micDeviceIndex() const;
void saveAudioSettings(); float micVolume() const;
bool micMuted() const;
bool micProximitySensorCanMute() const;
bool micReversePtt() const;
void eventLoopTick(); void reloadAudioProfiles();
void saveAudioProfiles();
int playbackDeviceIndex() const; Q_INVOKABLE int getPlaybackDeviceCount();
Q_INVOKABLE QString getPlaybackDeviceName( int index );
int mirrorDeviceIndex() const; Q_INVOKABLE int getRecordingDeviceCount();
float mirrorVolume() const; Q_INVOKABLE QString getRecordingDeviceName( int index );
bool mirrorMuted() const;
int micDeviceIndex() const; // TODO check if needed?
float micVolume() const; Q_INVOKABLE unsigned getAudioProfileCount();
bool micMuted() const; Q_INVOKABLE QString getAudioProfileName( unsigned index );
bool micProximitySensorCanMute() const;
bool micReversePtt() const;
void reloadAudioProfiles(); void onNewRecordingDevice();
void saveAudioProfiles(); void onNewPlaybackDevice();
void onNewMirrorDevice();
void onDeviceStateChanged();
Q_INVOKABLE int getPlaybackDeviceCount(); public slots:
Q_INVOKABLE QString getPlaybackDeviceName(int index); void setMirrorVolume( float value, bool notify = true );
void setMirrorMuted( bool value, bool notify = true );
Q_INVOKABLE int getRecordingDeviceCount(); void setMicVolume( float value, bool notify = true );
Q_INVOKABLE QString getRecordingDeviceName(int index); void setMicMuted( bool value, bool notify = true );
void setMicProximitySensorCanMute( bool value, bool notify = true );
void setMicReversePtt( bool value, bool notify = true );
//TODO check if needed? void setPlaybackDeviceIndex( int value, bool notify = true );
Q_INVOKABLE unsigned getAudioProfileCount(); void setMirrorDeviceIndex( int value, bool notify = true );
Q_INVOKABLE QString getAudioProfileName(unsigned index); void setMicDeviceIndex( int value, bool notify = true );
void onNewRecordingDevice(); void addAudioProfile( QString name );
void onNewPlaybackDevice(); void applyAudioProfile( unsigned index );
void onNewMirrorDevice(); void deleteAudioProfile( unsigned index );
void onDeviceStateChanged();
public slots: signals:
void setMirrorVolume(float value, bool notify = true); void playbackDeviceIndexChanged( int index );
void setMirrorMuted(bool value, bool notify = true);
void setMicVolume(float value, bool notify = true); void mirrorDeviceIndexChanged( int index );
void setMicMuted(bool value, bool notify = true); void mirrorVolumeChanged( float value );
void setMicProximitySensorCanMute(bool value, bool notify = true); void mirrorMutedChanged( bool value );
void setMicReversePtt(bool value, bool notify = true);
void setPlaybackDeviceIndex(int value, bool notify = true); void micDeviceIndexChanged( int index );
void setMirrorDeviceIndex(int value, bool notify = true); void micVolumeChanged( float value );
void setMicDeviceIndex(int value, bool notify = true); void micMutedChanged( bool value );
void micProximitySensorCanMuteChanged( bool value );
void micReversePttChanged( bool value );
void addAudioProfile(QString name); void playbackDeviceListChanged();
void applyAudioProfile(unsigned index); void recordingDeviceListChanged();
void deleteAudioProfile(unsigned index);
signals: void audioProfilesUpdated();
void playbackDeviceIndexChanged(int index); };
void mirrorDeviceIndexChanged(int index);
void mirrorVolumeChanged(float value);
void mirrorMutedChanged(bool value);
void micDeviceIndexChanged(int index);
void micVolumeChanged(float value);
void micMutedChanged(bool value);
void micProximitySensorCanMuteChanged(bool value);
void micReversePttChanged(bool value);
void playbackDeviceListChanged();
void recordingDeviceListChanged();
void audioProfilesUpdated();
};
} // namespace advsettings } // namespace advsettings
File diff suppressed because it is too large Load Diff
+218 -166
View File
@@ -9,234 +9,286 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
struct ChaperoneProfile
{
std::string profileName;
struct ChaperoneProfile { bool includesChaperoneGeometry = false;
std::string profileName; unsigned chaperoneGeometryQuadCount = 0;
std::unique_ptr<vr::HmdQuad_t> chaperoneGeometryQuads = nullptr;
vr::HmdMatrix34_t standingCenter;
float playSpaceAreaX = 0.0f;
float playSpaceAreaZ = 0.0f;
bool includesChaperoneGeometry = false; bool includesVisibility = false;
unsigned chaperoneGeometryQuadCount = 0; float visibility = 0.6f;
std::unique_ptr<vr::HmdQuad_t> chaperoneGeometryQuads = nullptr;
vr::HmdMatrix34_t standingCenter;
float playSpaceAreaX = 0.0f;
float playSpaceAreaZ = 0.0f;
bool includesVisibility = false; bool includesFadeDistance = false;
float visibility = 0.6f; float fadeDistance = 0.7f;
bool includesFadeDistance = false; bool includesCenterMarker = false;
float fadeDistance = 0.7f; bool centerMarker = false;
bool includesCenterMarker = false; bool includesPlaySpaceMarker = false;
bool centerMarker = false; bool playSpaceMarker = false;
bool includesPlaySpaceMarker = false; bool includesFloorBoundsMarker = false;
bool playSpaceMarker = false; bool floorBoundsMarker = false;
bool includesFloorBoundsMarker = false; bool includesBoundsColor = false;
bool floorBoundsMarker = false; int boundsColor[3] = { 0, 0, 0 };
bool includesBoundsColor = false; bool includesChaperoneStyle = false;
int boundsColor[3] = {0, 0, 0}; int chaperoneStyle = 0;
bool includesChaperoneStyle = false; bool includesForceBounds = false;
int chaperoneStyle = 0; bool forceBounds = false;
bool includesForceBounds = false; bool includesProximityWarningSettings = false;
bool forceBounds = false; bool enableChaperoneSwitchToBeginner = false;
float chaperoneSwitchToBeginnerDistance = 0.0f;
bool includesProximityWarningSettings = false; bool enableChaperoneHapticFeedback = false;
bool enableChaperoneSwitchToBeginner = false; float chaperoneHapticFeedbackDistance = 0.0f;
float chaperoneSwitchToBeginnerDistance = 0.0f; bool enableChaperoneAlarmSound = false;
bool enableChaperoneHapticFeedback = false; bool chaperoneAlarmSoundLooping = true;
float chaperoneHapticFeedbackDistance = 0.0f; bool chaperoneAlarmSoundAdjustVolume = false;
bool enableChaperoneAlarmSound = false; float chaperoneAlarmSoundDistance = 0.0f;
bool chaperoneAlarmSoundLooping = true; bool enableChaperoneShowDashboard = false;
bool chaperoneAlarmSoundAdjustVolume = false; float chaperoneShowDashboardDistance = 0.0f;
float chaperoneAlarmSoundDistance = 0.0f; bool enableChaperoneVelocityModifier = false;
bool enableChaperoneShowDashboard = false; float chaperoneVelocityModifier = 0.0f;
float chaperoneShowDashboardDistance = 0.0f;
bool enableChaperoneVelocityModifier = false;
float chaperoneVelocityModifier = 0.0f;
}; };
class ChaperoneTabController : public QObject
{
Q_OBJECT
Q_PROPERTY( float boundsVisibility READ boundsVisibility WRITE
setBoundsVisibility NOTIFY boundsVisibilityChanged )
Q_PROPERTY( float fadeDistance READ fadeDistance WRITE setFadeDistance
NOTIFY fadeDistanceChanged )
Q_PROPERTY( float height READ height WRITE setHeight NOTIFY heightChanged )
Q_PROPERTY( bool centerMarker READ centerMarker WRITE setCenterMarker NOTIFY
centerMarkerChanged )
Q_PROPERTY( bool playSpaceMarker READ playSpaceMarker WRITE
setPlaySpaceMarker NOTIFY playSpaceMarkerChanged )
Q_PROPERTY( bool forceBounds READ forceBounds WRITE setForceBounds NOTIFY
forceBoundsChanged )
class ChaperoneTabController : public QObject { Q_PROPERTY( bool chaperoneSwitchToBeginnerEnabled READ
Q_OBJECT isChaperoneSwitchToBeginnerEnabled WRITE
Q_PROPERTY(float boundsVisibility READ boundsVisibility WRITE setBoundsVisibility NOTIFY boundsVisibilityChanged) setChaperoneSwitchToBeginnerEnabled NOTIFY
Q_PROPERTY(float fadeDistance READ fadeDistance WRITE setFadeDistance NOTIFY fadeDistanceChanged) chaperoneSwitchToBeginnerEnabledChanged )
Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged) Q_PROPERTY( float chaperoneSwitchToBeginnerDistance READ
Q_PROPERTY(bool centerMarker READ centerMarker WRITE setCenterMarker NOTIFY centerMarkerChanged) chaperoneSwitchToBeginnerDistance WRITE
Q_PROPERTY(bool playSpaceMarker READ playSpaceMarker WRITE setPlaySpaceMarker NOTIFY playSpaceMarkerChanged) setChaperoneSwitchToBeginnerDistance NOTIFY
Q_PROPERTY(bool forceBounds READ forceBounds WRITE setForceBounds NOTIFY forceBoundsChanged) chaperoneSwitchToBeginnerDistanceChanged )
Q_PROPERTY(bool chaperoneSwitchToBeginnerEnabled READ isChaperoneSwitchToBeginnerEnabled WRITE setChaperoneSwitchToBeginnerEnabled NOTIFY chaperoneSwitchToBeginnerEnabledChanged) Q_PROPERTY( bool chaperoneHapticFeedbackEnabled READ
Q_PROPERTY(float chaperoneSwitchToBeginnerDistance READ chaperoneSwitchToBeginnerDistance WRITE setChaperoneSwitchToBeginnerDistance NOTIFY chaperoneSwitchToBeginnerDistanceChanged) isChaperoneHapticFeedbackEnabled WRITE
setChaperoneHapticFeedbackEnabled NOTIFY
chaperoneHapticFeedbackEnabledChanged )
Q_PROPERTY( float chaperoneHapticFeedbackDistance READ
chaperoneHapticFeedbackDistance WRITE
setChaperoneHapticFeedbackDistance NOTIFY
chaperoneHapticFeedbackDistanceChanged )
Q_PROPERTY(bool chaperoneHapticFeedbackEnabled READ isChaperoneHapticFeedbackEnabled WRITE setChaperoneHapticFeedbackEnabled NOTIFY chaperoneHapticFeedbackEnabledChanged) Q_PROPERTY(
Q_PROPERTY(float chaperoneHapticFeedbackDistance READ chaperoneHapticFeedbackDistance WRITE setChaperoneHapticFeedbackDistance NOTIFY chaperoneHapticFeedbackDistanceChanged) bool chaperoneAlarmSoundEnabled READ isChaperoneAlarmSoundEnabled WRITE
setChaperoneAlarmSoundEnabled NOTIFY
chaperoneAlarmSoundEnabledChanged )
Q_PROPERTY(
bool chaperoneAlarmSoundLooping READ isChaperoneAlarmSoundLooping WRITE
setChaperoneAlarmSoundLooping NOTIFY
chaperoneAlarmSoundLoopingChanged )
Q_PROPERTY( bool chaperoneAlarmSoundAdjustVolume READ
isChaperoneAlarmSoundAdjustVolume WRITE
setChaperoneAlarmSoundAdjustVolume NOTIFY
chaperoneAlarmSoundAdjustVolumeChanged )
Q_PROPERTY(
float chaperoneAlarmSoundDistance READ chaperoneAlarmSoundDistance WRITE
setChaperoneAlarmSoundDistance NOTIFY
chaperoneAlarmSoundDistanceChanged )
Q_PROPERTY(bool chaperoneAlarmSoundEnabled READ isChaperoneAlarmSoundEnabled WRITE setChaperoneAlarmSoundEnabled NOTIFY chaperoneAlarmSoundEnabledChanged) Q_PROPERTY(
Q_PROPERTY(bool chaperoneAlarmSoundLooping READ isChaperoneAlarmSoundLooping WRITE setChaperoneAlarmSoundLooping NOTIFY chaperoneAlarmSoundLoopingChanged) bool chaperoneShowDashboardEnabled READ isChaperoneShowDashboardEnabled
Q_PROPERTY(bool chaperoneAlarmSoundAdjustVolume READ isChaperoneAlarmSoundAdjustVolume WRITE setChaperoneAlarmSoundAdjustVolume NOTIFY chaperoneAlarmSoundAdjustVolumeChanged) WRITE setChaperoneShowDashboardEnabled NOTIFY
Q_PROPERTY(float chaperoneAlarmSoundDistance READ chaperoneAlarmSoundDistance WRITE setChaperoneAlarmSoundDistance NOTIFY chaperoneAlarmSoundDistanceChanged) chaperoneShowDashboardEnabledChanged )
Q_PROPERTY(
float chaperoneShowDashboardDistance READ chaperoneShowDashboardDistance
WRITE setChaperoneShowDashboardDistance NOTIFY
chaperoneShowDashboardDistanceChanged )
Q_PROPERTY(bool chaperoneShowDashboardEnabled READ isChaperoneShowDashboardEnabled WRITE setChaperoneShowDashboardEnabled NOTIFY chaperoneShowDashboardEnabledChanged) Q_PROPERTY( bool chaperoneVelocityModifierEnabled READ
Q_PROPERTY(float chaperoneShowDashboardDistance READ chaperoneShowDashboardDistance WRITE setChaperoneShowDashboardDistance NOTIFY chaperoneShowDashboardDistanceChanged) isChaperoneVelocityModifierEnabled WRITE
setChaperoneVelocityModifierEnabled NOTIFY
Q_PROPERTY(bool chaperoneVelocityModifierEnabled READ isChaperoneVelocityModifierEnabled WRITE setChaperoneVelocityModifierEnabled NOTIFY chaperoneVelocityModifierEnabledChanged) chaperoneVelocityModifierEnabledChanged )
Q_PROPERTY(float chaperoneVelocityModifier READ chaperoneVelocityModifier WRITE setChaperoneVelocityModifier NOTIFY chaperoneVelocityModifierChanged) Q_PROPERTY( float chaperoneVelocityModifier READ chaperoneVelocityModifier
WRITE setChaperoneVelocityModifier NOTIFY
chaperoneVelocityModifierChanged )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
float m_visibility = 0.6f; float m_visibility = 0.6f;
float m_fadeDistance = 0.7f; float m_fadeDistance = 0.7f;
float m_fadeDistanceModified = 0.7f; float m_fadeDistanceModified = 0.7f;
float m_height = 2.0f; float m_height = 2.0f;
bool m_centerMarker = false; bool m_centerMarker = false;
bool m_playSpaceMarker = false; bool m_playSpaceMarker = false;
bool m_forceBounds = false; bool m_forceBounds = false;
bool m_enableChaperoneSwitchToBeginner = false; bool m_enableChaperoneSwitchToBeginner = false;
float m_chaperoneSwitchToBeginnerDistance = 0.5f; float m_chaperoneSwitchToBeginnerDistance = 0.5f;
bool m_chaperoneSwitchToBeginnerActive = false; bool m_chaperoneSwitchToBeginnerActive = false;
int32_t m_chaperoneSwitchToBeginnerLastStyle = 0; int32_t m_chaperoneSwitchToBeginnerLastStyle = 0;
bool m_enableChaperoneHapticFeedback = true; bool m_enableChaperoneHapticFeedback = true;
float m_chaperoneHapticFeedbackDistance = 0.5f; float m_chaperoneHapticFeedbackDistance = 0.5f;
bool m_chaperoneHapticFeedbackActive = false; bool m_chaperoneHapticFeedbackActive = false;
std::thread m_chaperoneHapticFeedbackThread; std::thread m_chaperoneHapticFeedbackThread;
bool m_enableChaperoneAlarmSound = false; bool m_enableChaperoneAlarmSound = false;
bool m_chaperoneAlarmSoundLooping = true; bool m_chaperoneAlarmSoundLooping = true;
bool m_chaperoneAlarmSoundAdjustVolume = false; bool m_chaperoneAlarmSoundAdjustVolume = false;
float m_chaperoneAlarmSoundDistance = 0.5f; float m_chaperoneAlarmSoundDistance = 0.5f;
bool m_chaperoneAlarmSoundActive = false; bool m_chaperoneAlarmSoundActive = false;
bool m_enableChaperoneShowDashboard = false; bool m_enableChaperoneShowDashboard = false;
float m_chaperoneShowDashboardDistance = 0.5f; float m_chaperoneShowDashboardDistance = 0.5f;
bool m_chaperoneShowDashboardActive = false; bool m_chaperoneShowDashboardActive = false;
bool m_enableChaperoneVelocityModifier = false; bool m_enableChaperoneVelocityModifier = false;
float m_chaperoneVelocityModifier = 0.0f; float m_chaperoneVelocityModifier = 0.0f;
float m_chaperoneVelocityModifierCurrent = 1.0f; float m_chaperoneVelocityModifierCurrent = 1.0f;
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
std::vector<ChaperoneProfile> chaperoneProfiles; std::vector<ChaperoneProfile> chaperoneProfiles;
public: public:
~ChaperoneTabController(); ~ChaperoneTabController();
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed, float hmdSpeed); void eventLoopTick( vr::TrackedDevicePose_t* devicePoses,
void handleChaperoneWarnings(float distance); float leftSpeed,
float rightSpeed,
float hmdSpeed );
void handleChaperoneWarnings( float distance );
float boundsVisibility() const; float boundsVisibility() const;
float fadeDistance() const; float fadeDistance() const;
float height() const; float height() const;
bool centerMarker() const; bool centerMarker() const;
bool playSpaceMarker() const; bool playSpaceMarker() const;
bool forceBounds() const; bool forceBounds() const;
bool isChaperoneSwitchToBeginnerEnabled() const; bool isChaperoneSwitchToBeginnerEnabled() const;
float chaperoneSwitchToBeginnerDistance() const; float chaperoneSwitchToBeginnerDistance() const;
bool isChaperoneHapticFeedbackEnabled() const; bool isChaperoneHapticFeedbackEnabled() const;
float chaperoneHapticFeedbackDistance() const; float chaperoneHapticFeedbackDistance() const;
bool isChaperoneAlarmSoundEnabled() const; bool isChaperoneAlarmSoundEnabled() const;
bool isChaperoneAlarmSoundLooping() const; bool isChaperoneAlarmSoundLooping() const;
bool isChaperoneAlarmSoundAdjustVolume() const; bool isChaperoneAlarmSoundAdjustVolume() const;
float chaperoneAlarmSoundDistance() const; float chaperoneAlarmSoundDistance() const;
bool isChaperoneShowDashboardEnabled() const; bool isChaperoneShowDashboardEnabled() const;
float chaperoneShowDashboardDistance() const; float chaperoneShowDashboardDistance() const;
bool isChaperoneVelocityModifierEnabled() const; bool isChaperoneVelocityModifierEnabled() const;
float chaperoneVelocityModifier() const; float chaperoneVelocityModifier() const;
void reloadChaperoneProfiles(); void reloadChaperoneProfiles();
void saveChaperoneProfiles(); void saveChaperoneProfiles();
Q_INVOKABLE unsigned getChaperoneProfileCount(); Q_INVOKABLE unsigned getChaperoneProfileCount();
Q_INVOKABLE QString getChaperoneProfileName(unsigned index); Q_INVOKABLE QString getChaperoneProfileName( unsigned index );
float getBoundsMaxY(); float getBoundsMaxY();
public slots: public slots:
void setBoundsVisibility(float value, bool notify = true); void setBoundsVisibility( float value, bool notify = true );
void setFadeDistance(float value, bool notify = true); void setFadeDistance( float value, bool notify = true );
void setHeight(float value, bool notify = true); void setHeight( float value, bool notify = true );
void updateHeight(float value, bool notify = true); void updateHeight( float value, bool notify = true );
void setCenterMarker(bool value, bool notify = true); void setCenterMarker( bool value, bool notify = true );
void setPlaySpaceMarker(bool value, bool notify = true); void setPlaySpaceMarker( bool value, bool notify = true );
void setForceBounds(bool value, bool notify = true); void setForceBounds( bool value, bool notify = true );
void setChaperoneSwitchToBeginnerEnabled(bool value, bool notify = true); void setChaperoneSwitchToBeginnerEnabled( bool value, bool notify = true );
void setChaperoneSwitchToBeginnerDistance(float value, bool notify = true); void setChaperoneSwitchToBeginnerDistance( float value,
bool notify = true );
void setChaperoneHapticFeedbackEnabled(bool value, bool notify = true); void setChaperoneHapticFeedbackEnabled( bool value, bool notify = true );
void setChaperoneHapticFeedbackDistance(float value, bool notify = true); void setChaperoneHapticFeedbackDistance( float value, bool notify = true );
void setChaperoneAlarmSoundEnabled(bool value, bool notify = true); void setChaperoneAlarmSoundEnabled( bool value, bool notify = true );
void setChaperoneAlarmSoundLooping(bool value, bool notify = true); void setChaperoneAlarmSoundLooping( bool value, bool notify = true );
void setChaperoneAlarmSoundAdjustVolume(bool value, bool notify = true); void setChaperoneAlarmSoundAdjustVolume( bool value, bool notify = true );
void setChaperoneAlarmSoundDistance(float value, bool notify = true); void setChaperoneAlarmSoundDistance( float value, bool notify = true );
void setChaperoneShowDashboardEnabled(bool value, bool notify = true); void setChaperoneShowDashboardEnabled( bool value, bool notify = true );
void setChaperoneShowDashboardDistance(float value, bool notify = true); void setChaperoneShowDashboardDistance( float value, bool notify = true );
void setChaperoneVelocityModifierEnabled(bool value, bool notify = true); void setChaperoneVelocityModifierEnabled( bool value, bool notify = true );
void setChaperoneVelocityModifier(float value, bool notify = true); void setChaperoneVelocityModifier( float value, bool notify = true );
void flipOrientation(); void flipOrientation();
void reloadFromDisk(); void reloadFromDisk();
void addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker, void addChaperoneProfile( QString name,
bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds, bool includeGeometry,
bool includesProximityWarningSettings); bool includeVisbility,
void applyChaperoneProfile(unsigned index); bool includeFadeDistance,
void deleteChaperoneProfile(unsigned index); bool includeCenterMarker,
bool includePlaySpaceMarker,
bool includeFloorBounds,
bool includeBoundsColor,
bool includeChaperoneStyle,
bool includeForceBounds,
bool includesProximityWarningSettings );
void applyChaperoneProfile( unsigned index );
void deleteChaperoneProfile( unsigned index );
void reset(); void reset();
void shutdown(); void shutdown();
signals: signals:
void boundsVisibilityChanged(float value); void boundsVisibilityChanged( float value );
void fadeDistanceChanged(float value); void fadeDistanceChanged( float value );
void heightChanged(float value); void heightChanged( float value );
void centerMarkerChanged(bool value); void centerMarkerChanged( bool value );
void playSpaceMarkerChanged(bool value); void playSpaceMarkerChanged( bool value );
void forceBoundsChanged(bool value); void forceBoundsChanged( bool value );
void chaperoneSwitchToBeginnerEnabledChanged(bool value); void chaperoneSwitchToBeginnerEnabledChanged( bool value );
void chaperoneSwitchToBeginnerDistanceChanged(float value); void chaperoneSwitchToBeginnerDistanceChanged( float value );
void chaperoneHapticFeedbackEnabledChanged(bool value); void chaperoneHapticFeedbackEnabledChanged( bool value );
void chaperoneHapticFeedbackDistanceChanged(float value); void chaperoneHapticFeedbackDistanceChanged( float value );
void chaperoneAlarmSoundEnabledChanged(bool value); void chaperoneAlarmSoundEnabledChanged( bool value );
void chaperoneAlarmSoundLoopingChanged(bool value); void chaperoneAlarmSoundLoopingChanged( bool value );
void chaperoneAlarmSoundAdjustVolumeChanged(bool value); void chaperoneAlarmSoundAdjustVolumeChanged( bool value );
void chaperoneAlarmSoundDistanceChanged(float value); void chaperoneAlarmSoundDistanceChanged( float value );
void chaperoneShowDashboardEnabledChanged(bool value); void chaperoneShowDashboardEnabledChanged( bool value );
void chaperoneShowDashboardDistanceChanged(float value); void chaperoneShowDashboardDistanceChanged( float value );
void chaperoneVelocityModifierEnabledChanged(bool value); void chaperoneVelocityModifierEnabledChanged( bool value );
void chaperoneVelocityModifierChanged(float value); void chaperoneVelocityModifierChanged( float value );
void chaperoneProfilesUpdated(); void chaperoneProfilesUpdated();
}; };
} // namespace advsettings } // namespace advsettings
+212 -155
View File
@@ -3,177 +3,234 @@
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
void FixFloorTabController::initStage1() {}
void FixFloorTabController::initStage2( OverlayController* var_parent,
void FixFloorTabController::initStage1() { QQuickWindow* var_widget )
{
this->parent = var_parent;
this->widget = var_widget;
} }
void FixFloorTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { void FixFloorTabController::eventLoopTick(
this->parent = var_parent; vr::TrackedDevicePose_t* devicePoses )
this->widget = var_widget; {
if ( state > 0 )
{
if ( measurementCount == 0 )
{
// Get Controller ids for left/right hand
auto leftId
= vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(
vr::TrackedControllerRole_LeftHand );
if ( leftId == vr::k_unTrackedDeviceIndexInvalid )
{
statusMessage = "No left controller found.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
auto rightId
= vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(
vr::TrackedControllerRole_RightHand );
if ( rightId == vr::k_unTrackedDeviceIndexInvalid )
{
statusMessage = "No right controller found.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
// Get poses
vr::TrackedDevicePose_t* leftPose = devicePoses + leftId;
vr::TrackedDevicePose_t* rightPose = devicePoses + rightId;
if ( !leftPose->bPoseIsValid || !leftPose->bDeviceIsConnected
|| leftPose->eTrackingResult != vr::TrackingResult_Running_OK )
{
statusMessage = "Left controller tracking problems.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
else if ( !rightPose->bPoseIsValid || !rightPose->bDeviceIsConnected
|| rightPose->eTrackingResult
!= vr::TrackingResult_Running_OK )
{
statusMessage = "Right controller tracking problems.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
else
{
// The controller with the lowest y-pos is the floor fix
// reference
if ( leftPose->mDeviceToAbsoluteTracking.m[1][3]
< rightPose->mDeviceToAbsoluteTracking.m[1][3] )
{
referenceController = leftId;
}
else
{
referenceController = rightId;
}
auto& m = devicePoses[referenceController]
.mDeviceToAbsoluteTracking.m;
tempOffsetX = ( double ) m[0][3];
tempOffsetY = ( double ) m[1][3];
tempOffsetZ = ( double ) m[2][3];
/*
| Intrinsic y-x'-z" rotation matrix:
| cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy |
| cp*sr | cp*cr |-sp |
| cy*sp*sr-cr*sy | cr*cy*sp+sr*sy | cp*cy |
yaw = atan2(cp*sy, cp*cy) [pi, -pi], CCW
pitch = -asin(-sp) [pi/2, -pi/2]
roll = atan2(cp*sr, cp*cr) [pi, -pi], CW
*/
tempRoll = std::atan2( ( double ) m[1][0], ( double ) m[1][1] );
measurementCount = 1;
}
}
else
{
measurementCount++;
auto& m
= devicePoses[referenceController].mDeviceToAbsoluteTracking.m;
double rollDiff
= std::atan2( ( double ) m[1][0], ( double ) m[1][1] )
- tempRoll;
if ( rollDiff > M_PI )
{
rollDiff -= 2.0 * M_PI;
}
else if ( rollDiff < -M_PI )
{
rollDiff += 2.0 * M_PI;
}
tempRoll += rollDiff / ( double ) measurementCount;
if ( tempRoll > M_PI )
{
tempRoll -= 2.0 * M_PI;
}
else if ( tempRoll < -M_PI )
{
tempRoll += 2.0 * M_PI;
}
if ( measurementCount >= 25 )
{
if ( std::abs( tempRoll ) <= M_PI_2 )
{
floorOffsetY = tempOffsetY - controllerUpOffsetCorrection;
}
else
{
floorOffsetY = tempOffsetY - controllerDownOffsetCorrection;
}
floorOffsetX = tempOffsetX;
floorOffsetZ = tempOffsetZ;
LOG( INFO )
<< "Fix Floor and adjust playspace center: Floor Offset = ["
<< floorOffsetX << ", " << floorOffsetY << ", "
<< floorOffsetZ << "]";
float offset[3] = { 0, 0, 0 };
offset[1] = floorOffsetY;
if ( state == 2 )
{
offset[0] = floorOffsetX;
offset[2] = floorOffsetZ;
}
parent->AddOffsetToUniverseCenter(
vr::TrackingUniverseStanding, offset, true );
statusMessage
= ( state == 2 ) ? "Recentering ... Ok" : "Fixing ... OK";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
emit measureEndSignal();
setCanUndo( true );
state = 0;
}
}
}
} }
void FixFloorTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses) { QString FixFloorTabController::currentStatusMessage()
if (state > 0) { {
if (measurementCount == 0) { return statusMessage;
// Get Controller ids for left/right hand
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
if (leftId == vr::k_unTrackedDeviceIndexInvalid) {
statusMessage = "No left controller found.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
if (rightId == vr::k_unTrackedDeviceIndexInvalid) {
statusMessage = "No right controller found.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
// Get poses
vr::TrackedDevicePose_t* leftPose = devicePoses + leftId;
vr::TrackedDevicePose_t* rightPose = devicePoses + rightId;
if (!leftPose->bPoseIsValid || !leftPose->bDeviceIsConnected || leftPose->eTrackingResult != vr::TrackingResult_Running_OK) {
statusMessage = "Left controller tracking problems.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
} else if (!rightPose->bPoseIsValid || !rightPose->bDeviceIsConnected || rightPose->eTrackingResult != vr::TrackingResult_Running_OK) {
statusMessage = "Right controller tracking problems.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
} else {
// The controller with the lowest y-pos is the floor fix reference
if (leftPose->mDeviceToAbsoluteTracking.m[1][3] < rightPose->mDeviceToAbsoluteTracking.m[1][3]) {
referenceController = leftId;
} else {
referenceController = rightId;
}
auto& m = devicePoses[referenceController].mDeviceToAbsoluteTracking.m;
tempOffsetX = (double)m[0][3];
tempOffsetY = (double)m[1][3];
tempOffsetZ = (double)m[2][3];
/*
| Intrinsic y-x'-z" rotation matrix:
| cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy |
| cp*sr | cp*cr |-sp |
| cy*sp*sr-cr*sy | cr*cy*sp+sr*sy | cp*cy |
yaw = atan2(cp*sy, cp*cy) [pi, -pi], CCW
pitch = -asin(-sp) [pi/2, -pi/2]
roll = atan2(cp*sr, cp*cr) [pi, -pi], CW
*/
tempRoll = std::atan2((double)m[1][0], (double)m[1][1]);
measurementCount = 1;
}
} else {
measurementCount++;
auto& m = devicePoses[referenceController].mDeviceToAbsoluteTracking.m;
double rollDiff = std::atan2((double)m[1][0], (double)m[1][1]) - tempRoll;
if (rollDiff > M_PI) {
rollDiff -= 2.0 * M_PI;
} else if (rollDiff < -M_PI) {
rollDiff += 2.0 * M_PI;
}
tempRoll += rollDiff / (double)measurementCount;
if (tempRoll > M_PI) {
tempRoll -= 2.0 * M_PI;
} else if (tempRoll < -M_PI) {
tempRoll += 2.0 * M_PI;
}
if (measurementCount >= 25) {
if (std::abs(tempRoll) <= M_PI_2) {
floorOffsetY = tempOffsetY - controllerUpOffsetCorrection;
} else {
floorOffsetY = tempOffsetY - controllerDownOffsetCorrection;
}
floorOffsetX = tempOffsetX;
floorOffsetZ = tempOffsetZ;
LOG(INFO) << "Fix Floor and adjust playspace center: Floor Offset = [" << floorOffsetX << ", " << floorOffsetY << ", " << floorOffsetZ << "]";
float offset[3] = { 0, 0, 0 };
offset[1] = floorOffsetY;
if (state == 2) {
offset[0] = floorOffsetX;
offset[2] = floorOffsetZ;
}
parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, offset, true);
statusMessage = (state == 2) ? "Recentering ... Ok" : "Fixing ... OK";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
emit measureEndSignal();
setCanUndo(true);
state = 0;
}
}
}
} }
QString FixFloorTabController::currentStatusMessage() { float FixFloorTabController::currentStatusMessageTimeout()
return statusMessage; {
return statusMessageTimeout;
} }
float FixFloorTabController::currentStatusMessageTimeout() { bool FixFloorTabController::canUndo() const
return statusMessageTimeout; {
return m_canUndo;
} }
bool FixFloorTabController::canUndo() const { void FixFloorTabController::setCanUndo( bool value, bool notify )
return m_canUndo; {
if ( m_canUndo != value )
{
m_canUndo = value;
if ( notify )
{
emit canUndoChanged( m_canUndo );
}
}
} }
void FixFloorTabController::setCanUndo(bool value, bool notify) { void FixFloorTabController::fixFloorClicked()
if (m_canUndo != value) { {
m_canUndo = value; statusMessage = "Fixing ...";
if (notify) { statusMessageTimeout = 1.0;
emit canUndoChanged(m_canUndo); emit statusMessageSignal();
} emit measureStartSignal();
} measurementCount = 0;
state = 1;
} }
void FixFloorTabController::fixFloorClicked() { void FixFloorTabController::recenterClicked()
statusMessage = "Fixing ..."; {
statusMessageTimeout = 1.0; statusMessage = "Fixing ...";
emit statusMessageSignal(); statusMessageTimeout = 1.0;
emit measureStartSignal(); emit statusMessageSignal();
measurementCount = 0; emit measureStartSignal();
state = 1; measurementCount = 0;
state = 2;
} }
void FixFloorTabController::recenterClicked() { void FixFloorTabController::undoFixFloorClicked()
statusMessage = "Fixing ..."; {
statusMessageTimeout = 1.0; parent->AddOffsetToUniverseCenter(
emit statusMessageSignal(); vr::TrackingUniverseStanding, 0, -floorOffsetX, false );
emit measureStartSignal(); parent->AddOffsetToUniverseCenter(
measurementCount = 0; vr::TrackingUniverseStanding, 1, -floorOffsetY, false );
state = 2; parent->AddOffsetToUniverseCenter(
vr::TrackingUniverseStanding, 2, -floorOffsetZ, false );
LOG( INFO ) << "Fix Floor: Undo Floor Offset = [" << -floorOffsetX << ", "
<< -floorOffsetY << ", " << -floorOffsetZ << "]";
floorOffsetY = 0.0f;
statusMessage = "Undo ... OK";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
setCanUndo( false );
} }
void FixFloorTabController::undoFixFloorClicked() { } // namespace advsettings
parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 0, -floorOffsetX, false);
parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 1, -floorOffsetY, false);
parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 2, -floorOffsetZ, false);
LOG(INFO) << "Fix Floor: Undo Floor Offset = [" << -floorOffsetX << ", " << -floorOffsetY << ", " << -floorOffsetZ << "]";
floorOffsetY = 0.0f;
statusMessage = "Undo ... OK";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
setCanUndo(false);
}
} // namespace advconfig
+42 -37
View File
@@ -6,60 +6,65 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
class FixFloorTabController : public QObject { class FixFloorTabController : public QObject
Q_OBJECT {
Q_PROPERTY(bool canUndo READ canUndo WRITE setCanUndo NOTIFY canUndoChanged) Q_OBJECT
Q_PROPERTY(
bool canUndo READ canUndo WRITE setCanUndo NOTIFY canUndoChanged )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
float controllerUpOffsetCorrection = 0.062f; // Controller touchpad facing upwards float controllerUpOffsetCorrection
float controllerDownOffsetCorrection = 0.006f; // Controller touchpad facing downwards = 0.062f; // Controller touchpad facing upwards
float controllerDownOffsetCorrection
int state = 0; // 0 .. idle, 1 .. floor fix in progress, 2 .. recenter in progress = 0.006f; // Controller touchpad facing downwards
vr::TrackedDeviceIndex_t referenceController = vr::k_unTrackedDeviceIndexInvalid;
unsigned measurementCount = 0;
double tempOffsetX = 0.0;
double tempOffsetY = 0.0;
double tempOffsetZ = 0.0;
double tempRoll = 0.0;
float floorOffsetX = 0.0f;
float floorOffsetY = 0.0f;
float floorOffsetZ = 0.0f;
QString statusMessage = "";
float statusMessageTimeout = 0.0f;
bool m_canUndo = false;
int state
= 0; // 0 .. idle, 1 .. floor fix in progress, 2 .. recenter in progress
vr::TrackedDeviceIndex_t referenceController
= vr::k_unTrackedDeviceIndexInvalid;
unsigned measurementCount = 0;
double tempOffsetX = 0.0;
double tempOffsetY = 0.0;
double tempOffsetZ = 0.0;
double tempRoll = 0.0;
float floorOffsetX = 0.0f;
float floorOffsetY = 0.0f;
float floorOffsetZ = 0.0f;
QString statusMessage = "";
float statusMessageTimeout = 0.0f;
bool m_canUndo = false;
public: public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(vr::TrackedDevicePose_t* devicePoses); void eventLoopTick( vr::TrackedDevicePose_t* devicePoses );
Q_INVOKABLE QString currentStatusMessage(); Q_INVOKABLE QString currentStatusMessage();
Q_INVOKABLE float currentStatusMessageTimeout(); Q_INVOKABLE float currentStatusMessageTimeout();
bool canUndo() const; bool canUndo() const;
public slots: public slots:
void fixFloorClicked(); void fixFloorClicked();
void recenterClicked(); void recenterClicked();
void undoFixFloorClicked(); void undoFixFloorClicked();
void setCanUndo(bool value, bool notify = true); void setCanUndo( bool value, bool notify = true );
signals: signals:
void statusMessageSignal(); void statusMessageSignal();
void measureStartSignal(); void measureStartSignal();
void measureEndSignal(); void measureEndSignal();
void canUndoChanged(bool value); void canUndoChanged( bool value );
}; };
} // namespace advsettings } // namespace advsettings
+6 -7
View File
@@ -4,20 +4,19 @@
#include <QString> #include <QString>
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class AudioTabController; class AudioTabController;
class KeyboardInput class KeyboardInput
{ {
public: public:
virtual ~KeyboardInput() {}; virtual ~KeyboardInput(){};
virtual void sendKeyboardInput(QString input) = 0; virtual void sendKeyboardInput( QString input ) = 0;
virtual void sendKeyboardEnter() = 0; virtual void sendKeyboardEnter() = 0;
virtual void sendKeyboardBackspace(int count) = 0; virtual void sendKeyboardBackspace( int count ) = 0;
virtual void sendKeyboardAltTab() = 0; virtual void sendKeyboardAltTab() = 0;
}; };
} } // namespace advsettings
+514 -391
View File
@@ -2,465 +2,588 @@
#include <QQuickWindow> #include <QQuickWindow>
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
void rotateCoordinates(float coordinates[3], float angle) { void rotateCoordinates( float coordinates[3], float angle )
if (angle == 0) { {
return; if ( angle == 0 )
} {
float s = sin(angle); return;
float c = cos(angle); }
float newX = coordinates[0] * c - coordinates[2] * s; float s = sin( angle );
float newZ = coordinates[0] * s + coordinates[2] * c; float c = cos( angle );
coordinates[0] = newX; float newX = coordinates[0] * c - coordinates[2] * s;
coordinates[2] = newZ; float newZ = coordinates[0] * s + coordinates[2] * c;
coordinates[0] = newX;
coordinates[2] = newZ;
} }
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
using std::chrono::duration_cast; using std::chrono::duration_cast;
using std::chrono::milliseconds; using std::chrono::milliseconds;
typedef std::chrono::system_clock clock; typedef std::chrono::system_clock clock;
void MoveCenterTabController::initStage1() { void MoveCenterTabController::initStage1()
setTrackingUniverse(vr::VRCompositor()->GetTrackingSpace()); {
auto settings = OverlayController::appSettings(); setTrackingUniverse( vr::VRCompositor()->GetTrackingSpace() );
settings->beginGroup("playspaceSettings"); auto settings = OverlayController::appSettings();
auto value = settings->value("adjustChaperone", m_adjustChaperone); settings->beginGroup( "playspaceSettings" );
if (value.isValid() && !value.isNull()) { auto value = settings->value( "adjustChaperone", m_adjustChaperone );
m_adjustChaperone = value.toBool(); if ( value.isValid() && !value.isNull() )
} {
value = settings->value("moveShortcutRight", m_moveShortcutRightEnabled); m_adjustChaperone = value.toBool();
if (value.isValid() && !value.isNull()) { }
m_moveShortcutRightEnabled = value.toBool(); value = settings->value( "moveShortcutRight", m_moveShortcutRightEnabled );
} if ( value.isValid() && !value.isNull() )
value = settings->value("moveShortcutLeft", m_moveShortcutLeftEnabled); {
if (value.isValid() && !value.isNull()) { m_moveShortcutRightEnabled = value.toBool();
m_moveShortcutLeftEnabled = value.toBool(); }
} value = settings->value( "moveShortcutLeft", m_moveShortcutLeftEnabled );
value = settings->value("requireDoubleClick", m_requireDoubleClick); if ( value.isValid() && !value.isNull() )
if (value.isValid() && !value.isNull()) { {
m_moveShortcutLeftEnabled = value.toBool();
}
value = settings->value( "requireDoubleClick", m_requireDoubleClick );
if ( value.isValid() && !value.isNull() )
{
m_requireDoubleClick = value.toBool(); m_requireDoubleClick = value.toBool();
} }
value = settings->value("lockXToggle", m_lockXToggle); value = settings->value( "lockXToggle", m_lockXToggle );
if (value.isValid() && !value.isNull()) { if ( value.isValid() && !value.isNull() )
m_lockXToggle = value.toBool(); {
} m_lockXToggle = value.toBool();
value = settings->value("lockYToggle", m_lockYToggle); }
if (value.isValid() && !value.isNull()) { value = settings->value( "lockYToggle", m_lockYToggle );
m_lockYToggle = value.toBool(); if ( value.isValid() && !value.isNull() )
} {
value = settings->value("lockZToggle", m_lockZToggle); m_lockYToggle = value.toBool();
if (value.isValid() && !value.isNull()) { }
m_lockZToggle = value.toBool(); value = settings->value( "lockZToggle", m_lockZToggle );
} if ( value.isValid() && !value.isNull() )
settings->endGroup(); {
m_lockZToggle = value.toBool();
}
settings->endGroup();
lastMoveButtonClick[0] = lastMoveButtonClick[1] = clock::now(); lastMoveButtonClick[0] = lastMoveButtonClick[1] = clock::now();
} }
void MoveCenterTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { void MoveCenterTabController::initStage2( OverlayController* var_parent,
this->parent = var_parent; QQuickWindow* var_widget )
this->widget = var_widget; {
this->parent = var_parent;
this->widget = var_widget;
} }
int MoveCenterTabController::trackingUniverse() const
int MoveCenterTabController::trackingUniverse() const { {
return (int)m_trackingUniverse; return ( int ) m_trackingUniverse;
} }
void MoveCenterTabController::setTrackingUniverse(int value, bool notify) { void MoveCenterTabController::setTrackingUniverse( int value, bool notify )
if (m_trackingUniverse != value) { {
reset(); if ( m_trackingUniverse != value )
m_trackingUniverse = value; {
if (notify) { reset();
emit trackingUniverseChanged(m_trackingUniverse); m_trackingUniverse = value;
} if ( notify )
} {
} emit trackingUniverseChanged( m_trackingUniverse );
}
float MoveCenterTabController::offsetX() const {
return m_offsetX;
}
void MoveCenterTabController::setOffsetX(float value, bool notify) {
if (m_offsetX != value) {
modOffsetX(value - m_offsetX, notify);
}
}
float MoveCenterTabController::offsetY() const {
return m_offsetY;
}
void MoveCenterTabController::setOffsetY(float value, bool notify) {
if (m_offsetY != value) {
modOffsetY(value - m_offsetY, notify);
}
}
float MoveCenterTabController::offsetZ() const {
return m_offsetZ;
}
void MoveCenterTabController::setOffsetZ(float value, bool notify) {
if (m_offsetZ != value) {
modOffsetZ(value - m_offsetZ, notify);
}
}
int MoveCenterTabController::rotation() const {
return m_rotation;
}
void MoveCenterTabController::setRotation(int value, bool notify) {
if (m_rotation != value) {
//float angle = (value - m_rotation) * 2 * M_PI / 360.0;
//parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, angle, m_adjustChaperone);
m_rotation = value;
if (notify) {
emit rotationChanged(m_rotation);
}
}
}
void MoveCenterTabController::applyRotation() {
if (m_rotation != m_rotationOld) {
float angle = (m_rotationOld - m_rotation) * 2 * M_PI / 360.0;
parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, angle, m_adjustChaperone);
m_rotationOld = m_rotation;
}
}
bool MoveCenterTabController::adjustChaperone() const {
return m_adjustChaperone;
}
void MoveCenterTabController::setAdjustChaperone(bool value, bool notify) {
if (m_adjustChaperone != value) {
m_adjustChaperone = value;
if (m_trackingUniverse == vr::TrackingUniverseStanding) {
auto angle = m_rotation * 2 * M_PI / 360.0;
float offsetdir = m_adjustChaperone ? -1.0 : 1.0;
float offset[3] = {
offsetdir * m_offsetX,
offsetdir * m_offsetY,
offsetdir * m_offsetZ
};
rotateCoordinates(offset, angle);
parent->AddOffsetToCollisionBounds(offset);
}
auto settings = OverlayController::appSettings();
settings->beginGroup("playspaceSettings");
settings->setValue("adjustChaperone", m_adjustChaperone);
settings->endGroup();
settings->sync();
if (notify) {
emit adjustChaperoneChanged(m_adjustChaperone);
}
}
}
bool MoveCenterTabController::moveShortcutRight() const {
return m_moveShortcutRightEnabled;
}
void MoveCenterTabController::setMoveShortcutRight(bool value, bool notify) {
m_moveShortcutRightEnabled = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("playspaceSettings");
settings->setValue("moveShortcutRight", m_moveShortcutRightEnabled);
settings->endGroup();
settings->sync();
if (notify) {
emit moveShortcutRightChanged(m_moveShortcutRightEnabled);
}
}
bool MoveCenterTabController::moveShortcutLeft() const {
return m_moveShortcutLeftEnabled;
}
void MoveCenterTabController::setMoveShortcutLeft(bool value, bool notify) {
m_moveShortcutLeftEnabled = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("playspaceSettings");
settings->setValue("moveShortcutLeft", m_moveShortcutLeftEnabled);
settings->endGroup();
settings->sync();
if (notify) {
emit moveShortcutLeftChanged(m_moveShortcutLeftEnabled);
}
}
bool MoveCenterTabController::requireDoubleClick() const {
return m_requireDoubleClick;
}
void MoveCenterTabController::setRequireDoubleClick(bool value, bool notify) {
m_requireDoubleClick = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("playspaceSettings");
settings->setValue("requireDoubleClick", m_requireDoubleClick);
settings->endGroup();
settings->sync();
if (notify) {
emit requireDoubleClickChanged(m_requireDoubleClick);
} }
} }
bool MoveCenterTabController::lockXToggle() const { float MoveCenterTabController::offsetX() const
return m_lockXToggle; {
return m_offsetX;
} }
void MoveCenterTabController::setLockX(bool value, bool notify) { void MoveCenterTabController::setOffsetX( float value, bool notify )
m_lockXToggle = value; {
auto settings = OverlayController::appSettings(); if ( m_offsetX != value )
settings->beginGroup("playspaceSettings"); {
settings->setValue("lockXToggle", m_lockXToggle); modOffsetX( value - m_offsetX, notify );
settings->endGroup(); }
settings->sync();
if (notify) {
emit requireLockXChanged(m_lockXToggle);
}
} }
float MoveCenterTabController::offsetY() const
bool MoveCenterTabController::lockYToggle() const { {
return m_lockYToggle; return m_offsetY;
} }
void MoveCenterTabController::setLockY(bool value, bool notify) { void MoveCenterTabController::setOffsetY( float value, bool notify )
m_lockYToggle = value; {
auto settings = OverlayController::appSettings(); if ( m_offsetY != value )
settings->beginGroup("playspaceSettings"); {
settings->setValue("lockYToggle", m_lockYToggle); modOffsetY( value - m_offsetY, notify );
settings->endGroup(); }
settings->sync();
if (notify) {
emit requireLockYChanged(m_lockYToggle);
}
} }
bool MoveCenterTabController::lockZToggle() const { float MoveCenterTabController::offsetZ() const
return m_lockZToggle; {
return m_offsetZ;
} }
void MoveCenterTabController::setLockZ(bool value, bool notify) { void MoveCenterTabController::setOffsetZ( float value, bool notify )
m_lockZToggle = value; {
auto settings = OverlayController::appSettings(); if ( m_offsetZ != value )
settings->beginGroup("playspaceSettings"); {
settings->setValue("lockZToggle", m_lockZToggle); modOffsetZ( value - m_offsetZ, notify );
settings->endGroup(); }
settings->sync();
if (notify) {
emit requireLockZChanged(m_lockZToggle);
}
} }
int MoveCenterTabController::rotation() const
{
void MoveCenterTabController::modOffsetX(float value, bool notify) { return m_rotation;
//TODO ? possible issue with locking position this way
if (!m_lockXToggle) {
auto angle = m_rotation * 2 * M_PI / 360.0;
float offset[3] = { value, 0, 0 };
rotateCoordinates(offset, angle);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, offset, m_adjustChaperone);
m_offsetX += value;
if (notify) {
emit offsetXChanged(m_offsetX);
}
}
} }
void MoveCenterTabController::modOffsetY(float value, bool notify) { void MoveCenterTabController::setRotation( int value, bool notify )
if (!m_lockYToggle) { {
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, value, m_adjustChaperone); if ( m_rotation != value )
m_offsetY += value; {
if (notify) { // float angle = (value - m_rotation) * 2 * M_PI / 360.0;
emit offsetYChanged(m_offsetY); // parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse,
} // angle, m_adjustChaperone);
} m_rotation = value;
if ( notify )
{
emit rotationChanged( m_rotation );
}
}
} }
void MoveCenterTabController::modOffsetZ(float value, bool notify) { void MoveCenterTabController::applyRotation()
if (!m_lockZToggle) { {
auto angle = m_rotation * 2 * M_PI / 360.0; if ( m_rotation != m_rotationOld )
float offset[3] = { 0, 0, value }; {
rotateCoordinates(offset, angle); float angle = ( m_rotationOld - m_rotation ) * 2 * M_PI / 360.0;
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, offset, m_adjustChaperone); parent->RotateUniverseCenter(
m_offsetZ += value; ( vr::TrackingUniverseOrigin ) m_trackingUniverse,
if (notify) { angle,
emit offsetZChanged(m_offsetZ); m_adjustChaperone );
} m_rotationOld = m_rotation;
} }
} }
void MoveCenterTabController::reset() { bool MoveCenterTabController::adjustChaperone() const
vr::VRChaperoneSetup()->RevertWorkingCopy(); {
parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, -m_rotation * 2 * M_PI / 360.0, m_adjustChaperone, false); return m_adjustChaperone;
float offset[3] = {
-m_offsetX,
-m_offsetY,
-m_offsetZ
};
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, offset, m_adjustChaperone, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
m_offsetX = 0.0f;
m_offsetY = 0.0f;
m_offsetZ = 0.0f;
m_rotation = 0;
emit offsetXChanged(m_offsetX);
emit offsetYChanged(m_offsetY);
emit offsetZChanged(m_offsetZ);
emit rotationChanged(m_rotation);
} }
bool isMoveShortCutPressed(vr::ETrackedControllerRole hand) { void MoveCenterTabController::setAdjustChaperone( bool value, bool notify )
auto handId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(hand); {
if (handId == vr::k_unTrackedDeviceIndexInvalid || handId >= vr::k_unMaxTrackedDeviceCount) { if ( m_adjustChaperone != value )
return false; {
} m_adjustChaperone = value;
if ( m_trackingUniverse == vr::TrackingUniverseStanding )
{
auto angle = m_rotation * 2 * M_PI / 360.0;
float offsetdir = m_adjustChaperone ? -1.0 : 1.0;
float offset[3] = { offsetdir * m_offsetX,
offsetdir * m_offsetY,
offsetdir * m_offsetZ };
rotateCoordinates( offset, angle );
vr::VRControllerState_t state; parent->AddOffsetToCollisionBounds( offset );
if (vr::VRSystem()->GetControllerState(handId, &state, sizeof(vr::VRControllerState_t))) { }
return state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu); auto settings = OverlayController::appSettings();
} settings->beginGroup( "playspaceSettings" );
settings->setValue( "adjustChaperone", m_adjustChaperone );
return false; settings->endGroup();
settings->sync();
if ( notify )
{
emit adjustChaperoneChanged( m_adjustChaperone );
}
}
} }
vr::ETrackedControllerRole MoveCenterTabController::getMoveShortcutHand() { bool MoveCenterTabController::moveShortcutRight() const
auto activeHand = m_activeMoveController; {
return m_moveShortcutRightEnabled;
}
bool rightPressed = m_moveShortcutRightEnabled && isMoveShortCutPressed(vr::TrackedControllerRole_RightHand); void MoveCenterTabController::setMoveShortcutRight( bool value, bool notify )
bool leftPressed = m_moveShortcutLeftEnabled && isMoveShortCutPressed(vr::TrackedControllerRole_LeftHand); {
bool checkDoubleClick = m_requireDoubleClick && activeHand == vr::TrackedControllerRole_Invalid; m_moveShortcutRightEnabled = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "moveShortcutRight", m_moveShortcutRightEnabled );
settings->endGroup();
settings->sync();
if ( notify )
{
emit moveShortcutRightChanged( m_moveShortcutRightEnabled );
}
}
bool MoveCenterTabController::moveShortcutLeft() const
{
return m_moveShortcutLeftEnabled;
}
void MoveCenterTabController::setMoveShortcutLeft( bool value, bool notify )
{
m_moveShortcutLeftEnabled = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "moveShortcutLeft", m_moveShortcutLeftEnabled );
settings->endGroup();
settings->sync();
if ( notify )
{
emit moveShortcutLeftChanged( m_moveShortcutLeftEnabled );
}
}
bool MoveCenterTabController::requireDoubleClick() const
{
return m_requireDoubleClick;
}
void MoveCenterTabController::setRequireDoubleClick( bool value, bool notify )
{
m_requireDoubleClick = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "requireDoubleClick", m_requireDoubleClick );
settings->endGroup();
settings->sync();
if ( notify )
{
emit requireDoubleClickChanged( m_requireDoubleClick );
}
}
bool MoveCenterTabController::lockXToggle() const
{
return m_lockXToggle;
}
void MoveCenterTabController::setLockX( bool value, bool notify )
{
m_lockXToggle = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "lockXToggle", m_lockXToggle );
settings->endGroup();
settings->sync();
if ( notify )
{
emit requireLockXChanged( m_lockXToggle );
}
}
bool MoveCenterTabController::lockYToggle() const
{
return m_lockYToggle;
}
void MoveCenterTabController::setLockY( bool value, bool notify )
{
m_lockYToggle = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "lockYToggle", m_lockYToggle );
settings->endGroup();
settings->sync();
if ( notify )
{
emit requireLockYChanged( m_lockYToggle );
}
}
bool MoveCenterTabController::lockZToggle() const
{
return m_lockZToggle;
}
void MoveCenterTabController::setLockZ( bool value, bool notify )
{
m_lockZToggle = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "lockZToggle", m_lockZToggle );
settings->endGroup();
settings->sync();
if ( notify )
{
emit requireLockZChanged( m_lockZToggle );
}
}
void MoveCenterTabController::modOffsetX( float value, bool notify )
{
// TODO ? possible issue with locking position this way
if ( !m_lockXToggle )
{
auto angle = m_rotation * 2 * M_PI / 360.0;
float offset[3] = { value, 0, 0 };
rotateCoordinates( offset, angle );
parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
offset,
m_adjustChaperone );
m_offsetX += value;
if ( notify )
{
emit offsetXChanged( m_offsetX );
}
}
}
void MoveCenterTabController::modOffsetY( float value, bool notify )
{
if ( !m_lockYToggle )
{
parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
1,
value,
m_adjustChaperone );
m_offsetY += value;
if ( notify )
{
emit offsetYChanged( m_offsetY );
}
}
}
void MoveCenterTabController::modOffsetZ( float value, bool notify )
{
if ( !m_lockZToggle )
{
auto angle = m_rotation * 2 * M_PI / 360.0;
float offset[3] = { 0, 0, value };
rotateCoordinates( offset, angle );
parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
offset,
m_adjustChaperone );
m_offsetZ += value;
if ( notify )
{
emit offsetZChanged( m_offsetZ );
}
}
}
void MoveCenterTabController::reset()
{
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->RotateUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
-m_rotation * 2 * M_PI / 360.0,
m_adjustChaperone,
false );
float offset[3] = { -m_offsetX, -m_offsetY, -m_offsetZ };
parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
offset,
m_adjustChaperone,
false );
vr::VRChaperoneSetup()->CommitWorkingCopy( vr::EChaperoneConfigFile_Live );
m_offsetX = 0.0f;
m_offsetY = 0.0f;
m_offsetZ = 0.0f;
m_rotation = 0;
emit offsetXChanged( m_offsetX );
emit offsetYChanged( m_offsetY );
emit offsetZChanged( m_offsetZ );
emit rotationChanged( m_rotation );
}
bool isMoveShortCutPressed( vr::ETrackedControllerRole hand )
{
auto handId
= vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( hand );
if ( handId == vr::k_unTrackedDeviceIndexInvalid
|| handId >= vr::k_unMaxTrackedDeviceCount )
{
return false;
}
vr::VRControllerState_t state;
if ( vr::VRSystem()->GetControllerState(
handId, &state, sizeof( vr::VRControllerState_t ) ) )
{
return state.ulButtonPressed
& vr::ButtonMaskFromId( vr::k_EButton_ApplicationMenu );
}
return false;
}
vr::ETrackedControllerRole MoveCenterTabController::getMoveShortcutHand()
{
auto activeHand = m_activeMoveController;
bool rightPressed
= m_moveShortcutRightEnabled
&& isMoveShortCutPressed( vr::TrackedControllerRole_RightHand );
bool leftPressed
= m_moveShortcutLeftEnabled
&& isMoveShortCutPressed( vr::TrackedControllerRole_LeftHand );
bool checkDoubleClick = m_requireDoubleClick
&& activeHand == vr::TrackedControllerRole_Invalid;
auto now = clock::now(); auto now = clock::now();
// if we start pressing the shortcut on a controller we set the active one to it // if we start pressing the shortcut on a controller we set the active one
if (rightPressed && !m_moveShortcutRightPressed) { // to it
auto elapsed = duration_cast<milliseconds>(now - lastMoveButtonClick[0]).count(); if ( rightPressed && !m_moveShortcutRightPressed )
if (!checkDoubleClick || elapsed < 250) { {
auto elapsed
= duration_cast<milliseconds>( now - lastMoveButtonClick[0] )
.count();
if ( !checkDoubleClick || elapsed < 250 )
{
activeHand = vr::TrackedControllerRole_RightHand; activeHand = vr::TrackedControllerRole_RightHand;
} }
lastMoveButtonClick[0] = now; lastMoveButtonClick[0] = now;
} }
if (leftPressed && !m_moveShortcutLeftPressed) { if ( leftPressed && !m_moveShortcutLeftPressed )
auto elapsed = duration_cast<milliseconds>(now - lastMoveButtonClick[1]).count(); {
if (!checkDoubleClick || elapsed < 250) { auto elapsed
= duration_cast<milliseconds>( now - lastMoveButtonClick[1] )
.count();
if ( !checkDoubleClick || elapsed < 250 )
{
activeHand = vr::TrackedControllerRole_LeftHand; activeHand = vr::TrackedControllerRole_LeftHand;
} }
lastMoveButtonClick[1] = now; lastMoveButtonClick[1] = now;
} }
// if we let down of a shortcut we set the active hand to any remaining pressed down hand // if we let down of a shortcut we set the active hand to any remaining
if (!rightPressed && m_moveShortcutRightPressed) { // pressed down hand
activeHand = leftPressed ? vr::TrackedControllerRole_LeftHand : vr::TrackedControllerRole_Invalid; if ( !rightPressed && m_moveShortcutRightPressed )
} {
if (!leftPressed && m_moveShortcutLeftPressed) { activeHand = leftPressed ? vr::TrackedControllerRole_LeftHand
activeHand = rightPressed ? vr::TrackedControllerRole_RightHand : vr::TrackedControllerRole_Invalid; : vr::TrackedControllerRole_Invalid;
} }
if ( !leftPressed && m_moveShortcutLeftPressed )
{
activeHand = rightPressed ? vr::TrackedControllerRole_RightHand
: vr::TrackedControllerRole_Invalid;
}
if (!leftPressed && !rightPressed) { if ( !leftPressed && !rightPressed )
activeHand = vr::TrackedControllerRole_Invalid; {
if (m_activeMoveController != vr::TrackedControllerRole_Invalid) { activeHand = vr::TrackedControllerRole_Invalid;
if ( m_activeMoveController != vr::TrackedControllerRole_Invalid )
{
// grace period while switching hands // grace period while switching hands
lastMoveButtonClick[0] = lastMoveButtonClick[1] = now; lastMoveButtonClick[0] = lastMoveButtonClick[1] = now;
} }
} }
m_activeMoveController = activeHand; m_activeMoveController = activeHand;
m_moveShortcutRightPressed = rightPressed; m_moveShortcutRightPressed = rightPressed;
m_moveShortcutLeftPressed = leftPressed; m_moveShortcutLeftPressed = leftPressed;
return activeHand; return activeHand;
} }
void MoveCenterTabController::eventLoopTick(
void MoveCenterTabController::eventLoopTick(vr::ETrackingUniverseOrigin universe, vr::TrackedDevicePose_t* devicePoses) { vr::ETrackingUniverseOrigin universe,
if (settingsUpdateCounter >= 50) { vr::TrackedDevicePose_t* devicePoses )
setTrackingUniverse((int)universe); {
settingsUpdateCounter = 0; if ( settingsUpdateCounter >= 50 )
} else { {
settingsUpdateCounter++; setTrackingUniverse( ( int ) universe );
auto oldMoveHand = m_activeMoveController; settingsUpdateCounter = 0;
auto newMoveHand = getMoveShortcutHand(); }
if (newMoveHand == vr::TrackedControllerRole_Invalid) { else
emit offsetXChanged(m_offsetX); {
emit offsetYChanged(m_offsetY); settingsUpdateCounter++;
emit offsetZChanged(m_offsetZ); auto oldMoveHand = m_activeMoveController;
return; auto newMoveHand = getMoveShortcutHand();
} if ( newMoveHand == vr::TrackedControllerRole_Invalid )
auto handId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(newMoveHand); {
if (newMoveHand == vr::TrackedControllerRole_Invalid || handId == vr::k_unTrackedDeviceIndexInvalid || handId >= vr::k_unMaxTrackedDeviceCount) { emit offsetXChanged( m_offsetX );
if (oldMoveHand != vr::TrackedControllerRole_Invalid) { emit offsetYChanged( m_offsetY );
emit offsetXChanged(m_offsetX); emit offsetZChanged( m_offsetZ );
emit offsetYChanged(m_offsetY); return;
emit offsetZChanged(m_offsetZ); }
} auto handId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(
return; newMoveHand );
} if ( newMoveHand == vr::TrackedControllerRole_Invalid
vr::TrackedDevicePose_t* pose = devicePoses + handId; || handId == vr::k_unTrackedDeviceIndexInvalid
if (!pose->bPoseIsValid || !pose->bDeviceIsConnected || pose->eTrackingResult != vr::TrackingResult_Running_OK) { || handId >= vr::k_unMaxTrackedDeviceCount )
return; {
} if ( oldMoveHand != vr::TrackedControllerRole_Invalid )
float relativeControllerPosition[] = { {
pose->mDeviceToAbsoluteTracking.m[0][3], emit offsetXChanged( m_offsetX );
pose->mDeviceToAbsoluteTracking.m[1][3], emit offsetYChanged( m_offsetY );
pose->mDeviceToAbsoluteTracking.m[2][3] emit offsetZChanged( m_offsetZ );
}; }
return;
}
vr::TrackedDevicePose_t* pose = devicePoses + handId;
if ( !pose->bPoseIsValid || !pose->bDeviceIsConnected
|| pose->eTrackingResult != vr::TrackingResult_Running_OK )
{
return;
}
float relativeControllerPosition[]
= { pose->mDeviceToAbsoluteTracking.m[0][3],
pose->mDeviceToAbsoluteTracking.m[1][3],
pose->mDeviceToAbsoluteTracking.m[2][3] };
auto angle = m_rotation * 2 * M_PI / 360.0; auto angle = m_rotation * 2 * M_PI / 360.0;
rotateCoordinates(relativeControllerPosition, -angle); rotateCoordinates( relativeControllerPosition, -angle );
float absoluteControllerPosition[] = { float absoluteControllerPosition[] = {
relativeControllerPosition[0] + m_offsetX, relativeControllerPosition[0] + m_offsetX,
relativeControllerPosition[1] + m_offsetY, relativeControllerPosition[1] + m_offsetY,
relativeControllerPosition[2] + m_offsetZ, relativeControllerPosition[2] + m_offsetZ,
}; };
if (oldMoveHand == newMoveHand) { if ( oldMoveHand == newMoveHand )
{
float diff[3] = {
absoluteControllerPosition[0] - m_lastControllerPosition[0],
absoluteControllerPosition[1] - m_lastControllerPosition[1],
absoluteControllerPosition[2] - m_lastControllerPosition[2],
};
float diff[3] = { // offset is un-rotated coordinates
absoluteControllerPosition[0] - m_lastControllerPosition[0],
absoluteControllerPosition[1] - m_lastControllerPosition[1],
absoluteControllerPosition[2] - m_lastControllerPosition[2],
};
// offset is un-rotated coordinates // prevents UI from updating if axis movement is locked
if ( !m_lockXToggle )
{
m_offsetX += diff[0];
}
if ( !m_lockYToggle )
{
m_offsetY += diff[1];
}
if ( !m_lockZToggle )
{
m_offsetZ += diff[2];
}
//prevents UI from updating if axis movement is locked rotateCoordinates( diff, angle );
if (!m_lockXToggle) { // If locked removes movement
m_offsetX += diff[0]; if ( m_lockXToggle )
} {
if (!m_lockYToggle) { diff[0] = 0;
m_offsetY += diff[1]; }
} if ( m_lockYToggle )
if (!m_lockZToggle) { {
m_offsetZ += diff[2]; diff[1] = 0;
} }
if ( m_lockZToggle )
{
diff[2] = 0;
}
parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
rotateCoordinates(diff, angle); diff,
//If locked removes movement m_adjustChaperone );
if (m_lockXToggle) {
diff[0] = 0;
}
if (m_lockYToggle) {
diff[1] = 0;
}
if (m_lockZToggle) {
diff[2] = 0;
}
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, diff, m_adjustChaperone);
} }
m_lastControllerPosition[0] = absoluteControllerPosition[0]; m_lastControllerPosition[0] = absoluteControllerPosition[0];
m_lastControllerPosition[1] = absoluteControllerPosition[1]; m_lastControllerPosition[1] = absoluteControllerPosition[1];
m_lastControllerPosition[2] = absoluteControllerPosition[2]; m_lastControllerPosition[2] = absoluteControllerPosition[2];
} }
} }
} // namespace advconfig } // namespace advsettings
+91 -78
View File
@@ -7,112 +7,125 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
class MoveCenterTabController : public QObject
class MoveCenterTabController : public QObject { {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int trackingUniverse READ trackingUniverse WRITE setTrackingUniverse NOTIFY trackingUniverseChanged) Q_PROPERTY( int trackingUniverse READ trackingUniverse WRITE
Q_PROPERTY(float offsetX READ offsetX WRITE setOffsetX NOTIFY offsetXChanged) setTrackingUniverse NOTIFY trackingUniverseChanged )
Q_PROPERTY(float offsetY READ offsetY WRITE setOffsetY NOTIFY offsetYChanged) Q_PROPERTY(
Q_PROPERTY(float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged) float offsetX READ offsetX WRITE setOffsetX NOTIFY offsetXChanged )
Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged ) Q_PROPERTY(
Q_PROPERTY(bool adjustChaperone READ adjustChaperone WRITE setAdjustChaperone NOTIFY adjustChaperoneChanged) float offsetY READ offsetY WRITE setOffsetY NOTIFY offsetYChanged )
Q_PROPERTY(bool moveShortcutRight READ moveShortcutRight WRITE setMoveShortcutRight NOTIFY moveShortcutRightChanged) Q_PROPERTY(
Q_PROPERTY(bool moveShortcutLeft READ moveShortcutLeft WRITE setMoveShortcutLeft NOTIFY moveShortcutLeftChanged) float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged )
Q_PROPERTY(bool requireDoubleClick READ requireDoubleClick WRITE setRequireDoubleClick NOTIFY requireDoubleClickChanged) Q_PROPERTY(
Q_PROPERTY(bool lockXToggle READ lockXToggle WRITE setLockX NOTIFY requireLockXChanged) int rotation READ rotation WRITE setRotation NOTIFY rotationChanged )
Q_PROPERTY(bool lockYToggle READ lockYToggle WRITE setLockY NOTIFY requireLockYChanged) Q_PROPERTY( bool adjustChaperone READ adjustChaperone WRITE
Q_PROPERTY(bool lockZToggle READ lockZToggle WRITE setLockZ NOTIFY requireLockZChanged) setAdjustChaperone NOTIFY adjustChaperoneChanged )
Q_PROPERTY( bool moveShortcutRight READ moveShortcutRight WRITE
setMoveShortcutRight NOTIFY moveShortcutRightChanged )
Q_PROPERTY( bool moveShortcutLeft READ moveShortcutLeft WRITE
setMoveShortcutLeft NOTIFY moveShortcutLeftChanged )
Q_PROPERTY( bool requireDoubleClick READ requireDoubleClick WRITE
setRequireDoubleClick NOTIFY requireDoubleClickChanged )
Q_PROPERTY( bool lockXToggle READ lockXToggle WRITE setLockX NOTIFY
requireLockXChanged )
Q_PROPERTY( bool lockYToggle READ lockYToggle WRITE setLockY NOTIFY
requireLockYChanged )
Q_PROPERTY( bool lockZToggle READ lockZToggle WRITE setLockZ NOTIFY
requireLockZChanged )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
int m_trackingUniverse = (int)vr::TrackingUniverseStanding; int m_trackingUniverse = ( int ) vr::TrackingUniverseStanding;
float m_offsetX = 0.0f; float m_offsetX = 0.0f;
float m_offsetY = 0.0f; float m_offsetY = 0.0f;
float m_offsetZ = 0.0f; float m_offsetZ = 0.0f;
int m_rotation = 0; int m_rotation = 0;
int m_rotationOld = 0; int m_rotationOld = 0;
bool m_adjustChaperone = true; bool m_adjustChaperone = true;
bool m_moveShortcutRightPressed = false; bool m_moveShortcutRightPressed = false;
bool m_moveShortcutLeftPressed = false; bool m_moveShortcutLeftPressed = false;
vr::ETrackedControllerRole m_activeMoveController; vr::ETrackedControllerRole m_activeMoveController;
float m_lastControllerPosition[3]; float m_lastControllerPosition[3];
bool m_moveShortcutRightEnabled = false; bool m_moveShortcutRightEnabled = false;
bool m_moveShortcutLeftEnabled = false; bool m_moveShortcutLeftEnabled = false;
bool m_requireDoubleClick = false; bool m_requireDoubleClick = false;
bool m_lockXToggle = false; bool m_lockXToggle = false;
bool m_lockYToggle = false; bool m_lockYToggle = false;
bool m_lockZToggle = false; bool m_lockZToggle = false;
std::chrono::system_clock::time_point lastMoveButtonClick[2]; std::chrono::system_clock::time_point lastMoveButtonClick[2];
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
vr::ETrackedControllerRole getMoveShortcutHand(); vr::ETrackedControllerRole getMoveShortcutHand();
public: public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(vr::ETrackingUniverseOrigin universe, vr::TrackedDevicePose_t* devicePoses); void eventLoopTick( vr::ETrackingUniverseOrigin universe,
vr::TrackedDevicePose_t* devicePoses );
float offsetX() const; float offsetX() const;
float offsetY() const; float offsetY() const;
float offsetZ() const; float offsetZ() const;
int rotation() const; int rotation() const;
bool adjustChaperone() const; bool adjustChaperone() const;
bool moveShortcutRight() const; bool moveShortcutRight() const;
bool moveShortcutLeft() const; bool moveShortcutLeft() const;
bool requireDoubleClick() const; bool requireDoubleClick() const;
bool lockXToggle() const; bool lockXToggle() const;
bool lockYToggle() const; bool lockYToggle() const;
bool lockZToggle() const; bool lockZToggle() const;
public slots: public slots:
int trackingUniverse() const; int trackingUniverse() const;
void setTrackingUniverse(int value, bool notify = true); void setTrackingUniverse( int value, bool notify = true );
void setOffsetX(float value, bool notify = true); void setOffsetX( float value, bool notify = true );
void setOffsetY(float value, bool notify = true); void setOffsetY( float value, bool notify = true );
void setOffsetZ(float value, bool notify = true); void setOffsetZ( float value, bool notify = true );
void setRotation(int value , bool notify = true); void setRotation( int value, bool notify = true );
void setAdjustChaperone(bool value, bool notify = true); void setAdjustChaperone( bool value, bool notify = true );
void setMoveShortcutRight(bool value, bool notify = true); void setMoveShortcutRight( bool value, bool notify = true );
void setMoveShortcutLeft(bool value, bool notify = true); void setMoveShortcutLeft( bool value, bool notify = true );
void setRequireDoubleClick(bool value, bool notify = true); void setRequireDoubleClick( bool value, bool notify = true );
void modOffsetX(float value, bool notify = true); void modOffsetX( float value, bool notify = true );
void modOffsetY(float value, bool notify = true); void modOffsetY( float value, bool notify = true );
void modOffsetZ(float value, bool notify = true); void modOffsetZ( float value, bool notify = true );
void setLockX(bool value, bool notify = true); void setLockX( bool value, bool notify = true );
void setLockY(bool value, bool notify = true); void setLockY( bool value, bool notify = true );
void setLockZ(bool value, bool notify = true); void setLockZ( bool value, bool notify = true );
void applyRotation(); void applyRotation();
void reset(); void reset();
signals: signals:
void trackingUniverseChanged(int value); void trackingUniverseChanged( int value );
void offsetXChanged(float value); void offsetXChanged( float value );
void offsetYChanged(float value); void offsetYChanged( float value );
void offsetZChanged(float value); void offsetZChanged( float value );
void rotationChanged(int value); void rotationChanged( int value );
void adjustChaperoneChanged(bool value); void adjustChaperoneChanged( bool value );
void moveShortcutRightChanged(bool value); void moveShortcutRightChanged( bool value );
void moveShortcutLeftChanged(bool value); void moveShortcutLeftChanged( bool value );
void requireDoubleClickChanged(bool value); void requireDoubleClickChanged( bool value );
void requireLockXChanged(bool value); void requireLockXChanged( bool value );
void requireLockYChanged(bool value); void requireLockYChanged( bool value );
void requireLockZChanged(bool value); void requireLockZChanged( bool value );
}; };
} // namespace advsettings } // namespace advsettings
File diff suppressed because it is too large Load Diff
+80 -55
View File
@@ -10,45 +10,55 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration
class OverlayController;
// forward declaration enum TouchPadArea
class OverlayController; {
PAD_AREA_LEFT = ( 1 << 0 ),
PAD_AREA_TOP = ( 1 << 1 ),
PAD_AREA_RIGHT = ( 1 << 2 ),
PAD_AREA_BOTTOM = ( 1 << 3 ),
};
enum TouchPadArea { struct PttControllerConfig
PAD_AREA_LEFT = (1 << 0), {
PAD_AREA_TOP = (1 << 1),
PAD_AREA_RIGHT = (1 << 2),
PAD_AREA_BOTTOM = (1 << 3),
};
struct PttControllerConfig {
QVariantList digitalButtons; QVariantList digitalButtons;
uint64_t digitalButtonMask = 0; uint64_t digitalButtonMask = 0;
unsigned triggerMode = 0; // 0 .. disabled, 1 .. enabled unsigned triggerMode = 0; // 0 .. disabled, 1 .. enabled
unsigned touchpadMode = 0; // 0 .. disabled, 1 .. only touch, 2 .. only press, 3 .. both unsigned touchpadMode
= 0; // 0 .. disabled, 1 .. only touch, 2 .. only press, 3 .. both
unsigned touchpadAreas = 0; unsigned touchpadAreas = 0;
}; };
struct PttProfile { struct PttProfile
{
std::string profileName; std::string profileName;
bool showNotification = false; bool showNotification = false;
bool leftControllerEnabled = false; bool leftControllerEnabled = false;
bool rightControllerEnabled = false; bool rightControllerEnabled = false;
PttControllerConfig controllerConfigs[2]; PttControllerConfig controllerConfigs[2];
}; };
class PttController : public QObject
class PttController : public QObject { {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool pttEnabled READ pttEnabled WRITE setPttEnabled NOTIFY pttEnabledChanged) Q_PROPERTY( bool pttEnabled READ pttEnabled WRITE setPttEnabled NOTIFY
Q_PROPERTY(bool pttActive READ pttActive NOTIFY pttActiveChanged) pttEnabledChanged )
Q_PROPERTY(bool pttShowNotification READ pttShowNotification WRITE setPttShowNotification NOTIFY pttShowNotificationChanged) Q_PROPERTY( bool pttActive READ pttActive NOTIFY pttActiveChanged )
Q_PROPERTY(bool pttLeftControllerEnabled READ pttLeftControllerEnabled WRITE setPttLeftControllerEnabled NOTIFY pttLeftControllerEnabledChanged) Q_PROPERTY( bool pttShowNotification READ pttShowNotification WRITE
Q_PROPERTY(bool pttRightControllerEnabled READ pttRightControllerEnabled WRITE setPttRightControllerEnabled NOTIFY pttRightControllerEnabledChanged) setPttShowNotification NOTIFY pttShowNotificationChanged )
Q_PROPERTY(
bool pttLeftControllerEnabled READ pttLeftControllerEnabled WRITE
setPttLeftControllerEnabled NOTIFY pttLeftControllerEnabledChanged )
Q_PROPERTY( bool pttRightControllerEnabled READ pttRightControllerEnabled
WRITE setPttRightControllerEnabled NOTIFY
pttRightControllerEnabledChanged )
protected: protected:
bool m_pttEnabled = false; bool m_pttEnabled = false;
bool m_pttActive = false; bool m_pttActive = false;
bool m_pttShowNotification = false; bool m_pttShowNotification = false;
@@ -58,18 +68,24 @@ namespace advsettings {
std::vector<PttProfile> pttProfiles; std::vector<PttProfile> pttProfiles;
protected: protected:
void checkPttStatus(); void checkPttStatus();
virtual QString getSettingsName() = 0; virtual QString getSettingsName() = 0;
virtual void onPttStart() {}; virtual void onPttStart(){};
virtual void onPttStop() {}; virtual void onPttStop(){};
virtual void onPttEnabled() {}; virtual void onPttEnabled(){};
virtual void onPttDisabled() {}; virtual void onPttDisabled(){};
virtual bool pttChangeValid() { return true; } virtual bool pttChangeValid()
virtual vr::VROverlayHandle_t getNotificationOverlayHandle() { return vr::k_ulOverlayHandleInvalid; } {
return true;
}
virtual vr::VROverlayHandle_t getNotificationOverlayHandle()
{
return vr::k_ulOverlayHandleInvalid;
}
std::recursive_mutex eventLoopMutex; std::recursive_mutex eventLoopMutex;
public: public:
bool pttEnabled() const; bool pttEnabled() const;
bool pttActive() const; bool pttActive() const;
bool pttShowNotification() const; bool pttShowNotification() const;
@@ -84,36 +100,45 @@ namespace advsettings {
void savePttProfiles(); void savePttProfiles();
void savePttConfig(); void savePttConfig();
Q_INVOKABLE QVariantList pttDigitalButtons( unsigned controller );
Q_INVOKABLE QVariantList pttDigitalButtons(unsigned controller); Q_INVOKABLE unsigned long pttDigitalButtonMask( unsigned controller );
Q_INVOKABLE unsigned long pttDigitalButtonMask(unsigned controller); Q_INVOKABLE unsigned pttTouchpadMode( unsigned controller );
Q_INVOKABLE unsigned pttTouchpadMode(unsigned controller); Q_INVOKABLE unsigned pttTriggerMode( unsigned controller );
Q_INVOKABLE unsigned pttTriggerMode(unsigned controller); Q_INVOKABLE unsigned pttTouchpadArea( unsigned controller );
Q_INVOKABLE unsigned pttTouchpadArea(unsigned controller);
Q_INVOKABLE unsigned getPttProfileCount(); Q_INVOKABLE unsigned getPttProfileCount();
Q_INVOKABLE QString getPttProfileName(unsigned index); Q_INVOKABLE QString getPttProfileName( unsigned index );
public slots: public slots:
void setPttEnabled(bool value, bool notify = true, bool save = true); void setPttEnabled( bool value, bool notify = true, bool save = true );
void setPttShowNotification(bool value, bool notify = true, bool save = true); void setPttShowNotification( bool value,
void setPttLeftControllerEnabled(bool value, bool notify = true, bool save = true); bool notify = true,
void setPttRightControllerEnabled(bool value, bool notify = true, bool save = true); bool save = true );
void setPttLeftControllerEnabled( bool value,
bool notify = true,
bool save = true );
void setPttRightControllerEnabled( bool value,
bool notify = true,
bool save = true );
void setPttControllerConfig(unsigned controller, QVariantList buttons, unsigned triggerMode, unsigned padMode, unsigned padAreas); void setPttControllerConfig( unsigned controller,
QVariantList buttons,
unsigned triggerMode,
unsigned padMode,
unsigned padAreas );
void addPttProfile(QString name); void addPttProfile( QString name );
void applyPttProfile(unsigned index); void applyPttProfile( unsigned index );
void deletePttProfile(unsigned index); void deletePttProfile( unsigned index );
signals: signals:
void pttEnabledChanged(bool value); void pttEnabledChanged( bool value );
void pttActiveChanged(bool value); void pttActiveChanged( bool value );
void pttShowNotificationChanged(bool value); void pttShowNotificationChanged( bool value );
void pttLeftControllerEnabledChanged(bool value); void pttLeftControllerEnabledChanged( bool value );
void pttRightControllerEnabledChanged(bool value); void pttRightControllerEnabledChanged( bool value );
void pttProfilesUpdated(); void pttProfilesUpdated();
}; };
} // namespace advsettings } // namespace advsettings
File diff suppressed because it is too large Load Diff
+160 -138
View File
@@ -5,174 +5,196 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration
class OverlayController;
struct ReviveControllerProfile
{
std::string profileName;
int gripButtonMode;
bool triggerAsGrip;
float thumbDeadzone;
float thumbRange;
float touchPitch;
float touchYaw;
float touchRoll;
float touchX;
float touchY;
float touchZ;
};
// forward declaration class ReviveTabController : public QObject
class OverlayController; {
Q_OBJECT
Q_PROPERTY( int isOverlayInstalled READ isOverlayInstalled NOTIFY
isOverlayInstalledChanged )
Q_PROPERTY( int gripButtonMode READ gripButtonMode WRITE setGripButtonMode
NOTIFY gripButtonModeChanged )
Q_PROPERTY( int triggerAsGrip READ triggerAsGrip WRITE setTriggerAsGrip
NOTIFY triggerAsGripChanged )
Q_PROPERTY( bool pixelsPerDisplayPixelOverrideEnabled READ
isPixelsPerDisplayPixelOverrideEnabled WRITE
setPixelsPerDisplayPixelOverrideEnabled NOTIFY
pixelsPerDisplayPixelOverrideEnabledChanged )
Q_PROPERTY( float toggleDelay READ toggleDelay WRITE setToggleDelay NOTIFY
toggleDelayChanged )
Q_PROPERTY(
float pixelsPerDisplayPixelOverride READ pixelsPerDisplayPixelOverride
WRITE setPixelsPerDisplayPixelOverride NOTIFY
pixelsPerDisplayPixelOverrideChanged )
Q_PROPERTY( float thumbDeadzone READ thumbDeadzone WRITE setThumbDeadzone
NOTIFY thumbDeadzoneChanged )
Q_PROPERTY( float thumbRange READ thumbRange WRITE setThumbRange NOTIFY
thumbRangeChanged )
Q_PROPERTY( float touchPitch READ touchPitch WRITE setTouchPitch NOTIFY
touchPitchChanged )
Q_PROPERTY(
float touchYaw READ touchYaw WRITE setTouchYaw NOTIFY touchYawChanged )
Q_PROPERTY( float touchRoll READ touchRoll WRITE setTouchRoll NOTIFY
touchRollChanged )
Q_PROPERTY( float touchX READ touchX WRITE setTouchX NOTIFY touchXChanged )
Q_PROPERTY( float touchY READ touchY WRITE setTouchY NOTIFY touchYChanged )
Q_PROPERTY( float touchZ READ touchZ WRITE setTouchZ NOTIFY touchZChanged )
Q_PROPERTY( float piPlayerHeight READ piPlayerHeight WRITE setPiPlayerHeight
NOTIFY piPlayerHeightChanged )
Q_PROPERTY( float piEyeHeight READ piEyeHeight WRITE setPiEyeHeight NOTIFY
piEyeHeightChanged )
Q_PROPERTY( QString piUsername READ piUsername WRITE setPiUsername NOTIFY
piUsernameChanged )
Q_PROPERTY(
QString piName READ piName WRITE setPiName NOTIFY piNameChanged )
Q_PROPERTY(
int piGender READ piGender WRITE setPiGender NOTIFY piGenderChanged )
private:
OverlayController* parent;
QQuickWindow* widget;
struct ReviveControllerProfile { bool m_isOverlayInstalled = false;
std::string profileName; int m_gripButtonMode = 0;
int gripButtonMode; float m_toggleDelay = 0.5f;
bool triggerAsGrip; bool m_triggerAsGrip = false;
float thumbDeadzone; bool m_pixelsPerDisplayPixelOverrideEnabled = false;
float thumbRange; float m_pixelsPerDisplayPixelOverride = 1.0f;
float touchPitch; float m_thumbDeadzone = 0.3f;
float touchYaw; float m_thumbRange = 2.0f;
float touchRoll; float m_touchPitch = -28.0f;
float touchX; float m_touchYaw = 0.0f;
float touchY; float m_touchRoll = -14.0f;
float touchZ; float m_touchX = 0.016f;
}; float m_touchY = -0.036f;
float m_touchZ = 0.016f;
float m_piPlayerHeight = 1.778f;
float m_piEyeHeight = 1.675f;
QString m_piUsername = "";
QString m_piName = "";
int m_piGender = 0; // 0 .. Unknown, 1 .. Male, 2 .. Female
unsigned settingsUpdateCounter = 0;
class ReviveTabController : public QObject { std::vector<ReviveControllerProfile> controllerProfiles;
Q_OBJECT
Q_PROPERTY(int isOverlayInstalled READ isOverlayInstalled NOTIFY isOverlayInstalledChanged)
Q_PROPERTY(int gripButtonMode READ gripButtonMode WRITE setGripButtonMode NOTIFY gripButtonModeChanged)
Q_PROPERTY(int triggerAsGrip READ triggerAsGrip WRITE setTriggerAsGrip NOTIFY triggerAsGripChanged)
Q_PROPERTY(bool pixelsPerDisplayPixelOverrideEnabled READ isPixelsPerDisplayPixelOverrideEnabled WRITE setPixelsPerDisplayPixelOverrideEnabled NOTIFY pixelsPerDisplayPixelOverrideEnabledChanged)
Q_PROPERTY(float toggleDelay READ toggleDelay WRITE setToggleDelay NOTIFY toggleDelayChanged)
Q_PROPERTY(float pixelsPerDisplayPixelOverride READ pixelsPerDisplayPixelOverride WRITE setPixelsPerDisplayPixelOverride NOTIFY pixelsPerDisplayPixelOverrideChanged)
Q_PROPERTY(float thumbDeadzone READ thumbDeadzone WRITE setThumbDeadzone NOTIFY thumbDeadzoneChanged)
Q_PROPERTY(float thumbRange READ thumbRange WRITE setThumbRange NOTIFY thumbRangeChanged)
Q_PROPERTY(float touchPitch READ touchPitch WRITE setTouchPitch NOTIFY touchPitchChanged)
Q_PROPERTY(float touchYaw READ touchYaw WRITE setTouchYaw NOTIFY touchYawChanged)
Q_PROPERTY(float touchRoll READ touchRoll WRITE setTouchRoll NOTIFY touchRollChanged)
Q_PROPERTY(float touchX READ touchX WRITE setTouchX NOTIFY touchXChanged)
Q_PROPERTY(float touchY READ touchY WRITE setTouchY NOTIFY touchYChanged)
Q_PROPERTY(float touchZ READ touchZ WRITE setTouchZ NOTIFY touchZChanged)
Q_PROPERTY(float piPlayerHeight READ piPlayerHeight WRITE setPiPlayerHeight NOTIFY piPlayerHeightChanged)
Q_PROPERTY(float piEyeHeight READ piEyeHeight WRITE setPiEyeHeight NOTIFY piEyeHeightChanged)
Q_PROPERTY(QString piUsername READ piUsername WRITE setPiUsername NOTIFY piUsernameChanged)
Q_PROPERTY(QString piName READ piName WRITE setPiName NOTIFY piNameChanged)
Q_PROPERTY(int piGender READ piGender WRITE setPiGender NOTIFY piGenderChanged)
private: public:
OverlayController* parent; void initStage1( bool forceRevivePage );
QQuickWindow* widget; void initStage2( OverlayController* parent, QQuickWindow* widget );
bool m_isOverlayInstalled = false; void eventLoopTick();
int m_gripButtonMode = 0;
float m_toggleDelay = 0.5f;
bool m_triggerAsGrip = false;
bool m_pixelsPerDisplayPixelOverrideEnabled = false;
float m_pixelsPerDisplayPixelOverride = 1.0f;
float m_thumbDeadzone = 0.3f;
float m_thumbRange = 2.0f;
float m_touchPitch = -28.0f;
float m_touchYaw = 0.0f;
float m_touchRoll = -14.0f;
float m_touchX = 0.016f;
float m_touchY = -0.036f;
float m_touchZ = 0.016f;
float m_piPlayerHeight = 1.778f;
float m_piEyeHeight = 1.675f;
QString m_piUsername = "";
QString m_piName = "";
int m_piGender = 0; // 0 .. Unknown, 1 .. Male, 2 .. Female
unsigned settingsUpdateCounter = 0; bool isOverlayInstalled() const;
std::vector<ReviveControllerProfile> controllerProfiles; int gripButtonMode() const;
bool triggerAsGrip() const;
float toggleDelay() const;
public: bool isPixelsPerDisplayPixelOverrideEnabled() const;
void initStage1(bool forceRevivePage); float pixelsPerDisplayPixelOverride() const;
void initStage2(OverlayController* parent, QQuickWindow* widget);
void eventLoopTick(); float thumbDeadzone() const;
float thumbRange() const;
bool isOverlayInstalled() const; float touchPitch() const;
float touchYaw() const;
float touchRoll() const;
float touchX() const;
float touchY() const;
float touchZ() const;
int gripButtonMode() const; float piPlayerHeight() const;
bool triggerAsGrip() const; float piEyeHeight() const;
float toggleDelay() const; const QString& piUsername() const;
const QString& piName() const;
int piGender() const; // 0 .. Unknown, 1 .. Male, 2 .. Female
bool isPixelsPerDisplayPixelOverrideEnabled() const; Q_INVOKABLE float getCurrentHMDHeight();
float pixelsPerDisplayPixelOverride() const;
float thumbDeadzone() const; void reloadControllerProfiles();
float thumbRange() const; void saveControllerProfiles();
float touchPitch() const; Q_INVOKABLE unsigned getControllerProfileCount();
float touchYaw() const; Q_INVOKABLE QString getControllerProfileName( unsigned index );
float touchRoll() const;
float touchX() const;
float touchY() const;
float touchZ() const;
float piPlayerHeight() const; public slots:
float piEyeHeight() const; void setGripButtonMode( int value, bool notify = true );
const QString& piUsername() const; void setTriggerAsGrip( bool value, bool notify = true );
const QString& piName() const; void setToggleDelay( float value, bool notify = true );
int piGender() const; // 0 .. Unknown, 1 .. Male, 2 .. Female
Q_INVOKABLE float getCurrentHMDHeight(); void setPixelsPerDisplayPixelOverrideEnabled( bool value,
bool notify = true );
void setPixelsPerDisplayPixelOverride( float value, bool notify = true );
void reloadControllerProfiles(); void setThumbDeadzone( float value, bool notify = true );
void saveControllerProfiles(); void setThumbRange( float value, bool notify = true );
Q_INVOKABLE unsigned getControllerProfileCount(); void setTouchPitch( float value, bool notify = true );
Q_INVOKABLE QString getControllerProfileName(unsigned index); void setTouchYaw( float value, bool notify = true );
void setTouchRoll( float value, bool notify = true );
void setTouchX( float value, bool notify = true );
void setTouchY( float value, bool notify = true );
void setTouchZ( float value, bool notify = true );
public slots: void setPiPlayerHeight( float value, bool notify = true );
void setGripButtonMode(int value, bool notify = true); void setPiEyeHeight( float value, bool notify = true );
void setTriggerAsGrip(bool value, bool notify = true); void setPiUsername( const QString& value, bool notify = true );
void setToggleDelay(float value, bool notify = true); void setPiName( const QString& value, bool notify = true );
void setPiGender( int value,
bool notify
= true ); // 0 .. Unknown, 1 .. Male, 2 .. Female
void setPixelsPerDisplayPixelOverrideEnabled(bool value, bool notify = true); void addControllerProfile( QString name );
void setPixelsPerDisplayPixelOverride(float value, bool notify = true); void applyControllerProfile( unsigned index );
void deleteControllerProfile( unsigned index );
void setThumbDeadzone(float value, bool notify = true); void reset();
void setThumbRange(float value, bool notify = true);
void setTouchPitch(float value, bool notify = true); signals:
void setTouchYaw(float value, bool notify = true); void isOverlayInstalledChanged( bool value );
void setTouchRoll(float value, bool notify = true);
void setTouchX(float value, bool notify = true);
void setTouchY(float value, bool notify = true);
void setTouchZ(float value, bool notify = true);
void setPiPlayerHeight(float value, bool notify = true); void gripButtonModeChanged( int value );
void setPiEyeHeight(float value, bool notify = true); void triggerAsGripChanged( bool value );
void setPiUsername(const QString& value, bool notify = true); void toggleDelayChanged( float value );
void setPiName(const QString& value, bool notify = true);
void setPiGender(int value, bool notify = true); // 0 .. Unknown, 1 .. Male, 2 .. Female
void addControllerProfile(QString name); void pixelsPerDisplayPixelOverrideEnabledChanged( bool value );
void applyControllerProfile(unsigned index); void pixelsPerDisplayPixelOverrideChanged( float value );
void deleteControllerProfile(unsigned index);
void reset(); void thumbDeadzoneChanged( float value );
void thumbRangeChanged( float value );
signals: void touchPitchChanged( float value );
void isOverlayInstalledChanged(bool value); void touchYawChanged( float value );
void touchRollChanged( float value );
void touchXChanged( float value );
void touchYChanged( float value );
void touchZChanged( float value );
void gripButtonModeChanged(int value); void piPlayerHeightChanged( float value );
void triggerAsGripChanged(bool value); void piEyeHeightChanged( float value );
void toggleDelayChanged(float value); void piUsernameChanged( const QString& value );
void piNameChanged( const QString& value );
void piGenderChanged( int value );
void pixelsPerDisplayPixelOverrideEnabledChanged(bool value); void controllerProfilesUpdated();
void pixelsPerDisplayPixelOverrideChanged(float value); };
void thumbDeadzoneChanged(float value);
void thumbRangeChanged(float value);
void touchPitchChanged(float value);
void touchYawChanged(float value);
void touchRollChanged(float value);
void touchXChanged(float value);
void touchYChanged(float value);
void touchZChanged(float value);
void piPlayerHeightChanged(float value);
void piEyeHeightChanged(float value);
void piUsernameChanged(const QString& value);
void piNameChanged(const QString& value);
void piGenderChanged(int value);
void controllerProfilesUpdated();
};
} // namespace advsettings } // namespace advsettings
+71 -52
View File
@@ -3,69 +3,88 @@
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
void SettingsTabController::initStage1()
void SettingsTabController::initStage1() { {
m_autoStartEnabled = vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey); m_autoStartEnabled = vr::VRApplications()->GetApplicationAutoLaunch(
auto settings = OverlayController::appSettings(); OverlayController::applicationKey );
settings->beginGroup("applicationSettings"); auto settings = OverlayController::appSettings();
auto value = settings->value("forceRevivePage", m_forceRevivePage); settings->beginGroup( "applicationSettings" );
settings->endGroup(); auto value = settings->value( "forceRevivePage", m_forceRevivePage );
if (value.isValid() && !value.isNull()) { settings->endGroup();
m_forceRevivePage = value.toBool(); if ( value.isValid() && !value.isNull() )
} {
m_forceRevivePage = value.toBool();
}
} }
void SettingsTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { void SettingsTabController::initStage2( OverlayController* var_parent,
this->parent = var_parent; QQuickWindow* var_widget )
this->widget = var_widget; {
this->parent = var_parent;
this->widget = var_widget;
} }
void SettingsTabController::eventLoopTick() { void SettingsTabController::eventLoopTick()
if (settingsUpdateCounter >= 50) { {
setAutoStartEnabled(vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey)); if ( settingsUpdateCounter >= 50 )
settingsUpdateCounter = 0; {
} else { setAutoStartEnabled( vr::VRApplications()->GetApplicationAutoLaunch(
settingsUpdateCounter++; OverlayController::applicationKey ) );
} settingsUpdateCounter = 0;
}
else
{
settingsUpdateCounter++;
}
} }
bool SettingsTabController::autoStartEnabled() const { bool SettingsTabController::autoStartEnabled() const
return m_autoStartEnabled; {
return m_autoStartEnabled;
} }
void SettingsTabController::setAutoStartEnabled(bool value, bool notify) { void SettingsTabController::setAutoStartEnabled( bool value, bool notify )
if (m_autoStartEnabled != value) { {
m_autoStartEnabled = value; if ( m_autoStartEnabled != value )
auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(OverlayController::applicationKey, m_autoStartEnabled); {
if (apperror != vr::VRApplicationError_None) { m_autoStartEnabled = value;
LOG(ERROR) << "Could not set auto start: " << vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror); auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(
} OverlayController::applicationKey, m_autoStartEnabled );
if (notify) { if ( apperror != vr::VRApplicationError_None )
emit autoStartEnabledChanged(m_autoStartEnabled); {
} LOG( ERROR ) << "Could not set auto start: "
} << vr::VRApplications()
->GetApplicationsErrorNameFromEnum( apperror );
}
if ( notify )
{
emit autoStartEnabledChanged( m_autoStartEnabled );
}
}
} }
bool SettingsTabController::forceRevivePage() const
bool SettingsTabController::forceRevivePage() const { {
return m_forceRevivePage; return m_forceRevivePage;
} }
void SettingsTabController::setForceRevivePage( bool value, bool notify )
void SettingsTabController::setForceRevivePage(bool value, bool notify) { {
if (m_forceRevivePage != value) { if ( m_forceRevivePage != value )
m_forceRevivePage = value; {
auto settings = OverlayController::appSettings(); m_forceRevivePage = value;
settings->beginGroup("applicationSettings"); auto settings = OverlayController::appSettings();
settings->setValue("forceRevivePage", m_forceRevivePage); settings->beginGroup( "applicationSettings" );
settings->endGroup(); settings->setValue( "forceRevivePage", m_forceRevivePage );
settings->sync(); settings->endGroup();
if (notify) { settings->sync();
emit forceRevivePageChanged(m_forceRevivePage); if ( notify )
} {
} emit forceRevivePageChanged( m_forceRevivePage );
}
}
} }
} // namespace advconfig } // namespace advsettings
+23 -21
View File
@@ -5,42 +5,44 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
class SettingsTabController : public QObject
class SettingsTabController : public QObject { {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool autoStartEnabled READ autoStartEnabled WRITE setAutoStartEnabled NOTIFY autoStartEnabledChanged) Q_PROPERTY( bool autoStartEnabled READ autoStartEnabled WRITE
Q_PROPERTY(bool forceRevivePage READ forceRevivePage WRITE setForceRevivePage NOTIFY forceRevivePageChanged) setAutoStartEnabled NOTIFY autoStartEnabledChanged )
Q_PROPERTY( bool forceRevivePage READ forceRevivePage WRITE
setForceRevivePage NOTIFY forceRevivePageChanged )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
bool m_autoStartEnabled = false; bool m_autoStartEnabled = false;
bool m_forceRevivePage = false; bool m_forceRevivePage = false;
public: public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(); void eventLoopTick();
bool autoStartEnabled() const; bool autoStartEnabled() const;
bool forceRevivePage() const; bool forceRevivePage() const;
public slots: public slots:
void setAutoStartEnabled(bool value, bool notify = true); void setAutoStartEnabled( bool value, bool notify = true );
void setForceRevivePage(bool value, bool notify = true); void setForceRevivePage( bool value, bool notify = true );
signals: signals:
void autoStartEnabledChanged(bool value); void autoStartEnabledChanged( bool value );
void forceRevivePageChanged(bool value); void forceRevivePageChanged( bool value );
}; };
} // namespace advsettings } // namespace advsettings
+275 -188
View File
@@ -3,232 +3,319 @@
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
void StatisticsTabController::initStage1() {}
void StatisticsTabController::initStage1() { void StatisticsTabController::initStage2( OverlayController* var_parent,
QQuickWindow* var_widget )
{
this->parent = var_parent;
this->widget = var_widget;
} }
void StatisticsTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { void StatisticsTabController::eventLoopTick(
this->parent = var_parent; vr::TrackedDevicePose_t* devicePoses,
this->widget = var_widget; float leftSpeed,
float rightSpeed )
{
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(
&pStats, sizeof( vr::Compositor_CumulativeStats ) );
if ( pStats.m_nPid != m_cumStats.m_nPid )
{
m_cumStats = pStats;
m_droppedFramesOffset = 0;
m_reprojectedFramesOffset = 0;
m_timedOutOffset = 0;
m_totalRatioPresentedOffset = 0;
m_totalRatioReprojectedOffset = 0;
}
m_cumStats = pStats;
auto& m = devicePoses->mDeviceToAbsoluteTracking.m;
// Hmd Distance //
if ( lastPosTimer == 0 )
{
if ( devicePoses[0].bPoseIsValid
&& devicePoses[0].eTrackingResult
== vr::TrackingResult_Running_OK )
{
if ( !lastHmdPosValid )
{
lastHmdPosValid = true;
}
else
{
auto delta = std::sqrt(
std::pow( m[0][3] - lastHmdPos[0],
2 ) /*+ std::pow(m[1][3] - lastHmdPos[1], 2)*/
+ std::pow( m[2][3] - lastHmdPos[2], 2 ) );
if ( delta >= 0.01f )
{
m_hmdDistanceMoved += delta;
}
}
lastHmdPos[0] = m[0][3];
lastHmdPos[1] = m[1][3];
lastHmdPos[2] = m[2][3];
}
else
{
lastHmdPosValid = false;
}
}
// Controller speeds //
if ( leftSpeed > m_leftControllerMaxSpeed )
{
m_leftControllerMaxSpeed = leftSpeed;
}
if ( rightSpeed > m_rightControllerMaxSpeed )
{
m_rightControllerMaxSpeed = rightSpeed;
}
// Hmd Rotation //
/*
| Intrinsic y-x'-z" rotation matrix:
| cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy |
| cp*sr | cp*cr |-sp |
| cy*sp*sr-cr*sy | cr*cy*sp+sr*sy | cp*cy |
yaw = atan2(cp*sy, cp*cy) [pi, -pi], CCW
pitch = -asin(-sp) [pi/2, -pi/2]
roll = atan2(cp*sr, cp*cr) [pi, -pi], CW
*/
double yawRaw = 0.0;
double yaw = 0.0;
bool rotationChanged = false;
if ( devicePoses[0].bPoseIsValid
&& devicePoses[0].eTrackingResult == vr::TrackingResult_Running_OK )
{
yawRaw = std::atan2( m[0][2], m[2][2] );
if ( yawRaw < 0.0f )
{
yawRaw += 2 * M_PI; // map to [0, 2*pi], CCW
}
yaw = yawRaw - rotationOffset;
if ( yaw < 0.0 )
{
yaw = 2 * M_PI + yaw;
}
if ( rotationResetFlag )
{
rotationDir = 0;
rotationCounter = 0;
rotationOffset = yawRaw;
rotationResetFlag = false;
lastYaw = -1.0f;
rotationChanged = true;
}
else if ( lastYaw < 0.0f && yaw > 0.0 )
{
lastYaw = yaw;
rotationChanged = true;
if ( yaw <= M_PI )
{
rotationDir = 1;
}
else
{
rotationDir = -1;
}
}
else if ( std::abs( lastYaw - yaw ) >= 0.01 && yaw > 0.0 )
{
auto diff = yaw - lastYaw;
int mode = 0;
if ( std::abs( diff ) > M_PI )
{
if ( diff < -M_PI )
{ // CCW overflow
mode = 1;
}
else if ( diff > M_PI )
{ // CW overflow
mode = -1;
}
}
else
{
if ( lastYaw < 0.0 && yaw > 0.0 )
{
mode = 1;
}
else if ( lastYaw > 0.0 && yaw < 0.0 )
{
mode = -1;
}
}
if ( mode > 0 )
{
if ( rotationCounter == 0 && rotationDir <= 0 )
{
rotationDir = 1;
}
else
{
rotationCounter++;
}
}
else if ( mode < 0 )
{
if ( rotationCounter == 0 && rotationDir >= 0 )
{
rotationDir = -1;
}
else
{
rotationCounter--;
}
}
lastYaw = yaw;
rotationChanged = true;
}
}
else
{
lastYaw = -1;
}
if ( rotationChanged )
{
m_hmdRotation = ( float ) rotationCounter;
if ( rotationDir > 0 )
{
m_hmdRotation += yaw / ( 2 * M_PI );
}
else if ( rotationDir < 0 )
{
m_hmdRotation += -1.0f + yaw / ( 2 * M_PI );
}
}
if ( lastPosTimer == 0 )
{
lastPosTimer = 10;
}
else
{
lastPosTimer--;
}
} }
void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed) { float StatisticsTabController::hmdDistanceMoved() const
vr::Compositor_CumulativeStats pStats; {
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats)); return m_hmdDistanceMoved;
if (pStats.m_nPid != m_cumStats.m_nPid) {
m_cumStats = pStats;
m_droppedFramesOffset = 0;
m_reprojectedFramesOffset = 0;
m_timedOutOffset = 0;
m_totalRatioPresentedOffset = 0;
m_totalRatioReprojectedOffset = 0;
}
m_cumStats = pStats;
auto& m = devicePoses->mDeviceToAbsoluteTracking.m;
// Hmd Distance //
if (lastPosTimer == 0) {
if (devicePoses[0].bPoseIsValid && devicePoses[0].eTrackingResult == vr::TrackingResult_Running_OK) {
if (!lastHmdPosValid) {
lastHmdPosValid = true;
} else {
auto delta = std::sqrt(std::pow(m[0][3] - lastHmdPos[0], 2) /*+ std::pow(m[1][3] - lastHmdPos[1], 2)*/ + std::pow(m[2][3] - lastHmdPos[2], 2));
if (delta >= 0.01f) {
m_hmdDistanceMoved += delta;
}
}
lastHmdPos[0] = m[0][3];
lastHmdPos[1] = m[1][3];
lastHmdPos[2] = m[2][3];
} else {
lastHmdPosValid = false;
}
}
// Controller speeds //
if (leftSpeed > m_leftControllerMaxSpeed) {
m_leftControllerMaxSpeed = leftSpeed;
}
if (rightSpeed > m_rightControllerMaxSpeed) {
m_rightControllerMaxSpeed = rightSpeed;
}
// Hmd Rotation //
/*
| Intrinsic y-x'-z" rotation matrix:
| cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy |
| cp*sr | cp*cr |-sp |
| cy*sp*sr-cr*sy | cr*cy*sp+sr*sy | cp*cy |
yaw = atan2(cp*sy, cp*cy) [pi, -pi], CCW
pitch = -asin(-sp) [pi/2, -pi/2]
roll = atan2(cp*sr, cp*cr) [pi, -pi], CW
*/
double yawRaw = 0.0;
double yaw = 0.0;
bool rotationChanged = false;
if (devicePoses[0].bPoseIsValid && devicePoses[0].eTrackingResult == vr::TrackingResult_Running_OK) {
yawRaw = std::atan2(m[0][2], m[2][2]);
if (yawRaw < 0.0f) {
yawRaw += 2 * M_PI; // map to [0, 2*pi], CCW
}
yaw = yawRaw - rotationOffset;
if (yaw < 0.0) {
yaw = 2 * M_PI + yaw;
}
if (rotationResetFlag) {
rotationDir = 0;
rotationCounter = 0;
rotationOffset = yawRaw;
rotationResetFlag = false;
lastYaw = -1.0f;
rotationChanged = true;
} else if (lastYaw < 0.0f && yaw > 0.0) {
lastYaw = yaw;
rotationChanged = true;
if (yaw <= M_PI) {
rotationDir = 1;
} else {
rotationDir = -1;
}
} else if (std::abs(lastYaw - yaw) >= 0.01 && yaw > 0.0) {
auto diff = yaw - lastYaw;
int mode = 0;
if (std::abs(diff) > M_PI) {
if (diff < -M_PI) { // CCW overflow
mode = 1;
} else if (diff > M_PI) { // CW overflow
mode = -1;
}
} else {
if (lastYaw < 0.0 && yaw > 0.0) {
mode = 1;
} else if (lastYaw > 0.0 && yaw < 0.0) {
mode = -1;
}
}
if (mode > 0) {
if (rotationCounter == 0 && rotationDir <= 0) {
rotationDir = 1;
} else {
rotationCounter++;
}
} else if (mode < 0) {
if (rotationCounter == 0 && rotationDir >= 0) {
rotationDir = -1;
} else {
rotationCounter--;
}
}
lastYaw = yaw;
rotationChanged = true;
}
} else {
lastYaw = -1;
}
if (rotationChanged) {
m_hmdRotation = (float)rotationCounter;
if (rotationDir > 0) {
m_hmdRotation += yaw / (2 * M_PI);
} else if (rotationDir < 0) {
m_hmdRotation += -1.0f + yaw / (2 * M_PI);
}
}
if (lastPosTimer == 0) {
lastPosTimer = 10;
} else {
lastPosTimer--;
}
} }
float StatisticsTabController::hmdDistanceMoved() const { float StatisticsTabController::hmdRotations() const
return m_hmdDistanceMoved; {
return m_hmdRotation;
} }
float StatisticsTabController::hmdRotations() const { float StatisticsTabController::rightControllerMaxSpeed() const
return m_hmdRotation; {
return m_rightControllerMaxSpeed;
} }
float StatisticsTabController::rightControllerMaxSpeed() const { float StatisticsTabController::leftControllerMaxSpeed() const
return m_rightControllerMaxSpeed; {
return m_leftControllerMaxSpeed;
} }
float StatisticsTabController::leftControllerMaxSpeed() const { unsigned StatisticsTabController::presentedFrames() const
return m_leftControllerMaxSpeed; {
return m_cumStats.m_nNumFramePresents - m_presentedFramesOffset;
} }
unsigned StatisticsTabController::presentedFrames() const { unsigned StatisticsTabController::droppedFrames() const
return m_cumStats.m_nNumFramePresents - m_presentedFramesOffset; {
return m_cumStats.m_nNumDroppedFrames - m_droppedFramesOffset;
} }
unsigned StatisticsTabController::droppedFrames() const { unsigned StatisticsTabController::reprojectedFrames() const
return m_cumStats.m_nNumDroppedFrames - m_droppedFramesOffset; {
return m_cumStats.m_nNumReprojectedFrames - m_reprojectedFramesOffset;
} }
unsigned StatisticsTabController::reprojectedFrames() const { unsigned StatisticsTabController::timedOut() const
return m_cumStats.m_nNumReprojectedFrames - m_reprojectedFramesOffset; {
return m_cumStats.m_nNumTimedOut - m_timedOutOffset;
} }
unsigned StatisticsTabController::timedOut() const { float StatisticsTabController::totalReprojectedRatio() const
return m_cumStats.m_nNumTimedOut - m_timedOutOffset; {
float totalFrames = ( float ) ( m_cumStats.m_nNumFramePresents
- m_totalRatioPresentedOffset );
float reprojectedFrames = ( float ) ( m_cumStats.m_nNumReprojectedFrames
- m_totalRatioReprojectedOffset );
if ( totalFrames != 0.0f )
{
return reprojectedFrames / totalFrames;
}
else
{
return 0.0;
}
} }
float StatisticsTabController::totalReprojectedRatio() const { void StatisticsTabController::statsDistanceResetClicked()
float totalFrames = (float)(m_cumStats.m_nNumFramePresents - m_totalRatioPresentedOffset); {
float reprojectedFrames = (float)(m_cumStats.m_nNumReprojectedFrames - m_totalRatioReprojectedOffset); lastHmdPosValid = false;
if (totalFrames != 0.0f) { if ( m_hmdDistanceMoved != 0.0 )
return reprojectedFrames / totalFrames; {
} else { m_hmdDistanceMoved = 0.0;
return 0.0; }
}
} }
void StatisticsTabController::statsDistanceResetClicked() { void StatisticsTabController::statsRotationResetClicked()
lastHmdPosValid = false; {
if (m_hmdDistanceMoved != 0.0) { rotationResetFlag = true;
m_hmdDistanceMoved = 0.0;
}
} }
void StatisticsTabController::statsRotationResetClicked() { void StatisticsTabController::statsLeftControllerSpeedResetClicked()
rotationResetFlag = true; {
if ( m_leftControllerMaxSpeed != 0.0 )
{
m_leftControllerMaxSpeed = 0.0;
}
} }
void StatisticsTabController::statsLeftControllerSpeedResetClicked() { void StatisticsTabController::statsRightControllerSpeedResetClicked()
if (m_leftControllerMaxSpeed != 0.0) { {
m_leftControllerMaxSpeed = 0.0; if ( m_rightControllerMaxSpeed != 0.0 )
} {
m_rightControllerMaxSpeed = 0.0;
}
} }
void StatisticsTabController::statsRightControllerSpeedResetClicked() { void StatisticsTabController::presentedFramesResetClicked()
if (m_rightControllerMaxSpeed != 0.0) { {
m_rightControllerMaxSpeed = 0.0; m_presentedFramesOffset = m_cumStats.m_nNumFramePresents;
}
} }
void StatisticsTabController::presentedFramesResetClicked() { void StatisticsTabController::droppedFramesResetClicked()
m_presentedFramesOffset = m_cumStats.m_nNumFramePresents; {
m_droppedFramesOffset = m_cumStats.m_nNumDroppedFrames;
} }
void StatisticsTabController::droppedFramesResetClicked() { void StatisticsTabController::reprojectedFramesResetClicked()
m_droppedFramesOffset = m_cumStats.m_nNumDroppedFrames; {
m_reprojectedFramesOffset = m_cumStats.m_nNumReprojectedFrames;
} }
void StatisticsTabController::reprojectedFramesResetClicked() { void StatisticsTabController::timedOutResetClicked()
m_reprojectedFramesOffset = m_cumStats.m_nNumReprojectedFrames; {
m_timedOutOffset = m_cumStats.m_nNumTimedOut;
} }
void StatisticsTabController::timedOutResetClicked() { void StatisticsTabController::totalRatioResetClicked()
m_timedOutOffset = m_cumStats.m_nNumTimedOut; {
m_totalRatioPresentedOffset = m_cumStats.m_nNumFramePresents;
m_totalRatioReprojectedOffset = m_cumStats.m_nNumReprojectedFrames;
} }
void StatisticsTabController::totalRatioResetClicked() { } // namespace advsettings
m_totalRatioPresentedOffset = m_cumStats.m_nNumFramePresents;
m_totalRatioReprojectedOffset = m_cumStats.m_nNumReprojectedFrames;
}
} // namespace advconfig
+58 -57
View File
@@ -6,79 +6,80 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
class StatisticsTabController : public QObject
class StatisticsTabController : public QObject { {
Q_OBJECT Q_OBJECT
Q_PROPERTY(float hmdDistanceMoved READ hmdDistanceMoved) Q_PROPERTY( float hmdDistanceMoved READ hmdDistanceMoved )
Q_PROPERTY(float hmdRotations READ hmdRotations) Q_PROPERTY( float hmdRotations READ hmdRotations )
Q_PROPERTY(float leftControllerMaxSpeed READ leftControllerMaxSpeed) Q_PROPERTY( float leftControllerMaxSpeed READ leftControllerMaxSpeed )
Q_PROPERTY(float rightControllerMaxSpeed READ rightControllerMaxSpeed) Q_PROPERTY( float rightControllerMaxSpeed READ rightControllerMaxSpeed )
Q_PROPERTY(int presentedFrames READ presentedFrames) Q_PROPERTY( int presentedFrames READ presentedFrames )
Q_PROPERTY(int droppedFrames READ droppedFrames) Q_PROPERTY( int droppedFrames READ droppedFrames )
Q_PROPERTY(int reprojectedFrames READ reprojectedFrames) Q_PROPERTY( int reprojectedFrames READ reprojectedFrames )
Q_PROPERTY(int timedOut READ timedOut) Q_PROPERTY( int timedOut READ timedOut )
Q_PROPERTY(float totalReprojectedRatio READ totalReprojectedRatio) Q_PROPERTY( float totalReprojectedRatio READ totalReprojectedRatio )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
bool rotationResetFlag = false; bool rotationResetFlag = false;
float rotationOffset = 0.0f; float rotationOffset = 0.0f;
int rotationDir = 0; int rotationDir = 0;
int64_t rotationCounter = 0; int64_t rotationCounter = 0;
float lastYaw = -1.0f; float lastYaw = -1.0f;
unsigned lastPosTimer = 0; unsigned lastPosTimer = 0;
float lastHmdPos[3]; float lastHmdPos[3];
bool lastHmdPosValid = false; bool lastHmdPosValid = false;
float m_hmdRotation = 0.0f; float m_hmdRotation = 0.0f;
double m_hmdDistanceMoved = 0.0; double m_hmdDistanceMoved = 0.0;
float m_leftControllerMaxSpeed = 0.0f; float m_leftControllerMaxSpeed = 0.0f;
float m_rightControllerMaxSpeed = 0.0f; float m_rightControllerMaxSpeed = 0.0f;
vr::Compositor_CumulativeStats m_cumStats; vr::Compositor_CumulativeStats m_cumStats;
unsigned m_presentedFramesOffset = 0; unsigned m_presentedFramesOffset = 0;
unsigned m_droppedFramesOffset = 0; unsigned m_droppedFramesOffset = 0;
unsigned m_reprojectedFramesOffset = 0; unsigned m_reprojectedFramesOffset = 0;
unsigned m_timedOutOffset = 0; unsigned m_timedOutOffset = 0;
unsigned m_totalRatioPresentedOffset = 0; unsigned m_totalRatioPresentedOffset = 0;
unsigned m_totalRatioReprojectedOffset = 0; unsigned m_totalRatioReprojectedOffset = 0;
public: public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed); void eventLoopTick( vr::TrackedDevicePose_t* devicePoses,
float leftSpeed,
float rightSpeed );
float hmdDistanceMoved() const; float hmdDistanceMoved() const;
float hmdRotations() const; float hmdRotations() const;
float rightControllerMaxSpeed() const; float rightControllerMaxSpeed() const;
float leftControllerMaxSpeed() const; float leftControllerMaxSpeed() const;
unsigned presentedFrames() const; unsigned presentedFrames() const;
unsigned droppedFrames() const; unsigned droppedFrames() const;
unsigned reprojectedFrames() const; unsigned reprojectedFrames() const;
unsigned timedOut() const; unsigned timedOut() const;
float totalReprojectedRatio() const; float totalReprojectedRatio() const;
public slots: public slots:
void statsDistanceResetClicked(); void statsDistanceResetClicked();
void statsRotationResetClicked(); void statsRotationResetClicked();
void statsLeftControllerSpeedResetClicked(); void statsLeftControllerSpeedResetClicked();
void statsRightControllerSpeedResetClicked(); void statsRightControllerSpeedResetClicked();
void presentedFramesResetClicked(); void presentedFramesResetClicked();
void droppedFramesResetClicked(); void droppedFramesResetClicked();
void reprojectedFramesResetClicked(); void reprojectedFramesResetClicked();
void timedOutResetClicked(); void timedOutResetClicked();
void totalRatioResetClicked(); void totalRatioResetClicked();
}; };
} // namespace advsettings } // namespace advsettings
+524 -322
View File
@@ -2,386 +2,588 @@
#include <QQuickWindow> #include <QQuickWindow>
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
namespace vr { namespace vr
// this was removed from openvr_api.h in 1.0.8 {
static const char* const k_pch_SteamVR_RenderTargetMultiplier_Float = "renderTargetMultiplier"; // this was removed from openvr_api.h in 1.0.8
} static const char* const k_pch_SteamVR_RenderTargetMultiplier_Float
= "renderTargetMultiplier";
} // namespace vr
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// openvr's github repo hasn't been updated yet to reflect changes in beta 1477423729. // openvr's github repo hasn't been updated yet to reflect changes in beta
//static const char* vrsettings_steamvr_allowAsyncReprojection = "allowAsyncReprojection"; // 1477423729.
//static const char* vrsettings_steamvr_allowInterleavedReprojection = "allowInterleavedReprojection"; // static const char* vrsettings_steamvr_allowAsyncReprojection =
// "allowAsyncReprojection"; static const char*
// vrsettings_steamvr_allowInterleavedReprojection =
// "allowInterleavedReprojection";
static const char* vrsettings_steamvr_supersampleScale = "supersampleScale"; static const char* vrsettings_steamvr_supersampleScale = "supersampleScale";
static const char* vrsettings_steamvr_allowSupersampleFiltering = "allowSupersampleFiltering"; static const char* vrsettings_steamvr_allowSupersampleFiltering
= "allowSupersampleFiltering";
static const char* vrsettings_compositor_category = "compositor"; static const char* vrsettings_compositor_category = "compositor";
void SteamVRTabController::initStage1() { void SteamVRTabController::initStage1()
eventLoopTick(); {
reloadSteamVRProfiles(); eventLoopTick();
reloadSteamVRProfiles();
} }
void SteamVRTabController::initStage2( OverlayController* var_parent,
void SteamVRTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { QQuickWindow* var_widget )
this->parent = var_parent; {
this->widget = var_widget; this->parent = var_parent;
this->widget = var_widget;
} }
void SteamVRTabController::reloadSteamVRProfiles()
void SteamVRTabController::reloadSteamVRProfiles() { {
steamvrProfiles.clear(); steamvrProfiles.clear();
auto settings = OverlayController::appSettings(); auto settings = OverlayController::appSettings();
settings->beginGroup("steamVRSettings"); settings->beginGroup( "steamVRSettings" );
auto profileCount = settings->beginReadArray("steamVRProfiles"); auto profileCount = settings->beginReadArray( "steamVRProfiles" );
for (int i = 0; i < profileCount; i++) { for ( int i = 0; i < profileCount; i++ )
settings->setArrayIndex(i); {
steamvrProfiles.emplace_back(); settings->setArrayIndex( i );
auto& entry = steamvrProfiles[i]; steamvrProfiles.emplace_back();
entry.profileName = settings->value("profileName").toString().toStdString(); auto& entry = steamvrProfiles[i];
entry.includesSupersampling = settings->value("includesSupersampling", false).toBool(); entry.profileName
if (entry.includesSupersampling) { = settings->value( "profileName" ).toString().toStdString();
entry.supersampling = settings->value("supersampling", 1.0f).toFloat(); entry.includesSupersampling
} = settings->value( "includesSupersampling", false ).toBool();
entry.includesSupersampleFiltering = settings->value("includesSupersampleFiltering", false).toBool(); if ( entry.includesSupersampling )
if (entry.includesSupersampleFiltering) { {
entry.supersampleFiltering = settings->value("supersampleFiltering", true).toBool(); entry.supersampling
} = settings->value( "supersampling", 1.0f ).toFloat();
entry.includesReprojectionSettings = settings->value("includesReprojectionSettings", false).toBool(); }
if (entry.includesReprojectionSettings) { entry.includesSupersampleFiltering
entry.asynchronousReprojection = settings->value("asynchronousReprojection", true).toBool(); = settings->value( "includesSupersampleFiltering", false ).toBool();
entry.interleavedReprojection = settings->value("interleavedReprojection", true).toBool(); if ( entry.includesSupersampleFiltering )
entry.alwaysOnReprojection = settings->value("alwaysOnReprojection", true).toBool(); {
} entry.supersampleFiltering
} = settings->value( "supersampleFiltering", true ).toBool();
settings->endArray(); }
settings->endGroup(); entry.includesReprojectionSettings
= settings->value( "includesReprojectionSettings", false ).toBool();
if ( entry.includesReprojectionSettings )
{
entry.asynchronousReprojection
= settings->value( "asynchronousReprojection", true ).toBool();
entry.interleavedReprojection
= settings->value( "interleavedReprojection", true ).toBool();
entry.alwaysOnReprojection
= settings->value( "alwaysOnReprojection", true ).toBool();
}
}
settings->endArray();
settings->endGroup();
} }
void SteamVRTabController::saveSteamVRProfiles()
void SteamVRTabController::saveSteamVRProfiles() { {
auto settings = OverlayController::appSettings(); auto settings = OverlayController::appSettings();
settings->beginGroup("steamVRSettings"); settings->beginGroup( "steamVRSettings" );
settings->beginWriteArray("steamVRProfiles"); settings->beginWriteArray( "steamVRProfiles" );
unsigned i = 0; unsigned i = 0;
for (auto& p : steamvrProfiles) { for ( auto& p : steamvrProfiles )
settings->setArrayIndex(i); {
settings->setValue("profileName", QString::fromStdString(p.profileName)); settings->setArrayIndex( i );
settings->setValue("includesSupersampling", p.includesSupersampling); settings->setValue( "profileName",
if (p.includesSupersampling) { QString::fromStdString( p.profileName ) );
settings->setValue("supersampling", p.supersampling); settings->setValue( "includesSupersampling", p.includesSupersampling );
} if ( p.includesSupersampling )
settings->setValue("includesSupersampleFiltering", p.includesSupersampleFiltering); {
if (p.includesSupersampleFiltering) { settings->setValue( "supersampling", p.supersampling );
settings->setValue("supersampleFiltering", p.supersampleFiltering); }
} settings->setValue( "includesSupersampleFiltering",
settings->setValue("includesReprojectionSettings", p.includesReprojectionSettings); p.includesSupersampleFiltering );
if (p.includesReprojectionSettings) { if ( p.includesSupersampleFiltering )
settings->setValue("asynchronousReprojection", p.asynchronousReprojection); {
settings->setValue("interleavedReprojection", p.interleavedReprojection); settings->setValue( "supersampleFiltering",
settings->setValue("alwaysOnReprojection", p.alwaysOnReprojection); p.supersampleFiltering );
} }
i++; settings->setValue( "includesReprojectionSettings",
} p.includesReprojectionSettings );
settings->endArray(); if ( p.includesReprojectionSettings )
settings->endGroup(); {
settings->setValue( "asynchronousReprojection",
p.asynchronousReprojection );
settings->setValue( "interleavedReprojection",
p.interleavedReprojection );
settings->setValue( "alwaysOnReprojection",
p.alwaysOnReprojection );
}
i++;
}
settings->endArray();
settings->endGroup();
} }
Q_INVOKABLE unsigned SteamVRTabController::getSteamVRProfileCount()
Q_INVOKABLE unsigned SteamVRTabController::getSteamVRProfileCount() { {
return (unsigned)steamvrProfiles.size(); return ( unsigned ) steamvrProfiles.size();
} }
Q_INVOKABLE QString SteamVRTabController::getSteamVRProfileName(unsigned index) { Q_INVOKABLE QString
if (index >= steamvrProfiles.size()) { SteamVRTabController::getSteamVRProfileName( unsigned index )
return QString(); {
} else { if ( index >= steamvrProfiles.size() )
return QString::fromStdString(steamvrProfiles[index].profileName); {
} return QString();
}
else
{
return QString::fromStdString( steamvrProfiles[index].profileName );
}
} }
void SteamVRTabController::eventLoopTick()
void SteamVRTabController::eventLoopTick() { {
if (settingsUpdateCounter >= 50) { if ( settingsUpdateCounter >= 50 )
vr::EVRSettingsError vrSettingsError; {
auto ss = vr::VRSettings()->GetFloat(vr::k_pch_SteamVR_Section, vrsettings_steamvr_supersampleScale, &vrSettingsError); vr::EVRSettingsError vrSettingsError;
if (vrSettingsError != vr::VRSettingsError_None) { auto ss
LOG(WARNING) << "Could not read \"" << vrsettings_steamvr_supersampleScale << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); = vr::VRSettings()->GetFloat( vr::k_pch_SteamVR_Section,
if (m_superSampling != 1.0) { vrsettings_steamvr_supersampleScale,
LOG(DEBUG) << "OpenVR returns an error and we have a custom supersampling value: " << m_superSampling; &vrSettingsError );
setSuperSampling(1.0); if ( vrSettingsError != vr::VRSettingsError_None )
} {
} else if (m_superSampling != ss) { LOG( WARNING ) << "Could not read \""
LOG(DEBUG) << "OpenVR reports a changed supersampling value: " << m_superSampling << " => " << ss; << vrsettings_steamvr_supersampleScale
setSuperSampling(ss); << "\" setting: "
} << vr::VRSettings()->GetSettingsErrorNameFromEnum(
auto css = vr::VRSettings()->GetFloat(vrsettings_compositor_category, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, &vrSettingsError); vrSettingsError );
if (vrSettingsError != vr::VRSettingsError_None) { if ( m_superSampling != 1.0 )
if (vrSettingsError != vr::VRSettingsError_UnsetSettingHasNoDefault) { // does not appear in the default settings file as of beta 1477423729 {
LOG(WARNING) << "Could not read \"compositor::" << vr::k_pch_SteamVR_RenderTargetMultiplier_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); LOG( DEBUG ) << "OpenVR returns an error and we have a custom "
} "supersampling value: "
if (m_compositorSuperSampling != 1.0) { << m_superSampling;
LOG(DEBUG) << "OpenVR returns an error and we have a custom compositor supersampling value: " << m_compositorSuperSampling; setSuperSampling( 1.0 );
setCompositorSuperSampling(1.0); }
} }
} else if (m_compositorSuperSampling != css) { else if ( m_superSampling != ss )
LOG(DEBUG) << "OpenVR reports a changed compositor supersampling value: " << m_compositorSuperSampling << " => " << css; {
setCompositorSuperSampling(css); LOG( DEBUG ) << "OpenVR reports a changed supersampling value: "
} << m_superSampling << " => " << ss;
auto air = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowReprojection_Bool, &vrSettingsError); setSuperSampling( ss );
if (vrSettingsError != vr::VRSettingsError_None) { }
LOG(WARNING) << "Could not read \"" << vr::k_pch_SteamVR_AllowReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); auto css = vr::VRSettings()->GetFloat(
} vrsettings_compositor_category,
setAllowInterleavedReprojection(air); vr::k_pch_SteamVR_RenderTargetMultiplier_Float,
auto aar = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowAsyncReprojection_Bool, &vrSettingsError); &vrSettingsError );
if (vrSettingsError != vr::VRSettingsError_None) { if ( vrSettingsError != vr::VRSettingsError_None )
LOG(WARNING) << "Could not read \"" << vr::k_pch_SteamVR_AllowAsyncReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); {
} if ( vrSettingsError
setAllowAsyncReprojection(aar); != vr::VRSettingsError_UnsetSettingHasNoDefault )
auto fr = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, &vrSettingsError); { // does not appear in the default settings file as of beta
if (vrSettingsError != vr::VRSettingsError_None) { // 1477423729
LOG(WARNING) << "Could not read \"" << vr::k_pch_SteamVR_ForceReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); LOG( WARNING )
} << "Could not read \"compositor::"
setForceReprojection(fr); << vr::k_pch_SteamVR_RenderTargetMultiplier_Float
auto sf = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowSupersampleFiltering, &vrSettingsError); << "\" setting: "
if (vrSettingsError != vr::VRSettingsError_None) { << vr::VRSettings()->GetSettingsErrorNameFromEnum(
LOG(WARNING) << "Could not read \"" << vrsettings_steamvr_allowSupersampleFiltering << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); vrSettingsError );
} }
setAllowSupersampleFiltering(sf); if ( m_compositorSuperSampling != 1.0 )
settingsUpdateCounter = 0; {
} else { LOG( DEBUG ) << "OpenVR returns an error and we have a custom "
settingsUpdateCounter++; "compositor supersampling value: "
} << m_compositorSuperSampling;
setCompositorSuperSampling( 1.0 );
}
}
else if ( m_compositorSuperSampling != css )
{
LOG( DEBUG )
<< "OpenVR reports a changed compositor supersampling value: "
<< m_compositorSuperSampling << " => " << css;
setCompositorSuperSampling( css );
}
auto air = vr::VRSettings()->GetBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_AllowReprojection_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not read \""
<< vr::k_pch_SteamVR_AllowReprojection_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
setAllowInterleavedReprojection( air );
auto aar = vr::VRSettings()->GetBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_AllowAsyncReprojection_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not read \""
<< vr::k_pch_SteamVR_AllowAsyncReprojection_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
setAllowAsyncReprojection( aar );
auto fr = vr::VRSettings()->GetBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_ForceReprojection_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not read \""
<< vr::k_pch_SteamVR_ForceReprojection_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
setForceReprojection( fr );
auto sf = vr::VRSettings()->GetBool(
vr::k_pch_SteamVR_Section,
vrsettings_steamvr_allowSupersampleFiltering,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not read \""
<< vrsettings_steamvr_allowSupersampleFiltering
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
setAllowSupersampleFiltering( sf );
settingsUpdateCounter = 0;
}
else
{
settingsUpdateCounter++;
}
} }
void SteamVRTabController::setSuperSampling( float value, bool notify )
void SteamVRTabController::setSuperSampling(float value, bool notify) { {
bool override = false; bool override = false;
if (value <= 0.01f) { if ( value <= 0.01f )
LOG(WARNING) << "Encountered a supersampling value <= 0.01, setting supersampling to 1.0"; {
value = 1.0f; LOG( WARNING ) << "Encountered a supersampling value <= 0.01, setting "
override = true; "supersampling to 1.0";
} value = 1.0f;
if (override || m_superSampling != value) { override = true;
LOG(DEBUG) << "Supersampling value changed: " << m_superSampling << " => " << value; }
m_superSampling = value; if ( override || m_superSampling != value )
vr::VRSettings()->SetFloat(vr::k_pch_SteamVR_Section, vrsettings_steamvr_supersampleScale, m_superSampling); {
vr::VRSettings()->Sync(); LOG( DEBUG ) << "Supersampling value changed: " << m_superSampling
if (notify) { << " => " << value;
emit superSamplingChanged(m_superSampling); m_superSampling = value;
} vr::VRSettings()->SetFloat( vr::k_pch_SteamVR_Section,
} vrsettings_steamvr_supersampleScale,
m_superSampling );
vr::VRSettings()->Sync();
if ( notify )
{
emit superSamplingChanged( m_superSampling );
}
}
} }
void SteamVRTabController::setCompositorSuperSampling( float value,
void SteamVRTabController::setCompositorSuperSampling(float value, bool notify) { bool notify )
bool override = false; {
if (value <= 0.01f) { bool override = false;
LOG(WARNING) << "Encountered a compositor supersampling value <= 0.01, setting supersampling to 1.0"; if ( value <= 0.01f )
value = 1.0f; {
override = true; LOG( WARNING ) << "Encountered a compositor supersampling value <= "
} "0.01, setting supersampling to 1.0";
if (override || m_compositorSuperSampling != value) { value = 1.0f;
LOG(DEBUG) << "Compositor supersampling value changed: " << m_compositorSuperSampling << " => " << value; override = true;
m_compositorSuperSampling = value; }
vr::VRSettings()->SetFloat(vrsettings_compositor_category, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, m_compositorSuperSampling); if ( override || m_compositorSuperSampling != value )
vr::VRSettings()->Sync(); {
if (notify) { LOG( DEBUG ) << "Compositor supersampling value changed: "
emit compositorSuperSamplingChanged(m_compositorSuperSampling); << m_compositorSuperSampling << " => " << value;
} m_compositorSuperSampling = value;
} vr::VRSettings()->SetFloat(
vrsettings_compositor_category,
vr::k_pch_SteamVR_RenderTargetMultiplier_Float,
m_compositorSuperSampling );
vr::VRSettings()->Sync();
if ( notify )
{
emit compositorSuperSamplingChanged( m_compositorSuperSampling );
}
}
} }
float SteamVRTabController::superSampling() const
float SteamVRTabController::superSampling() const { {
return m_superSampling; return m_superSampling;
} }
float SteamVRTabController::compositorSuperSampling() const
float SteamVRTabController::compositorSuperSampling() const { {
return m_compositorSuperSampling; return m_compositorSuperSampling;
} }
bool SteamVRTabController::allowInterleavedReprojection() const
bool SteamVRTabController::allowInterleavedReprojection() const { {
return m_allowInterleavedReprojection; return m_allowInterleavedReprojection;
} }
bool SteamVRTabController::allowAsyncReprojection() const
bool SteamVRTabController::allowAsyncReprojection() const { {
return m_allowAsyncReprojection; return m_allowAsyncReprojection;
} }
void SteamVRTabController::setAllowInterleavedReprojection( bool value,
void SteamVRTabController::setAllowInterleavedReprojection(bool value, bool notify) { bool notify )
if (m_allowInterleavedReprojection != value) { {
m_allowInterleavedReprojection = value; if ( m_allowInterleavedReprojection != value )
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowReprojection_Bool, m_allowInterleavedReprojection); {
vr::VRSettings()->Sync(); m_allowInterleavedReprojection = value;
if (notify) { vr::VRSettings()->SetBool( vr::k_pch_SteamVR_Section,
emit allowInterleavedReprojectionChanged(m_allowInterleavedReprojection); vr::k_pch_SteamVR_AllowReprojection_Bool,
} m_allowInterleavedReprojection );
} vr::VRSettings()->Sync();
if ( notify )
{
emit allowInterleavedReprojectionChanged(
m_allowInterleavedReprojection );
}
}
} }
void SteamVRTabController::setAllowAsyncReprojection( bool value, bool notify )
void SteamVRTabController::setAllowAsyncReprojection(bool value, bool notify) { {
if (m_allowAsyncReprojection != value) { if ( m_allowAsyncReprojection != value )
m_allowAsyncReprojection = value; {
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowAsyncReprojection_Bool, m_allowAsyncReprojection); m_allowAsyncReprojection = value;
vr::VRSettings()->Sync(); vr::VRSettings()->SetBool(
if (notify) { vr::k_pch_SteamVR_Section,
emit allowAsyncReprojectionChanged(m_allowAsyncReprojection); vr::k_pch_SteamVR_AllowAsyncReprojection_Bool,
} m_allowAsyncReprojection );
} vr::VRSettings()->Sync();
if ( notify )
{
emit allowAsyncReprojectionChanged( m_allowAsyncReprojection );
}
}
} }
bool SteamVRTabController::forceReprojection() const { bool SteamVRTabController::forceReprojection() const
return m_forceReprojection; {
return m_forceReprojection;
} }
void SteamVRTabController::setForceReprojection( bool value, bool notify )
void SteamVRTabController::setForceReprojection(bool value, bool notify) { {
if (m_forceReprojection != value) { if ( m_forceReprojection != value )
m_forceReprojection = value; {
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, m_forceReprojection); m_forceReprojection = value;
vr::VRSettings()->Sync(); vr::VRSettings()->SetBool( vr::k_pch_SteamVR_Section,
if (notify) { vr::k_pch_SteamVR_ForceReprojection_Bool,
emit forceReprojectionChanged(m_forceReprojection); m_forceReprojection );
} vr::VRSettings()->Sync();
} if ( notify )
{
emit forceReprojectionChanged( m_forceReprojection );
}
}
} }
bool SteamVRTabController::allowSupersampleFiltering() const
bool SteamVRTabController::allowSupersampleFiltering() const { {
return m_allowSupersampleFiltering; return m_allowSupersampleFiltering;
} }
void SteamVRTabController::setAllowSupersampleFiltering( bool value,
void SteamVRTabController::setAllowSupersampleFiltering(bool value, bool notify) { bool notify )
if (m_allowSupersampleFiltering != value) { {
m_allowSupersampleFiltering = value; if ( m_allowSupersampleFiltering != value )
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowSupersampleFiltering, m_allowSupersampleFiltering); {
vr::VRSettings()->Sync(); m_allowSupersampleFiltering = value;
if (notify) { vr::VRSettings()->SetBool( vr::k_pch_SteamVR_Section,
emit allowSupersampleFilteringChanged(m_allowSupersampleFiltering); vrsettings_steamvr_allowSupersampleFiltering,
} m_allowSupersampleFiltering );
} vr::VRSettings()->Sync();
if ( notify )
{
emit allowSupersampleFilteringChanged(
m_allowSupersampleFiltering );
}
}
} }
void SteamVRTabController::reset()
{
vr::EVRSettingsError vrSettingsError;
void SteamVRTabController::reset() { vr::VRSettings()->RemoveKeyInSection( vr::k_pch_SteamVR_Section,
vr::EVRSettingsError vrSettingsError; vrsettings_steamvr_supersampleScale,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vrsettings_steamvr_supersampleScale << "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(vr::k_pch_SteamVR_Section, vrsettings_steamvr_supersampleScale, &vrSettingsError); setCompositorSuperSampling( 1.0f ); // Is not in default.vrsettings yet
if (vrSettingsError != vr::VRSettingsError_None) { vr::VRSettings()->RemoveKeyInSection(
LOG(WARNING) << "Could not remove \"" << vrsettings_steamvr_supersampleScale << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); vrsettings_compositor_category,
} vr::k_pch_SteamVR_RenderTargetMultiplier_Float,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vrsettings_compositor_category
<< "::" << vr::k_pch_SteamVR_RenderTargetMultiplier_Float
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
setCompositorSuperSampling(1.0f); // Is not in default.vrsettings yet vr::VRSettings()->RemoveKeyInSection(
vr::VRSettings()->RemoveKeyInSection(vrsettings_compositor_category, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, &vrSettingsError); vr::k_pch_SteamVR_Section,
if (vrSettingsError != vr::VRSettingsError_None) { vr::k_pch_SteamVR_AllowReprojection_Bool,
LOG(WARNING) << "Could not remove \"" << vrsettings_compositor_category << "::" << vr::k_pch_SteamVR_RenderTargetMultiplier_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); &vrSettingsError );
} if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vr::k_pch_SteamVR_AllowReprojection_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowReprojection_Bool, &vrSettingsError); vr::VRSettings()->RemoveKeyInSection(
if (vrSettingsError != vr::VRSettingsError_None) { vr::k_pch_SteamVR_Section,
LOG(WARNING) << "Could not remove \"" << vr::k_pch_SteamVR_AllowReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); vr::k_pch_SteamVR_AllowAsyncReprojection_Bool,
} &vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vr::k_pch_SteamVR_AllowAsyncReprojection_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowAsyncReprojection_Bool, &vrSettingsError); vr::VRSettings()->RemoveKeyInSection(
if (vrSettingsError != vr::VRSettingsError_None) { vr::k_pch_SteamVR_Section,
LOG(WARNING) << "Could not remove \"" << vr::k_pch_SteamVR_AllowAsyncReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); vr::k_pch_SteamVR_ForceReprojection_Bool,
} &vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vr::k_pch_SteamVR_ForceReprojection_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, &vrSettingsError); vr::VRSettings()->RemoveKeyInSection(
if (vrSettingsError != vr::VRSettingsError_None) { vr::k_pch_SteamVR_Section,
LOG(WARNING) << "Could not remove \"" << vr::k_pch_SteamVR_ForceReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); vrsettings_steamvr_allowSupersampleFiltering,
} &vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vrsettings_steamvr_allowSupersampleFiltering
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowSupersampleFiltering, &vrSettingsError); vr::VRSettings()->Sync();
if (vrSettingsError != vr::VRSettingsError_None) { settingsUpdateCounter = 999; // Easiest way to get default values
LOG(WARNING) << "Could not remove \"" << vrsettings_steamvr_allowSupersampleFiltering << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
vr::VRSettings()->Sync();
settingsUpdateCounter = 999; // Easiest way to get default values
} }
void SteamVRTabController::restartSteamVR()
void SteamVRTabController::restartSteamVR() { {
QString cmd = QString("cmd.exe /C restartvrserver.bat \"") + parent->getVRRuntimePathUrl().toLocalFile() + QString("\""); QString cmd = QString( "cmd.exe /C restartvrserver.bat \"" )
LOG(INFO) << "SteamVR Restart Command: " << cmd; + parent->getVRRuntimePathUrl().toLocalFile()
QProcess::startDetached(cmd); + QString( "\"" );
LOG( INFO ) << "SteamVR Restart Command: " << cmd;
QProcess::startDetached( cmd );
} }
void SteamVRTabController::addSteamVRProfile( QString name,
void SteamVRTabController::addSteamVRProfile(QString name, bool includeSupersampling, bool includeSupersampleFiltering, bool includeReprojectionSettings) { bool includeSupersampling,
SteamVRProfile* profile = nullptr; bool includeSupersampleFiltering,
for (auto& p : steamvrProfiles) { bool includeReprojectionSettings )
if (p.profileName.compare(name.toStdString()) == 0) { {
profile = &p; SteamVRProfile* profile = nullptr;
break; for ( auto& p : steamvrProfiles )
} {
} if ( p.profileName.compare( name.toStdString() ) == 0 )
if (!profile) { {
auto i = steamvrProfiles.size(); profile = &p;
steamvrProfiles.emplace_back(); break;
profile = &steamvrProfiles[i]; }
} }
profile->profileName = name.toStdString(); if ( !profile )
profile->includesSupersampling = includeSupersampling; {
if (includeSupersampling) { auto i = steamvrProfiles.size();
profile->supersampling = m_superSampling; steamvrProfiles.emplace_back();
} profile = &steamvrProfiles[i];
profile->includesSupersampleFiltering = includeSupersampleFiltering; }
if (includeSupersampleFiltering) { profile->profileName = name.toStdString();
profile->supersampleFiltering = m_allowSupersampleFiltering; profile->includesSupersampling = includeSupersampling;
} if ( includeSupersampling )
profile->includesReprojectionSettings = includeReprojectionSettings; {
if (includeReprojectionSettings) { profile->supersampling = m_superSampling;
profile->asynchronousReprojection = m_allowAsyncReprojection; }
profile->interleavedReprojection = m_allowInterleavedReprojection; profile->includesSupersampleFiltering = includeSupersampleFiltering;
profile->alwaysOnReprojection = m_forceReprojection; if ( includeSupersampleFiltering )
} {
saveSteamVRProfiles(); profile->supersampleFiltering = m_allowSupersampleFiltering;
OverlayController::appSettings()->sync(); }
emit steamVRProfilesUpdated(); profile->includesReprojectionSettings = includeReprojectionSettings;
if ( includeReprojectionSettings )
{
profile->asynchronousReprojection = m_allowAsyncReprojection;
profile->interleavedReprojection = m_allowInterleavedReprojection;
profile->alwaysOnReprojection = m_forceReprojection;
}
saveSteamVRProfiles();
OverlayController::appSettings()->sync();
emit steamVRProfilesUpdated();
} }
void SteamVRTabController::applySteamVRProfile( unsigned index )
void SteamVRTabController::applySteamVRProfile(unsigned index) { {
if (index < steamvrProfiles.size()) { if ( index < steamvrProfiles.size() )
auto& profile = steamvrProfiles[index]; {
if (profile.includesSupersampling) { auto& profile = steamvrProfiles[index];
setSuperSampling(profile.supersampling); if ( profile.includesSupersampling )
} {
if (profile.includesSupersampleFiltering) { setSuperSampling( profile.supersampling );
setAllowSupersampleFiltering(profile.supersampleFiltering); }
} if ( profile.includesSupersampleFiltering )
if (profile.includesReprojectionSettings) { {
setAllowAsyncReprojection(profile.asynchronousReprojection); setAllowSupersampleFiltering( profile.supersampleFiltering );
setAllowInterleavedReprojection(profile.interleavedReprojection); }
setForceReprojection(profile.alwaysOnReprojection); if ( profile.includesReprojectionSettings )
} {
vr::VRSettings()->Sync(true); setAllowAsyncReprojection( profile.asynchronousReprojection );
} setAllowInterleavedReprojection( profile.interleavedReprojection );
setForceReprojection( profile.alwaysOnReprojection );
}
vr::VRSettings()->Sync( true );
}
} }
void SteamVRTabController::deleteSteamVRProfile( unsigned index )
void SteamVRTabController::deleteSteamVRProfile(unsigned index) { {
if (index < steamvrProfiles.size()) { if ( index < steamvrProfiles.size() )
auto pos = steamvrProfiles.begin() + index; {
steamvrProfiles.erase(pos); auto pos = steamvrProfiles.begin() + index;
saveSteamVRProfiles(); steamvrProfiles.erase( pos );
OverlayController::appSettings()->sync(); saveSteamVRProfiles();
emit steamVRProfilesUpdated(); OverlayController::appSettings()->sync();
} emit steamVRProfilesUpdated();
}
} }
} // namespace advsettings
} // namespace advconfig
+77 -65
View File
@@ -3,99 +3,111 @@
#include <QObject> #include <QObject>
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration // forward declaration
class OverlayController; class OverlayController;
struct SteamVRProfile
{
std::string profileName;
struct SteamVRProfile { bool includesSupersampling = false;
std::string profileName; float supersampling = 1.0f;
bool includesSupersampling = false; bool includesSupersampleFiltering = false;
float supersampling = 1.0f; bool supersampleFiltering = false;
bool includesSupersampleFiltering = false; bool includesReprojectionSettings = false;
bool supersampleFiltering = false; bool asynchronousReprojection = true;
bool interleavedReprojection = true;
bool includesReprojectionSettings = false; bool alwaysOnReprojection = true;
bool asynchronousReprojection = true;
bool interleavedReprojection = true;
bool alwaysOnReprojection = true;
}; };
class SteamVRTabController : public QObject
class SteamVRTabController : public QObject { {
Q_OBJECT Q_OBJECT
Q_PROPERTY(float superSampling READ superSampling WRITE setSuperSampling NOTIFY superSamplingChanged) Q_PROPERTY( float superSampling READ superSampling WRITE setSuperSampling
Q_PROPERTY(float compositorSuperSampling READ compositorSuperSampling WRITE setCompositorSuperSampling NOTIFY compositorSuperSamplingChanged) NOTIFY superSamplingChanged )
Q_PROPERTY(bool allowInterleavedReprojection READ allowInterleavedReprojection WRITE setAllowInterleavedReprojection NOTIFY allowInterleavedReprojectionChanged) Q_PROPERTY(
Q_PROPERTY(bool allowAsyncReprojection READ allowAsyncReprojection WRITE setAllowAsyncReprojection NOTIFY allowAsyncReprojectionChanged) float compositorSuperSampling READ compositorSuperSampling WRITE
Q_PROPERTY(bool forceReprojection READ forceReprojection WRITE setForceReprojection NOTIFY forceReprojectionChanged) setCompositorSuperSampling NOTIFY compositorSuperSamplingChanged )
Q_PROPERTY(bool allowSupersampleFiltering READ allowSupersampleFiltering WRITE setAllowSupersampleFiltering NOTIFY allowSupersampleFilteringChanged) Q_PROPERTY(
bool allowInterleavedReprojection READ allowInterleavedReprojection
WRITE setAllowInterleavedReprojection NOTIFY
allowInterleavedReprojectionChanged )
Q_PROPERTY(
bool allowAsyncReprojection READ allowAsyncReprojection WRITE
setAllowAsyncReprojection NOTIFY allowAsyncReprojectionChanged )
Q_PROPERTY( bool forceReprojection READ forceReprojection WRITE
setForceReprojection NOTIFY forceReprojectionChanged )
Q_PROPERTY( bool allowSupersampleFiltering READ allowSupersampleFiltering
WRITE setAllowSupersampleFiltering NOTIFY
allowSupersampleFilteringChanged )
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
float m_superSampling = 1.0; float m_superSampling = 1.0;
float m_compositorSuperSampling = 1.0; float m_compositorSuperSampling = 1.0;
bool m_allowInterleavedReprojection = true; bool m_allowInterleavedReprojection = true;
bool m_allowAsyncReprojection = true; bool m_allowAsyncReprojection = true;
bool m_forceReprojection = false; bool m_forceReprojection = false;
bool m_allowSupersampleFiltering = true; bool m_allowSupersampleFiltering = true;
std::vector<SteamVRProfile> steamvrProfiles; std::vector<SteamVRProfile> steamvrProfiles;
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
public: public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2( OverlayController* parent, QQuickWindow* widget );
void eventLoopTick(); void eventLoopTick();
float superSampling() const; float superSampling() const;
float compositorSuperSampling() const; float compositorSuperSampling() const;
bool allowInterleavedReprojection() const; bool allowInterleavedReprojection() const;
bool allowAsyncReprojection() const; bool allowAsyncReprojection() const;
bool forceReprojection() const; bool forceReprojection() const;
bool allowSupersampleFiltering() const; bool allowSupersampleFiltering() const;
void reloadSteamVRProfiles(); void reloadSteamVRProfiles();
void saveSteamVRProfiles(); void saveSteamVRProfiles();
Q_INVOKABLE unsigned getSteamVRProfileCount(); Q_INVOKABLE unsigned getSteamVRProfileCount();
Q_INVOKABLE QString getSteamVRProfileName(unsigned index); Q_INVOKABLE QString getSteamVRProfileName( unsigned index );
public slots: public slots:
void setSuperSampling(float value, bool notify = true); void setSuperSampling( float value, bool notify = true );
void setCompositorSuperSampling(float value, bool notify = true); void setCompositorSuperSampling( float value, bool notify = true );
void setAllowInterleavedReprojection(bool value, bool notify = true); void setAllowInterleavedReprojection( bool value, bool notify = true );
void setAllowAsyncReprojection(bool value, bool notify = true); void setAllowAsyncReprojection( bool value, bool notify = true );
void setForceReprojection(bool value, bool notify = true); void setForceReprojection( bool value, bool notify = true );
void setAllowSupersampleFiltering(bool value, bool notify = true); void setAllowSupersampleFiltering( bool value, bool notify = true );
void addSteamVRProfile(QString name, bool includeSupersampling, bool includeSupersampleFiltering, bool includeReprojectionSettings); void addSteamVRProfile( QString name,
void applySteamVRProfile(unsigned index); bool includeSupersampling,
void deleteSteamVRProfile(unsigned index); bool includeSupersampleFiltering,
bool includeReprojectionSettings );
void applySteamVRProfile( unsigned index );
void deleteSteamVRProfile( unsigned index );
void reset(); void reset();
void restartSteamVR(); void restartSteamVR();
signals: signals:
void superSamplingChanged(float value); void superSamplingChanged( float value );
void compositorSuperSamplingChanged(float value); void compositorSuperSamplingChanged( float value );
void allowInterleavedReprojectionChanged(bool value); void allowInterleavedReprojectionChanged( bool value );
void allowAsyncReprojectionChanged(bool value); void allowAsyncReprojectionChanged( bool value );
void forceReprojectionChanged(bool value); void forceReprojectionChanged( bool value );
void allowSupersampleFilteringChanged(bool value); void allowSupersampleFilteringChanged( bool value );
void steamVRProfilesUpdated(); void steamVRProfilesUpdated();
}; };
} // namespace advsettings } // namespace advsettings
+562 -368
View File
@@ -4,399 +4,593 @@
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
#include <thread> #include <thread>
#ifdef _WIN32 #ifdef _WIN32
#include "keyboardinput/KeyboardInputWindows.h" # include "keyboardinput/KeyboardInputWindows.h"
#else #else
#include "keyboardinput/KeyboardInputDummy.h" # include "keyboardinput/KeyboardInputDummy.h"
#endif #endif
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
const char* steamDesktopOverlaykey = "valve.steam.desktop";
const char* steamDesktopOverlaykey = "valve.steam.desktop"; void UtilitiesTabController::initStage1()
{
#ifdef _WIN32
keyboardInput.reset( new KeyboardInputWindows() );
#else
keyboardInput.reset( new KeyboardInputDummy() );
#endif
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
auto qAlarmEnabled = settings->value( "alarmEnabled", m_alarmEnabled );
auto qAlarmIsModal = settings->value( "alarmIsModal", m_alarmIsModal );
auto qAlarmHour = settings->value( "alarmHour", 0 );
auto qAlarmMinute = settings->value( "alarmMinute", 0 );
settings->endGroup();
m_alarmEnabled = qAlarmEnabled.toBool();
m_alarmIsModal = qAlarmIsModal.toBool();
m_alarmTime = QTime( qAlarmHour.toInt(), qAlarmMinute.toInt() );
vr::VROverlayHandle_t pOverlayHandle;
auto error = vr::VROverlay()->FindOverlay( steamDesktopOverlaykey,
&pOverlayHandle );
if ( error != vr::VROverlayError_None )
{
m_steamDesktopOverlayAvailable = false;
LOG( INFO ) << "Could not find overlay \"" << steamDesktopOverlaykey
<< "\": "
<< vr::VROverlay()->GetOverlayErrorNameFromEnum( error );
}
else
{
m_steamDesktopOverlayAvailable = true;
float width;
error = vr::VROverlay()->GetOverlayWidthInMeters( pOverlayHandle,
&width );
if ( error != vr::VROverlayError_None )
{
LOG( ERROR ) << "Could not read overlay width of \""
<< steamDesktopOverlaykey << "\": "
<< vr::VROverlay()->GetOverlayErrorNameFromEnum(
error );
}
else
{
m_steamDesktopOverlayWidth = width;
}
}
}
void UtilitiesTabController::initStage1() { void UtilitiesTabController::initStage2( OverlayController* var_parent,
#ifdef _WIN32 QQuickWindow* var_widget )
keyboardInput.reset(new KeyboardInputWindows()); {
#else this->parent = var_parent;
keyboardInput.reset(new KeyboardInputDummy()); this->widget = var_widget;
#endif }
auto settings = OverlayController::appSettings();
settings->beginGroup("utilitiesSettings");
auto qAlarmEnabled = settings->value("alarmEnabled", m_alarmEnabled);
auto qAlarmIsModal = settings->value("alarmIsModal", m_alarmIsModal);
auto qAlarmHour = settings->value("alarmHour", 0);
auto qAlarmMinute = settings->value("alarmMinute", 0);
settings->endGroup();
m_alarmEnabled = qAlarmEnabled.toBool();
m_alarmIsModal = qAlarmIsModal.toBool();
m_alarmTime = QTime(qAlarmHour.toInt(), qAlarmMinute.toInt());
vr::VROverlayHandle_t pOverlayHandle;
auto error = vr::VROverlay()->FindOverlay(steamDesktopOverlaykey, &pOverlayHandle);
if (error != vr::VROverlayError_None) {
m_steamDesktopOverlayAvailable = false;
LOG(INFO) << "Could not find overlay \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error);
} else {
m_steamDesktopOverlayAvailable = true;
float width;
error = vr::VROverlay()->GetOverlayWidthInMeters(pOverlayHandle, &width);
if (error != vr::VROverlayError_None) {
LOG(ERROR) << "Could not read overlay width of \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error);
} else {
m_steamDesktopOverlayWidth = width;
}
}
} void UtilitiesTabController::sendKeyboardInput( QString input )
{
keyboardInput->sendKeyboardInput( input );
}
void UtilitiesTabController::initStage2(OverlayController * var_parent, QQuickWindow * var_widget) { void UtilitiesTabController::sendKeyboardEnter()
this->parent = var_parent; {
this->widget = var_widget; keyboardInput->sendKeyboardEnter();
} }
void UtilitiesTabController::sendKeyboardInput(QString input) { void UtilitiesTabController::sendKeyboardAltTab()
keyboardInput->sendKeyboardInput(input); {
} keyboardInput->sendKeyboardAltTab();
}
void UtilitiesTabController::sendKeyboardEnter() { void UtilitiesTabController::sendKeyboardBackspace( int count )
keyboardInput->sendKeyboardEnter(); {
} keyboardInput->sendKeyboardBackspace( count );
}
void UtilitiesTabController::sendKeyboardAltTab() { bool UtilitiesTabController::alarmEnabled() const
keyboardInput->sendKeyboardAltTab(); {
return m_alarmEnabled;
}
bool UtilitiesTabController::alarmIsModal() const
{
return m_alarmIsModal;
}
int UtilitiesTabController::alarmTimeHour() const
{
return m_alarmTime.hour();
}
int UtilitiesTabController::alarmTimeMinute() const
{
return m_alarmTime.minute();
}
void UtilitiesTabController::setAlarmEnabled( bool enabled, bool notify )
{
if ( m_alarmEnabled != enabled )
{
m_alarmEnabled = enabled;
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
settings->setValue( "alarmEnabled", m_alarmEnabled );
settings->endGroup();
settings->sync();
m_alarmLastCheckTime = QTime();
if ( notify )
{
emit alarmEnabledChanged( m_alarmEnabled );
}
}
}
void UtilitiesTabController::setAlarmIsModal( bool modal, bool notify )
{
if ( m_alarmIsModal != modal )
{
m_alarmIsModal = modal;
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
settings->setValue( "alarmIsModal", m_alarmIsModal );
settings->endGroup();
settings->sync();
if ( notify )
{
emit alarmIsModalChanged( m_alarmIsModal );
}
}
}
void UtilitiesTabController::setAlarmTimeHour( int hour, bool notify )
{
if ( m_alarmTime.hour() != hour )
{
if ( m_alarmTime.isValid() )
{
m_alarmTime = QTime( hour, m_alarmTime.minute() );
}
else
{
m_alarmTime = QTime( hour, 0 );
}
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
settings->setValue( "alarmHour", m_alarmTime.hour() );
settings->setValue( "alarmMinute", m_alarmTime.minute() );
settings->endGroup();
settings->sync();
m_alarmLastCheckTime = QTime();
if ( notify )
{
emit alarmTimeHourChanged( hour );
}
}
}
void UtilitiesTabController::setAlarmTimeMinute( int min, bool notify )
{
if ( m_alarmTime.minute() != min )
{
if ( m_alarmTime.isValid() )
{
m_alarmTime = QTime( m_alarmTime.hour(), min );
}
else
{
m_alarmTime = QTime( 0, min );
}
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
settings->setValue( "alarmHour", m_alarmTime.hour() );
settings->setValue( "alarmMinute", m_alarmTime.minute() );
settings->endGroup();
settings->sync();
m_alarmLastCheckTime = QTime();
if ( notify )
{
emit alarmTimeMinuteChanged( min );
}
}
}
void UtilitiesTabController::setAlarmTimeToCurrentTime()
{
auto now = QTime::currentTime();
setAlarmTimeHour( now.hour() );
setAlarmTimeMinute( now.minute() );
}
void UtilitiesTabController::modAlarmTimeHour( int value, bool notify )
{
auto h = m_alarmTime.hour();
m_alarmTime = m_alarmTime.addSecs( value * 60 * 60 );
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
settings->setValue( "alarmHour", m_alarmTime.hour() );
settings->setValue( "alarmMinute", m_alarmTime.minute() );
settings->endGroup();
settings->sync();
if ( h != m_alarmTime.hour() )
{
m_alarmLastCheckTime = QTime();
if ( notify )
{
emit alarmTimeHourChanged( m_alarmTime.hour() );
}
}
}
void UtilitiesTabController::modAlarmTimeMinute( int value, bool notify )
{
auto h = m_alarmTime.hour();
auto m = m_alarmTime.minute();
m_alarmTime = m_alarmTime.addSecs( value * 60 );
auto settings = OverlayController::appSettings();
settings->beginGroup( "utilitiesSettings" );
settings->setValue( "alarmHour", m_alarmTime.hour() );
settings->setValue( "alarmMinute", m_alarmTime.minute() );
settings->endGroup();
settings->sync();
if ( m != m_alarmTime.minute() || h != m_alarmTime.hour() )
{
m_alarmLastCheckTime = QTime();
if ( notify )
{
if ( h != m_alarmTime.hour() )
{
emit alarmTimeHourChanged( m_alarmTime.hour() );
}
if ( m != m_alarmTime.minute() )
{
emit alarmTimeMinuteChanged( m_alarmTime.minute() );
}
}
}
}
vr::VROverlayHandle_t createBatteryOverlay( vr::TrackedDeviceIndex_t index )
{
vr::VROverlayHandle_t handle = vr::k_ulOverlayHandleInvalid;
std::string batteryKey = std::string( OverlayController::applicationKey )
+ ".battery." + std::to_string( index );
vr::VROverlayError overlayError = vr::VROverlay()->CreateOverlay(
batteryKey.c_str(), batteryKey.c_str(), &handle );
if ( overlayError == vr::VROverlayError_None )
{
std::string batteryIconPath
= QApplication::applicationDirPath().toStdString()
+ "/res/battery_0.png";
if ( QFile::exists( QString::fromStdString( batteryIconPath ) ) )
{
vr::VROverlay()->SetOverlayFromFile( handle,
batteryIconPath.c_str() );
vr::VROverlay()->SetOverlayWidthInMeters( handle, 0.05f );
vr::HmdMatrix34_t notificationTransform
= { { { 1.0f, 0.0f, 0.0f, 0.00f },
{ 0.0f, -1.0f, 0.0f, 0.01f },
{ 0.0f, 0.0f, -1.0f, -0.013f } } };
vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative(
handle, index, &notificationTransform );
LOG( INFO ) << "Created battery overlay for device " << index;
}
else
{
LOG( ERROR ) << "Could not find battery icon \"" << batteryIconPath
<< "\"";
}
}
else
{
LOG( ERROR ) << "Could not create ptt notification overlay: "
<< vr::VROverlay()->GetOverlayErrorNameFromEnum(
overlayError );
} }
void UtilitiesTabController::sendKeyboardBackspace(int count) { return handle;
keyboardInput->sendKeyboardBackspace(count); }
}
void UtilitiesTabController::eventLoopTick()
bool UtilitiesTabController::alarmEnabled() const { {
return m_alarmEnabled; if ( settingsUpdateCounter >= 10 )
} {
vr::VROverlayHandle_t pOverlayHandle;
bool UtilitiesTabController::alarmIsModal() const { auto error = vr::VROverlay()->FindOverlay( steamDesktopOverlaykey,
return m_alarmIsModal; &pOverlayHandle );
} if ( error == vr::VROverlayError_None )
{
int UtilitiesTabController::alarmTimeHour() const { if ( !m_steamDesktopOverlayAvailable )
return m_alarmTime.hour(); {
} m_steamDesktopOverlayAvailable = true;
emit steamDesktopOverlayAvailableChanged(
int UtilitiesTabController::alarmTimeMinute() const { m_steamDesktopOverlayAvailable );
return m_alarmTime.minute(); }
} float width;
error = vr::VROverlay()->GetOverlayWidthInMeters( pOverlayHandle,
void UtilitiesTabController::setAlarmEnabled(bool enabled, bool notify) { &width );
if (m_alarmEnabled != enabled) { if ( error != vr::VROverlayError_None )
m_alarmEnabled = enabled; {
auto settings = OverlayController::appSettings(); LOG( ERROR )
settings->beginGroup("utilitiesSettings"); << "Could not read overlay width of \""
settings->setValue("alarmEnabled", m_alarmEnabled); << steamDesktopOverlaykey << "\": "
settings->endGroup(); << vr::VROverlay()->GetOverlayErrorNameFromEnum( error );
settings->sync(); }
m_alarmLastCheckTime = QTime(); else
if (notify) { {
emit alarmEnabledChanged(m_alarmEnabled); setSteamDesktopOverlayWidth( width, true, false );
} }
} }
} else
{
void UtilitiesTabController::setAlarmIsModal(bool modal, bool notify) { if ( m_steamDesktopOverlayAvailable )
if (m_alarmIsModal != modal) { {
m_alarmIsModal = modal; m_steamDesktopOverlayAvailable = false;
auto settings = OverlayController::appSettings(); emit steamDesktopOverlayAvailableChanged(
settings->beginGroup("utilitiesSettings"); m_steamDesktopOverlayAvailable );
settings->setValue("alarmIsModal", m_alarmIsModal);
settings->endGroup();
settings->sync();
if (notify) {
emit alarmIsModalChanged(m_alarmIsModal);
}
}
}
void UtilitiesTabController::setAlarmTimeHour(int hour, bool notify) {
if (m_alarmTime.hour() != hour) {
if (m_alarmTime.isValid()) {
m_alarmTime = QTime(hour, m_alarmTime.minute());
} else {
m_alarmTime = QTime(hour, 0);
}
auto settings = OverlayController::appSettings();
settings->beginGroup("utilitiesSettings");
settings->setValue("alarmHour", m_alarmTime.hour());
settings->setValue("alarmMinute", m_alarmTime.minute());
settings->endGroup();
settings->sync();
m_alarmLastCheckTime = QTime();
if (notify) {
emit alarmTimeHourChanged(hour);
}
}
}
void UtilitiesTabController::setAlarmTimeMinute(int min, bool notify) {
if (m_alarmTime.minute() != min) {
if (m_alarmTime.isValid()) {
m_alarmTime = QTime(m_alarmTime.hour(), min);
} else {
m_alarmTime = QTime(0, min);
}
auto settings = OverlayController::appSettings();
settings->beginGroup("utilitiesSettings");
settings->setValue("alarmHour", m_alarmTime.hour());
settings->setValue("alarmMinute", m_alarmTime.minute());
settings->endGroup();
settings->sync();
m_alarmLastCheckTime = QTime();
if (notify) {
emit alarmTimeMinuteChanged(min);
}
}
}
void UtilitiesTabController::setAlarmTimeToCurrentTime() {
auto now = QTime::currentTime();
setAlarmTimeHour(now.hour());
setAlarmTimeMinute(now.minute());
}
void UtilitiesTabController::modAlarmTimeHour(int value, bool notify) {
auto h = m_alarmTime.hour();
m_alarmTime = m_alarmTime.addSecs(value * 60 * 60);
auto settings = OverlayController::appSettings();
settings->beginGroup("utilitiesSettings");
settings->setValue("alarmHour", m_alarmTime.hour());
settings->setValue("alarmMinute", m_alarmTime.minute());
settings->endGroup();
settings->sync();
if (h != m_alarmTime.hour()) {
m_alarmLastCheckTime = QTime();
if (notify) {
emit alarmTimeHourChanged(m_alarmTime.hour());
}
}
}
void UtilitiesTabController::modAlarmTimeMinute(int value, bool notify) {
auto h = m_alarmTime.hour();
auto m = m_alarmTime.minute();
m_alarmTime = m_alarmTime.addSecs(value * 60);
auto settings = OverlayController::appSettings();
settings->beginGroup("utilitiesSettings");
settings->setValue("alarmHour", m_alarmTime.hour());
settings->setValue("alarmMinute", m_alarmTime.minute());
settings->endGroup();
settings->sync();
if (m != m_alarmTime.minute() || h != m_alarmTime.hour()) {
m_alarmLastCheckTime = QTime();
if (notify) {
if (h != m_alarmTime.hour()) {
emit alarmTimeHourChanged(m_alarmTime.hour());
}
if (m != m_alarmTime.minute()) {
emit alarmTimeMinuteChanged(m_alarmTime.minute());
}
}
}
}
vr::VROverlayHandle_t createBatteryOverlay(vr::TrackedDeviceIndex_t index) {
vr::VROverlayHandle_t handle = vr::k_ulOverlayHandleInvalid;
std::string batteryKey = std::string(OverlayController::applicationKey) + ".battery." + std::to_string(index);
vr::VROverlayError overlayError = vr::VROverlay()->CreateOverlay(batteryKey.c_str(), batteryKey.c_str(), &handle);
if (overlayError == vr::VROverlayError_None) {
std::string batteryIconPath = QApplication::applicationDirPath().toStdString() + "/res/battery_0.png";
if (QFile::exists(QString::fromStdString(batteryIconPath))) {
vr::VROverlay()->SetOverlayFromFile(handle, batteryIconPath.c_str());
vr::VROverlay()->SetOverlayWidthInMeters(handle, 0.05f);
vr::HmdMatrix34_t notificationTransform = {{
{1.0f, 0.0f, 0.0f, 0.00f},
{0.0f, -1.0f, 0.0f, 0.01f},
{0.0f, 0.0f, -1.0f, -0.013f}
}};
vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative(handle, index, &notificationTransform);
LOG(INFO) << "Created battery overlay for device " << index;
} else {
LOG(ERROR) << "Could not find battery icon \"" << batteryIconPath << "\"";
} }
} else {
LOG(ERROR) << "Could not create ptt notification overlay: " << vr::VROverlay()->GetOverlayErrorNameFromEnum(overlayError);
} }
return handle; if ( m_alarmEnabled && m_alarmTime.isValid() )
} {
auto now = QTime::currentTime();
if ( m_alarmLastCheckTime.isValid()
void UtilitiesTabController::eventLoopTick() { && m_alarmLastCheckTime <= m_alarmTime && m_alarmTime <= now )
if (settingsUpdateCounter >= 10) { {
setAlarmEnabled( false );
vr::VROverlayHandle_t pOverlayHandle; char alarmMessageBuffer[1024];
auto error = vr::VROverlay()->FindOverlay(steamDesktopOverlaykey, &pOverlayHandle); std::snprintf( alarmMessageBuffer,
if (error == vr::VROverlayError_None) { 1024,
if (!m_steamDesktopOverlayAvailable) { "The alarm at %02i:%02i went off.",
m_steamDesktopOverlayAvailable = true; alarmTimeHour(),
emit steamDesktopOverlayAvailableChanged(m_steamDesktopOverlayAvailable); alarmTimeMinute() );
} if ( m_alarmIsModal )
float width; {
error = vr::VROverlay()->GetOverlayWidthInMeters(pOverlayHandle, &width); std::thread messageThread(
if (error != vr::VROverlayError_None) { []( UtilitiesTabController* parent,
LOG(ERROR) << "Could not read overlay width of \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error); std::string message ) {
} else { auto res = vr::VROverlay()->ShowMessageOverlay(
setSteamDesktopOverlayWidth(width, true, false); message.c_str(),
} "Alarm Clock",
} else { "Ok",
if (m_steamDesktopOverlayAvailable) { "+15 min" );
m_steamDesktopOverlayAvailable = false; if ( res
emit steamDesktopOverlayAvailableChanged(m_steamDesktopOverlayAvailable); == vr::VRMessageOverlayResponse_ButtonPress_1 )
} {
} parent->setAlarmTimeToCurrentTime();
parent->modAlarmTimeMinute( 15 );
if (m_alarmEnabled && m_alarmTime.isValid()) { parent->setAlarmEnabled( true );
auto now = QTime::currentTime();
if (m_alarmLastCheckTime.isValid() && m_alarmLastCheckTime <= m_alarmTime && m_alarmTime <= now) {
setAlarmEnabled(false);
char alarmMessageBuffer[1024];
std::snprintf(alarmMessageBuffer, 1024, "The alarm at %02i:%02i went off.", alarmTimeHour(), alarmTimeMinute());
if (m_alarmIsModal) {
std::thread messageThread([](UtilitiesTabController* parent, std::string message) {
auto res = vr::VROverlay()->ShowMessageOverlay(message.c_str(), "Alarm Clock", "Ok", "+15 min");
if (res == vr::VRMessageOverlayResponse_ButtonPress_1) {
parent->setAlarmTimeToCurrentTime();
parent->modAlarmTimeMinute(15);
parent->setAlarmEnabled(true);
} else if (res >= vr::VRMessageOverlayResponse_CouldntFindSystemOverlay) {
static const char* errorMessages[] = { "CouldntFindSystemOverlay", "CouldntFindOrCreateClientOverlay", "ApplicationQuit" };
int errorCode = res - vr::VRMessageOverlayResponse_CouldntFindSystemOverlay;
if (res < 3) {
LOG(ERROR) << "Could not create Alarm Overlay: " << errorMessages[errorCode];
} else {
LOG(ERROR) << "Could not create Alarm Overlay: Unknown Error";
}
}
}, this, std::string(alarmMessageBuffer));
messageThread.detach();
} else {
vr::VRNotificationId notificationId;
vr::EVRInitError eError;
vr::IVRNotifications* vrnotification = (vr::IVRNotifications*)vr::VR_GetGenericInterface(vr::IVRNotifications_Version, &eError);
if (eError != vr::VRInitError_None) {
LOG(ERROR) << "Error while getting IVRNotifications interface" << vr::VR_GetVRInitErrorAsEnglishDescription(eError);
vrnotification = nullptr;
} else {
vr::NotificationBitmap_t* messageIconPtr = nullptr;
/*
// Can i even create this object on the stack, who takes ownership?
vr::NotificationBitmap_t messageIcon;
// First get image width and height
vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(), nullptr, 0, (uint32_t*)&messageIcon.m_nWidth, (uint32_t*)&messageIcon.m_nHeight);
messageIcon.m_nBytesPerPixel = 4;
unsigned bufferSize = messageIcon.m_nWidth*messageIcon.m_nHeight*messageIcon.m_nBytesPerPixel;
// Can I delete this buffer after this section? Who takes ownership?
std::unique_ptr<char> imageBuffer;
imageBuffer.reset(new char[bufferSize]);
messageIcon.m_pImageData = imageBuffer.get();
// Get image data
auto iconError = vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(), messageIcon.m_pImageData, bufferSize, (uint32_t*)&messageIcon.m_nWidth, (uint32_t*)&messageIcon.m_nHeight);
if (iconError != vr::VROverlayError_None) {
LOG(ERROR) << "Error while getting message overlay icon: " << vr::VROverlay()->GetOverlayErrorNameFromEnum(iconError);
} else {
messageIconPtr = &messageIcon;
}
*/
auto nError = vrnotification->CreateNotification(
parent->overlayHandle(), 666, vr::EVRNotificationType_Transient, alarmMessageBuffer, vr::EVRNotificationStyle_Application, messageIconPtr, &notificationId
);
if (nError != vr::VRNotificationError_OK) {
LOG(ERROR) << "Error while creating notification: " << nError;
vrnotification = nullptr;
}
}
}
}
m_alarmLastCheckTime = now;
}
// attach battery overlay to all tracked devices that aren't a controller or hmd
for(vr::TrackedDeviceIndex_t i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
vr::ETrackedDeviceClass deviceClass = vr::VRSystem()->GetTrackedDeviceClass(i);
if (deviceClass == vr::ETrackedDeviceClass::TrackedDeviceClass_GenericTracker) {
if (m_batteryOverlayHandles[i] == vr::k_ulOverlayHandleInvalid) {
LOG(INFO) << "Creating battery overlay for device " << i;
m_batteryOverlayHandles[i] = createBatteryOverlay(i);
m_batteryVisible[i] = true;
}
bool shouldShow = vr::VROverlay()->IsDashboardVisible();
if (shouldShow != m_batteryVisible[i]) {
if (shouldShow) {
vr::VROverlay()->ShowOverlay(m_batteryOverlayHandles[i]);
} else {
vr::VROverlay()->HideOverlay(m_batteryOverlayHandles[i]);
}
m_batteryVisible[i] = shouldShow;
}
bool hasBatteryStatus = vr::VRSystem()->GetBoolTrackedDeviceProperty(i, vr::ETrackedDeviceProperty::Prop_DeviceProvidesBatteryStatus_Bool);
if (hasBatteryStatus) {
float battery = vr::VRSystem()->GetFloatTrackedDeviceProperty(i, vr::ETrackedDeviceProperty::Prop_DeviceBatteryPercentage_Float);
int batteryState = ceil(battery * 5);
if (batteryState != m_batteryState[i]) {
LOG(INFO) << "Updating battery overlay for device " << i << " to " << batteryState << "(" << battery << "";
std::string batteryIconPath = QApplication::applicationDirPath().toStdString() + "/res/battery_" + std::to_string(batteryState) + ".png";
if (QFile::exists(QString::fromStdString(batteryIconPath))) {
vr::VROverlay()->SetOverlayFromFile(m_batteryOverlayHandles[i], batteryIconPath.c_str());
} else {
LOG(ERROR) << "Could not find battery icon \"" << batteryIconPath << "\"";
} }
m_batteryState[i] = batteryState; else if (
res
>= vr::VRMessageOverlayResponse_CouldntFindSystemOverlay )
{
static const char* errorMessages[]
= { "CouldntFindSystemOverlay",
"CouldntFindOrCreateClientOverlay",
"ApplicationQuit" };
int errorCode
= res
- vr::VRMessageOverlayResponse_CouldntFindSystemOverlay;
if ( res < 3 )
{
LOG( ERROR )
<< "Could not create Alarm Overlay: "
<< errorMessages[errorCode];
}
else
{
LOG( ERROR ) << "Could not create Alarm "
"Overlay: Unknown Error";
}
}
},
this,
std::string( alarmMessageBuffer ) );
messageThread.detach();
}
else
{
vr::VRNotificationId notificationId;
vr::EVRInitError eError;
vr::IVRNotifications* vrnotification
= ( vr::IVRNotifications* ) vr::VR_GetGenericInterface(
vr::IVRNotifications_Version, &eError );
if ( eError != vr::VRInitError_None )
{
LOG( ERROR )
<< "Error while getting IVRNotifications interface"
<< vr::VR_GetVRInitErrorAsEnglishDescription(
eError );
vrnotification = nullptr;
}
else
{
vr::NotificationBitmap_t* messageIconPtr = nullptr;
/*
// Can i even create this object on the stack, who takes
ownership? vr::NotificationBitmap_t messageIcon;
// First get image width and height
vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(),
nullptr, 0, (uint32_t*)&messageIcon.m_nWidth,
(uint32_t*)&messageIcon.m_nHeight);
messageIcon.m_nBytesPerPixel = 4;
unsigned bufferSize =
messageIcon.m_nWidth*messageIcon.m_nHeight*messageIcon.m_nBytesPerPixel;
// Can I delete this buffer after this section? Who
takes ownership? std::unique_ptr<char> imageBuffer;
imageBuffer.reset(new char[bufferSize]);
messageIcon.m_pImageData = imageBuffer.get();
// Get image data
auto iconError =
vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(),
messageIcon.m_pImageData, bufferSize,
(uint32_t*)&messageIcon.m_nWidth,
(uint32_t*)&messageIcon.m_nHeight); if (iconError !=
vr::VROverlayError_None) { LOG(ERROR) << "Error while
getting message overlay icon: " <<
vr::VROverlay()->GetOverlayErrorNameFromEnum(iconError);
} else {
messageIconPtr = &messageIcon;
}
*/
auto nError = vrnotification->CreateNotification(
parent->overlayHandle(),
666,
vr::EVRNotificationType_Transient,
alarmMessageBuffer,
vr::EVRNotificationStyle_Application,
messageIconPtr,
&notificationId );
if ( nError != vr::VRNotificationError_OK )
{
LOG( ERROR )
<< "Error while creating notification: "
<< nError;
vrnotification = nullptr;
} }
} }
} }
} }
m_alarmLastCheckTime = now;
}
settingsUpdateCounter = 0; // attach battery overlay to all tracked devices that aren't a
} else { // controller or hmd
settingsUpdateCounter++; for ( vr::TrackedDeviceIndex_t i = 0; i < vr::k_unMaxTrackedDeviceCount;
} i++ )
{
vr::ETrackedDeviceClass deviceClass
= vr::VRSystem()->GetTrackedDeviceClass( i );
if ( deviceClass
== vr::ETrackedDeviceClass::TrackedDeviceClass_GenericTracker )
{
if ( m_batteryOverlayHandles[i]
== vr::k_ulOverlayHandleInvalid )
{
LOG( INFO ) << "Creating battery overlay for device " << i;
m_batteryOverlayHandles[i] = createBatteryOverlay( i );
m_batteryVisible[i] = true;
}
bool shouldShow = vr::VROverlay()->IsDashboardVisible();
if ( shouldShow != m_batteryVisible[i] )
{
if ( shouldShow )
{
vr::VROverlay()->ShowOverlay(
m_batteryOverlayHandles[i] );
}
else
{
vr::VROverlay()->HideOverlay(
m_batteryOverlayHandles[i] );
}
m_batteryVisible[i] = shouldShow;
}
bool hasBatteryStatus
= vr::VRSystem()->GetBoolTrackedDeviceProperty(
i,
vr::ETrackedDeviceProperty::
Prop_DeviceProvidesBatteryStatus_Bool );
if ( hasBatteryStatus )
{
float battery
= vr::VRSystem()->GetFloatTrackedDeviceProperty(
i,
vr::ETrackedDeviceProperty::
Prop_DeviceBatteryPercentage_Float );
int batteryState = ceil( battery * 5 );
if ( batteryState != m_batteryState[i] )
{
LOG( INFO )
<< "Updating battery overlay for device " << i
<< " to " << batteryState << "(" << battery << "";
std::string batteryIconPath
= QApplication::applicationDirPath().toStdString()
+ "/res/battery_" + std::to_string( batteryState )
+ ".png";
if ( QFile::exists(
QString::fromStdString( batteryIconPath ) ) )
{
vr::VROverlay()->SetOverlayFromFile(
m_batteryOverlayHandles[i],
batteryIconPath.c_str() );
}
else
{
LOG( ERROR ) << "Could not find battery icon \""
<< batteryIconPath << "\"";
}
m_batteryState[i] = batteryState;
}
}
}
}
settingsUpdateCounter = 0;
} }
else
{
settingsUpdateCounter++;
}
}
bool UtilitiesTabController::steamDesktopOverlayAvailable() const
{
return m_steamDesktopOverlayAvailable;
}
bool UtilitiesTabController::steamDesktopOverlayAvailable() const { float UtilitiesTabController::steamDesktopOverlayWidth() const
return m_steamDesktopOverlayAvailable; {
} return m_steamDesktopOverlayWidth;
}
float UtilitiesTabController::steamDesktopOverlayWidth() const { void UtilitiesTabController::setSteamDesktopOverlayWidth( float width,
return m_steamDesktopOverlayWidth; bool notify,
} bool notifyOpenVr )
{
if ( std::abs( m_steamDesktopOverlayWidth - width ) > 0.01 )
{
m_steamDesktopOverlayWidth = width;
if ( notifyOpenVr )
{
vr::VROverlayHandle_t pOverlayHandle;
auto error = vr::VROverlay()->FindOverlay( steamDesktopOverlaykey,
&pOverlayHandle );
if ( error != vr::VROverlayError_None )
{
LOG( ERROR )
<< "Could not find overlay \"" << steamDesktopOverlaykey
<< "\": "
<< vr::VROverlay()->GetOverlayErrorNameFromEnum( error );
}
else
{
error = vr::VROverlay()->SetOverlayWidthInMeters(
pOverlayHandle, m_steamDesktopOverlayWidth );
if ( error != vr::VROverlayError_None )
{
LOG( ERROR )
<< "Could not modify overlay width of \""
<< steamDesktopOverlaykey << "\": "
<< vr::VROverlay()->GetOverlayErrorNameFromEnum(
error );
}
}
}
if ( notify )
{
emit steamDesktopOverlayWidthChanged( m_steamDesktopOverlayWidth );
}
}
}
void UtilitiesTabController::setSteamDesktopOverlayWidth(float width, bool notify, bool notifyOpenVr) { } // namespace advsettings
if (std::abs(m_steamDesktopOverlayWidth - width) > 0.01) {
m_steamDesktopOverlayWidth = width;
if (notifyOpenVr) {
vr::VROverlayHandle_t pOverlayHandle;
auto error = vr::VROverlay()->FindOverlay(steamDesktopOverlaykey, &pOverlayHandle);
if (error != vr::VROverlayError_None) {
LOG(ERROR) << "Could not find overlay \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error);
} else {
error = vr::VROverlay()->SetOverlayWidthInMeters(pOverlayHandle, m_steamDesktopOverlayWidth);
if (error != vr::VROverlayError_None) {
LOG(ERROR) << "Could not modify overlay width of \"" << steamDesktopOverlaykey << "\": " << vr::VROverlay()->GetOverlayErrorNameFromEnum(error);
}
}
}
if (notify) {
emit steamDesktopOverlayWidthChanged(m_steamDesktopOverlayWidth);
}
}
}
} // namespace advconfig
+69 -58
View File
@@ -9,77 +9,88 @@
class QQuickWindow; class QQuickWindow;
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
// forward declaration
class OverlayController;
// forward declaration class UtilitiesTabController : public QObject
class OverlayController; {
Q_OBJECT
Q_PROPERTY( bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled NOTIFY
alarmEnabledChanged )
Q_PROPERTY( bool alarmIsModal READ alarmIsModal WRITE setAlarmIsModal NOTIFY
alarmIsModalChanged )
Q_PROPERTY( int alarmTimeHour READ alarmTimeHour WRITE setAlarmTimeHour
NOTIFY alarmTimeHourChanged )
Q_PROPERTY( int alarmTimeMinute READ alarmTimeMinute WRITE
setAlarmTimeMinute NOTIFY alarmTimeMinuteChanged )
Q_PROPERTY(
bool steamDesktopOverlayAvailable READ steamDesktopOverlayAvailable
NOTIFY steamDesktopOverlayAvailableChanged )
Q_PROPERTY(
float steamDesktopOverlayWidth READ steamDesktopOverlayWidth WRITE
setSteamDesktopOverlayWidth NOTIFY steamDesktopOverlayWidthChanged )
private:
OverlayController* parent;
QQuickWindow* widget;
class UtilitiesTabController : public QObject { unsigned settingsUpdateCounter = 0;
Q_OBJECT
Q_PROPERTY(bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled NOTIFY alarmEnabledChanged)
Q_PROPERTY(bool alarmIsModal READ alarmIsModal WRITE setAlarmIsModal NOTIFY alarmIsModalChanged)
Q_PROPERTY(int alarmTimeHour READ alarmTimeHour WRITE setAlarmTimeHour NOTIFY alarmTimeHourChanged)
Q_PROPERTY(int alarmTimeMinute READ alarmTimeMinute WRITE setAlarmTimeMinute NOTIFY alarmTimeMinuteChanged)
Q_PROPERTY(bool steamDesktopOverlayAvailable READ steamDesktopOverlayAvailable NOTIFY steamDesktopOverlayAvailableChanged)
Q_PROPERTY(float steamDesktopOverlayWidth READ steamDesktopOverlayWidth WRITE setSteamDesktopOverlayWidth NOTIFY steamDesktopOverlayWidthChanged)
private: bool m_alarmEnabled = false;
OverlayController* parent; bool m_alarmIsModal = true;
QQuickWindow* widget; QTime m_alarmTime;
QTime m_alarmLastCheckTime;
bool m_steamDesktopOverlayAvailable = false;
float m_steamDesktopOverlayWidth = 4.0f;
vr::VROverlayHandle_t
m_batteryOverlayHandles[vr::k_unMaxTrackedDeviceCount];
int m_batteryState[vr::k_unMaxTrackedDeviceCount];
bool m_batteryVisible[vr::k_unMaxTrackedDeviceCount];
unsigned settingsUpdateCounter = 0; std::unique_ptr<KeyboardInput> keyboardInput;
bool m_alarmEnabled = false; public:
bool m_alarmIsModal = true; void initStage1();
QTime m_alarmTime; void initStage2( OverlayController* parent, QQuickWindow* widget );
QTime m_alarmLastCheckTime;
bool m_steamDesktopOverlayAvailable = false;
float m_steamDesktopOverlayWidth = 4.0f;
vr::VROverlayHandle_t m_batteryOverlayHandles[vr::k_unMaxTrackedDeviceCount];
int m_batteryState[vr::k_unMaxTrackedDeviceCount];
bool m_batteryVisible[vr::k_unMaxTrackedDeviceCount];
std::unique_ptr<KeyboardInput> keyboardInput; void eventLoopTick();
public: bool alarmEnabled() const;
void initStage1(); bool alarmIsModal() const;
void initStage2(OverlayController* parent, QQuickWindow* widget); int alarmTimeHour() const;
int alarmTimeMinute() const;
void eventLoopTick(); bool steamDesktopOverlayAvailable() const;
float steamDesktopOverlayWidth() const;
bool alarmEnabled() const; public slots:
bool alarmIsModal() const; void sendKeyboardInput( QString input );
int alarmTimeHour() const; void sendKeyboardEnter();
int alarmTimeMinute() const; void sendKeyboardAltTab();
void sendKeyboardBackspace( int count );
bool steamDesktopOverlayAvailable() const; void setAlarmEnabled( bool enabled, bool notify = true );
float steamDesktopOverlayWidth() const; void setAlarmIsModal( bool modal, bool notify = true );
void setAlarmTimeHour( int hour, bool notify = true );
void setAlarmTimeMinute( int min, bool notify = true );
void setAlarmTimeToCurrentTime();
void modAlarmTimeHour( int value, bool notify = true );
void modAlarmTimeMinute( int value, bool notify = true );
public slots: void setSteamDesktopOverlayWidth( float width,
void sendKeyboardInput(QString input); bool notify = true,
void sendKeyboardEnter(); bool notifyOpenVr = true );
void sendKeyboardAltTab();
void sendKeyboardBackspace(int count);
void setAlarmEnabled(bool enabled, bool notify = true); signals:
void setAlarmIsModal(bool modal, bool notify = true); void alarmEnabledChanged( bool enabled );
void setAlarmTimeHour(int hour, bool notify = true); void alarmIsModalChanged( bool modal );
void setAlarmTimeMinute(int min, bool notify = true); void alarmTimeHourChanged( int hour );
void setAlarmTimeToCurrentTime(); void alarmTimeMinuteChanged( int min );
void modAlarmTimeHour(int value, bool notify = true);
void modAlarmTimeMinute(int value, bool notify = true);
void setSteamDesktopOverlayWidth(float width, bool notify = true, bool notifyOpenVr = true); void steamDesktopOverlayAvailableChanged( bool available );
void steamDesktopOverlayWidthChanged( float width );
signals: };
void alarmEnabledChanged(bool enabled);
void alarmIsModalChanged(bool modal);
void alarmTimeHourChanged(int hour);
void alarmTimeMinuteChanged(int min);
void steamDesktopOverlayAvailableChanged(bool available);
void steamDesktopOverlayWidthChanged(float width);
};
} // namespace advsettings } // namespace advsettings
@@ -1,23 +1,23 @@
#include "AudioManagerDummy.h" #include "AudioManagerDummy.h"
// Used to get the compiler to shut up about C4100: unreferenced formal parameter. // Used to get the compiler to shut up about C4100: unreferenced formal
// The cast is to get GCC to shut up about it. // parameter. The cast is to get GCC to shut up about it.
#define UNREFERENCED_PARAMETER(P) static_cast<void>((P)) #define UNREFERENCED_PARAMETER( P ) static_cast<void>( ( P ) )
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
void AudioManagerDummy::init(AudioTabController *controller) void AudioManagerDummy::init( AudioTabController* controller )
{ {
// noop // noop
UNREFERENCED_PARAMETER(controller); UNREFERENCED_PARAMETER( controller );
} }
void AudioManagerDummy::setPlaybackDevice(const std::string &id, bool notify) void AudioManagerDummy::setPlaybackDevice( const std::string& id, bool notify )
{ {
// noop // noop
UNREFERENCED_PARAMETER(id); UNREFERENCED_PARAMETER( id );
UNREFERENCED_PARAMETER(notify); UNREFERENCED_PARAMETER( notify );
} }
std::string AudioManagerDummy::getPlaybackDevName() std::string AudioManagerDummy::getPlaybackDevName()
@@ -30,11 +30,11 @@ std::string AudioManagerDummy::getPlaybackDevId()
return "dummy"; return "dummy";
} }
void AudioManagerDummy::setMirrorDevice(const std::string &id, bool notify) void AudioManagerDummy::setMirrorDevice( const std::string& id, bool notify )
{ {
// noop // noop
UNREFERENCED_PARAMETER(id); UNREFERENCED_PARAMETER( id );
UNREFERENCED_PARAMETER(notify); UNREFERENCED_PARAMETER( notify );
} }
bool AudioManagerDummy::isMirrorValid() bool AudioManagerDummy::isMirrorValid()
@@ -57,9 +57,9 @@ float AudioManagerDummy::getMirrorVolume()
return 0; return 0;
} }
bool AudioManagerDummy::setMirrorVolume(float value) bool AudioManagerDummy::setMirrorVolume( float value )
{ {
UNREFERENCED_PARAMETER(value); UNREFERENCED_PARAMETER( value );
return false; return false;
} }
@@ -68,9 +68,9 @@ bool AudioManagerDummy::getMirrorMuted()
return true; return true;
} }
bool AudioManagerDummy::setMirrorMuted(bool value) bool AudioManagerDummy::setMirrorMuted( bool value )
{ {
UNREFERENCED_PARAMETER(value); UNREFERENCED_PARAMETER( value );
return false; return false;
} }
@@ -79,11 +79,11 @@ bool AudioManagerDummy::isMicValid()
return false; return false;
} }
void AudioManagerDummy::setMicDevice(const std::string &id, bool notify) void AudioManagerDummy::setMicDevice( const std::string& id, bool notify )
{ {
// noop // noop
UNREFERENCED_PARAMETER(id); UNREFERENCED_PARAMETER( id );
UNREFERENCED_PARAMETER(notify); UNREFERENCED_PARAMETER( notify );
} }
std::string AudioManagerDummy::getMicDevName() std::string AudioManagerDummy::getMicDevName()
@@ -101,9 +101,9 @@ float AudioManagerDummy::getMicVolume()
return 0; return 0;
} }
bool AudioManagerDummy::setMicVolume(float value) bool AudioManagerDummy::setMicVolume( float value )
{ {
UNREFERENCED_PARAMETER(value); UNREFERENCED_PARAMETER( value );
return false; return false;
} }
@@ -112,22 +112,22 @@ bool AudioManagerDummy::getMicMuted()
return true; return true;
} }
bool AudioManagerDummy::setMicMuted(bool value) bool AudioManagerDummy::setMicMuted( bool value )
{ {
UNREFERENCED_PARAMETER(value); UNREFERENCED_PARAMETER( value );
return false; return false;
} }
std::vector<std::pair<std::string, std::string> > AudioManagerDummy::getRecordingDevices() std::vector<std::pair<std::string, std::string>>
AudioManagerDummy::getRecordingDevices()
{ {
return {}; return {};
} }
std::vector<std::pair<std::string, std::string> > AudioManagerDummy::getPlaybackDevices() std::vector<std::pair<std::string, std::string>>
AudioManagerDummy::getPlaybackDevices()
{ {
return {}; return {};
} }
} // namespace advsettings
}
@@ -4,39 +4,43 @@
#include "../AudioManager.h" #include "../AudioManager.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class AudioManagerDummy : public AudioManager class AudioManagerDummy : public AudioManager
{ {
public: public:
virtual void init( AudioTabController* controller ) override;
virtual void init(AudioTabController* controller) override; virtual void setPlaybackDevice( const std::string& id,
bool notify = true ) override;
virtual void setPlaybackDevice(const std::string& id, bool notify = true) override;
virtual std::string getPlaybackDevName() override; virtual std::string getPlaybackDevName() override;
virtual std::string getPlaybackDevId() override; virtual std::string getPlaybackDevId() override;
virtual void setMirrorDevice(const std::string& id, bool notify = true) override; virtual void setMirrorDevice( const std::string& id,
bool notify = true ) override;
virtual bool isMirrorValid() override; virtual bool isMirrorValid() override;
virtual std::string getMirrorDevName() override; virtual std::string getMirrorDevName() override;
virtual std::string getMirrorDevId() override; virtual std::string getMirrorDevId() override;
virtual float getMirrorVolume() override; virtual float getMirrorVolume() override;
virtual bool setMirrorVolume(float value) override; virtual bool setMirrorVolume( float value ) override;
virtual bool getMirrorMuted() override; virtual bool getMirrorMuted() override;
virtual bool setMirrorMuted(bool value) override; virtual bool setMirrorMuted( bool value ) override;
virtual bool isMicValid() override; virtual bool isMicValid() override;
virtual void setMicDevice(const std::string& id, bool notify = true) override; virtual void setMicDevice( const std::string& id,
bool notify = true ) override;
virtual std::string getMicDevName() override; virtual std::string getMicDevName() override;
virtual std::string getMicDevId() override; virtual std::string getMicDevId() override;
virtual float getMicVolume() override; virtual float getMicVolume() override;
virtual bool setMicVolume(float value) override; virtual bool setMicVolume( float value ) override;
virtual bool getMicMuted() override; virtual bool getMicMuted() override;
virtual bool setMicMuted(bool value) override; virtual bool setMicMuted( bool value ) override;
virtual std::vector<std::pair<std::string, std::string>> getRecordingDevices() override; virtual std::vector<std::pair<std::string, std::string>>
virtual std::vector<std::pair<std::string, std::string>> getPlaybackDevices() override; getRecordingDevices() override;
virtual std::vector<std::pair<std::string, std::string>>
getPlaybackDevices() override;
}; };
} } // namespace advsettings
#endif // AUDIOMANAGERLINUX_H #endif // AUDIOMANAGERLINUX_H
File diff suppressed because it is too large Load Diff
@@ -8,77 +8,91 @@
#include "IPolicyConfig.h" #include "IPolicyConfig.h"
#include <mutex> #include <mutex>
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class AudioManagerWindows : public AudioManager, IMMNotificationClient
{
friend class AudioNotificationClient;
class AudioManagerWindows : public AudioManager, IMMNotificationClient {
friend class AudioNotificationClient;
private: private:
std::recursive_mutex _mutex; std::recursive_mutex _mutex;
AudioTabController* controller = nullptr; AudioTabController* controller = nullptr;
IMMDeviceEnumerator* audioDeviceEnumerator = nullptr; IMMDeviceEnumerator* audioDeviceEnumerator = nullptr;
IMMDevice* playbackAudioDevice = nullptr; IMMDevice* playbackAudioDevice = nullptr;
IMMDevice* mirrorAudioDevice = nullptr; IMMDevice* mirrorAudioDevice = nullptr;
IAudioEndpointVolume* mirrorAudioEndpointVolume = nullptr; IAudioEndpointVolume* mirrorAudioEndpointVolume = nullptr;
IMMDevice* micAudioDevice = nullptr; IMMDevice* micAudioDevice = nullptr;
IAudioEndpointVolume* micAudioEndpointVolume = nullptr; IAudioEndpointVolume* micAudioEndpointVolume = nullptr;
IPolicyConfig* policyConfig = nullptr; IPolicyConfig* policyConfig = nullptr;
public: public:
~AudioManagerWindows() override; ~AudioManagerWindows() override;
virtual void init(AudioTabController* controller) override; virtual void init( AudioTabController* controller ) override;
virtual void setPlaybackDevice(const std::string& id, bool notify = true) override; virtual void setPlaybackDevice( const std::string& id,
virtual std::string getPlaybackDevName() override; bool notify = true ) override;
virtual std::string getPlaybackDevId() override; virtual std::string getPlaybackDevName() override;
virtual std::string getPlaybackDevId() override;
virtual void setMirrorDevice(const std::string& id, bool notify = true) override; virtual void setMirrorDevice( const std::string& id,
virtual bool isMirrorValid() override; bool notify = true ) override;
virtual std::string getMirrorDevName() override; virtual bool isMirrorValid() override;
virtual std::string getMirrorDevId() override; virtual std::string getMirrorDevName() override;
virtual float getMirrorVolume() override; virtual std::string getMirrorDevId() override;
virtual bool setMirrorVolume(float value) override; virtual float getMirrorVolume() override;
virtual bool getMirrorMuted() override; virtual bool setMirrorVolume( float value ) override;
virtual bool setMirrorMuted(bool value) override; virtual bool getMirrorMuted() override;
virtual bool setMirrorMuted( bool value ) override;
virtual bool isMicValid() override; virtual bool isMicValid() override;
virtual void setMicDevice(const std::string& id, bool notify = true) override; virtual void setMicDevice( const std::string& id,
virtual std::string getMicDevName() override; bool notify = true ) override;
virtual std::string getMicDevId() override; virtual std::string getMicDevName() override;
virtual float getMicVolume() override; virtual std::string getMicDevId() override;
virtual bool setMicVolume(float value) override; virtual float getMicVolume() override;
virtual bool getMicMuted() override; virtual bool setMicVolume( float value ) override;
virtual bool setMicMuted(bool value) override; virtual bool getMicMuted() override;
virtual bool setMicMuted( bool value ) override;
virtual std::vector<std::pair<std::string, std::string>> getRecordingDevices() override; virtual std::vector<std::pair<std::string, std::string>>
virtual std::vector<std::pair<std::string, std::string>> getPlaybackDevices() override; getRecordingDevices() override;
virtual std::vector<std::pair<std::string, std::string>>
getPlaybackDevices() override;
void deleteMirrorDevice(); void deleteMirrorDevice();
// from IMMNotificationClient // from IMMNotificationClient
virtual HRESULT QueryInterface(REFIID riid, void ** ppvObject) override; virtual HRESULT QueryInterface( REFIID riid, void** ppvObject ) override;
virtual ULONG AddRef(void) override; virtual ULONG AddRef( void ) override;
virtual ULONG Release(void) override; virtual ULONG Release( void ) override;
virtual HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override; virtual HRESULT OnDeviceStateChanged( LPCWSTR pwstrDeviceId,
virtual HRESULT OnDeviceAdded(LPCWSTR pwstrDeviceId) override; DWORD dwNewState ) override;
virtual HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId) override; virtual HRESULT OnDeviceAdded( LPCWSTR pwstrDeviceId ) override;
virtual HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) override; virtual HRESULT OnDeviceRemoved( LPCWSTR pwstrDeviceId ) override;
virtual HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override; virtual HRESULT
OnDefaultDeviceChanged( EDataFlow flow,
ERole role,
LPCWSTR pwstrDefaultDeviceId ) override;
virtual HRESULT OnPropertyValueChanged( LPCWSTR pwstrDeviceId,
const PROPERTYKEY key ) override;
private: private:
IMMDeviceEnumerator* getAudioDeviceEnumerator(); IMMDeviceEnumerator* getAudioDeviceEnumerator();
IPolicyConfig* getPolicyConfig(); IPolicyConfig* getPolicyConfig();
IMMDevice* getDefaultRecordingDevice(IMMDeviceEnumerator* deviceEnumerator); IMMDevice*
IMMDevice* getDefaultPlaybackDevice(IMMDeviceEnumerator* deviceEnumerator); getDefaultRecordingDevice( IMMDeviceEnumerator* deviceEnumerator );
IMMDevice* getDevice(IMMDeviceEnumerator* deviceEnumerator, const std::string& id); IMMDevice*
IMMDevice* getDevice(IMMDeviceEnumerator* deviceEnumerator, LPCWSTR id); getDefaultPlaybackDevice( IMMDeviceEnumerator* deviceEnumerator );
IAudioEndpointVolume* getAudioEndpointVolume(IMMDevice* device); IMMDevice* getDevice( IMMDeviceEnumerator* deviceEnumerator,
std::string getDeviceName(IMMDevice* device); const std::string& id );
std::string getDeviceId(IMMDevice* device); IMMDevice* getDevice( IMMDeviceEnumerator* deviceEnumerator, LPCWSTR id );
std::vector<std::pair<std::string, std::string>> getDevices(IMMDeviceEnumerator* deviceEnumerator, EDataFlow dataFlow); IAudioEndpointVolume* getAudioEndpointVolume( IMMDevice* device );
std::string getDeviceName( IMMDevice* device );
std::string getDeviceId( IMMDevice* device );
std::vector<std::pair<std::string, std::string>>
getDevices( IMMDeviceEnumerator* deviceEnumerator, EDataFlow dataFlow );
}; };
} } // namespace advsettings
+49 -93
View File
@@ -5,96 +5,72 @@
// @author EreTIk // @author EreTIk
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#pragma once #pragma once
// ca286fc3-91fd-42c3-8e9b-caafa66242e3 // ca286fc3-91fd-42c3-8e9b-caafa66242e3
static const GUID IID_IPolicyConfig2 = { 0xCA286FC3, 0x91FD, 0x42C3, { 0x8E, 0x9B, 0xCA, 0xAF, 0xA6, 0x62, 0x42, 0xE3 } }; static const GUID IID_IPolicyConfig2
= { 0xCA286FC3,
0x91FD,
0x42C3,
{ 0x8E, 0x9B, 0xCA, 0xAF, 0xA6, 0x62, 0x42, 0xE3 } };
// 6be54be8-a068-4875-a49d-0c2966473b11 // 6be54be8-a068-4875-a49d-0c2966473b11
static const GUID IID_IPolicyConfig1 = { 0x6BE54BE8, 0xA068, 0x4875, { 0xA4, 0x9D, 0x0C, 0x29, 0x66, 0x47, 0x3B, 0x11 } }; static const GUID IID_IPolicyConfig1
= { 0x6BE54BE8,
0xA068,
0x4875,
{ 0xA4, 0x9D, 0x0C, 0x29, 0x66, 0x47, 0x3B, 0x11 } };
// f8679f50-850a-41cf-9c72-430f290290c8 // f8679f50-850a-41cf-9c72-430f290290c8
static const GUID IID_IPolicyConfig0 = { 0xF8679F50, 0x850A, 0x41CF, { 0x9C, 0x72, 0x43, 0x0F, 0x29, 0x02, 0x90, 0xC8 } }; static const GUID IID_IPolicyConfig0
= { 0xF8679F50,
0x850A,
0x41CF,
{ 0x9C, 0x72, 0x43, 0x0F, 0x29, 0x02, 0x90, 0xC8 } };
class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient; class DECLSPEC_UUID( "870af99c-171d-4f9e-af0d-e63df40c2bc9" )
CPolicyConfigClient;
interface IPolicyConfig : public IUnknown interface IPolicyConfig : public IUnknown
{ {
public: public:
virtual HRESULT GetMixFormat( PCWSTR, WAVEFORMATEX** );
virtual HRESULT GetMixFormat(
PCWSTR,
WAVEFORMATEX **
);
virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat(
PCWSTR, PCWSTR, INT, WAVEFORMATEX** );
INT,
WAVEFORMATEX **
);
virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( PCWSTR );
PCWSTR
);
virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat(
PCWSTR, PCWSTR, WAVEFORMATEX*, WAVEFORMATEX* );
WAVEFORMATEX *,
WAVEFORMATEX *
);
virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod(
PCWSTR, PCWSTR, INT, PINT64, PINT64 );
INT,
PINT64,
PINT64
);
virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( PCWSTR, PINT64 );
PCWSTR,
PINT64
);
virtual HRESULT STDMETHODCALLTYPE GetShareMode( virtual HRESULT STDMETHODCALLTYPE GetShareMode( PCWSTR,
PCWSTR, struct DeviceShareMode* );
struct DeviceShareMode *
);
virtual HRESULT STDMETHODCALLTYPE SetShareMode( virtual HRESULT STDMETHODCALLTYPE SetShareMode( PCWSTR,
PCWSTR, struct DeviceShareMode* );
struct DeviceShareMode *
);
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
PCWSTR, PCWSTR, int, const PROPERTYKEY&, const PROPVARIANT* );
int,
const PROPERTYKEY &,
const PROPVARIANT *
);
virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( virtual HRESULT STDMETHODCALLTYPE SetPropertyValue(
PCWSTR, PCWSTR, int, const PROPERTYKEY&, const PROPVARIANT* );
int,
const PROPERTYKEY &,
const PROPVARIANT *
);
virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint(
__in PCWSTR wszDeviceId, __in PCWSTR wszDeviceId, __in ERole eRole );
__in ERole eRole
);
virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( PCWSTR, INT );
PCWSTR,
INT
);
}; };
interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") interface DECLSPEC_UUID( "568b9108-44bf-40b4-9006-86afe5b5a620" )
IPolicyConfigVista; IPolicyConfigVista;
class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") class DECLSPEC_UUID( "294935CE-F637-4E7C-A41B-AB255460B862" )
CPolicyConfigVistaClient; CPolicyConfigVistaClient;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// class CPolicyConfigVistaClient // class CPolicyConfigVistaClient
// {294935CE-F637-4E7C-A41B-AB255460B862} // {294935CE-F637-4E7C-A41B-AB255460B862}
@@ -111,67 +87,47 @@ CPolicyConfigVistaClient;
interface IPolicyConfigVista : public IUnknown interface IPolicyConfigVista : public IUnknown
{ {
public: public:
virtual HRESULT GetMixFormat( virtual HRESULT GetMixFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX ** WAVEFORMATEX** ); // not available on Windows 7, use method from
); // not available on Windows 7, use method from IPolicyConfig // IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat(
PCWSTR, PCWSTR, INT, WAVEFORMATEX** );
INT,
WAVEFORMATEX **
);
virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat(
PCWSTR, PCWSTR, WAVEFORMATEX*, WAVEFORMATEX* );
WAVEFORMATEX *,
WAVEFORMATEX *
);
virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod(
PCWSTR, PCWSTR,
INT, INT,
PINT64, PINT64,
PINT64 PINT64 ); // not available on Windows 7, use method from IPolicyConfig
); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod(
PCWSTR, PCWSTR,
PINT64 PINT64 ); // not available on Windows 7, use method from IPolicyConfig
); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetShareMode( virtual HRESULT STDMETHODCALLTYPE GetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode * struct DeviceShareMode* ); // not available on Windows 7, use method
); // not available on Windows 7, use method from IPolicyConfig // from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE SetShareMode( virtual HRESULT STDMETHODCALLTYPE SetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode * struct DeviceShareMode* ); // not available on Windows 7, use method
); // not available on Windows 7, use method from IPolicyConfig // from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
PCWSTR, PCWSTR, int, const PROPERTYKEY&, const PROPVARIANT* );
int,
const PROPERTYKEY &,
const PROPVARIANT *
);
virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( virtual HRESULT STDMETHODCALLTYPE SetPropertyValue(
PCWSTR, PCWSTR, int, const PROPERTYKEY&, const PROPVARIANT* );
int,
const PROPERTYKEY &,
const PROPVARIANT *
);
virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint(
__in PCWSTR wszDeviceId, __in PCWSTR wszDeviceId, __in ERole eRole );
__in ERole eRole
);
virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility(
PCWSTR, PCWSTR,
INT INT ); // not available on Windows 7, use method from IPolicyConfig
); // not available on Windows 7, use method from IPolicyConfig
}; };
@@ -1,15 +1,15 @@
#include "KeyboardInputDummy.h" #include "KeyboardInputDummy.h"
// Used to get the compiler to shut up about C4100: unreferenced formal parameter. // Used to get the compiler to shut up about C4100: unreferenced formal
// The cast is to get GCC to shut up about it. // parameter. The cast is to get GCC to shut up about it.
#define UNREFERENCED_PARAMETER(P) static_cast<void>((P)) #define UNREFERENCED_PARAMETER( P ) static_cast<void>( ( P ) )
namespace advsettings { namespace advsettings
{
void KeyboardInputDummy::sendKeyboardInput(QString input) void KeyboardInputDummy::sendKeyboardInput( QString input )
{ {
// noop // noop
UNREFERENCED_PARAMETER(input); UNREFERENCED_PARAMETER( input );
} }
void KeyboardInputDummy::sendKeyboardEnter() void KeyboardInputDummy::sendKeyboardEnter()
@@ -17,10 +17,10 @@ void KeyboardInputDummy::sendKeyboardEnter()
// noop // noop
} }
void KeyboardInputDummy::sendKeyboardBackspace(int count) void KeyboardInputDummy::sendKeyboardBackspace( int count )
{ {
// noop // noop
UNREFERENCED_PARAMETER(count); UNREFERENCED_PARAMETER( count );
} }
void KeyboardInputDummy::sendKeyboardAltTab() void KeyboardInputDummy::sendKeyboardAltTab()
@@ -28,4 +28,4 @@ void KeyboardInputDummy::sendKeyboardAltTab()
// noop // noop
} }
} } // namespace advsettings
@@ -4,17 +4,17 @@
#include "../KeyboardInput.h" #include "../KeyboardInput.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class KeyboardInputDummy : public KeyboardInput class KeyboardInputDummy : public KeyboardInput
{ {
public: public:
virtual void sendKeyboardInput(QString input) override; virtual void sendKeyboardInput( QString input ) override;
virtual void sendKeyboardEnter() override; virtual void sendKeyboardEnter() override;
virtual void sendKeyboardBackspace(int count) override; virtual void sendKeyboardBackspace( int count ) override;
virtual void sendKeyboardAltTab() override; virtual void sendKeyboardAltTab() override;
}; };
} } // namespace advsettings
#endif // KEYBOARDINPUTDUMMY_H #endif // KEYBOARDINPUTDUMMY_H
@@ -2,14 +2,18 @@
#include <Windows.h> #include <Windows.h>
#include "../../logging.h" #include "../../logging.h"
namespace advsettings { namespace advsettings
{
void fillKiStruct(INPUT& ip, WORD scanCode, bool keyup) { void fillKiStruct( INPUT& ip, WORD scanCode, bool keyup )
{
ip.type = INPUT_KEYBOARD; ip.type = INPUT_KEYBOARD;
ip.ki.wVk = scanCode; ip.ki.wVk = scanCode;
if (keyup) { if ( keyup )
{
ip.ki.dwFlags = KEYEVENTF_KEYUP; ip.ki.dwFlags = KEYEVENTF_KEYUP;
} else { }
else
{
ip.ki.dwFlags = 0; ip.ki.dwFlags = 0;
} }
ip.ki.wScan = 0; ip.ki.wScan = 0;
@@ -17,78 +21,103 @@ void fillKiStruct(INPUT& ip, WORD scanCode, bool keyup) {
ip.ki.time = 0; ip.ki.time = 0;
}; };
void sendKeyboardInputRaw(int inputCount, LPINPUT input) { void sendKeyboardInputRaw( int inputCount, LPINPUT input )
if ((inputCount > 0) && !SendInput(static_cast<UINT>(inputCount), input, sizeof(INPUT))) { {
char *err; if ( ( inputCount > 0 )
&& !SendInput(
static_cast<UINT>( inputCount ), input, sizeof( INPUT ) ) )
{
char* err;
auto errCode = GetLastError(); auto errCode = GetLastError();
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, if ( !FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
nullptr, | FORMAT_MESSAGE_FROM_SYSTEM,
errCode, nullptr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language errCode,
reinterpret_cast<LPTSTR>(&err), MAKELANGID( LANG_NEUTRAL,
0, SUBLANG_DEFAULT ), // default language
nullptr)){ reinterpret_cast<LPTSTR>( &err ),
LOG(ERROR) << "Error calling SendInput(): Could not get error message (" << errCode << ")"; 0,
} else { nullptr ) )
LOG(ERROR) << "Error calling SendInput(): " << err; {
LOG( ERROR )
<< "Error calling SendInput(): Could not get error message ("
<< errCode << ")";
}
else
{
LOG( ERROR ) << "Error calling SendInput(): " << err;
} }
} }
} }
void KeyboardInputWindows::sendKeyboardInput(QString input) void KeyboardInputWindows::sendKeyboardInput( QString input )
{ {
int len = input.length(); int len = input.length();
if (len > 0) { if ( len > 0 )
LPINPUT ips = new INPUT[static_cast<unsigned int>(len) * 5 + 3]; {
LPINPUT ips = new INPUT[static_cast<unsigned int>( len ) * 5 + 3];
int ii = 0; int ii = 0;
bool shiftPressed = false; bool shiftPressed = false;
bool ctrlPressed = false; bool ctrlPressed = false;
bool altPressed = false; bool altPressed = false;
for (int i = 0; i < len; i++) { for ( int i = 0; i < len; i++ )
short tmp = VkKeyScan(input.at(i).toLatin1()); {
short tmp = VkKeyScan( input.at( i ).toLatin1() );
WORD c = tmp & 0xFF; WORD c = tmp & 0xFF;
short shiftState = tmp >> 8; short shiftState = tmp >> 8;
bool isShift = shiftState & 1; bool isShift = shiftState & 1;
bool isCtrl = shiftState & 2; bool isCtrl = shiftState & 2;
bool isAlt = shiftState & 4; bool isAlt = shiftState & 4;
if (isShift && !shiftPressed) { if ( isShift && !shiftPressed )
fillKiStruct(ips[ii++], VK_SHIFT, false); {
fillKiStruct( ips[ii++], VK_SHIFT, false );
shiftPressed = true; shiftPressed = true;
} else if (!isShift && shiftPressed) { }
fillKiStruct(ips[ii++], VK_SHIFT, true); else if ( !isShift && shiftPressed )
{
fillKiStruct( ips[ii++], VK_SHIFT, true );
shiftPressed = false; shiftPressed = false;
} }
if (isCtrl && !ctrlPressed) { if ( isCtrl && !ctrlPressed )
fillKiStruct(ips[ii++], VK_CONTROL, false); {
fillKiStruct( ips[ii++], VK_CONTROL, false );
ctrlPressed = true; ctrlPressed = true;
} else if (!isCtrl && ctrlPressed) { }
fillKiStruct(ips[ii++], VK_CONTROL, true); else if ( !isCtrl && ctrlPressed )
{
fillKiStruct( ips[ii++], VK_CONTROL, true );
ctrlPressed = false; ctrlPressed = false;
} }
if (isAlt && !altPressed) { if ( isAlt && !altPressed )
fillKiStruct(ips[ii++], VK_MENU, false); {
fillKiStruct( ips[ii++], VK_MENU, false );
altPressed = true; altPressed = true;
} else if (!isAlt && altPressed) { }
fillKiStruct(ips[ii++], VK_MENU, true); else if ( !isAlt && altPressed )
{
fillKiStruct( ips[ii++], VK_MENU, true );
altPressed = false; altPressed = false;
} }
fillKiStruct(ips[ii++], c, false); fillKiStruct( ips[ii++], c, false );
fillKiStruct(ips[ii++], c, true); fillKiStruct( ips[ii++], c, true );
} }
if (shiftPressed) { if ( shiftPressed )
fillKiStruct(ips[ii++], VK_SHIFT, true); {
fillKiStruct( ips[ii++], VK_SHIFT, true );
shiftPressed = false; shiftPressed = false;
} }
if (ctrlPressed) { if ( ctrlPressed )
fillKiStruct(ips[ii++], VK_CONTROL, true); {
fillKiStruct( ips[ii++], VK_CONTROL, true );
ctrlPressed = false; ctrlPressed = false;
} }
if (altPressed) { if ( altPressed )
fillKiStruct(ips[ii++], VK_MENU, true); {
fillKiStruct( ips[ii++], VK_MENU, true );
altPressed = false; altPressed = false;
} }
sendKeyboardInputRaw(ii, ips); sendKeyboardInputRaw( ii, ips );
delete[] ips; delete[] ips;
} }
} }
@@ -96,24 +125,26 @@ void KeyboardInputWindows::sendKeyboardInput(QString input)
void KeyboardInputWindows::sendKeyboardEnter() void KeyboardInputWindows::sendKeyboardEnter()
{ {
LPINPUT ips = new INPUT[2]; LPINPUT ips = new INPUT[2];
fillKiStruct(ips[0], VK_RETURN, false); fillKiStruct( ips[0], VK_RETURN, false );
fillKiStruct(ips[1], VK_RETURN, true); fillKiStruct( ips[1], VK_RETURN, true );
sendKeyboardInputRaw(2, ips); sendKeyboardInputRaw( 2, ips );
delete[] ips; delete[] ips;
} }
void KeyboardInputWindows::sendKeyboardBackspace(int count) void KeyboardInputWindows::sendKeyboardBackspace( int count )
{ {
if (count > 0) { if ( count > 0 )
{
// We ensure that count is nonnegative, therefore safe cast. // We ensure that count is nonnegative, therefore safe cast.
LPINPUT ips = new INPUT[static_cast<unsigned int>(count) * 2]; LPINPUT ips = new INPUT[static_cast<unsigned int>( count ) * 2];
for (int i = 0; i < count; i++) { for ( int i = 0; i < count; i++ )
fillKiStruct(ips[2 * i], VK_BACK, false); {
fillKiStruct(ips[2 * i + 1], VK_BACK, true); fillKiStruct( ips[2 * i], VK_BACK, false );
fillKiStruct( ips[2 * i + 1], VK_BACK, true );
} }
sendKeyboardInputRaw(count * 2, ips); sendKeyboardInputRaw( count * 2, ips );
delete[] ips; delete[] ips;
} }
} }
@@ -122,13 +153,13 @@ void KeyboardInputWindows::sendKeyboardAltTab()
{ {
LPINPUT ips = new INPUT[4]; LPINPUT ips = new INPUT[4];
// VK_MENU is alt // VK_MENU is alt
fillKiStruct(ips[0], VK_MENU, false); fillKiStruct( ips[0], VK_MENU, false );
fillKiStruct(ips[1], VK_TAB, false); fillKiStruct( ips[1], VK_TAB, false );
fillKiStruct(ips[2], VK_TAB, true); fillKiStruct( ips[2], VK_TAB, true );
fillKiStruct(ips[3], VK_MENU, true); fillKiStruct( ips[3], VK_MENU, true );
sendKeyboardInputRaw(4, ips); sendKeyboardInputRaw( 4, ips );
delete[] ips; delete[] ips;
} }
} } // namespace advsettings
@@ -4,17 +4,17 @@
#include "../KeyboardInput.h" #include "../KeyboardInput.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings
{
class KeyboardInputWindows : public KeyboardInput class KeyboardInputWindows : public KeyboardInput
{ {
public: public:
virtual void sendKeyboardInput(QString input) override; virtual void sendKeyboardInput( QString input ) override;
virtual void sendKeyboardEnter() override; virtual void sendKeyboardEnter() override;
virtual void sendKeyboardBackspace(int count) override; virtual void sendKeyboardBackspace( int count ) override;
virtual void sendKeyboardAltTab() override; virtual void sendKeyboardAltTab() override;
}; };
} } // namespace advsettings
#endif // KEYBOARDINPUTWINDOWS_H #endif // KEYBOARDINPUTWINDOWS_H
+93 -72
View File
@@ -2,80 +2,101 @@
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
namespace utils { namespace utils
{
float ChaperoneUtils::_getDistanceToChaperone(
float ChaperoneUtils::_getDistanceToChaperone(const vr::HmdVector3_t & x, vr::HmdVector3_t * projectedPoint) { const vr::HmdVector3_t& x,
float distance = NAN; vr::HmdVector3_t* projectedPoint )
vr::HmdVector3_t* _cornersPtr = _corners.get(); {
for (uint32_t i = 0; i < _quadsCount; i++) { float distance = NAN;
uint32_t i2 = (i + 1) % _quadsCount; vr::HmdVector3_t* _cornersPtr = _corners.get();
vr::HmdVector3_t& r0 = _cornersPtr[i]; for ( uint32_t i = 0; i < _quadsCount; i++ )
vr::HmdVector3_t& r1 = _cornersPtr[i2]; {
float u_x = r1.v[0] - r0.v[0]; uint32_t i2 = ( i + 1 ) % _quadsCount;
float u_z = r1.v[2] - r0.v[2]; vr::HmdVector3_t& r0 = _cornersPtr[i];
float r = ((x.v[0] - r0.v[0]) * u_x + (x.v[2] - r0.v[2]) * u_z) / (u_x*u_x + u_z*u_z); vr::HmdVector3_t& r1 = _cornersPtr[i2];
//int mode = 0; // 0 .. projected point on segment, 1 .. projected point outside of segment (r0 closer than r1), 2 .. projected point outside of segment (r1 closer than r0) float u_x = r1.v[0] - r0.v[0];
float d; float u_z = r1.v[2] - r0.v[2];
float x1_x; float r = ( ( x.v[0] - r0.v[0] ) * u_x + ( x.v[2] - r0.v[2] ) * u_z )
float x1_z; / ( u_x * u_x + u_z * u_z );
if (r < 0.0f || r > 1.0f) { // projected point outside of segment // int mode = 0; // 0 .. projected point on segment, 1 .. projected
float d_x = r0.v[0] - x.v[0]; // point outside of segment (r0 closer than r1), 2 .. projected point
float d_z = r0.v[2] - x.v[2]; // outside of segment (r1 closer than r0)
float d1 = sqrt(d_x*d_x + d_z*d_z); float d;
d_x = r1.v[0] - x.v[0]; float x1_x;
d_z = r1.v[2] - x.v[2]; float x1_z;
float d2 = sqrt(d_x*d_x + d_z*d_z); if ( r < 0.0f || r > 1.0f )
if (d1 < d2) { { // projected point outside of segment
d = d1; float d_x = r0.v[0] - x.v[0];
x1_x = r0.v[0]; float d_z = r0.v[2] - x.v[2];
x1_z = r0.v[2]; float d1 = sqrt( d_x * d_x + d_z * d_z );
} else { d_x = r1.v[0] - x.v[0];
d = d2; d_z = r1.v[2] - x.v[2];
x1_x = r1.v[0]; float d2 = sqrt( d_x * d_x + d_z * d_z );
x1_z = r1.v[2]; if ( d1 < d2 )
} {
} else { // projected point on segment d = d1;
x1_x = r0.v[0] + r * u_x; x1_x = r0.v[0];
x1_z = r0.v[2] + r * u_z; x1_z = r0.v[2];
float d_x = x1_x - x.v[0]; }
float d_z = x1_z - x.v[2]; else
d = sqrt(d_x*d_x + d_z*d_z); {
} d = d2;
if (std::isnan(distance) || d < distance) { x1_x = r1.v[0];
distance = d; x1_z = r1.v[2];
if (projectedPoint) { }
projectedPoint->v[0] = x1_x; }
projectedPoint->v[1] = x.v[1]; else
projectedPoint->v[2] = x1_z; { // projected point on segment
} x1_x = r0.v[0] + r * u_x;
} x1_z = r0.v[2] + r * u_z;
} float d_x = x1_x - x.v[0];
return distance; float d_z = x1_z - x.v[2];
d = sqrt( d_x * d_x + d_z * d_z );
}
if ( std::isnan( distance ) || d < distance )
{
distance = d;
if ( projectedPoint )
{
projectedPoint->v[0] = x1_x;
projectedPoint->v[1] = x.v[1];
projectedPoint->v[2] = x1_z;
}
}
}
return distance;
} }
void ChaperoneUtils::loadChaperoneData()
void ChaperoneUtils::loadChaperoneData() { {
std::lock_guard<std::recursive_mutex> lock(_mutex); std::lock_guard<std::recursive_mutex> lock( _mutex );
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &_quadsCount); vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( nullptr, &_quadsCount );
if (_quadsCount > 0) { if ( _quadsCount > 0 )
std::unique_ptr<vr::HmdQuad_t> quadsBuffer(new vr::HmdQuad_t[_quadsCount]); {
vr::HmdQuad_t* quadsBufferPtr = quadsBuffer.get(); std::unique_ptr<vr::HmdQuad_t> quadsBuffer(
_corners.reset((vr::HmdVector3_t*)new vr::HmdQuad_t[_quadsCount]); new vr::HmdQuad_t[_quadsCount] );
vr::HmdVector3_t* _cornersPtr = _corners.get(); vr::HmdQuad_t* quadsBufferPtr = quadsBuffer.get();
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(quadsBufferPtr, &_quadsCount); _corners.reset( ( vr::HmdVector3_t* ) new vr::HmdQuad_t[_quadsCount] );
for (uint32_t i = 0; i < _quadsCount; i++) { vr::HmdVector3_t* _cornersPtr = _corners.get();
_cornersPtr[i] = quadsBufferPtr[i].vCorners[0]; vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( quadsBufferPtr,
uint32_t i2 = (i + 1) % _quadsCount; &_quadsCount );
if (quadsBufferPtr[i].vCorners[3].v[0] != quadsBufferPtr[i2].vCorners[0].v[0] for ( uint32_t i = 0; i < _quadsCount; i++ )
|| quadsBufferPtr[i].vCorners[3].v[1] != quadsBufferPtr[i2].vCorners[0].v[1] {
|| quadsBufferPtr[i].vCorners[3].v[2] != quadsBufferPtr[i2].vCorners[0].v[2] _cornersPtr[i] = quadsBufferPtr[i].vCorners[0];
|| quadsBufferPtr[i].vCorners[0].v[1] != 0.0f) { uint32_t i2 = ( i + 1 ) % _quadsCount;
_chaperoneWellFormed = false; if ( quadsBufferPtr[i].vCorners[3].v[0]
} != quadsBufferPtr[i2].vCorners[0].v[0]
} || quadsBufferPtr[i].vCorners[3].v[1]
} != quadsBufferPtr[i2].vCorners[0].v[1]
|| quadsBufferPtr[i].vCorners[3].v[2]
!= quadsBufferPtr[i2].vCorners[0].v[2]
|| quadsBufferPtr[i].vCorners[0].v[1] != 0.0f )
{
_chaperoneWellFormed = false;
}
}
}
} }
} // end namespace utils } // end namespace utils
+37 -22
View File
@@ -4,35 +4,50 @@
#include <mutex> #include <mutex>
#include <openvr.h> #include <openvr.h>
namespace utils { namespace utils
{
class ChaperoneUtils { class ChaperoneUtils
{
private: private:
std::recursive_mutex _mutex; std::recursive_mutex _mutex;
uint32_t _quadsCount = 0; uint32_t _quadsCount = 0;
std::unique_ptr<vr::HmdVector3_t> _corners; std::unique_ptr<vr::HmdVector3_t> _corners;
bool _chaperoneWellFormed = true; bool _chaperoneWellFormed = true;
float _getDistanceToChaperone(const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint); float _getDistanceToChaperone( const vr::HmdVector3_t& point,
vr::HmdVector3_t* projectedPoint );
public: public:
uint32_t quadsCount() const noexcept { return _quadsCount; } uint32_t quadsCount() const noexcept
bool isChaperoneWellFormed() const noexcept { return _chaperoneWellFormed; } {
return _quadsCount;
}
bool isChaperoneWellFormed() const noexcept
{
return _chaperoneWellFormed;
}
std::recursive_mutex& mutex() noexcept { return _mutex; } std::recursive_mutex& mutex() noexcept
{
return _mutex;
}
void loadChaperoneData(); void loadChaperoneData();
float getDistanceToChaperone(const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint = nullptr, bool doLock = false) { float getDistanceToChaperone( const vr::HmdVector3_t& point,
if (doLock) { vr::HmdVector3_t* projectedPoint = nullptr,
std::lock_guard<std::recursive_mutex> lock(_mutex); bool doLock = false )
return _getDistanceToChaperone(point, projectedPoint); {
} else { if ( doLock )
return _getDistanceToChaperone(point, projectedPoint); {
} std::lock_guard<std::recursive_mutex> lock( _mutex );
} return _getDistanceToChaperone( point, projectedPoint );
}
else
{
return _getDistanceToChaperone( point, projectedPoint );
}
}
}; };
} // end namespace utils } // end namespace utils
+96 -83
View File
@@ -3,95 +3,108 @@
#include <openvr.h> #include <openvr.h>
#include <cmath> #include <cmath>
namespace utils
namespace utils { {
inline vr::HmdMatrix34_t& initRotationMatrix( vr::HmdMatrix34_t& matrix,
inline vr::HmdMatrix34_t& initRotationMatrix(vr::HmdMatrix34_t& matrix, unsigned axisId, float angle) { unsigned axisId,
switch (axisId) { float angle )
case 0: // x-axis {
matrix.m[0][0] = 1.0f; switch ( axisId )
matrix.m[0][1] = 0.0f; {
matrix.m[0][2] = 0.0f; case 0: // x-axis
matrix.m[0][3] = 0.0f; matrix.m[0][0] = 1.0f;
matrix.m[1][0] = 0.0f; matrix.m[0][1] = 0.0f;
matrix.m[1][1] = std::cos(angle); matrix.m[0][2] = 0.0f;
matrix.m[1][2] = -std::sin(angle); matrix.m[0][3] = 0.0f;
matrix.m[1][3] = 0.0f; matrix.m[1][0] = 0.0f;
matrix.m[2][0] = 0.0f; matrix.m[1][1] = std::cos( angle );
matrix.m[2][1] = std::sin(angle); matrix.m[1][2] = -std::sin( angle );
matrix.m[2][2] = std::cos(angle); matrix.m[1][3] = 0.0f;
matrix.m[2][3] = 0.0f; matrix.m[2][0] = 0.0f;
break; matrix.m[2][1] = std::sin( angle );
case 1: // y-axis matrix.m[2][2] = std::cos( angle );
matrix.m[0][0] = std::cos(angle); matrix.m[2][3] = 0.0f;
matrix.m[0][1] = 0.0f; break;
matrix.m[0][2] = std::sin(angle); case 1: // y-axis
matrix.m[0][3] = 0.0f; matrix.m[0][0] = std::cos( angle );
matrix.m[1][0] = 0.0f; matrix.m[0][1] = 0.0f;
matrix.m[1][1] = 1.0f; matrix.m[0][2] = std::sin( angle );
matrix.m[1][2] = 0.0f; matrix.m[0][3] = 0.0f;
matrix.m[1][3] = 0.0f; matrix.m[1][0] = 0.0f;
matrix.m[2][0] = -std::sin(angle); matrix.m[1][1] = 1.0f;
matrix.m[2][1] = 0.0f; matrix.m[1][2] = 0.0f;
matrix.m[2][2] = std::cos(angle); matrix.m[1][3] = 0.0f;
matrix.m[2][3] = 0.0f; matrix.m[2][0] = -std::sin( angle );
break; matrix.m[2][1] = 0.0f;
case 2: // z-axis matrix.m[2][2] = std::cos( angle );
matrix.m[0][0] = std::cos(angle); matrix.m[2][3] = 0.0f;
matrix.m[0][1] = -std::sin(angle); break;
matrix.m[0][2] = 0.0f; case 2: // z-axis
matrix.m[0][3] = 0.0f; matrix.m[0][0] = std::cos( angle );
matrix.m[1][0] = std::sin(angle); matrix.m[0][1] = -std::sin( angle );
matrix.m[1][1] = std::cos(angle); matrix.m[0][2] = 0.0f;
matrix.m[1][2] = 0.0f; matrix.m[0][3] = 0.0f;
matrix.m[1][3] = 0.0f; matrix.m[1][0] = std::sin( angle );
matrix.m[2][0] = 0.0f; matrix.m[1][1] = std::cos( angle );
matrix.m[2][1] = 0.0f; matrix.m[1][2] = 0.0f;
matrix.m[2][2] = 1.0f; matrix.m[1][3] = 0.0f;
matrix.m[2][3] = 0.0f; matrix.m[2][0] = 0.0f;
break; matrix.m[2][1] = 0.0f;
default: matrix.m[2][2] = 1.0f;
break; matrix.m[2][3] = 0.0f;
} break;
return matrix; default:
break;
}
return matrix;
} }
inline vr::HmdMatrix34_t& matMul33( vr::HmdMatrix34_t& result,
inline vr::HmdMatrix34_t& matMul33(vr::HmdMatrix34_t& result, const vr::HmdMatrix34_t& a, const vr::HmdMatrix34_t& b) { const vr::HmdMatrix34_t& a,
for (unsigned i = 0; i < 3; i++) { const vr::HmdMatrix34_t& b )
for (unsigned j = 0; j < 3; j++) { {
result.m[i][j] = 0.0f; for ( unsigned i = 0; i < 3; i++ )
for (unsigned k = 0; k < 3; k++) { {
result.m[i][j] += a.m[i][k] * b.m[k][j]; for ( unsigned j = 0; j < 3; j++ )
} {
} result.m[i][j] = 0.0f;
} for ( unsigned k = 0; k < 3; k++ )
return result; {
result.m[i][j] += a.m[i][k] * b.m[k][j];
}
}
}
return result;
} }
inline vr::HmdVector3_t& matMul33( vr::HmdVector3_t& result,
inline vr::HmdVector3_t& matMul33(vr::HmdVector3_t& result, const vr::HmdMatrix34_t& a, const vr::HmdVector3_t& b) { const vr::HmdMatrix34_t& a,
for (unsigned i = 0; i < 3; i++) { const vr::HmdVector3_t& b )
result.v[i] = 0.0f; {
for (unsigned k = 0; k < 3; k++) { for ( unsigned i = 0; i < 3; i++ )
result.v[i] += a.m[i][k] * b.v[k]; {
}; result.v[i] = 0.0f;
} for ( unsigned k = 0; k < 3; k++ )
return result; {
result.v[i] += a.m[i][k] * b.v[k];
};
}
return result;
} }
inline vr::HmdVector3_t& matMul33( vr::HmdVector3_t& result,
inline vr::HmdVector3_t& matMul33(vr::HmdVector3_t& result, const vr::HmdVector3_t& a, const vr::HmdMatrix34_t& b) { const vr::HmdVector3_t& a,
for (unsigned i = 0; i < 3; i++) { const vr::HmdMatrix34_t& b )
result.v[i] = 0.0f; {
for (unsigned k = 0; k < 3; k++) { for ( unsigned i = 0; i < 3; i++ )
result.v[i] += a.v[k] * b.m[k][i]; {
}; result.v[i] = 0.0f;
} for ( unsigned k = 0; k < 3; k++ )
return result; {
result.v[i] += a.v[k] * b.m[k][i];
};
}
return result;
} }
} // end namespace utils } // end namespace utils