├── .gitattributes ├── .gitignore ├── README.md └── VRUMG ├── Binaries └── Win64 │ ├── UE4Editor-VRUMG.pdb │ ├── UE4Editor.modules │ └── VRUMGEditor.target ├── Config ├── DefaultEditor.ini ├── DefaultEngine.ini ├── DefaultGame.ini └── DefaultInput.ini ├── Content ├── Blueprints │ ├── MenuActor.uasset │ └── VRMotionControllerUMGPawn.uasset ├── TestLevel.umap └── UMG │ └── UMG.uasset ├── Plugins └── VRUMGPlugin │ ├── Binaries │ └── Win64 │ │ ├── UE4Editor-VRUMGPlugin.pdb │ │ └── UE4Editor.modules │ ├── Resources │ └── Icon128.png │ ├── Source │ └── VRUMGPlugin │ │ ├── Private │ │ ├── VRUMGPlugin.cpp │ │ ├── VRUMGPluginBPLibrary.cpp │ │ ├── VRUMGPluginPrivatePCH.h │ │ └── VRWidgetComponent.cpp │ │ ├── Public │ │ ├── VRUMGPlugin.h │ │ ├── VRUMGPluginBPLibrary.h │ │ └── VRWidgetComponent.h │ │ └── VRUMGPlugin.Build.cs │ └── VRUMGPlugin.uplugin ├── Source ├── VRUMG.Target.cs ├── VRUMG │ ├── MyClass.cpp │ ├── MyClass.h │ ├── VRUMG.Build.cs │ ├── VRUMG.cpp │ └── VRUMG.h └── VRUMGEditor.Target.cs └── VRUMG.uproject /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2015 user specific files 2 | .vs/ 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | 22 | # Compiled Static libraries 23 | *.lai 24 | *.la 25 | *.a 26 | *.lib 27 | 28 | # Executables 29 | *.exe 30 | *.out 31 | *.app 32 | *.ipa 33 | 34 | # These project files can be generated by the engine 35 | *.xcodeproj 36 | *.sln 37 | *.suo 38 | *.opensdf 39 | *.sdf 40 | *.VC.opendb 41 | 42 | # Precompiled Assets 43 | SourceArt/**/*.png 44 | SourceArt/**/*.tga 45 | 46 | # Binary Files 47 | Binaries/* 48 | 49 | # Builds 50 | Build/* 51 | 52 | # Don't ignore icon files in Build 53 | !Build/**/*.ico 54 | 55 | # Configuration files generated by the Editor 56 | Saved/* 57 | 58 | # Compiled source files for the engine to use 59 | Intermediate/* 60 | 61 | # Cache files for the editor to use 62 | DerivedDataCache/* 63 | 64 | # ========================= 65 | # Operating System Files 66 | # ========================= 67 | 68 | # OSX 69 | # ========================= 70 | 71 | .DS_Store 72 | .AppleDouble 73 | .LSOverride 74 | 75 | # Thumbnails 76 | ._* 77 | 78 | # Files that might appear in the root of a volume 79 | .DocumentRevisions-V100 80 | .fseventsd 81 | .Spotlight-V100 82 | .TemporaryItems 83 | .Trashes 84 | .VolumeIcon.icns 85 | 86 | # Directories potentially created on remote AFP share 87 | .AppleDB 88 | .AppleDesktop 89 | Network Trash Folder 90 | Temporary Items 91 | .apdisk 92 | 93 | # Windows 94 | # ========================= 95 | 96 | # Windows image file caches 97 | Thumbs.db 98 | ehthumbs.db 99 | 100 | # Folder config file 101 | Desktop.ini 102 | 103 | # Recycle Bin used on file shares 104 | $RECYCLE.BIN/ 105 | 106 | # Windows Installer files 107 | *.cab 108 | *.msi 109 | *.msm 110 | *.msp 111 | 112 | # Windows shortcuts 113 | *.lnk 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VRUMGPlugin-ExampleProject 2 | Example project for the [VRUMGPlugin](https://github.com/mitchemmc/VRUMGPlugin) for UE4 3 | -------------------------------------------------------------------------------- /VRUMG/Binaries/Win64/UE4Editor-VRUMG.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Binaries/Win64/UE4Editor-VRUMG.pdb -------------------------------------------------------------------------------- /VRUMG/Binaries/Win64/UE4Editor.modules: -------------------------------------------------------------------------------- 1 | { 2 | "Changelist" : 2946394, 3 | "BuildId" : "4a4277d3-9135-4af6-a92f-ac54fcfd940d", 4 | "Modules" : 5 | { 6 | "VRUMG" : "UE4Editor-VRUMG.dll" 7 | } 8 | } -------------------------------------------------------------------------------- /VRUMG/Binaries/Win64/VRUMGEditor.target: -------------------------------------------------------------------------------- 1 | { 2 | "TargetName" : "VRUMGEditor", 3 | "Platform" : "Win64", 4 | "Configuration" : "Development", 5 | "BuildId" : "4a4277d3-9135-4af6-a92f-ac54fcfd940d", 6 | "Version" : 7 | { 8 | "MajorVersion" : 4, 9 | "MinorVersion" : 11, 10 | "PatchVersion" : 2, 11 | "Changelist" : 2946394, 12 | "IsLicenseeVersion" : 0, 13 | "BranchName" : "++UE4+Release-4.11" 14 | }, 15 | "BuildProducts" : 16 | [ 17 | { 18 | "Path" : "$(ProjectDir)\\Plugins\\VRUMGPlugin\\Binaries\\Win64\\UE4Editor-VRUMGPlugin.dll", 19 | "Type" : "DynamicLibrary" 20 | }, 21 | { 22 | "Path" : "$(ProjectDir)\\Plugins\\VRUMGPlugin\\Binaries\\Win64\\UE4Editor-VRUMGPlugin.pdb", 23 | "Type" : "SymbolFile" 24 | }, 25 | { 26 | "Path" : "$(ProjectDir)\\Plugins\\VRUMGPlugin\\Intermediate\\Build\\Win64\\UE4Editor\\Development\\UE4Editor-VRUMGPlugin.lib", 27 | "Type" : "ImportLibrary" 28 | }, 29 | { 30 | "Path" : "$(ProjectDir)\\Binaries\\Win64\\UE4Editor-VRUMG.dll", 31 | "Type" : "DynamicLibrary" 32 | }, 33 | { 34 | "Path" : "$(ProjectDir)\\Binaries\\Win64\\UE4Editor-VRUMG.pdb", 35 | "Type" : "SymbolFile" 36 | }, 37 | { 38 | "Path" : "$(ProjectDir)\\Intermediate\\Build\\Win64\\UE4Editor\\Development\\UE4Editor-VRUMG.lib", 39 | "Type" : "ImportLibrary" 40 | } 41 | ], 42 | "RuntimeDependencies" : 43 | [ 44 | ] 45 | } -------------------------------------------------------------------------------- /VRUMG/Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | [EditoronlyBP] 2 | bAllowClassAndBlueprintPinMatching=true 3 | bReplaceBlueprintWithClass=true 4 | bDontLoadBlueprintOutsideEditor=true 5 | bBlueprintIsNotBlueprintType=true 6 | -------------------------------------------------------------------------------- /VRUMG/Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [URL] 2 | 3 | [/Script/HardwareTargeting.HardwareTargetingSettings] 4 | TargetedHardwareClass=Desktop 5 | AppliedTargetedHardwareClass=Desktop 6 | DefaultGraphicsPerformance=Maximum 7 | AppliedDefaultGraphicsPerformance=Maximum 8 | 9 | [/Script/EngineSettings.GameMapsSettings] 10 | EditorStartupMap=/Game/TestLevel.TestLevel 11 | GameDefaultMap=/Game/TestLevel.TestLevel 12 | 13 | -------------------------------------------------------------------------------- /VRUMG/Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | [/Script/EngineSettings.GeneralProjectSettings] 2 | ProjectID=8FADB3874A5C8C8DA2CF73BC27CD4F6B 3 | -------------------------------------------------------------------------------- /VRUMG/Config/DefaultInput.ini: -------------------------------------------------------------------------------- 1 | 2 | [/Script/Engine.InputSettings] 3 | -AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 4 | -AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 5 | -AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 6 | -AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) 7 | -AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) 8 | -AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) 9 | +AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 10 | +AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 11 | +AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 12 | +AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 13 | +AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) 14 | +AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) 15 | bAltEnterTogglesFullscreen=True 16 | bUseMouseForTouch=False 17 | bEnableMouseSmoothing=True 18 | bEnableFOVScaling=True 19 | FOVScale=0.011110 20 | DoubleClickTime=0.200000 21 | DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown 22 | bAlwaysShowTouchInterface=False 23 | bShowConsoleOnFourFingerTap=True 24 | DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks 25 | ConsoleKey=None 26 | -ConsoleKeys=Tilde 27 | +ConsoleKeys=Tilde 28 | 29 | 30 | -------------------------------------------------------------------------------- /VRUMG/Content/Blueprints/MenuActor.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Content/Blueprints/MenuActor.uasset -------------------------------------------------------------------------------- /VRUMG/Content/Blueprints/VRMotionControllerUMGPawn.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Content/Blueprints/VRMotionControllerUMGPawn.uasset -------------------------------------------------------------------------------- /VRUMG/Content/TestLevel.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Content/TestLevel.umap -------------------------------------------------------------------------------- /VRUMG/Content/UMG/UMG.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Content/UMG/UMG.uasset -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Binaries/Win64/UE4Editor-VRUMGPlugin.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Plugins/VRUMGPlugin/Binaries/Win64/UE4Editor-VRUMGPlugin.pdb -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Binaries/Win64/UE4Editor.modules: -------------------------------------------------------------------------------- 1 | { 2 | "Changelist" : 2946394, 3 | "BuildId" : "5460479d-caa4-463c-bd2d-67def8605897", 4 | "Modules" : 5 | { 6 | "VRUMGPlugin" : "UE4Editor-VRUMGPlugin.dll" 7 | } 8 | } -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchemmc/VRUMGPlugin-ExampleProject/3eb07ee593db1a4dcb452ef3b00591b16b655ffa/VRUMG/Plugins/VRUMGPlugin/Resources/Icon128.png -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Private/VRUMGPlugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "VRUMGPluginPrivatePCH.h" 4 | 5 | #define LOCTEXT_NAMESPACE "FVRUMGPluginModule" 6 | 7 | void FVRUMGPluginModule::StartupModule() 8 | { 9 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 10 | 11 | } 12 | 13 | void FVRUMGPluginModule::ShutdownModule() 14 | { 15 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 16 | // we call this function before unloading the module. 17 | 18 | } 19 | 20 | #undef LOCTEXT_NAMESPACE 21 | 22 | IMPLEMENT_MODULE(FVRUMGPluginModule, VRUMGPlugin) -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Private/VRUMGPluginBPLibrary.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "VRUMGPluginPrivatePCH.h" 4 | #include "VRUMGPluginBPLibrary.h" 5 | 6 | UVRUMGPluginBPLibrary::UVRUMGPluginBPLibrary(const FObjectInitializer& ObjectInitializer) 7 | : Super(ObjectInitializer) 8 | { 9 | 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Private/VRUMGPluginPrivatePCH.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "VRUMGPlugin.h" 4 | 5 | // You should place include statements to your module's private header files here. You only need to 6 | // add includes for headers that are used in most of your module's source files though. -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Private/VRWidgetComponent.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "VRUMGPluginPrivatePCH.h" 4 | #include "VRWidgetComponent.h" 5 | #include "HittestGrid.h" 6 | #include "Slate/WidgetRenderer.h" 7 | #include "Events.h" 8 | 9 | 10 | 11 | DECLARE_CYCLE_STAT(TEXT("3DHitTesting"), STAT_Slate3DHitTesting, STATGROUP_Slate); 12 | 13 | /** 14 | * The hit tester used by all Widget Component objects. 15 | */ 16 | class FWidgetVRHitTester : public ICustomHitTestPath 17 | { 18 | public: 19 | FWidgetVRHitTester(UWorld* InWorld) 20 | : World(InWorld) 21 | , CachedFrame(-1), UseCustomHit(false) 22 | {} 23 | 24 | // ICustomHitTestPath implementation 25 | virtual TArray GetBubblePathAndVirtualCursors(const FGeometry& InGeometry, FVector2D DesktopSpaceCoordinate, bool bIgnoreEnabledStatus) const override 26 | { 27 | SCOPE_CYCLE_COUNTER(STAT_Slate3DHitTesting); 28 | 29 | if (World.IsValid() && ensure(World->IsGameWorld())) 30 | { 31 | UWorld* SafeWorld = World.Get(); 32 | if (SafeWorld) 33 | { 34 | ULocalPlayer* const TargetPlayer = GEngine->GetLocalPlayerFromControllerId(SafeWorld, 0); 35 | 36 | if (TargetPlayer && TargetPlayer->PlayerController) 37 | { 38 | if (UPrimitiveComponent* HitComponent = GetHitResultAtScreenPositionAndCache(TargetPlayer->PlayerController, InGeometry.AbsoluteToLocal(DesktopSpaceCoordinate))) 39 | { 40 | if (UWidgetComponent* WidgetComponent = Cast(HitComponent)) 41 | { 42 | // Get the "forward" vector based on the current rotation system. 43 | const FVector ForwardVector = WidgetComponent->IsUsingLegacyRotation() ? WidgetComponent->GetUpVector() : WidgetComponent->GetForwardVector(); 44 | 45 | // Make sure the player is interacting with the front of the widget 46 | if (FVector::DotProduct(ForwardVector, CachedHitResult.ImpactPoint - CachedHitResult.TraceStart) < 0.f) 47 | { 48 | // Make sure the player is close enough to the widget to interact with it 49 | if (FVector::DistSquared(CachedHitResult.TraceStart, WidgetComponent->GetComponentLocation()) <= FMath::Square(WidgetComponent->GetMaxInteractionDistance())) 50 | { 51 | return WidgetComponent->GetHitWidgetPath(CachedHitResult.Location, bIgnoreEnabledStatus); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | 60 | return TArray(); 61 | } 62 | 63 | virtual void ArrangeChildren(FArrangedChildren& ArrangedChildren) const override 64 | { 65 | for (TWeakObjectPtr Component : RegisteredComponents) 66 | { 67 | UWidgetComponent* WidgetComponent = Component.Get(); 68 | // Check if visible; 69 | if (WidgetComponent && WidgetComponent->GetSlateWidget().IsValid()) 70 | { 71 | FGeometry WidgetGeom; 72 | 73 | ArrangedChildren.AddWidget(FArrangedWidget(WidgetComponent->GetSlateWidget().ToSharedRef(), WidgetGeom.MakeChild(WidgetComponent->GetDrawSize(), FSlateLayoutTransform()))); 74 | } 75 | } 76 | } 77 | 78 | virtual TSharedPtr TranslateMouseCoordinateFor3DChild(const TSharedRef& ChildWidget, const FGeometry& ViewportGeometry, const FVector2D& ScreenSpaceMouseCoordinate, const FVector2D& LastScreenSpaceMouseCoordinate) const override 79 | { 80 | if (World.IsValid() && ensure(World->IsGameWorld())) 81 | { 82 | ULocalPlayer* const TargetPlayer = GEngine->GetLocalPlayerFromControllerId(World.Get(), 0); 83 | if (TargetPlayer && TargetPlayer->PlayerController) 84 | { 85 | FVector2D LocalMouseCoordinate = ViewportGeometry.AbsoluteToLocal(ScreenSpaceMouseCoordinate); 86 | 87 | // Check for a hit against any widget components in the world 88 | for (TWeakObjectPtr Component : RegisteredComponents) 89 | { 90 | UWidgetComponent* WidgetComponent = Component.Get(); 91 | // Check if visible; 92 | if (WidgetComponent && WidgetComponent->GetSlateWidget() == ChildWidget) 93 | { 94 | if (UPrimitiveComponent* HitComponent = GetHitResultAtScreenPositionAndCache(TargetPlayer->PlayerController, LocalMouseCoordinate)) 95 | { 96 | if (WidgetComponent == HitComponent) 97 | { 98 | TSharedPtr VirtualCursorPos = MakeShareable(new FVirtualPointerPosition); 99 | 100 | FVector2D LocalHitLocation; 101 | WidgetComponent->GetLocalHitLocation(CachedHitResult.Location, LocalHitLocation); 102 | 103 | VirtualCursorPos->CurrentCursorPosition = LocalHitLocation; 104 | VirtualCursorPos->LastCursorPosition = LocalHitLocation; 105 | 106 | return VirtualCursorPos; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | 114 | return nullptr; 115 | } 116 | // End ICustomHitTestPath 117 | 118 | UPrimitiveComponent* GetHitResultAtScreenPositionAndCache(APlayerController* PlayerController, FVector2D ScreenPosition) const 119 | { 120 | UPrimitiveComponent* HitComponent = nullptr; 121 | 122 | if (UseCustomHit) 123 | { 124 | return CachedHitResult.Component.Get(); 125 | } 126 | 127 | if (GFrameNumber != CachedFrame || CachedScreenPosition != ScreenPosition) 128 | { 129 | CachedFrame = GFrameNumber; 130 | CachedScreenPosition = ScreenPosition; 131 | 132 | if (PlayerController) 133 | { 134 | if (PlayerController->GetHitResultAtScreenPosition(ScreenPosition, ECC_Visibility, true, CachedHitResult)) 135 | { 136 | return CachedHitResult.Component.Get(); 137 | } 138 | } 139 | } 140 | else 141 | { 142 | return CachedHitResult.Component.Get(); 143 | } 144 | 145 | return nullptr; 146 | } 147 | 148 | void SetCustomHit(FHitResult hit) 149 | { 150 | if (!UseCustomHit) 151 | { 152 | UseCustomHit = true; 153 | } 154 | CachedHitResult = hit; 155 | } 156 | 157 | void RegisterWidgetComponent(UWidgetComponent* InComponent) 158 | { 159 | RegisteredComponents.AddUnique(InComponent); 160 | } 161 | 162 | void UnregisterWidgetComponent(UWidgetComponent* InComponent) 163 | { 164 | RegisteredComponents.RemoveSingleSwap(InComponent); 165 | } 166 | 167 | uint32 GetNumRegisteredComponents() const { return RegisteredComponents.Num(); } 168 | 169 | UWorld* GetWorld() const { return World.Get(); } 170 | 171 | private: 172 | TArray< TWeakObjectPtr > RegisteredComponents; 173 | TWeakObjectPtr World; 174 | 175 | mutable int64 CachedFrame; 176 | mutable FVector2D CachedScreenPosition; 177 | mutable FHitResult CachedHitResult; 178 | mutable bool UseCustomHit; 179 | }; 180 | 181 | void UVRWidgetComponent::OnRegister() 182 | { 183 | Super::Super::OnRegister(); 184 | 185 | #if !UE_SERVER 186 | if (!IsRunningDedicatedServer()) 187 | { 188 | if (Space != EWidgetSpace::Screen) 189 | { 190 | if (GetWorld()->IsGameWorld()) 191 | { 192 | TSharedPtr GameViewportWidget = GEngine->GetGameViewportWidget(); 193 | 194 | if (GameViewportWidget.IsValid()) 195 | { 196 | TSharedPtr CustomHitTestPath = GameViewportWidget->GetCustomHitTestPath(); 197 | if (!CustomHitTestPath.IsValid()) 198 | { 199 | CustomHitTestPath = MakeShareable(new FWidgetVRHitTester(GetWorld())); 200 | GameViewportWidget->SetCustomHitTestPath(CustomHitTestPath); 201 | } 202 | 203 | TSharedPtr WidgetVRHitTester = StaticCastSharedPtr(CustomHitTestPath); 204 | if (WidgetVRHitTester->GetWorld() == GetWorld()) 205 | { 206 | WidgetVRHitTester->RegisterWidgetComponent(this); 207 | WidgetHitTester = WidgetVRHitTester; 208 | } 209 | } 210 | } 211 | 212 | if (!MaterialInstance) 213 | { 214 | UpdateMaterialInstance(); 215 | } 216 | } 217 | 218 | if (Space != EWidgetSpace::Screen) 219 | { 220 | if (!WidgetRenderer.IsValid() && !GUsingNullRHI) 221 | { 222 | WidgetRenderer = MakeShareable(new FWidgetRenderer()); 223 | } 224 | } 225 | 226 | BodySetup = nullptr; 227 | 228 | InitWidget(); 229 | } 230 | #endif // !UE_SERVER 231 | 232 | } 233 | 234 | void UVRWidgetComponent::OnUnregister() 235 | { 236 | if (GetWorld()->IsGameWorld()) 237 | { 238 | TSharedPtr GameViewportWidget = GEngine->GetGameViewportWidget(); 239 | if (GameViewportWidget.IsValid()) 240 | { 241 | TSharedPtr CustomHitTestPath = GameViewportWidget->GetCustomHitTestPath(); 242 | if (CustomHitTestPath.IsValid()) 243 | { 244 | TSharedPtr WidgetHitTestPath = StaticCastSharedPtr(CustomHitTestPath); 245 | 246 | WidgetHitTestPath->UnregisterWidgetComponent(this); 247 | 248 | if (WidgetHitTestPath->GetNumRegisteredComponents() == 0) 249 | { 250 | GameViewportWidget->SetCustomHitTestPath(nullptr); 251 | } 252 | } 253 | } 254 | } 255 | 256 | #if WITH_EDITOR 257 | if (!GetWorld()->IsGameWorld()) 258 | { 259 | ReleaseResources(); 260 | } 261 | #endif 262 | 263 | Super::Super::OnUnregister(); 264 | } 265 | 266 | void UVRWidgetComponent::GetLocalHit(FVector WorldHitLocation, FVector2D& OutLocalHitLocation) 267 | { 268 | GetLocalHitLocation(WorldHitLocation, OutLocalHitLocation); 269 | } 270 | 271 | 272 | void UVRWidgetComponent::SetCustomHit(FHitResult Hit) 273 | { 274 | WidgetHitTester->SetCustomHit(Hit); 275 | } 276 | 277 | void UVRWidgetComponent::EmulateTouchDown(FHitResult Hit, bool PressLeftMouseButton) 278 | { 279 | TArray ArrangedWidgets = GetHitWidgetPath(Hit.Location, false, 1.0); 280 | if (HitTestGrid.IsValid()) 281 | { 282 | for (FWidgetAndPointer& ArrangedWidget : ArrangedWidgets) 283 | { 284 | // Create a new touch pointer event and call mouse down on our widget 285 | const FPointerEvent pointerEvent = FPointerEvent(0, 0, ArrangedWidget.PointerPosition->CurrentCursorPosition, ArrangedWidget.PointerPosition->LastCursorPosition, PressLeftMouseButton); 286 | FReply reply = ArrangedWidget.Widget->OnMouseButtonDown(ArrangedWidget.Geometry, pointerEvent); 287 | 288 | // Handle the reply from our mouse up to make sure we capture the mouse if we need 289 | FWidgetPath widgetPath = FWidgetPath(WidgetHitTester->GetBubblePathAndVirtualCursors(FGeometry(), FVector2D(), false)); // Use empty geometry and mouse location as we are going to use our custom hit 290 | FSlateApplication::Get().ProcessReply(widgetPath, reply, nullptr, &pointerEvent, 0); 291 | 292 | } 293 | } 294 | } 295 | 296 | 297 | void UVRWidgetComponent::EmulateTouchUp(FHitResult Hit, bool PressLeftMouseButton) 298 | { 299 | TArray ArrangedWidgets = GetHitWidgetPath(Hit.Location, false, 1.0); 300 | if (HitTestGrid.IsValid()) 301 | { 302 | for (FWidgetAndPointer& ArrangedWidget : ArrangedWidgets) 303 | { 304 | // Create a new touch pointer event and call mouse up on our widget 305 | const FPointerEvent pointerEvent = FPointerEvent(0, 0, ArrangedWidget.PointerPosition->CurrentCursorPosition, ArrangedWidget.PointerPosition->LastCursorPosition, PressLeftMouseButton); 306 | FReply reply = ArrangedWidget.Widget->OnMouseButtonUp(ArrangedWidget.Geometry, pointerEvent); 307 | 308 | // Handle the reply from our mouse up to make sure we release capuring if we need to 309 | FWidgetPath widgetPath = FWidgetPath(WidgetHitTester->GetBubblePathAndVirtualCursors(FGeometry(), FVector2D(), false)); // Use empty geometry and mouse location as we are going to use our custom hit 310 | FSlateApplication::Get().ProcessReply(widgetPath, reply, nullptr, &pointerEvent, 0); 311 | } 312 | } 313 | } 314 | 315 | void UVRWidgetComponent::EmulateTouchMove(FHitResult Hit, bool PressLeftMouseButton) 316 | { 317 | TArray ArrangedWidgets = GetHitWidgetPath(Hit.Location, false, 1.0); 318 | if (HitTestGrid.IsValid()) 319 | { 320 | for (FWidgetAndPointer& ArrangedWidget : ArrangedWidgets) 321 | { 322 | // Create a new touch pointer event and call mouse move on our widget 323 | ArrangedWidget.Widget->OnMouseMove(ArrangedWidget.Geometry, FPointerEvent(0, 0, ArrangedWidget.PointerPosition->CurrentCursorPosition, ArrangedWidget.PointerPosition->LastCursorPosition, PressLeftMouseButton)); 324 | } 325 | } 326 | } 327 | 328 | void UVRWidgetComponent::EmulateActivateKeyDown(FHitResult Hit) 329 | { 330 | TArray ArrangedWidgets = GetHitWidgetPath(Hit.Location, false, 1.0); 331 | if (HitTestGrid.IsValid()) 332 | { 333 | for (FWidgetAndPointer& ArrangedWidget : ArrangedWidgets) 334 | { 335 | // Create a new key event with for the enter key to simulate a activate key down 336 | ArrangedWidget.Widget->OnKeyDown(ArrangedWidget.Geometry, FKeyEvent(EKeys::Enter, FModifierKeysState(), 0, false, 0, 0)); 337 | } 338 | } 339 | } 340 | 341 | void UVRWidgetComponent::EmulateActivateKeyUp(FHitResult Hit) 342 | { 343 | TArray ArrangedWidgets = GetHitWidgetPath(Hit.Location, false, 1.0); 344 | if (HitTestGrid.IsValid()) 345 | { 346 | for (FWidgetAndPointer& ArrangedWidget : ArrangedWidgets) 347 | { 348 | // Create a new key event with for the enter key to simulate a activate key up 349 | ArrangedWidget.Widget->OnKeyUp(ArrangedWidget.Geometry, FKeyEvent(EKeys::Enter, FModifierKeysState(), 0, false, 0, 0)); 350 | } 351 | } 352 | } -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Public/VRUMGPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "ModuleManager.h" 6 | 7 | class FVRUMGPluginModule : public IModuleInterface 8 | { 9 | public: 10 | 11 | /** IModuleInterface implementation */ 12 | virtual void StartupModule() override; 13 | virtual void ShutdownModule() override; 14 | }; -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Public/VRUMGPluginBPLibrary.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Engine.h" 6 | #include "VRUMGPluginBPLibrary.generated.h" 7 | 8 | /* 9 | * Function library class. 10 | * Each function in it is expected to be static and represents blueprint node that can be called in any blueprint. 11 | * 12 | * When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable. 13 | * BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins. 14 | * BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins. 15 | * DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu. 16 | * Its lets you name the node using characters not allowed in C++ function names. 17 | * CompactNodeTitle - the word(s) that appear on the node. 18 | * Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu. 19 | * Good example is "Print String" node which you can find also by using keyword "log". 20 | * Category - the category your node will be under in the Blueprint drop-down menu. 21 | * 22 | * For more info on custom blueprint nodes visit documentation: 23 | * https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation 24 | */ 25 | UCLASS() 26 | class UVRUMGPluginBPLibrary : public UBlueprintFunctionLibrary 27 | { 28 | GENERATED_UCLASS_BODY() 29 | }; 30 | -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/Public/VRWidgetComponent.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Components/WidgetComponent.h" 6 | #include "VRWidgetComponent.generated.h" 7 | 8 | /** 9 | * 10 | */ 11 | UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) 12 | class UVRWidgetComponent : public UWidgetComponent 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | 18 | virtual void OnRegister() override; 19 | virtual void OnUnregister() override; 20 | 21 | /** Converts a world hit location to a local hit location */ 22 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 23 | void GetLocalHit(FVector WorldHitLocation, FVector2D& OutLocalHitLocation); 24 | 25 | /** Tells the Widget to ignore mouse events and use this custom hit event */ 26 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 27 | void SetCustomHit(FHitResult Hit); 28 | 29 | /** Emulates a touch press event for the given hit */ 30 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 31 | void EmulateTouchDown(FHitResult Hit, bool PressLeftMouseButton); 32 | 33 | /** Emulates a touch release event for the given hit */ 34 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 35 | void EmulateTouchUp(FHitResult Hit, bool PressLeftMouseButton); 36 | 37 | /** Emulates a touch move event for the given hit */ 38 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 39 | void EmulateTouchMove(FHitResult Hit, bool PressLeftMouseButton); 40 | 41 | /** Emulates an 'enter' key down event */ 42 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 43 | void EmulateActivateKeyDown(FHitResult Hit); 44 | 45 | /** Emulates an 'enter' key up event */ 46 | UFUNCTION(BlueprintCallable, Category = "VR Widget") 47 | void EmulateActivateKeyUp(FHitResult Hit); 48 | 49 | protected: 50 | /** The hit tester to use for this component */ 51 | TSharedPtr WidgetHitTester; 52 | 53 | }; 54 | -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/Source/VRUMGPlugin/VRUMGPlugin.Build.cs: -------------------------------------------------------------------------------- 1 | // Some copyright should be here... 2 | 3 | using UnrealBuildTool; 4 | 5 | public class VRUMGPlugin : ModuleRules 6 | { 7 | public VRUMGPlugin(TargetInfo Target) 8 | { 9 | 10 | PublicIncludePaths.AddRange( 11 | new string[] { 12 | "VRUMGPlugin/Public" 13 | 14 | // ... add public include paths required here ... 15 | } 16 | ); 17 | 18 | 19 | PrivateIncludePaths.AddRange( 20 | new string[] { 21 | "VRUMGPlugin/Private", 22 | 23 | // ... add other private include paths required here ... 24 | } 25 | ); 26 | 27 | 28 | PublicDependencyModuleNames.AddRange( 29 | new string[] 30 | { 31 | "Core", 32 | 33 | // ... add other public dependencies that you statically link with here ... 34 | } 35 | ); 36 | 37 | 38 | PrivateDependencyModuleNames.AddRange( 39 | new string[] 40 | { 41 | "CoreUObject", 42 | "Engine", 43 | "Slate", 44 | "SlateCore", 45 | "UMG", 46 | "RHI" , 47 | "InputCore" 48 | // ... add private dependencies that you statically link with here ... 49 | } 50 | ); 51 | 52 | 53 | DynamicallyLoadedModuleNames.AddRange( 54 | new string[] 55 | { 56 | // ... add any modules that your module loads dynamically here ... 57 | } 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /VRUMG/Plugins/VRUMGPlugin/VRUMGPlugin.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "1.0", 5 | "FriendlyName": "VR UMG Plugin", 6 | "Description": "Adds a compatabilty layer for UMG and VR", 7 | "Category": "Other", 8 | "CreatedBy": "Mitchell McCaffrey (mitchemmc)", 9 | "CreatedByURL": "http://mitchellmccaffrey.com/", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "", 13 | "EnabledByDefault": false, 14 | "CanContainContent": false, 15 | "IsBetaVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "VRUMGPlugin", 20 | "Type": "Runtime", 21 | "LoadingPhase": "Default" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /VRUMG/Source/VRUMG.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class VRUMGTarget : TargetRules 7 | { 8 | public VRUMGTarget(TargetInfo Target) 9 | { 10 | Type = TargetType.Game; 11 | } 12 | 13 | // 14 | // TargetRules interface. 15 | // 16 | 17 | public override void SetupBinaries( 18 | TargetInfo Target, 19 | ref List OutBuildBinaryConfigurations, 20 | ref List OutExtraModuleNames 21 | ) 22 | { 23 | OutExtraModuleNames.AddRange( new string[] { "VRUMG" } ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /VRUMG/Source/VRUMG/MyClass.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "VRUMG.h" 4 | #include "MyClass.h" 5 | 6 | MyClass::MyClass() 7 | { 8 | } 9 | 10 | MyClass::~MyClass() 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /VRUMG/Source/VRUMG/MyClass.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | /** 6 | * 7 | */ 8 | class VRUMG_API MyClass 9 | { 10 | public: 11 | MyClass(); 12 | ~MyClass(); 13 | }; 14 | -------------------------------------------------------------------------------- /VRUMG/Source/VRUMG/VRUMG.Build.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class VRUMG : ModuleRules 6 | { 7 | public VRUMG(TargetInfo Target) 8 | { 9 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); 10 | 11 | PrivateDependencyModuleNames.AddRange(new string[] { }); 12 | 13 | // Uncomment if you are using Slate UI 14 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 15 | 16 | // Uncomment if you are using online features 17 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 18 | // if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64)) 19 | // { 20 | // if (UEBuildConfiguration.bCompileSteamOSS == true) 21 | // { 22 | // DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam"); 23 | // } 24 | // } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /VRUMG/Source/VRUMG/VRUMG.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #include "VRUMG.h" 4 | 5 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, VRUMG, "VRUMG" ); 6 | -------------------------------------------------------------------------------- /VRUMG/Source/VRUMG/VRUMG.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "Engine.h" 6 | 7 | -------------------------------------------------------------------------------- /VRUMG/Source/VRUMGEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class VRUMGEditorTarget : TargetRules 7 | { 8 | public VRUMGEditorTarget(TargetInfo Target) 9 | { 10 | Type = TargetType.Editor; 11 | } 12 | 13 | // 14 | // TargetRules interface. 15 | // 16 | 17 | public override void SetupBinaries( 18 | TargetInfo Target, 19 | ref List OutBuildBinaryConfigurations, 20 | ref List OutExtraModuleNames 21 | ) 22 | { 23 | OutExtraModuleNames.AddRange( new string[] { "VRUMG" } ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /VRUMG/VRUMG.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "4.11", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "VRUMG", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default" 11 | } 12 | ] 13 | } --------------------------------------------------------------------------------