Compare commits

..

4 Commits

Author SHA1 Message Date
3f2553a7cc android stub 2026-06-12 08:08:43 +02:00
47eb7c89e0 Move VBS_SDK ThirdParty under Source/
Why: Epic's own engine layout puts third-party libraries under
Engine/Source/ThirdParty/, treating them as compile-time inputs
alongside the modules. Aligning the plugin with this convention keeps
all build inputs (modules + third-party) self-contained under Source/.

- Rename Plugins/PS_ViveVBS/ThirdParty/ -> Plugins/PS_ViveVBS/Source/ThirdParty/.
- Update SdkRoot in Build.cs to Path.Combine(PluginDirectory, "Source", "ThirdParty", "VBS_SDK").
- Update FilterPlugin.ini paths.

Validated by clean rebuilds of Editor and Game Win64 Development
targets, both exit 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 07:53:40 +02:00
5e8a775fa7 Consolidate Vive SDK lib + DLLs under ThirdParty/VBS_SDK/Win64/
Why: vendor SDKs distributed inside UE plugins typically ship a single
folder per platform rather than the Unix-style include/lib/bin split.
Grouping VS_PC_SDK.lib alongside the three runtime DLLs matches what
HTC and most XR SDKs publish and keeps the layout closer to what a
maintainer expects when dropping in a new SDK release.

- Move VS_PC_SDK.lib from lib/Win64/ into Win64/ alongside the DLLs.
- Remove the now-empty lib/ and bin/ subdirectories.
- Update Build.cs to use a single Win64Dir variable.
- Update FilterPlugin.ini to reference the consolidated path.

Validated by clean rebuilds of PS_ViveVBSEditor and PS_ViveVBS Win64
Development targets, both exit 0 with the three DLLs auto-copied next
to the binary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 07:31:11 +02:00
7f9d5cbe4c Refactor ViveVBS plugin build to UE5 conventions
Why: the previous Build.cs copied the Vive DLLs manually via File.Copy
only for the Editor target, leaving Game/packaged builds with missing
runtime dependencies. The DYNAMIC_LINKAGE branch was also syntactically
broken, the SDK header/lib lived inside Source/, and the .uplugin used
the deprecated WhitelistPlatforms key.

- Move SDK to ThirdParty/VBS_SDK/{include,lib/Win64,bin/Win64}/ via
  git renames so history is preserved.
- Replace File.Copy + Editor-only branch with idiomatic
  RuntimeDependencies.Add(staged, source, NonUFS) — UBT now copies the
  DLLs next to the binary for both Editor (modular) and Game (monolithic)
  and stages them at packaging time.
- Drop dead #if DYNAMIC_LINKAGE block.
- Move SDK include path from Public to Private (no public header
  exposes Vive types) and remove the now-dead include from 4 public
  headers; add the SDK include to the 4 .cpp that actually use it.
- Rename WhitelistPlatforms -> PlatformAllowList (UE5).
- Populate FilterPlugin.ini with the ThirdParty paths so the plugin
  is redistributable when packaged standalone.

Validated by clean builds of PS_ViveVBSEditor (Win64 Development) and
PS_ViveVBS (Win64 Development Game), both exit 0, with UBT logging
the automatic Copy steps for the 3 Vive DLLs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 07:25:15 +02:00
17 changed files with 128 additions and 99 deletions

View File

