From d20fe694aa0838ab084f69ebfc57b0f2759b77e2 Mon Sep 17 00:00:00 2001 From: Neil Smith <neil.smith@falconviz.com> Date: Wed, 26 Apr 2023 20:24:34 -0700 Subject: [PATCH] offaxisplugin --- Config/Android_LenovoA3.ini | 112 ++++++++++++++++++ Config/Android_Quest.ini | 108 +++++++++++++++++ Config/DefaultEngine.ini | 49 ++++---- CyberProject.uproject | 4 + .../xrPerson/Blueprints/BP_VRPawn.uasset | 4 +- .../Blueprints/SplineNavigator.uasset | 4 +- .../xrPerson/Hands/HandSprayActor.uasset | 4 +- .../CyberArchWarehouse.uplugin | 5 +- .../CyberArchWarehouse.Build.cs | 23 ++-- Plugins/Freetrack/Resources/Icon128.png | Bin 0 -> 13099 bytes .../freetrack/Private/freetrackBPLibrary.cpp | 39 ++++++ .../Source/freetrack/Private/freetrackP.cpp | 19 +++ .../Source/freetrack/Public/freetrack.h | 16 +++ .../freetrack/Public/freetrackBPLibrary.h | 64 ++++++++++ .../Source/freetrack/freetrack.Build.cs | 57 +++++++++ Plugins/Freetrack/freetrack.uplugin | 27 +++++ Plugins/Freetrack/freetrackclient64.dll | Bin 0 -> 16384 bytes Plugins/OffAxisProjection | 1 + 18 files changed, 499 insertions(+), 37 deletions(-) create mode 100644 Config/Android_LenovoA3.ini create mode 100644 Config/Android_Quest.ini create mode 100644 Plugins/Freetrack/Resources/Icon128.png create mode 100644 Plugins/Freetrack/Source/freetrack/Private/freetrackBPLibrary.cpp create mode 100644 Plugins/Freetrack/Source/freetrack/Private/freetrackP.cpp create mode 100644 Plugins/Freetrack/Source/freetrack/Public/freetrack.h create mode 100644 Plugins/Freetrack/Source/freetrack/Public/freetrackBPLibrary.h create mode 100644 Plugins/Freetrack/Source/freetrack/freetrack.Build.cs create mode 100644 Plugins/Freetrack/freetrack.uplugin create mode 100644 Plugins/Freetrack/freetrackclient64.dll create mode 160000 Plugins/OffAxisProjection diff --git a/Config/Android_LenovoA3.ini b/Config/Android_LenovoA3.ini new file mode 100644 index 0000000..5a89df1 --- /dev/null +++ b/Config/Android_LenovoA3.ini @@ -0,0 +1,112 @@ +[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings] +PackageName=com.cyberarch.samples.ue +StoreVersion=1 +StoreVersionOffsetArm64=0 +StoreVersionOffsetX8664=0 +ApplicationDisplayName=CyberArchWarehouse +VersionDisplayName=0.12.1 +MinSDKVersion=29 +TargetSDKVersion=29 +InstallLocation=InternalOnly +bEnableLint=False +bPackageDataInsideApk=True +bCreateAllPlatformsInstall=False +bDisableVerifyOBBOnStartUp=True +bForceSmallOBBFiles=False +bAllowLargeOBBFiles=False +bAllowPatchOBBFile=False +bAllowOverflowOBBFiles=False +bUseExternalFilesDir=False +bPublicLogFiles=True +Orientation=Landscape +MaxAspectRatio=10.000000 +bUseDisplayCutout=False +bRestoreNotificationsOnReboot=False +bFullScreen=True +bEnableNewKeyboard=True +DepthBufferPreference=Default +bValidateTextureFormats=True +bForceCompressNativeLibs=False +bEnableAdvancedBinaryCompression=False +bEnableBundle=False +bEnableUniversalAPK=True +bBundleABISplit=True +bBundleLanguageSplit=True +bBundleDensitySplit=True +ExtraManifestNodeTags= +ExtraManifestNodeTags=xmlns:tools="http://schemas.android.com/tools" +ExtraApplicationNodeTags= +ExtraApplicationSettings=<activity android:name="com.qualcomm.snapdragon.spaces.unrealcustomlauncher.SpacesLauncher" tools:node="merge">\n<intent-filter>\n<category android:name="android.intent.category.LAUNCHER" />\n</intent-filter>\n</activity> +ExtraActivitySettings= +ExtraPermissions=android.permission.READ_EXTERNAL_STORAGE +ExtraPermissions=android.permission.WRITE_EXTERNAL_STORAGE +ExtraPermissions=android.permission.SET_DEBUG_APP +bAndroidVoiceEnabled=False +bRemoveOSIG=False +KeyStore= +KeyAlias= +KeyStorePassword= +KeyPassword= +bBuildForArm64=True +bBuildForX8664=False +bBuildForES31=False +bSupportsVulkan=True +bSupportsVulkanSM5=False +DebugVulkanLayerDirectory=(Path="") +bAndroidOpenGLSupportsBackbufferSampling=False +bDetectVulkanByDefault=True +bBuildWithHiddenSymbolVisibility=False +bDisableStackProtector=False +bDisableLibCppSharedDependencyValidation=False +bSaveSymbols=False +bStripShaderReflection=True +bEnableGooglePlaySupport=False +bUseGetAccounts=False +GamesAppID= +bEnableSnapshots=False +bSupportAdMob=True +AdMobAdUnitID= +GooglePlayLicenseKey= +GCMClientSenderID= +bShowLaunchImage=False +bAllowIMU=False +bAllowControllers=True +bBlockAndroidKeysOnControllers=False +bControllersBlockDeviceFeedback=False +AndroidAudio=Default +AudioSampleRate=44100 +AudioCallbackBufferFrameSize=1024 +AudioNumBuffersToEnqueue=4 +AudioMaxChannels=0 +AudioNumSourceWorkers=0 +SpatializationPlugin= +SourceDataOverridePlugin= +ReverbPlugin= +OcclusionPlugin= +CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0) +CacheSizeKB=0 +MaxChunkSizeOverrideKB=0 +bResampleForDevice=False +SoundCueCookQualityIndex=-1 +MaxSampleRate=0.000000 +HighSampleRate=0.000000 +MedSampleRate=0.000000 +LowSampleRate=0.000000 +MinSampleRate=0.000000 +CompressionQualityModifier=0.000000 +AutoStreamingThreshold=0.000000 +AndroidGraphicsDebugger=None +MaliGraphicsDebuggerPath=(Path="") +bEnableMaliPerfCounters=False +bMultiTargetFormat_ETC2=True +bMultiTargetFormat_DXT=True +bMultiTargetFormat_ASTC=True +TextureFormatPriority_ETC2=0.200000 +TextureFormatPriority_DXT=0.600000 +TextureFormatPriority_ASTC=0.900000 +SDKAPILevelOverride= +NDKAPILevelOverride= +BuildToolsOverride= +bStreamLandscapeMeshLODs=False +bEnableDomStorage=False + diff --git a/Config/Android_Quest.ini b/Config/Android_Quest.ini new file mode 100644 index 0000000..39bb4ea --- /dev/null +++ b/Config/Android_Quest.ini @@ -0,0 +1,108 @@ +[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings] +PackageName=com.FalconViz.ArHBIM +StoreVersion=1 +StoreVersionOffsetArm64=0 +StoreVersionOffsetX8664=0 +ApplicationDisplayName= +VersionDisplayName=1.0 +MinSDKVersion=29 +TargetSDKVersion=29 +InstallLocation=InternalOnly +bEnableLint=False +bPackageDataInsideApk=True +bCreateAllPlatformsInstall=False +bDisableVerifyOBBOnStartUp=False +bForceSmallOBBFiles=False +bAllowLargeOBBFiles=False +bAllowPatchOBBFile=False +bAllowOverflowOBBFiles=False +bUseExternalFilesDir=False +bPublicLogFiles=True +Orientation=SensorLandscape +MaxAspectRatio=2.100000 +bUseDisplayCutout=False +bRestoreNotificationsOnReboot=False +bFullScreen=True +bEnableNewKeyboard=True +DepthBufferPreference=Default +bValidateTextureFormats=True +bForceCompressNativeLibs=False +bEnableAdvancedBinaryCompression=False +bEnableBundle=False +bEnableUniversalAPK=True +bBundleABISplit=True +bBundleLanguageSplit=True +bBundleDensitySplit=True +ExtraApplicationSettings= +ExtraActivitySettings= +bAndroidVoiceEnabled=False +PackageForOculusMobile=Quest2 +PackageForOculusMobile=Quest +bRemoveOSIG=False +KeyStore= +KeyAlias= +KeyStorePassword= +KeyPassword= +bBuildForArm64=True +bBuildForX8664=False +bBuildForES31=True +bSupportsVulkan=True +bSupportsVulkanSM5=False +DebugVulkanLayerDirectory=(Path="") +bAndroidOpenGLSupportsBackbufferSampling=False +bDetectVulkanByDefault=True +bBuildWithHiddenSymbolVisibility=False +bDisableStackProtector=False +bDisableLibCppSharedDependencyValidation=False +bSaveSymbols=False +bStripShaderReflection=True +bEnableGooglePlaySupport=False +bUseGetAccounts=False +GamesAppID= +bEnableSnapshots=False +bSupportAdMob=True +AdMobAdUnitID= +GooglePlayLicenseKey= +GCMClientSenderID= +bShowLaunchImage=True +bAllowIMU=False +bAllowControllers=True +bBlockAndroidKeysOnControllers=False +bControllersBlockDeviceFeedback=False +AndroidAudio=Default +AudioSampleRate=44100 +AudioCallbackBufferFrameSize=1024 +AudioNumBuffersToEnqueue=4 +AudioMaxChannels=0 +AudioNumSourceWorkers=0 +SpatializationPlugin= +SourceDataOverridePlugin= +ReverbPlugin= +OcclusionPlugin= +CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0) +CacheSizeKB=65536 +MaxChunkSizeOverrideKB=0 +bResampleForDevice=False +SoundCueCookQualityIndex=-1 +MaxSampleRate=48000.000000 +HighSampleRate=32000.000000 +MedSampleRate=24000.000000 +LowSampleRate=12000.000000 +MinSampleRate=8000.000000 +CompressionQualityModifier=1.000000 +AutoStreamingThreshold=0.000000 +AndroidGraphicsDebugger=None +MaliGraphicsDebuggerPath=(Path="") +bEnableMaliPerfCounters=False +bMultiTargetFormat_ETC2=True +bMultiTargetFormat_DXT=True +bMultiTargetFormat_ASTC=True +TextureFormatPriority_ETC2=0.200000 +TextureFormatPriority_DXT=0.600000 +TextureFormatPriority_ASTC=0.900000 +SDKAPILevelOverride= +NDKAPILevelOverride= +BuildToolsOverride= +bStreamLandscapeMeshLODs=False +bEnableDomStorage=False + diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 11e3847..d8b600a 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -1,5 +1,5 @@ [/Script/EngineSettings.GameMapsSettings] -GameDefaultMap=/CyberArchWarehouse/SpatialAnchorsSample/Maps/SA_Showcase.SA_Showcase +GameDefaultMap=/CyberArchWarehouse/xrPerson/Maps/EmptyStart.EmptyStart EditorStartupMap=/CyberArchWarehouse/xrPerson/Maps/EmptyStart.EmptyStart GlobalDefaultGameMode=/CyberArchWarehouse/xrPerson/Blueprints/BP_FirstPersonGameMode.BP_FirstPersonGameMode_C @@ -175,6 +175,8 @@ CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' [/Script/Engine.Engine] +ActiveGameNameRedirects=(OldGameName="TP_BlankBP",NewGameName="/Script/CyberProject") +ActiveGameNameRedirects=(OldGameName="/Script/TP_BlankBP",NewGameName="/Script/CyberProject") +NearClipPlane=0.100000 +LocalPlayerClassName=/Script/OffAxisProjection.OffAxisLocalPlayer [/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] bEnablePlugin=True @@ -198,29 +200,27 @@ bAnchorSupportEnabled=True bSupportExperimentalFeatures=True [/Script/AndroidRuntimeSettings.AndroidRuntimeSettings] -PackageName=com.FalconViz.ArHBIM +PackageName=com.cyberarch.samples.ue StoreVersion=1 -StoreVersionOffsetArmV7=0 StoreVersionOffsetArm64=0 StoreVersionOffsetX8664=0 -ApplicationDisplayName= -VersionDisplayName=1.0 +ApplicationDisplayName=CyberArchWarehouse +VersionDisplayName=0.12.1 MinSDKVersion=29 TargetSDKVersion=29 InstallLocation=InternalOnly -bEnableGradle=True bEnableLint=False bPackageDataInsideApk=True bCreateAllPlatformsInstall=False -bDisableVerifyOBBOnStartUp=False +bDisableVerifyOBBOnStartUp=True bForceSmallOBBFiles=False bAllowLargeOBBFiles=False bAllowPatchOBBFile=False bAllowOverflowOBBFiles=False bUseExternalFilesDir=False bPublicLogFiles=True -Orientation=SensorLandscape -MaxAspectRatio=2.100000 +Orientation=Landscape +MaxAspectRatio=10.000000 bUseDisplayCutout=False bRestoreNotificationsOnReboot=False bFullScreen=True @@ -234,8 +234,14 @@ bEnableUniversalAPK=True bBundleABISplit=True bBundleLanguageSplit=True bBundleDensitySplit=True -ExtraApplicationSettings= ++ExtraManifestNodeTags= ++ExtraManifestNodeTags=xmlns:tools="http://schemas.android.com/tools" ++ExtraApplicationNodeTags= +ExtraApplicationSettings=<activity android:name="com.qualcomm.snapdragon.spaces.unrealcustomlauncher.SpacesLauncher" tools:node="merge">\n<intent-filter>\n<category android:name="android.intent.category.LAUNCHER" />\n</intent-filter>\n</activity> ExtraActivitySettings= ++ExtraPermissions=android.permission.READ_EXTERNAL_STORAGE ++ExtraPermissions=android.permission.WRITE_EXTERNAL_STORAGE ++ExtraPermissions=android.permission.SET_DEBUG_APP bAndroidVoiceEnabled=False +PackageForOculusMobile=Quest2 +PackageForOculusMobile=Quest @@ -246,15 +252,17 @@ KeyStorePassword= KeyPassword= bBuildForArm64=True bBuildForX8664=False -bBuildForES31=True +bBuildForES31=False bSupportsVulkan=True bSupportsVulkanSM5=False DebugVulkanLayerDirectory=(Path="") bAndroidOpenGLSupportsBackbufferSampling=False bDetectVulkanByDefault=True bBuildWithHiddenSymbolVisibility=False +bDisableStackProtector=False +bDisableLibCppSharedDependencyValidation=False bSaveSymbols=False -bForceLDLinker=False +bStripShaderReflection=True bEnableGooglePlaySupport=False bUseGetAccounts=False GamesAppID= @@ -263,7 +271,7 @@ bSupportAdMob=True AdMobAdUnitID= GooglePlayLicenseKey= GCMClientSenderID= -bShowLaunchImage=True +bShowLaunchImage=False bAllowIMU=False bAllowControllers=True bBlockAndroidKeysOnControllers=False @@ -275,19 +283,20 @@ AudioNumBuffersToEnqueue=4 AudioMaxChannels=0 AudioNumSourceWorkers=0 SpatializationPlugin= +SourceDataOverridePlugin= ReverbPlugin= OcclusionPlugin= CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0) -CacheSizeKB=65536 +CacheSizeKB=0 MaxChunkSizeOverrideKB=0 bResampleForDevice=False SoundCueCookQualityIndex=-1 -MaxSampleRate=48000.000000 -HighSampleRate=32000.000000 -MedSampleRate=24000.000000 -LowSampleRate=12000.000000 -MinSampleRate=8000.000000 -CompressionQualityModifier=1.000000 +MaxSampleRate=0.000000 +HighSampleRate=0.000000 +MedSampleRate=0.000000 +LowSampleRate=0.000000 +MinSampleRate=0.000000 +CompressionQualityModifier=0.000000 AutoStreamingThreshold=0.000000 AndroidGraphicsDebugger=None MaliGraphicsDebuggerPath=(Path="") diff --git a/CyberProject.uproject b/CyberProject.uproject index 9c6fa35..4eb1d59 100644 --- a/CyberProject.uproject +++ b/CyberProject.uproject @@ -153,6 +153,10 @@ "Mac", "Linux" ] + }, + { + "Name": "freetrack", + "Enabled": true } ] } \ No newline at end of file diff --git a/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/BP_VRPawn.uasset b/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/BP_VRPawn.uasset index cb11008..db8ca33 100644 --- a/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/BP_VRPawn.uasset +++ b/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/BP_VRPawn.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9d9215ec34ca2a0c19a81a045a53efb8903fcb1bc422797f7d02de211cc2c47 -size 1018565 +oid sha256:5af711184298a3a3db083426073c6bc61f94f2f5da79bd320995273c418a0372 +size 1007405 diff --git a/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/SplineNavigator.uasset b/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/SplineNavigator.uasset index 0def16b..edd4403 100644 --- a/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/SplineNavigator.uasset +++ b/Plugins/CyberArchWarehouse/Content/xrPerson/Blueprints/SplineNavigator.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c11f348418d0cbd4d29477b24a000bb02dd4e6920ada9f6124b1fa20b9805d04 -size 397587 +oid sha256:c3163fe61dafe64876fe20a2a11d742b8ceda1809f9a4c4daa6fdb69514ca34b +size 385369 diff --git a/Plugins/CyberArchWarehouse/Content/xrPerson/Hands/HandSprayActor.uasset b/Plugins/CyberArchWarehouse/Content/xrPerson/Hands/HandSprayActor.uasset index 290f1ec..3d47d6a 100644 --- a/Plugins/CyberArchWarehouse/Content/xrPerson/Hands/HandSprayActor.uasset +++ b/Plugins/CyberArchWarehouse/Content/xrPerson/Hands/HandSprayActor.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9859e5ced1e376c66aa60321cb8c2ad24b08f9042a301cbba6d38451af92c2f0 -size 24091 +oid sha256:5c05247e4d897eef43d936829c7630703a0e119b23224044a249d0c99cf823e2 +size 22219 diff --git a/Plugins/CyberArchWarehouse/CyberArchWarehouse.uplugin b/Plugins/CyberArchWarehouse/CyberArchWarehouse.uplugin index 30c5925..0d8fa17 100644 --- a/Plugins/CyberArchWarehouse/CyberArchWarehouse.uplugin +++ b/Plugins/CyberArchWarehouse/CyberArchWarehouse.uplugin @@ -21,7 +21,10 @@ "Plugins": [ { "Name": "USDImporter", - "Enabled": true + "Enabled": true, + "PlatformAllowList": [ + "Win64" + ] } ] } \ No newline at end of file diff --git a/Plugins/CyberArchWarehouse/Source/CyberArchWarehouse/CyberArchWarehouse.Build.cs b/Plugins/CyberArchWarehouse/Source/CyberArchWarehouse/CyberArchWarehouse.Build.cs index 0ba98c9..bb9b933 100644 --- a/Plugins/CyberArchWarehouse/Source/CyberArchWarehouse/CyberArchWarehouse.Build.cs +++ b/Plugins/CyberArchWarehouse/Source/CyberArchWarehouse/CyberArchWarehouse.Build.cs @@ -22,15 +22,6 @@ public class CyberArchWarehouse : ModuleRules "UMG", "Slate", "SlateCore", - "USDStage", - "UnrealUSDWrapper", - "USDUtilities", - "USDClasses", - "USDStageEditor", - "USDStageImporter", - "USDExporter", - "USDSchemas", - "USDTests", "ProceduralMeshComponent" } ); @@ -41,7 +32,19 @@ public class CyberArchWarehouse : ModuleRules { //RuntimeDependencies.Add("C:/Program Files/Epic Games/UE_5.1/Engine/Plugins/Importers/USDImporter/Binaries/Win64/UnrealEditor-UnrealUSDWrapper.dll"); //RuntimeDependencies.Add("C:/Program Files/Epic Games/UE_5.1/Engine/Plugins/Importers/USDImporter/Binaries/Win64/UnrealEditor - USDStage.dll"); - + PublicDependencyModuleNames.AddRange( + new string[] { + "USDStage", + "UnrealUSDWrapper", + "USDUtilities", + "USDClasses", + "USDStageEditor", + "USDStageImporter", + "USDExporter", + "USDSchemas", + "USDTests" + } + ); } } diff --git a/Plugins/Freetrack/Resources/Icon128.png b/Plugins/Freetrack/Resources/Icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..d39bc4abb1bf82a043289cce0dd3fff77a78f29a GIT binary patch literal 13099 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 Aj{pDw literal 0 HcmV?d00001 diff --git a/Plugins/Freetrack/Source/freetrack/Private/freetrackBPLibrary.cpp b/Plugins/Freetrack/Source/freetrack/Private/freetrackBPLibrary.cpp new file mode 100644 index 0000000..d206b0e --- /dev/null +++ b/Plugins/Freetrack/Source/freetrack/Private/freetrackBPLibrary.cpp @@ -0,0 +1,39 @@ +#include "freetrackBPLibrary.h" + +void* UfreetrackBPLibrary::DLLHandle; +FreeTrackData UfreetrackBPLibrary::data; +FreeTrackData* UfreetrackBPLibrary::pData; + +typedef char*(*_FTProvider)(void); +typedef bool(*_FTGetData)(FreeTrackData * data); + +UfreetrackBPLibrary::UfreetrackBPLibrary(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + FString filePath; + #if PLATFORM_64BITS + filePath = FPaths::Combine(*FPaths::ProjectPluginsDir(), TEXT("freetrack/"), TEXT("FreeTrackClient64.dll")); + #else + filePath = FPaths::Combine(*FPaths::GamePluginsDir(), TEXT("freetrack/"), TEXT("FreeTrackClient.dll")); + #endif + + if(!FPaths::FileExists(filePath)) + { + UE_LOG(LogTemp, Fatal, TEXT("%s not found"), *filePath); + }else{ + UE_LOG(LogTemp, Log, TEXT("loading freetrack")); + DLLHandle = FPlatformProcess::GetDllHandle(*filePath); + pData = &data; + }; +} + + +void UfreetrackBPLibrary::getFreetrackData(const float TranslationSensitivity, const float RotationSensitivity, FVector& translation, FRotator& rotation, bool& enabled){ + + _FTGetData FTGetData = NULL; + FString procName = "FTGetData"; + FTGetData = (_FTGetData)FPlatformProcess::GetDllExport(DLLHandle, *procName); // Export the DLL function. + enabled=FTGetData(pData); + translation = FVector(-data.z*TranslationSensitivity, -data.x*TranslationSensitivity, data.y*TranslationSensitivity); + rotation = FRotator(-data.pitch*RotationSensitivity, -data.yaw * RotationSensitivity, -data.roll * RotationSensitivity); +}; \ No newline at end of file diff --git a/Plugins/Freetrack/Source/freetrack/Private/freetrackP.cpp b/Plugins/Freetrack/Source/freetrack/Private/freetrackP.cpp new file mode 100644 index 0000000..534f233 --- /dev/null +++ b/Plugins/Freetrack/Source/freetrack/Private/freetrackP.cpp @@ -0,0 +1,19 @@ +// Some copyright should be here... +#include "freetrack.h" + +#define LOCTEXT_NAMESPACE "FfreetrackModule" + +void FfreetrackModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FfreetrackModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FfreetrackModule, freetrack) \ No newline at end of file diff --git a/Plugins/Freetrack/Source/freetrack/Public/freetrack.h b/Plugins/Freetrack/Source/freetrack/Public/freetrack.h new file mode 100644 index 0000000..8f6fd0a --- /dev/null +++ b/Plugins/Freetrack/Source/freetrack/Public/freetrack.h @@ -0,0 +1,16 @@ +// Some copyright should be here... + +#pragma once + +#include "Modules/ModuleManager.h" + + + +class FfreetrackModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/Freetrack/Source/freetrack/Public/freetrackBPLibrary.h b/Plugins/Freetrack/Source/freetrack/Public/freetrackBPLibrary.h new file mode 100644 index 0000000..ad78aa2 --- /dev/null +++ b/Plugins/Freetrack/Source/freetrack/Public/freetrackBPLibrary.h @@ -0,0 +1,64 @@ +#pragma once +#include "Engine.h" +#include "freetrackBPLibrary.generated.h" + +/* +* Function library class. +* Each function in it is expected to be static and represents blueprint node that can be called in any blueprint. +* +* When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable. +* BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins. +* BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins. +* DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu. +* Its lets you name the node using characters not allowed in C++ function names. +* CompactNodeTitle - the word(s) that appear on the node. +* Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu. +* Good example is "Print String" node which you can find also by using keyword "log". +* Category - the category your node will be under in the Blueprint drop-down menu. +* +* For more info on custom blueprint nodes visit documentation: +* https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation +*/ + +typedef struct +{ + unsigned long int dataID; + long int camWidth; + long int camHeight; + + float yaw; + float pitch; + float roll; + float x; + float y; + float z; + + float rawyaw; + float rawpitch; + float rawroll; + float rawx; + float rawy; + float rawz; + + float x1; + float y1; + float x2; + float y2; + float x3; + float y3; + float x4; + float y4; +}FreeTrackData; + +UCLASS() +class UfreetrackBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + static void* DLLHandle; + static FreeTrackData data; + static FreeTrackData *pData; + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "get Freetrack Data", Keywords = "freetrack get data"), Category = "freetrack") + static void getFreetrackData(const float TranslationSensitivity, const float RotationSensitivity, FVector& translation, FRotator& rotation, bool& enabled); +}; \ No newline at end of file diff --git a/Plugins/Freetrack/Source/freetrack/freetrack.Build.cs b/Plugins/Freetrack/Source/freetrack/freetrack.Build.cs new file mode 100644 index 0000000..694b799 --- /dev/null +++ b/Plugins/Freetrack/Source/freetrack/freetrack.Build.cs @@ -0,0 +1,57 @@ +// Some copyright should be here... + +using UnrealBuildTool; + +public class freetrack : ModuleRules +{ + public freetrack(ReadOnlyTargetRules Target) : base(Target) + { + + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + "freetrack/Public" + + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + "freetrack/Private", + + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", "Engine", "Slate", "SlateCore" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/Freetrack/freetrack.uplugin b/Plugins/Freetrack/freetrack.uplugin new file mode 100644 index 0000000..9ce5c12 --- /dev/null +++ b/Plugins/Freetrack/freetrack.uplugin @@ -0,0 +1,27 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "Freetrack", + "Description": "", + "Category": "Input Devices", + "CreatedBy": "worstplayer", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "EngineVersion": "5.1.0", + "CanContainContent": true, + "IsBetaVersion": true, + "Installed": true, + "Modules": [ + { + "Name": "freetrack", + "Type": "Runtime", + "LoadingPhase": "Default", + "PlatformAllowList": [ + "Win64" + ] + } + ] +} \ No newline at end of file diff --git a/Plugins/Freetrack/freetrackclient64.dll b/Plugins/Freetrack/freetrackclient64.dll new file mode 100644 index 0000000000000000000000000000000000000000..e1074592661e622c459df3ef985a4d592a232da5 GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/Plugins/OffAxisProjection b/Plugins/OffAxisProjection new file mode 160000 index 0000000..f6a1340 --- /dev/null +++ b/Plugins/OffAxisProjection @@ -0,0 +1 @@ +Subproject commit f6a13407cb0a0c39bb488286d3ace9ed2e3119bc -- GitLab