diff options
author | Aaron Leiby <aaronl@valvesoftware.com> | 2022-08-18 20:39:17 +0300 |
---|---|---|
committer | Aaron Leiby <aaronl@valvesoftware.com> | 2022-08-18 20:39:17 +0300 |
commit | 758906251fd932f59f50c510d8c375aa34229887 (patch) | |
tree | 3990d5c6b840aeec3c6db39cc9f64947b89660c0 | |
parent | 4c85abcb7f7f1f02adaf3812018c99fc593bc341 (diff) |
Merging using vr_steamvr_rel_to_sdk_release
Integration via vr_steamvr_main_to_rel of:
Change 7445792 by aaronl:
[ steamvr - vrsdk ] * Adding the scripts we use to codegen C# and C bindings to the public SDK.
[git-p4: depot-paths = "//vr/steamvr/sdk_release/": change = 7445965]
-rw-r--r-- | codegen/README.md | 36 | ||||
-rwxr-xr-x | codegen/api_shared.py | 1057 | ||||
-rwxr-xr-x | codegen/openvr_capi.cpp.py | 88 | ||||
-rwxr-xr-x | codegen/openvr_capi.h.py | 290 | ||||
-rwxr-xr-x | codegen/openvr_interop.cs.py | 597 |
5 files changed, 2068 insertions, 0 deletions
diff --git a/codegen/README.md b/codegen/README.md new file mode 100644 index 0000000..a042236 --- /dev/null +++ b/codegen/README.md @@ -0,0 +1,36 @@ +Codegen +--- +The OpenVR SDK ships with metadata for its headers at [openvr_api.json](https://github.com/ValveSoftware/openvr/blob/master/headers/openvr_api.json). + +This can be used to generate bindings for other languages such as C or C#. + +We include the scripts we use to generate the existing bindings that ship as part of the SDK here. + +### Usage + +These scripts assume Python 2.7. + +We use [Artistic Style](http://astyle.sourceforge.net/) for formatting. + +#### C# bindings: + +``` +python openvr_interop.cs.py > openvr_interop.cs +astyle -T -O openvr_interop.cs +``` + +#### C bindings: + +``` +python openvr_capi.h.py > openvr_capi.h +astyle -T -O openvr_capi.h +``` + +#### C implementation: + +This file is build into openvr_api.dll and is used by both the C and C# bindings. + +``` +python openvr_capi.cpp.py > openvr_capi.cpp +astyle -T -O openvr_capi.cpp +```
\ No newline at end of file diff --git a/codegen/api_shared.py b/codegen/api_shared.py new file mode 100755 index 0000000..af064d6 --- /dev/null +++ b/codegen/api_shared.py @@ -0,0 +1,1057 @@ +import json +import sys +import operator +from functools import reduce + +structlist = {} +typedeflist = {} +enumlist = {} + +# These are not exported to the json, so we just maintain the small subset here by hand for now. +structparents = { + 'VRTextureWithPose_t' : 'Texture_t', + 'VRTextureWithDepth_t' : 'Texture_t', + 'VRTextureWithPoseAndDepth_t' : 'VRTextureWithPose_t' } + +structindices = {} + +def loadfile(filename, ns): + with open(filename) as data_file: + data = json.load(data_file) + + i = 0 + for struct in data['structs']: + if(len(struct) > 0 and len(struct['struct'])): + structname = struct['struct'] + structlist[structname] = 'struct' + structindices[getclasswithoutnamespace(structname)] = i + i += 1 + + for typedef in data['typedefs']: + if(len(typedef) > 0 and len(typedef['typedef'])): + typedeflist[typedef['typedef']] = typedef['type'] + for enum in data['enums']: + enumname = enum['enumname'] + namespace = getnamespace(enumname) + if(len(enum) > 0 and len(enum['enumname'])): + enumlist[enum['enumname'].replace('::','_')] = enum['enumname'] + return data + + +def paramshavelength(params, paramname): + checkname = paramname[1:] + for param in params: + name = param['paramname'] + name = name[3:len(name)-4] + sys.stdout.write ('// ' + name + ' ' + checkname + '\n'); + if(name == checkname): + return True + return False + +def calculateinteropmethodname(classname, methodname): + return classname.replace('vr::', 'VR::').replace('::', '_') + '_' + methodname + +def unmanagedtype(thetype): + if(thetype == 'float'): + return 'R4' + if(thetype == 'double'): + return 'R8' + if(thetype == 'char'): + return 'I1' + if(thetype == 'byte'): + return 'U1' + if(thetype == 'ulong'): + return 'U8' + if(thetype == 'uint'): + return 'U4' + if(thetype == 'CSteamID'): # Special case for CSteamID which is a complex C def but is 64-bits. + return 'U8' + return 'Struct' + +def ctype(thetype): + thetype = thetype.replace('vr::','') + if(thetype[0:6] == 'const '): + thetype = thetype[6:] + if(thetype[0:6] == 'class '): # for C replaces classes by pointers + thetype = 'intptr_t' + if(thetype == 'ulong'): + return 'unsigned long long' + if(thetype == 'uint'): + return 'unsigned long' + return thetype + +def striparraysuffix(thetype): + if(thetype[len(thetype) - 1] == ']'): + thetype = thetype[0:thetype.find('[')-1] + if(thetype == '_Bool'): + thetype = 'bool' + return thetype + +def converttype(thetype): + if(thetype[0:11] == 'struct vr::'): + thetype = thetype[11:] + if(thetype[0:17] == 'const struct vr::'): + thetype = thetype[17:] + if(thetype[0:10] == 'class vr::'): + thetype = thetype[10:] + if(thetype == 'const char *const'): + thetype = 'string' + #thetype = thetype.replace('::', '_') + thetypewithnamespace = thetype + thetype = getclasswithoutnamespace(thetype) + if(thetype[0:6] == 'const '): + thetype = thetype[6:] + if(thetype == 'class CSteamID'): + thetype = 'ulong' + if(thetype == 'uint8'): + thetype = 'byte' + if(thetype == 'uint8_t'): + thetype = 'byte' + if(thetype == 'unsigned short'): + thetype = 'ushort' + if(thetype == 'unsigned char'): + thetype = 'byte' + #if(thetype == 'unsigned int'): + # thetype = 'uint' + if(thetype == 'uint16'): + thetype = 'ushort' + if(thetype == 'uint16_t'): + thetype = 'ushort' + if(thetype == 'uint32'): + thetype = 'uint' + if(thetype == 'uint32_t'): + thetype = 'uint' + if(thetype == 'uint64'): + thetype = 'ulong' + if(thetype == 'short'): + thetype = 'short' + if(thetype == 'int32'): + thetype = 'int' + if(thetype == 'int32_t'): + thetype = 'int' + if(thetype == 'int64'): + thetype = 'long' + if(thetype == 'uint64_t'): + thetype = 'ulong' + if(thetype == '_Bool'): + thetype = 'bool' + if(thetype == 'char *'): + thetype = 'string' + if(thetype == 'char **'): + thetype = 'string' + if(thetype == 'void *'): + thetype = 'IntPtr' + if(thetype == 'byte *'): + thetype = 'IntPtr' + if(thetype == 'uint8 *'): + thetype = 'IntPtr' + if(thetype == 'T *'): + thetype = 'IntPtr' + if(thetype == 'func_t'): + thetype = 'IntPtr' + if(thetype == 'RenderModel_t *'): + thetype = 'IntPtr' + if(thetype == 'RenderModel_TextureMap_t *'): + thetype = 'IntPtr' + if(thetype == 'struct VkPhysicalDevice_T *'): + thetype = 'IntPtr' + if(thetype == 'struct VkInstance_T *'): + thetype = 'IntPtr' + if(thetype == 'SteamLeaderboard_t'): + thetype = 'ulong' + if(thetype == 'SteamLeaderboardEntries_t'): + thetype = 'ulong' + if(thetype == 'ScreenshotHandle'): + thetype = 'uint' + if(thetype == 'AudioPlayback_Status'): + thetype = 'int' + if(thetype == 'FriendsGroupID_t'): + thetype = 'char' + if(thetype == 'EOverlayToStoreFlag'): + thetype = 'char' + if(thetype == 'ESteamAPICallFailure'): + thetype = 'int' + if(thetype == 'EGamepadTextInputMode'): + thetype = 'int' + if(thetype == 'EGamepadTextInputLineMode'): + thetype = 'int' + if(thetype == 'EUniverse'): + thetype = 'int' + if(thetype == 'ISteamHTMLSurface::EHTMLMouseButton'): + thetype = 'int' + if(thetype == 'ISteamHTMLSurface::EHTMLKeyModifiers'): + thetype = 'int' + if(thetype == 'SteamInventoryResult_t'): + thetype = 'int' + if(thetype == 'RTime32'): + thetype = 'ulong' + if(thetype == 'AccountID_t'): + thetype = 'uint' + if(thetype == 'AppId_t'): + thetype = 'uint' + if(thetype == 'VRComponentProperties'): + thetype = 'uint' + if(thetype == 'SteamAPICall_t'): + thetype = 'ulong' + if(thetype == 'UGCQueryHandle_t'): + thetype = 'ulong' + if(thetype == 'UGCUpdateHandle_t'): + thetype = 'ulong' + if(thetype == 'ClientUnifiedMessageHandle'): + thetype = 'ulong' + if(thetype == 'UGCFileWriteStreamHandle_t'): + thetype = 'ulong' + if(thetype == 'PublishedFileUpdateHandle_t'): + thetype = 'ulong' + if(thetype == 'SteamAPIWarningMessageHook_t'): + thetype = 'IntPtr' + if(thetype == 'SteamAPI_PostAPIResultInProcess_t'): + thetype = 'IntPtr' + if(thetype == 'SteamAPI_CheckCallbackRegistered_t'): + thetype = 'IntPtr' + if(thetype == 'class CGameID'): + thetype = 'ulong' + if(thetype == 'PublishedFileId_t'): + thetype = 'ulong' + if(thetype == 'UGCHandle_t'): + thetype = 'ulong' + if(thetype == 'SNetListenSocket_t'): + thetype = 'uint' + if(thetype == 'SNetSocket_t'): + thetype = 'uint' + if(thetype == 'TrackedDeviceIndex_t'): + thetype = 'uint' + if(thetype == 'VROverlayHandle_t'): + thetype = 'ulong' + if(thetype == 'PropertyTypeTag_t'): + thetype = 'uint' + if(thetype == 'PropertyContainerHandle_t'): + thetype = 'ulong' + if(thetype == 'SpatialAnchorHandle_t'): + thetype = 'uint' + if(thetype == 'DriverHandle_t'): + thetype = 'ulong' + if(thetype == 'VRActionHandle_t'): + thetype = 'ulong' + if(thetype == 'VRActionSetHandle_t'): + thetype = 'ulong' + if(thetype == 'VRInputValueHandle_t'): + thetype = 'ulong' + if(thetype == 'VRInputOriginHandle_t'): + thetype = 'ulong' + if(thetype == 'PathHandle_t'): + thetype = 'ulong' + if(thetype == 'VRNotificationId'): + thetype = 'uint' + if(thetype == 'TextureID_t'): + thetype = 'int' + if(thetype == 'WebConsoleHandle_t'): + thetype = 'ulong' + + if(thetype[0:7] == 'struct '): + thetype = thetype[7:] + if(thetype[0:6] == 'class '): + thetype = thetype[6:] + if(thetype[0:6] == 'union '): + thetype = thetype[6:] + if(thetype[0] == 'H' and thetype[0:3] != "Hmd" and thetype[0:16] != "HiddenAreaMesh_t"): + thetype = 'uint' + if(thetype[0:5] == 'enum '): + thetype = thetype[5:] + if(thetype[len(thetype) - 1] == '*' and thetype[len(thetype) - 2] == '*'): + thetype = 'IntPtr' + if(thetype[len(thetype) - 1] == '*'): + if("VRControllerState_t" not in thetype): + thetype = converttype(thetypewithnamespace[:len(thetypewithnamespace)-2]) + else: + thetype = converttype(thetype[:len(thetype)-2]) +# thetype = 'IntPtr' + if(thetype[len(thetype) - 1] == '&'): + thetype = 'IntPtr' + if(thetype[len(thetype) - 1] == ']'): + thetype = thetype[0:thetype.find('[')-1] + if(thetype in typedeflist): + thetype = converttype(typedeflist[thetype]) + if(thetypewithnamespace in typedeflist): + thetype = converttype(typedeflist[thetypewithnamespace]) + return thetype + +def getnamespace(classname): + if(classname.find('::') != -1): + return classname[:classname.find('::')] + else: + return '' + +def getclasswithoutnamespace(classname): + if(classname.rfind('::') != -1): + return classname[classname.rfind('::')+2:] + else: + return classname + +def outputenums(namespace, data): + for enum in data['enums']: + if(len(enum) > 0 and len(enum['enumname'])): + ns = getnamespace(enum['enumname']) + enumname = getclasswithoutnamespace(enum['enumname']) + if(ns == namespace or (namespace == '' and ns[:1] == 'I')): + print('public enum '+enumname+'\n{') + enumNameWithoutE = enumname + if( enumname.startswith( "E" ) ): + enumNameWithoutE = enumname[1:] + for enumvalue in enum['values']: + entry = enumvalue['name'] + if(entry.startswith(enumname)): entry = entry[len(enumname):] # strip off enum name + if(entry.startswith(enumNameWithoutE)): entry = entry[len(enumNameWithoutE):] # strip off enum name + if(entry.startswith('_')): entry = entry[1:] # strip off leading underscore + print('\t'+entry+' = '+enumvalue['value']+',') + print('}') + +def outputstructfields(struct, data): + + # recursively add base class fields first + basename = getclasswithoutnamespace(struct['struct']) + if basename in structparents: + parentname = structparents[basename] + i = structindices[parentname]; + outputstructfields(data['structs'][i], data) + + for enumvalue in struct['fields']: + fieldtype = enumvalue['fieldtype'] + otype = converttype(fieldtype) + lastchar = fieldtype[len(fieldtype) - 1] + if(lastchar == ']'): + #print('\tpublic fixed '+otype+' '+enumvalue['fieldname']+ fieldtype[fieldtype.find('['):]+';') + dims = map(int, fieldtype[fieldtype.find('[')+1:-1].split('][')) + size = reduce(operator.mul, dims, 1) + utype = unmanagedtype(otype) + if(otype == 'char'): + #print('\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = '+str(size)+')]') + sys.stdout.write('public byte '+enumvalue['fieldname']+'0') + for i in range(1, size): + sys.stdout.write(',' + enumvalue['fieldname'] + str(i)) + print(';') + + + print('public string ' + enumvalue['fieldname'] + '\n{') + print('get\n{') + print('return new string(new char[] {') + for i in range(0, size-1): + print('(char)' + enumvalue['fieldname'] + str(i) + ',') + print('(char)' + enumvalue['fieldname'] + str(size-1) + '}).TrimEnd(\'\\0\');') + print('}') + print('}') + else: + #print('\t[MarshalAs(UnmanagedType.ByValArray, SizeConst = '+str(size)+', ArraySubType = UnmanagedType.'+utype+')]') + for i in range(size): + print('\tpublic '+otype+' '+enumvalue['fieldname']+str(i)+';'+(' //'+otype+fieldtype[fieldtype.find('['):] if(i==0) else '')) + else: + if(otype == 'bool'): print('\t[MarshalAs(UnmanagedType.I1)]') + if(lastchar == '*'): + print('\tpublic IntPtr '+enumvalue['fieldname']+';'+' // '+fieldtype) + else: + print('\tpublic '+otype+' '+enumvalue['fieldname']+';') + +def outputstructs(namespace, data): + for struct in data['structs']: + if(len(struct) > 0 and len(struct['struct'])): + structname = struct['struct'] + #print('//'+structname) + ns = getnamespace(structname) + basename = getclasswithoutnamespace(structname) + if(basename != '(anonymous)' and (ns == namespace or (namespace == '' and ns[:1] == 'I') or (namespace == '' and ns[:1] == 'C'))): + for key, value in typedeflist.items(): + if(converttype(value) == basename): + basename = getclasswithoutnamespace(key) + break + + print('[StructLayout(LayoutKind.Sequential)] public struct '+basename+'\n{') + outputstructfields(struct, data) + + if (basename == 'HmdMatrix34_t'): + print('#if UNITY_5_3_OR_NEWER') + print('\n\tpublic Vector3 GetPosition()') + print('\t{') + print('\t\treturn new Vector3(m3, m7, -m11);') + print('\t}') + + print('\n\tpublic bool IsRotationValid()') + print('\t{') + print('\t\treturn ((m2 != 0 || m6 != 0 || m10 != 0) && (m1 != 0 || m5 != 0 || m9 != 0));') + print('\t}') + + print('\n\tpublic Quaternion GetRotation()') + print('\t{') + print('\t\tif (IsRotationValid())') + print('\t\t{') + print('\t\t\tfloat w = Mathf.Sqrt(Mathf.Max(0, 1 + m0 + m5 + m10)) / 2;') + print('\t\t\tfloat x = Mathf.Sqrt(Mathf.Max(0, 1 + m0 - m5 - m10)) / 2;') + print('\t\t\tfloat y = Mathf.Sqrt(Mathf.Max(0, 1 - m0 + m5 - m10)) / 2;') + print('\t\t\tfloat z = Mathf.Sqrt(Mathf.Max(0, 1 - m0 - m5 + m10)) / 2;') + + print('\n\t\t\t_copysign(ref x, -m9 - -m6);') + print('\t\t\t_copysign(ref y, -m2 - -m8);') + print('\t\t\t_copysign(ref z, m4 - m1);') + + print('\n\t\t\treturn new Quaternion(x, y, z, w);') + print('\t\t}') + + print('\t\treturn Quaternion.identity;') + print('\t}') + + print('\n\tprivate static void _copysign(ref float sizeval, float signval)') + print('\t{') + print('\t\tif (signval > 0 != sizeval > 0)') + print('\t\t\tsizeval = -sizeval;') + print('\t}') + + print('#endif') + print('}') + else: + print('}') + + # The following structures were originally compiled with pack(4) on Linux & OSX by mistake. Generate + # a packed version of the structure so we can workaround this in the C# interop code + if ((basename == 'RenderModel_t') or + (basename == 'VRControllerState_t') or + (basename == 'RenderModel_TextureMap_t') or + (basename == 'VREvent_t')): + print('// This structure is for backwards binary compatibility on Linux and OSX only') + print('[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct '+basename+'_Packed\n{') + outputstructfields(struct, data) + print('\tpublic '+basename+'_Packed('+basename+' unpacked)'); + print('\t{') + for enumvalue in struct['fields']: + fieldtype = enumvalue['fieldtype'] + otype = converttype(fieldtype) + if fieldtype[-1] == ']': + dims = map(int, fieldtype[fieldtype.find('[')+1:-1].split('][')) + size = reduce(operator.mul, dims, 1) + utype = unmanagedtype(otype) + for i in range(size): + print('\t\tthis.'+enumvalue['fieldname']+str(i)+' = unpacked.'+enumvalue['fieldname']+str(i)+';') + + else: + print('\t\tthis.'+enumvalue['fieldname']+' = unpacked.'+enumvalue['fieldname']+';') + print('\t}') + + print('\tpublic void Unpack(ref '+basename+' unpacked)'); + print('\t{') + for enumvalue in struct['fields']: + fieldtype = enumvalue['fieldtype'] + otype = converttype(fieldtype) + if fieldtype[-1] == ']': + dims = map(int, fieldtype[fieldtype.find('[')+1:-1].split('][')) + size = reduce(operator.mul, dims, 1) + utype = unmanagedtype(otype) + for i in range(size): + print('\t\tunpacked.'+enumvalue['fieldname']+str(i)+' = this.'+enumvalue['fieldname']+str(i)+';') + + else: + print('\t\tunpacked.'+enumvalue['fieldname']+' = this.'+enumvalue['fieldname']+';') + print('\t}') + print('}') + + +def outputinterfaces(namespace, data): + lastclass = '' + lastmethod = '' + for method in data['methods']: + if (len(method) > 0): + returntype = converttype(method['returntype']) + if(method['returntype'][len(method['returntype']) - 1] == '*'): + # Native methods which return pointers are cast to IntPtr + returntype = 'IntPtr' + + methodname = method['methodname'] + if(methodname == lastmethod): + methodname = methodname + repr(count) + count = count + 1 + else: + count = 0 + lastmethod = method['methodname'] + + classname = method['classname'] + + if(namespace != getnamespace(classname)): + continue + + classname = getclasswithoutnamespace(classname) + if(classname != lastclass): + if(lastclass != ''): + print("\t}\n"); + + print("\t[StructLayout(LayoutKind.Sequential)]") + print("\tpublic struct " + classname + "\n\t{") + lastclass = classname + + + paramlist = [] + if('params' in method): + for param in method['params']: + paramtype = converttype(param['paramtype']) + if(param['paramtype'][len(param['paramtype']) - 1] == '*' and param['paramtype'][len(param['paramtype']) - 2] == '*'): + paramlist.append('ref ' + paramtype + ' ' + param['paramname']) + elif(param['paramtype'][len(param['paramtype']) - 1] == '*'): + if('out_array_count' in param) or ('array_call' in param) or ('array_count' in param) or ('out_array_call' in param): + paramlist.append('[In, Out] ' + paramtype + '[] ' + param['paramname']) + elif('out_string_count' in param): + paramlist.append('System.Text.StringBuilder ' + param['paramname']) + elif('out_struct' in param): + paramlist.append('ref '+ paramtype +' ' + param['paramname']) + elif('out_string' in param): + paramlist.append('System.Text.StringBuilder ' + param['paramname']) +# elif(structlist.has_key(paramtype)): +# paramlist.append(paramtype+' ' + param['paramname']) +# elif(paramtype[0:1] == 'I' and paramtype != 'IntPtr'): +# paramlist.append('IntPtr ' + param['paramname']) + elif (paramtype == 'uint' or paramtype == 'int' or paramtype == 'char' or paramtype == 'bool'): + # Output params for ints,uints,char + paramlist.append('ref ' + paramtype + ' ' + param['paramname']) + elif (paramtype == 'string' and param['paramtype'] == 'const char *'): + # Managed strings on Windows need to be converted to Utf8 native ptrs + paramlist.append('IntPtr ' + param['paramname']) + elif (paramtype == 'string' or paramtype == 'IntPtr'): + # Strings and IntPtrs are just straight + paramlist.append(paramtype + ' ' + param['paramname']) + else: +# paramlist.append('ref ' + converttype(paramtype) + ' ' + param['paramname']) + paramlist.append('ref ' + paramtype + ' ' + param['paramname']) + else: + paramlist.append(paramtype + ' ' + param['paramname']) + + print("\t\t[UnmanagedFunctionPointer(CallingConvention.StdCall)]") + print("\t\tinternal delegate "+returntype+" _"+methodname+"("+", ".join(paramlist)+");") + print("\t\t[MarshalAs(UnmanagedType.FunctionPtr)]") + print("\t\tinternal _"+methodname+" "+methodname+";\n") + print("\t}\n\n"); + + +def outputfntables(namespace, data): + lastclass = '' + lastmethod = '' + for method in data['methods']: + if (len(method) > 0): + returntype = method['returntype'] + if(returntype == 'class CSteamID'): + returntype = 'uint64' + methodname = method['methodname'] + if(methodname == lastmethod): + methodname = methodname + repr(count) + count = count + 1 + else: + count = 0 + lastmethod = method['methodname'] + + classname = method['classname'] + + if(namespace != getnamespace(classname)): + continue + + classname = getclasswithoutnamespace(classname) + if(classname != lastclass): + if(lastclass != ''): + print("};\n"); + + fntablename = method['classname'].replace('vr::', 'VR::').replace('::', '_') + '_FnTable' + print("struct " + fntablename + "\n{") + lastclass = classname + + sys.stdout.write ('\t'+ ctype(returntype) + ' (OPENVR_FNTABLE_CALLTYPE *' + methodname + ')') + + paramlist = [] + if('params' in method): + for param in method['params']: + paramlist.append(ctype(param['paramtype']) + ' ' + param['paramname']) + + print('('+", ".join(paramlist)+");") + + print("};\n"); + +def outputfntabledecls(namespace, data): + lastclass = '' + lastmethod = '' + fntablename = '' + for method in data['methods']: + if (len(method) > 0): + returntype = method['returntype'] + if(returntype == 'class CSteamID'): + returntype = 'uint64' + methodname = method['methodname'] + if(methodname == lastmethod): + methodname = methodname + repr(count) + count = count + 1 + else: + count = 0 + lastmethod = method['methodname'] + + classname = method['classname'] + + if(namespace != getnamespace(classname)): + continue + + classname = getclasswithoutnamespace(classname) + if(classname != lastclass): + if(lastclass != ''): + print("};\n\n"); + + fntablename = method['classname'].replace('vr::', 'VR::').replace('::', '_') + '_FnTable' + print("static " + fntablename + " g_" + fntablename + " =\n{") + lastclass = classname + + print('\t&' + fntablename + '_' + methodname + ',') + + print("};\n\n"); + +def outputfntableinit(namespace, data): + print("extern void *FindInterface( const char *pchInterfaceName );\n") + print("void InitializeInterfaceFnTables()\n{") + lastclass = '' + for method in data['methods']: + if (len(method) > 0): + classname = method['classname'] + + if(namespace != getnamespace(classname)): + continue + + classname = getclasswithoutnamespace(classname) + if(classname != lastclass): + instancename = 'g_p' + classname + print("\t" + instancename + " = ( " + namespace + "::" + classname + " * )FindInterface( " + namespace + "::" + classname + "_Version );") + lastclass = classname + print("}\n") + +def outputfntableaccess(namespace, data): + lastclass = '' + for method in data['methods']: + if (len(method) > 0): + classname = method['classname'] + + if(namespace != getnamespace(classname)): + continue + + classname = getclasswithoutnamespace(classname) + if(classname != lastclass): + fntablename = method['classname'].replace('vr::', 'VR::').replace('::', '_') + '_FnTable' + print('FnTableRegistration autoreg_'+fntablename+'( '+classname+'_Version, &g_'+fntablename+' );') + lastclass = classname + +def outputfntablefuncs(namespace, data): + lastclass = '' + lastmethod = '' + instancename = '' + for method in data['methods']: + if (len(method) > 0): + returntype = method['returntype'] + if(returntype == 'class CSteamID'): + returntype = 'uint64' + methodname = method['methodname'] + if(methodname == lastmethod): + methodname = methodname + repr(count) + count = count + 1 + else: + count = 0 + lastmethod = method['methodname'] + + classname = method['classname'] + + if(namespace != getnamespace(classname)): + continue + + classname = getclasswithoutnamespace(classname) + if(classname != lastclass): + if(lastclass != ''): + print("\n\n"); + + instancename = 'g_p' + classname + print("/** " + classname + " FnTable functions */\n") + print("static " + namespace + "::" + classname + " *" + instancename + " = nullptr;\n") + lastclass = classname + + creturntype = ctype(returntype) + sys.stdout.write ('static '+ creturntype + ' OPENVR_FNTABLE_CALLTYPE '+method['classname'].replace('vr::', 'VR::').replace('::', '_') + '_FnTable_' + methodname) + paramlist = [] + if('params' in method): + for param in method['params']: + paramlist.append(ctype(param['paramtype'])+' '+param['paramname']) + + print('('+", ".join(paramlist)+")\n{") + + paramlist = [] + if('params' in method): + for param in method['params']: + paramtype = param['paramtype'] + cparamtype = ctype(paramtype) + if paramtype != cparamtype: + if paramtype.startswith('struct'): + paramlist.append('*('+paramtype+'*)&'+param['paramname']) + else: + paramlist.append('('+paramtype+')'+param['paramname']) + else: + paramlist.append(param['paramname']) + + # if the method is a destructor + if(method['methodname'][:8] == 'Destruct'): + sys.stdout.write ('delete instance;') + # void returntype does not return + elif (returntype == 'void'): + sys.stdout.write (instancename+'->'+method['methodname']+'(') + if('params' in method): + sys.stdout.write(", ".join(paramlist)) + sys.stdout.write (');') + elif (creturntype.startswith('struct') and creturntype != returntype): + sys.stdout.write (returntype+' result = '+instancename+'->'+method['methodname']+'(') + if('params' in method): + sys.stdout.write(", ".join(paramlist)) + sys.stdout.write (');\n') + sys.stdout.write ('return *('+creturntype+'*)&result;') + else: + if creturntype != returntype: + sys.stdout.write ('return ('+creturntype+')'+instancename+'->'+method['methodname']+'(') + else: + sys.stdout.write ('return '+instancename+'->'+method['methodname']+'(') + if('params' in method): + sys.stdout.write(", ".join(paramlist)) + sys.stdout.write (');') + sys.stdout.write ('\n}\n'); + + +############################### +# OUTPUT CLASSES +############################### + +def isparamptr(paramname, paramlist): + for param in paramlist: + if(param['paramname'] == paramname): + return param['paramtype'][len(param['paramtype']) - 1] == '*' + + +def outputclasses(namespace, data): + + print("""public class Utils + { + public static IntPtr ToUtf8(string managedString) + { + if (managedString == null) + { + return IntPtr.Zero; + } + + int size = System.Text.Encoding.UTF8.GetByteCount(managedString) + 1; + if (buffer.Length < size) buffer = new byte[size]; + int written = System.Text.Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0); + buffer[written] = 0x00; // null terminate + IntPtr nativeUtf8 = Marshal.AllocHGlobal(written+1); + Marshal.Copy(buffer, 0, nativeUtf8, written+1); + return nativeUtf8; + } + private static byte[] buffer = new byte[1024]; + } + """) + + # the following methods take a mispacked VRControllerState_t on Linux and OSX so we generate + # a special hacky method to account for that on those platforms. + controller_packed_methods = ['GetControllerState', 'GetControllerStateWithPose', 'GetComponentState'] + event_packed_methods = ['PollNextEvent', 'PollNextEventWithPost', 'PollNextOverlayEvent'] + if(namespace == ''): + namespaceextra = '' + elif(namespace == 'vr'): + namespaceextra = 'VR_' + else: + namespaceextra = namespace+'_' + lastclass = '' + lastmethod = '' + for method in data['methods']: + if (len(method) > 0): + returntype = converttype(method['returntype']) + + interfacename = method['classname'] + + if(namespace != getnamespace(interfacename)): + continue + + interfacename = getclasswithoutnamespace(interfacename) + methodname = method['methodname'] + if(methodname == lastmethod): + methodname = methodname + repr(count) + count = count + 1 + else: + count = 0 + lastmethod = method['methodname'] + + if(interfacename != lastclass): + if(lastclass != ''): + print("}\n\n"); + classname = 'C' + interfacename[1:] + classshort = interfacename[1:] + print("public class " + classname+"\n{") + print(interfacename+" FnTable;") + print("internal " + classname + "(IntPtr pInterface)") + print("{") + print("\tFnTable = ("+interfacename+")Marshal.PtrToStructure(pInterface, typeof("+interfacename+"));") + print("}") + + lastclass = interfacename + + paramlist = [] + # Native params are always ref and include count params + nativeparamlist = [] + skipparam = '' + outarray = 0 + outstruct = 0 + twocalls = 0 + skipref = 0 + arraytype = '' + arrayname = '' + arrayreplace = '' + skipcount = '' + skiptype = '' + paramtypelist = [] + if('params' in method): + for param in method['params']: + paramtype = converttype(param['paramtype']) + if(param['paramname'] != skipparam): + if('out_array_count' in param): + paramlist.append(param['paramname']) + paramtypelist.append('out ' + paramtype + ' [] ' + param['paramname']) + nativeparamlist.append(param['paramname']) + skipparam = param['out_array_count'] + arraytype = paramtype + arrayname = param['paramname'] + arrayreplace = 'null' + twocalls = 1 + outarray = 1 + skipref = 1 + elif('out_string_count' in param): + paramlist.append(param['paramname']) + paramtypelist.append('out string ' + param['paramname']) + nativeparamlist.append('pStrBuffer') + skipparam = param['out_string_count'] + arraytype = paramtype + arrayname = 'pStrBuffer' + arrayreplace = 'null' + twocalls = 1 + skipref = 1 + elif('out_array_call' in param): + paramlist.append(param['paramname']) + paramtypelist.append('out ' + paramtype + ' [] ' + param['paramname']) + nativeparamlist.append(param['paramname']) + skipparam = param['out_array_call'].split(',')[0] + arraytype = paramtype + arrayname = param['paramname'] + arrayreplace = 'null' + outarray = 1 + skipref = 0 + elif('out_string_count' in param): + paramlist.append(param['paramname']) + paramtypelist.append('out ' + paramtype + ' ' + param['paramname']) + nativeparamlist.append('ref ' + param['paramname']) + skipparam = param['out_string_count'] + elif('out_struct' in param): + paramlist.append(param['paramname']) + paramtypelist.append('out ' + paramtype + ' ' + param['paramname']) + nativeparamlist.append('ref ' + param['paramname']) + elif('array_count' in param): + paramlist.append(param['paramname']) + paramtypelist.append(paramtype + ' [] ' + param['paramname']) + nativeparamlist.append(param['paramname']) + skipparam = param['array_count'] + skipcount = param['paramname'] +# elif(paramtype[0:1] == 'I' and paramtype != 'IntPtr' and not enumlist.has_key(paramtype)): +# #print("//" + paramtype) +# paramlist.append(param['paramname']) +# paramtypelist.append(paramtype + ' ' + param['paramname']) +# #nativeparamlist.append('ptr') +# nativeparamlist.append(param['paramname'] + '.GetIntPtr()') +# elif (structlist.has_key(paramtype)): +# paramlist.append(' ' + param['paramname']) +# paramtypelist.append(' ' + paramtype + ' ' + param['paramname']) +# nativeparamlist.append(' ' + param['paramname']) + elif (param['paramtype'][len(param['paramtype']) - 1] == '*' and param['paramtype'][len(param['paramtype']) - 2] == '*'): + paramlist.append('ref ' + param['paramname']) + paramtypelist.append('ref ' + paramtype + ' ' + param['paramname']) + nativeparamlist.append('ref ' + param['paramname']) + if(paramtype != 'uint' and paramtype != 'int' and paramtype != 'char' and paramtype != 'bool'): + outstruct = 1 + arraytype = paramtype + arrayname = param['paramname'] + arrayreplace = 'null' + elif (param['paramtype'][len(param['paramtype']) - 1] == '*' and paramtype != 'string' and paramtype != 'IntPtr'): + paramlist.append('ref ' + param['paramname']) + paramtypelist.append('ref ' + paramtype + ' ' + param['paramname']) + nativeparamlist.append('ref ' + param['paramname']) + if(paramtype != 'uint' and paramtype != 'int' and paramtype != 'char' and paramtype != 'bool'): + outstruct = 1 + arraytype = paramtype + arrayname = param['paramname'] + arrayreplace = 'null' + elif ('out_string' in param): + paramlist.append(param['paramname']) + paramtypelist.append('System.Text.StringBuilder ' + param['paramname']) + nativeparamlist.append(param['paramname']) + elif (paramtype == 'string' and param['paramtype'] == 'const char *'): + paramlist.append(param['paramname']) + paramtypelist.append(paramtype + ' ' + param['paramname']) + nativeparamlist.append(param['paramname']+'Utf8') + else: + paramlist.append(param['paramname']) + paramtypelist.append(paramtype + ' ' + param['paramname']) + nativeparamlist.append(param['paramname']) + else: + skiptype = paramtype + if(skipref): + nativeparamlist.append('ref ' + param['paramname']) + elif(skipcount != ''): + nativeparamlist.append("(" + paramtype +") " + skipcount + ".Length" ) + else: + nativeparamlist.append(param['paramname']) + skipparam = 0 + if methodname in controller_packed_methods or methodname in event_packed_methods: + if methodname in controller_packed_methods: + packedlist=[w.replace('VRControllerState_t','VRControllerState_t_Packed').replace('string', 'IntPtr') for w in paramtypelist] + else: + packedlist=[w.replace('VREvent_t','VREvent_t_Packed') for w in paramtypelist] + print('// This is a terrible hack to workaround the fact that VRControllerState_t and VREvent_t were ') + print('// originally mis-compiled with the wrong packing for Linux and OSX.') + print('[UnmanagedFunctionPointer(CallingConvention.StdCall)]') + print('internal delegate '+returntype+' _'+methodname+'Packed('+','.join(packedlist)+');') + print('[StructLayout(LayoutKind.Explicit)]') + print('struct '+methodname+'Union\n{') + print('\t[FieldOffset(0)]\n\tpublic '+interfacename+'._'+methodname+' p'+methodname+';') + print('\t[FieldOffset(0)]\n\tpublic _'+methodname+'Packed p'+methodname+'Packed;\n}') + + sys.stdout.write ('public '+returntype+' '+methodname+'('+','.join(paramtypelist)+')\n{\n') + # PROCESS THE STUFF BEFORE THE API CALLS + if('params' in method): + for param in method['params']: + if(skipparam != param['paramname']): + paramtype = converttype(param['paramtype']) + if('out_array_count' in param and skipparam != param['out_array_count']): + skipparam = param['out_array_count'] + sys.stdout.write( '\t'+skiptype+' '+skipparam+' = 0;\n' ) + elif('out_string_count' in param and skipparam != param['out_string_count']): + skipparam = param['out_string_count'] + #if(isparamptr(skipparam, param)): + sys.stdout.write( '\t'+skiptype+' '+skipparam+' = 0;\n' ) + elif('out_array_call' in param): + vals = param['out_array_call'].split(',') + sys.stdout.write( '\tint '+vals[0]+' = '+vals[1]+' ('+vals[2]+');\n' ) + sys.stdout.write( '\t'+param['paramname']+' = new '+paramtype+'['+vals[0]+'];\n' ) + elif('out_struct' in param): + sys.stdout.write( '\t'+param['paramname']+' = new '+paramtype+'();\n' ) + elif (param['paramtype'][len(param['paramtype']) - 1] == '*' and (paramtype == 'int' or paramtype == 'uint' or paramtype == 'float' or paramtype == 'long' or paramtype == 'ulong' or paramtype == 'double') and not 'array_count' in param): + # Out parameters need to be initialized to zero + sys.stdout.write( '\t'+param['paramname']+' = 0;\n' ) + elif (param['paramtype'][len(param['paramtype']) - 2:] == '**' and (paramtype == 'string')): + # Out parameters need to be initialized to zero + sys.stdout.write( '\t'+param['paramname']+' = "";\n' ) + elif (param['paramtype'][len(param['paramtype']) - 1] == '*' and (paramtype == 'char')): + # Out parameters need to be initialized to zero + sys.stdout.write( '\t'+param['paramname']+' = (char) 0;\n' ) + elif (param['paramtype'][len(param['paramtype']) - 1] == '*' and (paramtype == 'bool')): + # Out parameters need to be initialized to zero + sys.stdout.write( '\t'+param['paramname']+' = false;\n' ) + elif (paramtype == 'string' and param['paramtype'] == 'const char *'): + # In strings need to be converted to UTF-8 + sys.stdout.write( '\tIntPtr '+param['paramname']+'Utf8 = Utils.ToUtf8('+param['paramname']+');\n') + #elif(paramtype[0:1] == 'I' and paramtype != 'IntPtr' and not enumlist.has_key(paramtype)): + # Returning an interface ptr needs ptr defined + # sys.stdout.write( '\tIntPtr ptr = IntPtr.Zero;\n' ) + + + # PROCESS THE FIRST OPTIONAL API CALL + if(twocalls): + paramsnull = ','.join(map((lambda x: (arrayreplace if (x==arrayname) else x)),nativeparamlist)) + sys.stdout.write ('\t'+('' if (returntype=='void') else (returntype+' result = '))+'FnTable.'+methodname+'('+paramsnull+');\n') + + # PROCESS IN BETWEEN THE API CALLS + # Allocate the array or buffer + if('params' in method): + for param in method['params']: + if('out_array_count' in param): + sys.stdout.write( '\t'+param['paramname']+'= new ' + converttype(param['paramtype']) + '['+param['out_array_count']+'];\n' ) + if('out_string_count' in param): + sys.stdout.write( '\tSystem.Text.StringBuilder pStrBuffer = new System.Text.StringBuilder((int)'+skipparam+');\n' ) + + + # PROCESS THE FINAL API CALL + if methodname in controller_packed_methods: + packedparamlist = [w.replace('pControllerState','state_packed') + .replace('unControllerStateSize','(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed))') + for w in nativeparamlist] + + print('#if !UNITY_METRO') + print('\tif ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||') + print('\t (System.Environment.OSVersion.Platform == System.PlatformID.Unix))') + print('\t{') + print('\t\t'+methodname+'Union u;') + print('\t\tVRControllerState_t_Packed state_packed = new VRControllerState_t_Packed(pControllerState);') + print('\t\tu.p'+methodname+'Packed = null;') + print('\t\tu.p'+methodname+' = FnTable.'+methodname+';') + print('\t\t'+returntype+' packed_result = u.p'+methodname+'Packed('+','.join(packedparamlist)+');\n') + print('\t\tstate_packed.Unpack(ref pControllerState);') + print('\t\treturn packed_result;') + print('\t}') + print('#endif') + if methodname in event_packed_methods: + packedparamlist = [w.replace('pEvent','event_packed') + .replace('uncbVREvent','(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VREvent_t_Packed))') + for w in nativeparamlist] + + print('#if !UNITY_METRO') + print('\tif ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||') + print('\t (System.Environment.OSVersion.Platform == System.PlatformID.Unix))') + print('\t{') + print('\t\t'+methodname+'Union u;') + print('\t\tVREvent_t_Packed event_packed = new VREvent_t_Packed();') + print('\t\tu.p'+methodname+'Packed = null;') + print('\t\tu.p'+methodname+' = FnTable.'+methodname+';') + print('\t\t'+returntype+' packed_result = u.p'+methodname+'Packed('+','.join(packedparamlist)+');\n') + print('\t\tevent_packed.Unpack(ref pEvent);') + print('\t\treturn packed_result;') + print('\t}') + print('#endif') + + + savereturn = returntype + if(method['returntype'][len(method['returntype']) - 1] == '*'): + returntype = 'IntPtr' + if(returntype == 'void'): + if(len(nativeparamlist) > 0): + sys.stdout.write ('\tFnTable.'+methodname+'('+','.join(nativeparamlist)+');\n') + else: + sys.stdout.write ('\tFnTable.'+methodname+'();\n') + else: + if(len(nativeparamlist) > 0): + #if(returntype[0:1] == 'I' and returntype != 'IntPtr'): + # sys.stdout.write ('\tC'+returntype[1:]+' result = new C'+returntype[1:]+'(FnTable.'+methodname+'('+','.join(nativeparamlist)+'));\n') + if(returntype == 'string'): + sys.stdout.write ('\tstring result = Marshal.PtrToStringAuto(FnTable.'+methodname+'('+','.join(nativeparamlist)+'));\n') + else: + sys.stdout.write ('\t'+('' if twocalls else returntype)+' result = FnTable.'+methodname+'('+','.join(nativeparamlist)+');\n') + else: + if(returntype == 'string'): + sys.stdout.write ('\tstring result = Marshal.PtrToStringAuto(FnTable.'+methodname+'());\n') + else: + sys.stdout.write ('\t'+('' if twocalls else returntype)+' result = FnTable.'+methodname+'();\n') + + + # PROCESS AFTER THE API CALL + if('params' in method): + for param in method['params']: + paramtype = converttype(param['paramtype']) + if('out_string_count' in param): + sys.stdout.write( '\t'+param['paramname']+' = pStrBuffer.ToString();\n' ) + elif (paramtype == 'string' and param['paramtype'] == 'const char *'): + sys.stdout.write( '\tMarshal.FreeHGlobal('+param['paramname']+'Utf8);\n') + #elif(paramtype[0:1] == 'I' and paramtype != 'IntPtr' and not enumlist.has_key(paramtype)): + # Interface. Need to construct a class wrapper + #sys.stdout.write( '\t'+param['paramname']+'= new C' + paramtype[1:] + '(ptr);\n' ) + + if(method['returntype'][len(method['returntype']) - 1] == '*'): + if(savereturn == 'string'): + sys.stdout.write ('\treturn Marshal.PtrToStringAnsi(result);\n') + else: + sys.stdout.write ('\treturn ('+savereturn+') Marshal.PtrToStructure(result, typeof('+savereturn+'));\n') + elif(returntype != 'void'): + sys.stdout.write ('\treturn result;\n') + sys.stdout.write ('}\n') diff --git a/codegen/openvr_capi.cpp.py b/codegen/openvr_capi.cpp.py new file mode 100755 index 0000000..33e7e8d --- /dev/null +++ b/codegen/openvr_capi.cpp.py @@ -0,0 +1,88 @@ +print ("""//======= Copyright (c) Valve Corporation, All rights reserved. =============== +// +// Purpose: This is a flattened version of the OpenVR_API interfaces. +// This file is auto-generated, do not edit it. +// +//============================================================================= +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <ShellAPI.h> +#endif + +#if defined(OSX) +#include <sys/syslimits.h> +#include <signal.h> +#define MAX_PATH PATH_MAX +#elif defined(LINUX) +#include <linux/limits.h> +#include <signal.h> +#define MAX_PATH PATH_MAX +#elif defined(WIN32) +#else +#error +#endif + +#ifdef POSIX +#include <fcntl.h> +#include <dlfcn.h> // dlopen,dlclose, et al +#include <unistd.h> +#include <stdarg.h> +#define HMODULE void * +#define GetProcAddress dlsym +#define OutputDebugString( pchMsg ) fputs( pchMsg, stderr ) +#define _strnicmp strncasecmp +//#include "../../common/linuxhelpers_nodeps.h" +#endif + +#ifdef OSX +#include <sys/sysctl.h> +#endif + +#include <stdlib.h> +#include <assert.h> + +#include "openvr.h" +#include "ivrsystem.h" +#include "ivrchaperone.h" +#include "ivrchaperonesetup.h" +#include "ivrcompositor.h" +#include "ivroverlay.h" +#include "ivrrendermodels.h" +#include "ivrnotifications.h" +#include "ivrblockqueue.h" + +#include "../vrclient/interface_adapters_client.h" +#include "_dynamic_openvr_api_flat.h" + +class FnTableRegistration +{ +public: + FnTableRegistration( const char *pchInterfaceName, void *pInterface ) + { + char buffer[255]; + sprintf(buffer, "FnTable:%s", pchInterfaceName); + m_pInterfaceRegistration = new GenericInterfaceRegistration( buffer, pInterface ); + } + ~FnTableRegistration() + { + delete m_pInterfaceRegistration; + } +private: + GenericInterfaceRegistration *m_pInterfaceRegistration; +}; + +""") + + +import json +import sys +with open('_dynamic_openvr_api.json') as data_file: + data = json.load(data_file) + +import api_shared +api_shared.outputfntablefuncs('vr', data) +api_shared.outputfntabledecls('vr', data) +api_shared.outputfntableinit('vr', data) +api_shared.outputfntableaccess('vr', data) + diff --git a/codegen/openvr_capi.h.py b/codegen/openvr_capi.h.py new file mode 100755 index 0000000..1b912cd --- /dev/null +++ b/codegen/openvr_capi.h.py @@ -0,0 +1,290 @@ +import sys +import api_shared +import operator +from functools import reduce + +print ("""//======= Copyright (c) Valve Corporation, All rights reserved. =============== +// +// Purpose: Header for flatted SteamAPI. Use this for binding to other languages. +// This file is auto-generated, do not edit it. +// +//============================================================================= + +#ifndef __OPENVR_API_FLAT_H__ +#define __OPENVR_API_FLAT_H__ +#if defined( _WIN32 ) || defined( __clang__ ) +#pragma once +#endif + +#ifdef __cplusplus +#define EXTERN_C extern "C" +#else +#define EXTERN_C +#endif + +#if defined( _WIN32 ) +#define OPENVR_FNTABLE_CALLTYPE __stdcall +#else +#define OPENVR_FNTABLE_CALLTYPE +#endif + +// OPENVR API export macro +#if defined( _WIN32 ) && !defined( _X360 ) + #if defined( OPENVR_API_EXPORTS ) + #define S_API EXTERN_C __declspec( dllexport ) + #elif defined( OPENVR_API_NODLL ) + #define S_API EXTERN_C + #else + #define S_API extern "C" __declspec( dllimport ) + #endif // OPENVR_API_EXPORTS +#elif defined( __GNUC__ ) + #if defined( OPENVR_API_EXPORTS ) + #define S_API EXTERN_C __attribute__ ((visibility("default"))) + #else + #define S_API EXTERN_C + #endif // OPENVR_API_EXPORTS +#else // !WIN32 + #if defined( OPENVR_API_EXPORTS ) + #define S_API EXTERN_C + #else + #define S_API EXTERN_C + #endif // OPENVR_API_EXPORTS +#endif + +#include <stdint.h> + +#if defined( __WIN32 ) +typedef char bool; +#else +#include <stdbool.h> +#endif + +typedef uint64_t PropertyContainerHandle_t; +typedef uint32_t PropertyTypeTag_t; +typedef uint64_t VRActionHandle_t; +typedef uint64_t VRActionSetHandle_t; +typedef uint64_t VRInputValueHandle_t; +typedef uint64_t PathHandle_t; +""") + + + +data = api_shared.loadfile('_dynamic_openvr_api.json', 'vr') +converttype = api_shared.converttype +striparraysuffix = api_shared.striparraysuffix +structlist = api_shared.structlist +structparents = api_shared.structparents +structindices = api_shared.structindices +typedeflist = api_shared.typedeflist +enumlist = api_shared.enumlist +getnamespace = api_shared.getnamespace +getclasswithoutnamespace = api_shared.getclasswithoutnamespace +unmanagedtype = api_shared.unmanagedtype +ctype = api_shared.ctype +namespace = 'vr' + +def OutputStructFields(struct): + + # recursively add base class fields first + basename = getclasswithoutnamespace(struct['struct']) + if basename in structparents: + parentname = structparents[basename] + i = structindices[parentname]; + OutputStructFields(data['structs'][i]) + + for enumvalue in struct['fields']: + fieldtype = enumvalue['fieldtype'] + otype = striparraysuffix(fieldtype) + lastchar = fieldtype[len(fieldtype) - 1] + if(lastchar == ']'): + #print('\t//fixed '+otype+' '+enumvalue['fieldname']+ fieldtype[fieldtype.find('['):]+';') + dims = map(int, fieldtype[fieldtype.find('[')+1:-1].split('][')) + size = reduce(operator.mul, dims, 1) + utype = unmanagedtype(otype) + print('\t'+('char ' if(otype=='char') else ctype(otype)+' ')+enumvalue['fieldname']+ fieldtype[fieldtype.find('['):]+'; //'+otype+fieldtype[fieldtype.find('['):]) + else: + if(lastchar == '*'): + print('\t'+ctype(fieldtype)+' '+enumvalue['fieldname']+';'+' // '+fieldtype) + else: + print('\t'+ctype(otype)+' '+enumvalue['fieldname']+';') + +######## +# Output constants into OpenVR class +print (""" +// OpenVR Constants +""") +for const in data['consts']: + if(len(const) > 0): + consttype = converttype(const['consttype']) + constval = const['constval'] + if(consttype == 'string'): + constval = '\"' + constval + '\"' + consttype = 'char *' + print('static const '+ctype(consttype)+' '+const['constname']+' = '+constval+';') + +###### +# Output enums +print (""" +// OpenVR Enums +""") +for enum in data['enums']: + if(len(enum) > 0 and len(enum['enumname'])): + ns = getnamespace(enum['enumname']) + enumname = getclasswithoutnamespace(enum['enumname']) + if(ns == namespace or (namespace == '' and ns[:1] == 'I')): + print('typedef enum '+enumname+'\n{') + for enumvalue in enum['values']: + entry = enumvalue['name'] + if(entry.startswith(enumname)): entry = entry[len(enumname):] # strip off enum name + if(entry.startswith('_')): entry = entry[1:] # strip off leading underscore + print('\t'+enumname+'_'+entry+' = '+enumvalue['value']+',') + print('} '+enumname+';\n') + +######## +# Output typedefs into OpenVR class + +print (""" +// OpenVR typedefs + +typedef uint32_t TrackedDeviceIndex_t; +typedef uint32_t VRNotificationId; +typedef uint64_t VROverlayHandle_t; +""") + +for typedef in data['typedefs']: + if(len(typedef) > 0): + thetype = typedef['type'] + if(thetype[0:6] != 'union ' and thetype[0:7] != 'struct '): + thetypedef = getclasswithoutnamespace(typedef['typedef']) # remove the vr:: bit from thetypedef + thetype = getclasswithoutnamespace(thetype) + print('typedef '+thetype+' '+thetypedef+';') + +###### +# Output structs +print (""" +// OpenVR Structs +""") +for struct in data['structs']: + if(len(struct) > 0 and len(struct['struct'])): + structname = struct['struct'] + #print('//'+structname) + ns = getnamespace(structname) + basename = getclasswithoutnamespace(structname) + if(basename != 'VREvent_t' and basename != 'VROverlayIntersectionMaskPrimitive_t' and basename != '(anonymous)' and (ns == namespace or (namespace == '' and ns[:1] == 'I') or (namespace == '' and ns[:1] == 'C'))): + #if basename != '(anonymous)': + unsafe = 0 + for enumvalue in struct['fields']: + fieldtype = enumvalue['fieldtype'] + if(fieldtype[len(fieldtype) - 1] == ']'): + unsafe = 1 + + pack = ((basename == 'RenderModel_t') or + (basename == 'VRControllerState_t') or + (basename=='RenderModel_TextureMap_t') or + (basename=='VREvent_t')) + + # resolve typedefs used to rename structs + for key, value in typedeflist.items(): + if(converttype(value) == basename): + basename = getclasswithoutnamespace(key) + break + + if (pack): + print('#if defined(__linux__) || defined(__APPLE__)\n#pragma pack( push, 4 )\n#endif') + if(unsafe == 1): + print('typedef struct '+basename+'\n{') # this was for potentially putting unsafe fields in + else: + print('typedef struct '+basename+'\n{') + + OutputStructFields(struct) + + print('} '+basename+';\n') + if pack: + print('#if defined(__linux__) || defined(__APPLE__)\n#pragma pack( pop )\n#endif') + +print (""" +typedef union +{ + VREvent_Reserved_t reserved; + VREvent_Controller_t controller; + VREvent_Mouse_t mouse; + VREvent_Scroll_t scroll; + VREvent_Process_t process; + VREvent_Notification_t notification; + VREvent_Overlay_t overlay; + VREvent_Status_t status; + VREvent_Keyboard_t keyboard; + VREvent_Ipd_t ipd; + VREvent_Chaperone_t chaperone; + VREvent_PerformanceTest_t performanceTest; + VREvent_TouchPadMove_t touchPadMove; + VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset; + VREvent_Screenshot_t screenshot; + VREvent_ScreenshotProgress_t screenshotProgress; + VREvent_ApplicationLaunch_t applicationLaunch; + VREvent_EditingCameraSurface_t cameraSurface; + VREvent_MessageOverlay_t messageOverlay; + VREvent_Property_t property; + VREvent_HapticVibration_t hapticVibration; + VREvent_WebConsole_t webConsole; + VREvent_InputBindingLoad_t inputBinding; + VREvent_InputActionManifestLoad_t actionManifest; + VREvent_SpatialAnchor_t spatialAnchor; +} VREvent_Data_t; + +#if defined(__linux__) || defined(__APPLE__) +// This structure was originally defined mis-packed on Linux, preserved for +// compatibility. +#pragma pack( push, 4 ) +#endif + +/** An event posted by the server to all running applications */ +struct VREvent_t +{ + uint32_t eventType; // EVREventType enum + TrackedDeviceIndex_t trackedDeviceIndex; + float eventAgeSeconds; + // event data must be the end of the struct as its size is variable + VREvent_Data_t data; +}; + +#if defined(__linux__) || defined(__APPLE__) +#pragma pack( pop ) +#endif +""") + +print (""" +typedef union +{ + IntersectionMaskRectangle_t m_Rectangle; + IntersectionMaskCircle_t m_Circle; +} VROverlayIntersectionMaskPrimitive_Data_t; + +struct VROverlayIntersectionMaskPrimitive_t +{ + EVROverlayIntersectionMaskPrimitiveType m_nPrimitiveType; + VROverlayIntersectionMaskPrimitive_Data_t m_Primitive; +}; +""") + +print (""" +// OpenVR Function Pointer Tables +""") +api_shared.outputfntables(namespace, data) + +print (""" +#if 0 +// Global entry points +S_API intptr_t VR_InitInternal( EVRInitError *peError, EVRApplicationType eType ); +S_API void VR_ShutdownInternal(); +S_API bool VR_IsHmdPresent(); +S_API intptr_t VR_GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError ); +S_API bool VR_IsRuntimeInstalled(); +S_API const char * VR_GetVRInitErrorAsSymbol( EVRInitError error ); +S_API const char * VR_GetVRInitErrorAsEnglishDescription( EVRInitError error ); +#endif + +#endif // __OPENVR_API_FLAT_H__ + +""") + diff --git a/codegen/openvr_interop.cs.py b/codegen/openvr_interop.cs.py new file mode 100755 index 0000000..cfabeb2 --- /dev/null +++ b/codegen/openvr_interop.cs.py @@ -0,0 +1,597 @@ +import sys +import api_shared +calculateinteropmethodname = api_shared.calculateinteropmethodname + +print ("""//======= Copyright (c) Valve Corporation, All rights reserved. =============== +// +// Purpose: This file contains C#/managed code bindings for the OpenVR interfaces +// This file is auto-generated, do not edit it. +// +//============================================================================= +#if !OPENVR_XR_API + +using System; +using System.Runtime.InteropServices; +using Valve.VR; + +#if UNITY_5_3_OR_NEWER +using UnityEngine; +#endif + +namespace Valve.VR +{ +""") + + + +data = api_shared.loadfile('_dynamic_openvr_api.json', 'vr') +converttype = api_shared.converttype +structlist = api_shared.structlist +typedeflist = api_shared.typedeflist +enumlist = api_shared.enumlist +lastmethod = '' + + +############## define Csharp interfaces ###################### + +api_shared.outputinterfaces('vr', data) + +############ define csharp classes + +api_shared.outputclasses('vr', data) + +print("}\n\n"); + +# Output the OpenVRInterop class +print('public class OpenVRInterop\n{') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_InitInternal", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern uint InitInternal(ref EVRInitError peError, EVRApplicationType eApplicationType);') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_InitInternal2", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern uint InitInternal2(ref EVRInitError peError, EVRApplicationType eApplicationType,[In, MarshalAs(UnmanagedType.LPStr)] string pStartupInfo);') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_ShutdownInternal", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern void ShutdownInternal();') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_IsHmdPresent", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern bool IsHmdPresent();') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_IsRuntimeInstalled", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern bool IsRuntimeInstalled();') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_RuntimePath", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern string RuntimePath();') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_GetRuntimePath", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern bool GetRuntimePath(System.Text.StringBuilder pchPathBuffer, uint unBufferSize, ref uint punRequiredBufferSize);') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_GetStringForHmdError", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern IntPtr GetStringForHmdError(EVRInitError error);') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_GetGenericInterface", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern IntPtr GetGenericInterface([In, MarshalAs(UnmanagedType.LPStr)] string pchInterfaceVersion, ref EVRInitError peError);') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_IsInterfaceVersionValid", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern bool IsInterfaceVersionValid([In, MarshalAs(UnmanagedType.LPStr)] string pchInterfaceVersion);') +print('[DllImportAttribute("openvr_api", EntryPoint = "VR_GetInitToken", CallingConvention = CallingConvention.Cdecl)]') +print('internal static extern uint GetInitToken();') +print("}\n\n"); + +api_shared.outputenums('vr', data) + +print(""" + [StructLayout(LayoutKind.Explicit)] public struct VREvent_Data_t + { + [FieldOffset(0)] public VREvent_Reserved_t reserved; + [FieldOffset(0)] public VREvent_Controller_t controller; + [FieldOffset(0)] public VREvent_Mouse_t mouse; + [FieldOffset(0)] public VREvent_Scroll_t scroll; + [FieldOffset(0)] public VREvent_Process_t process; + [FieldOffset(0)] public VREvent_Notification_t notification; + [FieldOffset(0)] public VREvent_Overlay_t overlay; + [FieldOffset(0)] public VREvent_Status_t status; + [FieldOffset(0)] public VREvent_Ipd_t ipd; + [FieldOffset(0)] public VREvent_Chaperone_t chaperone; + [FieldOffset(0)] public VREvent_PerformanceTest_t performanceTest; + [FieldOffset(0)] public VREvent_TouchPadMove_t touchPadMove; + [FieldOffset(0)] public VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset; + [FieldOffset(0)] public VREvent_Screenshot_t screenshot; + [FieldOffset(0)] public VREvent_ScreenshotProgress_t screenshotProgress; + [FieldOffset(0)] public VREvent_ApplicationLaunch_t applicationLaunch; + [FieldOffset(0)] public VREvent_EditingCameraSurface_t cameraSurface; + [FieldOffset(0)] public VREvent_MessageOverlay_t messageOverlay; + [FieldOffset(0)] public VREvent_Property_t property; + [FieldOffset(0)] public VREvent_HapticVibration_t hapticVibration; + [FieldOffset(0)] public VREvent_WebConsole_t webConsole; + [FieldOffset(0)] public VREvent_InputBindingLoad_t inputBinding; + [FieldOffset(0)] public VREvent_SpatialAnchor_t spatialAnchor; + [FieldOffset(0)] public VREvent_InputActionManifestLoad_t actionManifest; + [FieldOffset(0)] public VREvent_ProgressUpdate_t progressUpdate; + [FieldOffset(0)] public VREvent_ShowUI_t showUi; + [FieldOffset(0)] public VREvent_ShowDevTools_t showDevTools; + [FieldOffset(0)] public VREvent_HDCPError_t hdcpError; + [FieldOffset(0)] public VREvent_Keyboard_t keyboard; // This has to be at the end due to a mono bug + } + """) + +print(""" + [StructLayout(LayoutKind.Explicit)] public struct VROverlayIntersectionMaskPrimitive_Data_t + { + [FieldOffset(0)] public IntersectionMaskRectangle_t m_Rectangle; + [FieldOffset(0)] public IntersectionMaskCircle_t m_Circle; + } + """) + +api_shared.outputstructs('vr', data) + + +# Output the OpenVR class +print('\npublic class OpenVR\n{') +print(""" + public static uint InitInternal(ref EVRInitError peError, EVRApplicationType eApplicationType) + { + return OpenVRInterop.InitInternal(ref peError, eApplicationType); + } + + public static uint InitInternal2(ref EVRInitError peError, EVRApplicationType eApplicationType, string pchStartupInfo) + { + return OpenVRInterop.InitInternal2(ref peError, eApplicationType, pchStartupInfo); + } + + public static void ShutdownInternal() + { + OpenVRInterop.ShutdownInternal(); + } + + public static bool IsHmdPresent() + { + return OpenVRInterop.IsHmdPresent(); + } + + public static bool IsRuntimeInstalled() + { + return OpenVRInterop.IsRuntimeInstalled(); + } + + public static string RuntimePath() + { + try + { + uint pathSize = 512; + uint requiredPathSize = 512; + System.Text.StringBuilder path = new System.Text.StringBuilder((int)pathSize); + bool success = OpenVRInterop.GetRuntimePath(path, pathSize, ref requiredPathSize); + if (success == false) + { + return null; + } + + return path.ToString(); + } catch + { + return OpenVRInterop.RuntimePath(); //this api is deprecated but here to support older unity versions + } + } + + public static string GetStringForHmdError(EVRInitError error) + { + return Marshal.PtrToStringAnsi(OpenVRInterop.GetStringForHmdError(error)); + } + + public static IntPtr GetGenericInterface(string pchInterfaceVersion, ref EVRInitError peError) + { + return OpenVRInterop.GetGenericInterface(pchInterfaceVersion, ref peError); + } + + public static bool IsInterfaceVersionValid(string pchInterfaceVersion) + { + return OpenVRInterop.IsInterfaceVersionValid(pchInterfaceVersion); + } + + public static uint GetInitToken() + { + return OpenVRInterop.GetInitToken(); + } +""") + +######## +# Output constants into OpenVR class + +for const in data['consts']: + if(len(const) > 0): + consttype = converttype(const['consttype']) + constval = const['constval'] + if(consttype == 'string'): + constval = '\"' + constval + '\"' + print('public const '+consttype+' '+const['constname']+' = '+constval+';') + +######## +# Output static constructors into OpenVR class +#lastclass = '' +#lastmethod = '' +#for method in data['methods']: +# if (len(method) > 0): +# returntype = converttype(method['returntype']) +# +# methodname = method['methodname'] +# if(methodname == lastmethod): +# methodname = methodname + `count` +# count = count + 1 +# else: +# count = 0 +# lastmethod = method['methodname'] +# +# interfacename = method['classname'] +# namespace = api_shared.getnamespace(interfacename) +# if(interfacename.find('::') == -1): +# classname= 'C' + interfacename[1:] +# else: +# interfacename = interfacename[interfacename.find('::') + 2:] +# classname = 'C' + interfacename[1:] +# if(namespace != ''): +# if(interfacename != lastclass): +# shortname = interfacename[1:] +# print('public static '+interfacename+' '+shortname+'()\n{\nreturn new '+classname+'(OpenVRInterop.'+shortname+'());\n}\n') +# lastclass = interfacename + +######## +# Output interface wrappers into OpenVR class + +print(""" + static uint VRToken { get; set; } + + const string FnTable_Prefix = "FnTable:"; + + class COpenVRContext + { + public COpenVRContext() { Clear(); } + + public void Clear() + { + m_pVRSystem = null; + m_pVRChaperone = null; + m_pVRChaperoneSetup = null; + m_pVRCompositor = null; + m_pVRHeadsetView = null; + m_pVROverlay = null; + m_pVROverlayView = null; + m_pVRRenderModels = null; + m_pVRExtendedDisplay = null; + m_pVRSettings = null; + m_pVRApplications = null; + m_pVRScreenshots = null; + m_pVRTrackedCamera = null; + m_pVRInput = null; + m_pVRIOBuffer = null; + m_pVRSpatialAnchors = null; + m_pVRNotifications = null; + m_pVRDebug = null; + } + + void CheckClear() + { + if (VRToken != GetInitToken()) + { + Clear(); + VRToken = GetInitToken(); + } + } + + public CVRSystem VRSystem() + { + CheckClear(); + if (m_pVRSystem == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRSystem_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRSystem = new CVRSystem(pInterface); + } + return m_pVRSystem; + } + + public CVRChaperone VRChaperone() + { + CheckClear(); + if (m_pVRChaperone == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRChaperone_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRChaperone = new CVRChaperone(pInterface); + } + return m_pVRChaperone; + } + + public CVRChaperoneSetup VRChaperoneSetup() + { + CheckClear(); + if (m_pVRChaperoneSetup == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRChaperoneSetup_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRChaperoneSetup = new CVRChaperoneSetup(pInterface); + } + return m_pVRChaperoneSetup; + } + + public CVRCompositor VRCompositor() + { + CheckClear(); + if (m_pVRCompositor == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRCompositor_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRCompositor = new CVRCompositor(pInterface); + } + return m_pVRCompositor; + } + + public CVRHeadsetView VRHeadsetView() + { + CheckClear(); + if (m_pVRHeadsetView == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRHeadsetView_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRHeadsetView = new CVRHeadsetView(pInterface); + } + return m_pVRHeadsetView; + } + + public CVROverlay VROverlay() + { + CheckClear(); + if (m_pVROverlay == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVROverlay_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVROverlay = new CVROverlay(pInterface); + } + return m_pVROverlay; + } + + public CVROverlayView VROverlayView() + { + CheckClear(); + if (m_pVROverlayView == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVROverlayView_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVROverlayView = new CVROverlayView(pInterface); + } + return m_pVROverlayView; + } + + public CVRRenderModels VRRenderModels() + { + CheckClear(); + if (m_pVRRenderModels == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRRenderModels_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRRenderModels = new CVRRenderModels(pInterface); + } + return m_pVRRenderModels; + } + + public CVRExtendedDisplay VRExtendedDisplay() + { + CheckClear(); + if (m_pVRExtendedDisplay == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRExtendedDisplay_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRExtendedDisplay = new CVRExtendedDisplay(pInterface); + } + return m_pVRExtendedDisplay; + } + + public CVRSettings VRSettings() + { + CheckClear(); + if (m_pVRSettings == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRSettings_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRSettings = new CVRSettings(pInterface); + } + return m_pVRSettings; + } + + public CVRApplications VRApplications() + { + CheckClear(); + if (m_pVRApplications == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRApplications_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRApplications = new CVRApplications(pInterface); + } + return m_pVRApplications; + } + + public CVRScreenshots VRScreenshots() + { + CheckClear(); + if (m_pVRScreenshots == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRScreenshots_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRScreenshots = new CVRScreenshots(pInterface); + } + return m_pVRScreenshots; + } + + public CVRTrackedCamera VRTrackedCamera() + { + CheckClear(); + if (m_pVRTrackedCamera == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRTrackedCamera_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRTrackedCamera = new CVRTrackedCamera(pInterface); + } + return m_pVRTrackedCamera; + } + + public CVRInput VRInput() + { + CheckClear(); + if (m_pVRInput == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRInput_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRInput = new CVRInput(pInterface); + } + return m_pVRInput; + } + + public CVRIOBuffer VRIOBuffer() + { + CheckClear(); + if (m_pVRIOBuffer == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix + IVRIOBuffer_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRIOBuffer = new CVRIOBuffer(pInterface); + } + return m_pVRIOBuffer; + } + + public CVRSpatialAnchors VRSpatialAnchors() + { + CheckClear(); + if (m_pVRSpatialAnchors == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix + IVRSpatialAnchors_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRSpatialAnchors = new CVRSpatialAnchors(pInterface); + } + return m_pVRSpatialAnchors; + } + + public CVRDebug VRDebug() + { + CheckClear(); + if (m_pVRDebug == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix + IVRDebug_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRDebug = new CVRDebug(pInterface); + } + return m_pVRDebug; + } + + public CVRNotifications VRNotifications() + { + CheckClear(); + if (m_pVRNotifications == null) + { + var eError = EVRInitError.None; + var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix + IVRNotifications_Version, ref eError); + if (pInterface != IntPtr.Zero && eError == EVRInitError.None) + m_pVRNotifications = new CVRNotifications(pInterface); + } + return m_pVRNotifications; + } + + private CVRSystem m_pVRSystem; + private CVRChaperone m_pVRChaperone; + private CVRChaperoneSetup m_pVRChaperoneSetup; + private CVRCompositor m_pVRCompositor; + private CVRHeadsetView m_pVRHeadsetView; + private CVROverlay m_pVROverlay; + private CVROverlayView m_pVROverlayView; + private CVRRenderModels m_pVRRenderModels; + private CVRExtendedDisplay m_pVRExtendedDisplay; + private CVRSettings m_pVRSettings; + private CVRApplications m_pVRApplications; + private CVRScreenshots m_pVRScreenshots; + private CVRTrackedCamera m_pVRTrackedCamera; + private CVRInput m_pVRInput; + private CVRIOBuffer m_pVRIOBuffer; + private CVRSpatialAnchors m_pVRSpatialAnchors; + private CVRNotifications m_pVRNotifications; + private CVRDebug m_pVRDebug; + }; + + private static COpenVRContext _OpenVRInternal_ModuleContext = null; + static COpenVRContext OpenVRInternal_ModuleContext + { + get + { + if (_OpenVRInternal_ModuleContext == null) + _OpenVRInternal_ModuleContext = new COpenVRContext(); + return _OpenVRInternal_ModuleContext; + } + } + + public static CVRSystem System { get { return OpenVRInternal_ModuleContext.VRSystem(); } } + public static CVRChaperone Chaperone { get { return OpenVRInternal_ModuleContext.VRChaperone(); } } + public static CVRChaperoneSetup ChaperoneSetup { get { return OpenVRInternal_ModuleContext.VRChaperoneSetup(); } } + public static CVRCompositor Compositor { get { return OpenVRInternal_ModuleContext.VRCompositor(); } } + public static CVRHeadsetView HeadsetView { get { return OpenVRInternal_ModuleContext.VRHeadsetView(); } } + public static CVROverlay Overlay { get { return OpenVRInternal_ModuleContext.VROverlay(); } } + public static CVROverlayView OverlayView { get { return OpenVRInternal_ModuleContext.VROverlayView(); } } + public static CVRRenderModels RenderModels { get { return OpenVRInternal_ModuleContext.VRRenderModels(); } } + public static CVRExtendedDisplay ExtendedDisplay { get { return OpenVRInternal_ModuleContext.VRExtendedDisplay(); } } + public static CVRSettings Settings { get { return OpenVRInternal_ModuleContext.VRSettings(); } } + public static CVRApplications Applications { get { return OpenVRInternal_ModuleContext.VRApplications(); } } + public static CVRScreenshots Screenshots { get { return OpenVRInternal_ModuleContext.VRScreenshots(); } } + public static CVRTrackedCamera TrackedCamera { get { return OpenVRInternal_ModuleContext.VRTrackedCamera(); } } + public static CVRInput Input { get { return OpenVRInternal_ModuleContext.VRInput(); } } + public static CVRIOBuffer IOBuffer { get { return OpenVRInternal_ModuleContext.VRIOBuffer(); } } + public static CVRSpatialAnchors SpatialAnchors { get { return OpenVRInternal_ModuleContext.VRSpatialAnchors(); } } + public static CVRNotifications Notifications { get { return OpenVRInternal_ModuleContext.VRNotifications(); } } + public static CVRDebug Debug { get { return OpenVRInternal_ModuleContext.VRDebug(); } } + + + /** Finds the active installation of vrclient.dll and initializes it */ + public static CVRSystem Init(ref EVRInitError peError, EVRApplicationType eApplicationType = EVRApplicationType.VRApplication_Scene, string pchStartupInfo= "") + { + try + { + VRToken = InitInternal2(ref peError, eApplicationType, pchStartupInfo); + } + catch (EntryPointNotFoundException) + { + VRToken = InitInternal(ref peError, eApplicationType); + } + + OpenVRInternal_ModuleContext.Clear(); + + if (peError != EVRInitError.None) + return null; + + bool bInterfaceValid = IsInterfaceVersionValid(IVRSystem_Version); + if (!bInterfaceValid) + { + ShutdownInternal(); + peError = EVRInitError.Init_InterfaceNotFound; + return null; + } + + return OpenVR.System; + } + + /** unloads vrclient.dll. Any interface pointers from the interface are + * invalid after this point */ + public static void Shutdown() + { + ShutdownInternal(); + } +""") + +print("}\n\n"); + +print (""" +} +#endif +""") |