@@ -1,8 +1,6 @@
[FilterPlugin]
; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and
; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively.
;
; Examples:
; /README.txt
; /Extras/...
; /Binaries/ThirdParty/*.dll
/Source/ThirdParty/VBS_SDK/include/...
/Source/ThirdParty/VBS_SDK/Win64/...

View File

@@ -3,6 +3,10 @@
#include "../Public/Global.h"
#if PLATFORM_WINDOWS
#include "VS_PC_SDK.h"
#endif
DEFINE_LOG_CATEGORY(PS_ViveVBS);
#define LOCTEXT_NAMESPACE "VBS"
@@ -10,6 +14,7 @@ DEFINE_LOG_CATEGORY(PS_ViveVBS);
int UGlobal::markerState = 0;
#if PLATFORM_WINDOWS
void OnServerStatusUpdate(wchar_t* strName, wchar_t* strValue)
{
if (wcscmp(strName, L"3011") == 0)
@@ -35,14 +40,26 @@ void OnSDKDebugLog(const wchar_t* log)
{
UE_LOG(PS_ViveVBS, Display, TEXT("OnSDKDebugLog : strName:%s\n"), log);
}
#endif // PLATFORM_WINDOWS
int UGlobal::VBS_GetVersion()
{
#if !PLATFORM_WINDOWS
// VBS SDK is Windows-only: stub so Blueprint calls resolve without crashing.
return 0;
#else
return VS_Version();
#endif
}
int UGlobal::VBS_Init()
{
#if !PLATFORM_WINDOWS
// VBS SDK is Windows-only: stub reports failure so calibration/menu logic treats VBS as unavailable.
UGlobal::markerState = 0;
UE_LOG(PS_ViveVBS, Display, TEXT("VBS_Init : stub, VBS SDK not available on this platform"));
return -1;
#else
int retCode = VS_Init();
UGlobal::markerState = 0;
@@ -57,11 +74,16 @@ int UGlobal::VBS_Init()
}
return retCode;
#endif // PLATFORM_WINDOWS
}
int UGlobal::VBS_Release()
{
#if !PLATFORM_WINDOWS
return -1;
#else
return VS_Release();
#endif
}
#undef LOCTEXT_NAMESPACE

View File

@@ -3,12 +3,21 @@
#include "../Public/GunMode.h"
#if PLATFORM_WINDOWS
#include "VS_PC_SDK.h"
#endif
//DEFINE_LOG_CATEGORY(PS_ViveVBS);
#define LOCTEXT_NAMESPACE "VBS"
bool UGunMode::VBS_SetGunMode(const bool active)
{
#if !PLATFORM_WINDOWS
// VBS SDK is Windows-only: stub so Blueprint calls resolve and report failure.
UE_LOG(PS_ViveVBS, Display, TEXT("VBS_SetGunMode(%d) : stub, VBS SDK not available on this platform"), active ? 1 : 0);
return false;
#else
bool success = false;
if (active)
{
@@ -35,6 +44,7 @@ bool UGunMode::VBS_SetGunMode(const bool active)
}
}
return success;
#endif // PLATFORM_WINDOWS
}

View File

@@ -4,12 +4,24 @@
#include "../Public/MBLS.h"
#include "../Public/Global.h"
#if PLATFORM_WINDOWS
#include "VS_PC_SDK.h"
#else
// VBS SDK is Windows-only: on other platforms every function below is a stub
// returning failure, so Blueprint calls resolve without crashing.
#define VBS_STUB_LOG(FuncName) UE_LOG(PS_ViveVBS, Display, TEXT(FuncName " : stub, VBS SDK not available on this platform"))
#endif
//DEFINE_LOG_CATEGORY(PS_ViveVBS);
#define LOCTEXT_NAMESPACE "VBS"
bool UMBLS::DefineSingleArcuoMarker(const int32 IDMarker1, const float sizeMarker1, const float height)
{
#if !PLATFORM_WINDOWS
VBS_STUB_LOG("DefineSingleArcuoMarker");
return false;
#else
UE_LOG(PS_ViveVBS, Display, TEXT("DefineArcuoMarker ID : %d - Size : %f"), IDMarker1, sizeMarker1);
const FString parameters = FString::Printf(TEXT("PLAYER00InitMA{\"marker1\":{\"id\":%d,\"behavior\":3,\"size\":%f,\"pose\":[0,0,0,1,0,%f,0]}}"), IDMarker1, sizeMarker1, height);
@@ -24,10 +36,15 @@ bool UMBLS::DefineSingleArcuoMarker(const int32 IDMarker1, const float sizeMarke
UE_LOG(PS_ViveVBS, Display, TEXT("Define Single ArcuoMarker : FAILED"));
return false;
}
#endif // PLATFORM_WINDOWS
}
bool UMBLS::DefineTwoArcuoMarker(const int32 IDMarker1, const int32 IDMarker2, const float sizeMarker, const float height)
{
#if !PLATFORM_WINDOWS
VBS_STUB_LOG("DefineTwoArcuoMarker");
return false;
#else
UE_LOG(PS_ViveVBS, Display, TEXT("DefineTwoArcuoMarker ID : %d - ID2 : %d - Size : %f"), IDMarker1, IDMarker2, sizeMarker);
FString parameters = FString::Printf(TEXT("PLAYER00InitMA{\"marker1\":{\"id\":%d,\"behavior\":3,\"size\":%f,\"isMainMarker\":true,\"pairMarkerID\":%d,\"pose\":[0,0,0,1,0,%f,0]},\"marker2\":{\"id\":%d,\"behavior\":3,\"size\":%f,\"isMainMarker\":false,\"pairMarkerID\":%d,\"pose\":[0,0,0,1,0,%f,0]}}"), IDMarker1, sizeMarker, IDMarker2, height, IDMarker2, sizeMarker, IDMarker1, height);
@@ -42,6 +59,7 @@ bool UMBLS::DefineTwoArcuoMarker(const int32 IDMarker1, const int32 IDMarker2, c
UE_LOG(PS_ViveVBS, Display, TEXT("Define Two ArcuoMarker : FAILED"));
return false;
}
#endif // PLATFORM_WINDOWS
}
/*
@@ -69,24 +87,32 @@ bool UMBLS::RecenterXForm()
{
UE_LOG(LogInit, Display, TEXT("RecenterXForm"));
#if !PLATFORM_WINDOWS
return false;
#else
bool success = true;
success = success && VS_WVRSetParameters(DEVICE_TYPE_HMD, L"ClearRecenterXform");
success = success && VS_WVRSetParameters(DEVICE_TYPE_CONTROLLER_RIGHT, L"ClearRecenterXform");
success = success && VS_WVRSetParameters(DEVICE_TYPE_CONTROLLER_LEFT, L"ClearRecenterXform");
return success;
#endif
}
bool UMBLS::RecenterXFormTR()
{
UE_LOG(LogInit, Display, TEXT("RecenterXFormTR"));
#if !PLATFORM_WINDOWS
return false;
#else
bool success = true;
success = success && VS_WVRSetParameters(DEVICE_TYPE_HMD, L"ClearRecenterXformTR");
success = success && VS_WVRSetParameters(DEVICE_TYPE_CONTROLLER_RIGHT, L"ClearRecenterXformTR");
success = success && VS_WVRSetParameters(DEVICE_TYPE_CONTROLLER_LEFT, L"ClearRecenterXformTR");
return success;
#endif
}
bool UMBLS::StartMarkerScanning()
@@ -94,6 +120,10 @@ bool UMBLS::StartMarkerScanning()
UE_LOG(LogInit, Display, TEXT("StartMarkerScanning"));
UGlobal::markerState = 0;
#if !PLATFORM_WINDOWS
VBS_STUB_LOG("StartMarkerScanning");
return false;
#else
if (VS_WVRGetParameters(DEVICE_TYPE_HMD, L"PLAYER00StartScan"))
{
UE_LOG(PS_ViveVBS, Display, TEXT("StartMarkerScanning : SUCCESS"));
@@ -104,12 +134,16 @@ bool UMBLS::StartMarkerScanning()
UE_LOG(PS_ViveVBS, Display, TEXT("StartMarkerScanning : FAILED"));
return false;
}
#endif // PLATFORM_WINDOWS
}
bool UMBLS::StopMarkerScanning()
{
UE_LOG(LogInit, Display, TEXT("StopMarkerScanning"));
#if !PLATFORM_WINDOWS
return false;
#else
if (VS_WVRGetParameters(DEVICE_TYPE_HMD, L"PLAYER00StopScan"))
{
UE_LOG(PS_ViveVBS, Display, TEXT("StopMarkerScanning : SUCCESS"));
@@ -120,12 +154,16 @@ bool UMBLS::StopMarkerScanning()
UE_LOG(PS_ViveVBS, Display, TEXT("StopMarkerScanning : FAILED"));
return false;
}
#endif // PLATFORM_WINDOWS
}
int32 UMBLS::CheckScanStatus()
{
UE_LOG(LogInit, Display, TEXT("CheckMarkerScanning"));
#if !PLATFORM_WINDOWS
return 0;
#else
if (VS_WVRGetParameters(DEVICE_TYPE_HMD, L"PLAYER00CheckMA"))
{
UE_LOG(PS_ViveVBS, Display, TEXT("CheckMarkerScanning : SUCCESS - Value is %d"), UGlobal::markerState);
@@ -136,6 +174,7 @@ int32 UMBLS::CheckScanStatus()
UE_LOG(PS_ViveVBS, Display, TEXT("CheckMarkerScanning : FAILED"));
return 0;
}
#endif // PLATFORM_WINDOWS
}
void UMBLS::ResetMarkerState()
@@ -146,11 +185,15 @@ void UMBLS::ResetMarkerState()
int32 UMBLS::RetrievePreviousScan()
{
#if !PLATFORM_WINDOWS
return 0;
#else
CheckScanStatus();
VS_WVRSetParameters(DEVICE_TYPE_HMD, L"ClearRecenterXform");
VS_WVRSetParameters(DEVICE_TYPE_CONTROLLER_RIGHT, L"ClearRecenterXform");
VS_WVRSetParameters(DEVICE_TYPE_CONTROLLER_LEFT, L"ClearRecenterXform");
return UGlobal::markerState;
#endif
}
/*

View File

@@ -3,12 +3,21 @@
#include "../Public/Passthrough.h"
#if PLATFORM_WINDOWS
#include "VS_PC_SDK.h"
#endif
//DEFINE_LOG_CATEGORY(PS_ViveVBS);
#define LOCTEXT_NAMESPACE "VBS"
bool UPassthrough::VBS_SetPassthrough(const bool active)
{
#if !PLATFORM_WINDOWS
// VBS SDK is Windows-only: stub so Blueprint calls resolve and report failure.
UE_LOG(PS_ViveVBS, Display, TEXT("VBS_SetPassthrough(%d) : stub, VBS SDK not available on this platform"), active ? 1 : 0);
return false;
#else
bool success = false;
if (active)
{
@@ -35,6 +44,7 @@ bool UPassthrough::VBS_SetPassthrough(const bool active)
}
}
return success;
#endif // PLATFORM_WINDOWS
}

View File

@@ -1,7 +1,10 @@
// Copyright Asterion VR. All right reserved
#include "ViveVBS.h"
#if PLATFORM_WINDOWS
#include "VS_PC_SDK.h"
#endif
#define LOCTEXT_NAMESPACE "FViveVBSModule"

View File

@@ -4,7 +4,6 @@
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "../VBS_SDK/VS_PC_SDK.h"
#include "Global.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(PS_ViveVBS, Log, All);

View File

@@ -4,7 +4,6 @@
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "../VBS_SDK/VS_PC_SDK.h"
#include "Global.h"
#include "GunMode.generated.h"

View File

@@ -4,7 +4,6 @@
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "../VBS_SDK/VS_PC_SDK.h"
#include "Global.h"
#include "MBLS.generated.h"

View File

@@ -4,7 +4,6 @@
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "../VBS_SDK/VS_PC_SDK.h"
#include "Global.h"
#include "Passthrough.generated.h"

View File

@@ -8,96 +8,42 @@ public class ViveVBS : ModuleRules
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
});
PrivateDependencyModuleNames.AddRange(
new string[]
PrivateDependencyModuleNames.AddRange(new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
// ... add private dependencies that you statically link with here ...
}
);
});
if (Target.Platform == UnrealTargetPlatform.Win64)
{
string SdkRoot = Path.Combine(PluginDirectory, "Source", "ThirdParty", "VBS_SDK");
string IncludeDir = Path.Combine(SdkRoot, "include");
string Win64Dir = Path.Combine(SdkRoot, "Win64");
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
#if DYNAMIC_LINKAGE
PublicDefinitions.Add("VBS_DYNAMIC_LINKAGE=1");
#endif
string VBS_SDK_PATH = Path.Combine(PluginDirectory, "Source/ViveVBS/VBS_SDK/");
PublicIncludePaths.Add(VBS_SDK_PATH);
#if DYNAMIC_LINKAGE
PublicDelayLoadDLLs.Add("VS_PC_SDK.dll");
PublicDelayLoadDLLs.Add("RRServerManageAPI.dll");
RuntimeDependencies.Add("$(EngineDir)/Binaries/ThirdParty/VBS_SDK/VS_PC_SDK.dll"));
RuntimeDependencies.Add("$(EngineDir)/Binaries/ThirdParty/VBS_SDK/RRServerManageAPI.dll"));
PrivateIncludePaths.Add(IncludeDir);
PublicAdditionalLibraries.Add(Path.Combine(Win64Dir, "VS_PC_SDK.lib"));
#else
PublicAdditionalLibraries.Add(Path.Combine(VBS_SDK_PATH, "VS_PC_SDK.lib"));
string[] Dlls =
{
"VS_PC_SDK.dll",
"RRServerManageAPI.dll",
"VSWPipeVarClient64U_MT.dll",
};
if (Target.Type == TargetRules.TargetType.Editor)
foreach (string Dll in Dlls)
{
string srcPath = Path.Combine(ModuleDirectory, "../../ThirdParty/Win64/");
string destPath = Path.Combine(ModuleDirectory, "../../../../Binaries/Win64/");
string[] dlls = { "VS_PC_SDK.dll", "RRServerManageAPI.dll", "VSWPipeVarClient64U_MT.dll" };
foreach (string dll in dlls)
{
string src = srcPath + dll;
string dest = destPath + dll;
bool needCopy = !File.Exists(dest);
if (!needCopy)
{
var srcInfo = new FileInfo(src);
var destInfo = new FileInfo(dest);
needCopy = srcInfo.LastWriteTimeUtc > destInfo.LastWriteTimeUtc
|| srcInfo.Length != destInfo.Length;
}
if (needCopy)
{
try
{
File.Copy(src, dest, true);
}
catch (IOException)
{
System.Console.WriteLine("ViveVBS: Could not copy " + dll + " (file locked). Using existing copy.");
RuntimeDependencies.Add(
Path.Combine("$(BinaryOutputDir)", Dll),
Path.Combine(Win64Dir, Dll),
StagedFileType.NonUFS);
}
}
}
}
RuntimeDependencies.Add("$(ProjectDir)/Binaries/Win64/VS_PC_SDK.dll");
RuntimeDependencies.Add("$(ProjectDir)/Binaries/Win64/RRServerManageAPI.dll");
RuntimeDependencies.Add("$(ProjectDir)/Binaries/Win64/VSWPipeVarClient64U_MT.dll");
#endif
}
}

View File

@@ -19,8 +19,9 @@
"Name": "ViveVBS",
"Type": "Runtime",
"LoadingPhase": "Default",
"WhitelistPlatforms": [
"Win64"
"PlatformAllowList": [
"Win64",
"Android"
]
}
]