├── .gitignore ├── Content └── BlueprintHoverComponent.uasset ├── HoverPlugin.uplugin ├── LICENSE ├── README.md ├── Resources └── Icon128.png └── Source └── HoverPlugin ├── HoverPlugin.Build.cs ├── Private ├── AsyncCodeHoverComponent.cpp ├── HoverPlugin.cpp └── SimpleCodeHoverComponent.cpp └── Public ├── AsyncCodeHoverComponent.h └── SimpleCodeHoverComponent.h /.gitignore: -------------------------------------------------------------------------------- 1 | Binaries/ 2 | Intermediate/ 3 | -------------------------------------------------------------------------------- /Content/BlueprintHoverComponent.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ue4plugins/HoverPlugin/fc09504d26bd9d85cb0bab2559d9f9a886fb98a6/Content/BlueprintHoverComponent.uasset -------------------------------------------------------------------------------- /HoverPlugin.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 9, 4 | "VersionName": "9.0", 5 | "EngineVersion" : "4.19.0", 6 | "FriendlyName": "HoverPlugin", 7 | "Description": "Demonstrates how to convert a BP component to a C++ component (as presented by Zak Parrish and Gerke Max Preussner at GDCE Europe 2015).", 8 | "Category": "GDCE15", 9 | "CreatedBy": "Epic Games, Inc.", 10 | "CreatedByURL": "http://epicgames.com", 11 | "DocsURL": "", 12 | "MarketplaceURL": "", 13 | "SupportURL": "https://forums.unrealengine.com/showthread.php?81573-GDCE-2015-Blueprint-Components-to-C", 14 | "Modules": [ 15 | { 16 | "Name": "HoverPlugin", 17 | "Type": "Developer", 18 | "LoadingPhase": "Default" 19 | } 20 | ], 21 | "EnabledByDefault": true, 22 | "CanContainContent": true, 23 | "IsBetaVersion": false, 24 | "Installed": false 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015 Epic Games, Inc. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HoverPlugin 2 | 3 | Unreal Engine 4 plug-in with hover effect components. 4 | 5 | 6 | ## About 7 | 8 | This Unreal Engine 4 plug-in shows how to convert a BP component to a C++ 9 | component as presented by Zak Parrish and Gerke Max Preussner during the 10 | live coding demonstration at GDCE Europe 2015. It accompanies the corresponding 11 | [presentation slides](https://headcrash.industries/vault/presentations/gdc-europe/) 12 | 13 | 14 | ## Supported Platforms 15 | 16 | This plug-in was last built against **Unreal Engine 4.19** and works on all 17 | platforms. 18 | 19 | 20 | ## Dependencies 21 | 22 | This plug-in requires Visual Studio and either a C++ code project or a the full 23 | Unreal Engine 4 source code from GitHub. If you are new to programming in UE4, 24 | please see the official [Programming Guide](https://docs.unrealengine.com/latest/INT/Programming/index.html)! 25 | 26 | 27 | ## Usage 28 | 29 | You can use this plug-in as a project plug-in, or an Engine plug-in. 30 | 31 | If you use it as a project plug-in, clone this repository into your project's 32 | */Plugins* directory and compile your game in Visual Studio. A C++ code project 33 | is required for this to work. 34 | 35 | If you use it as an Engine plug-in, clone this repository into the 36 | */Engine/Plugins/Media* directory and compile your game. Full Unreal Engine 4 37 | source code from GitHub (4.9 or higher) is required for this. 38 | 39 | After compiling the plug-in, you have to **enable it** in Unreal Editor's plug-in 40 | browser. 41 | 42 | In order to use the Blueprint version of the hover component, copy the file 43 | */Content/BlueprintHoverComponent.uasset* into your project's */Content* directory. 44 | 45 | Perform the following steps to test the components: 46 | 47 | 1. Drag a *Sphere* from the *Basic Shapes* tab into your level 48 | 2. Select the actor, lift it off the floor a bit, and click the *Add Component* button in the *Details* panel 49 | 3. Add the desired hover component, i.e. *SimpleHoverComponent* or *BlueprintHoverComponent* 50 | 4. Make sure the *Mobility* of the actor's StaticMeshComponent is set to *Movable* 51 | 5. Hit the *Play* button to start the game in the Editor 52 | 53 | Your sphere should now be hovering above the floor, slowly bouncing up and down into 54 | a stable position. 55 | 56 | Please note that the *HoverForce* value in the *SimpleHoverComponent* depends on 57 | the mass of the static mesh actor, and its default value has been adjusted to 58 | match the mass of a Sphere actor, which is currently 109.456337 kg. If you use 59 | *SimpleHoverComponent* with a mesh other than the default Sphere then you have 60 | to set its HoverForce to: *HoverForce = Mass * 10000.0* instead, or otherwise 61 | the physics won't match those of *AsyncHoverComponent* if you compare the two. 62 | 63 | 64 | ## Support 65 | 66 | Please [file an issue](https://github.com/ue4plugins/HoverPlugin/issues), submit a 67 | [pull request](https://github.com/ue4plugins/HoverPlugin/pulls?q=is%3Aopen+is%3Apr) 68 | or email us at info@headcrash.industries 69 | 70 | 71 | ## References 72 | 73 | * [GDCE 2015: Blueprint Components to C++](https://forums.unrealengine.com/showthread.php?81573-GDCE-2015-Blueprint-Components-to-C) 74 | * [Introduction to UE4 Plugins](https://wiki.unrealengine.com/An_Introduction_to_UE4_Plugins) 75 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ue4plugins/HoverPlugin/fc09504d26bd9d85cb0bab2559d9f9a886fb98a6/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/HoverPlugin/HoverPlugin.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class HoverPlugin : ModuleRules 6 | { 7 | public HoverPlugin(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | "HoverPlugin/Public" 14 | 15 | // ... add public include paths required here ... 16 | }); 17 | 18 | 19 | PrivateIncludePaths.AddRange( 20 | new string[] { 21 | "HoverPlugin/Private", 22 | 23 | // ... add other private include paths required here ... 24 | }); 25 | 26 | 27 | PublicDependencyModuleNames.AddRange( 28 | new string[] { 29 | "Core", 30 | "CoreUObject", 31 | "Engine", 32 | "InputCore", 33 | 34 | // ... add other public dependencies that you statically link with here ... 35 | }); 36 | 37 | 38 | PrivateDependencyModuleNames.AddRange( 39 | new string[] { 40 | "Slate", "SlateCore" 41 | // ... add private dependencies that you statically link with here ... 42 | }); 43 | 44 | 45 | DynamicallyLoadedModuleNames.AddRange( 46 | new string[] { 47 | 48 | // ... add any modules that your module loads dynamically here ... 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Source/HoverPlugin/Private/AsyncCodeHoverComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AsyncCodeHoverComponent.h" 4 | 5 | #include "Classes/Components/PrimitiveComponent.h" 6 | #include "Classes/Engine/World.h" 7 | #include "DrawDebugHelpers.h" 8 | #include "Math/Vector.h" 9 | #include "UObject/NameTypes.h" 10 | #include "WorldCollision.h" 11 | 12 | 13 | UAsyncCodeHoverComponent::UAsyncCodeHoverComponent() 14 | : MaxHoverForce(10000.0f) 15 | , MaxHoverForceDistance(200.0f) 16 | , PrimitiveComponent(nullptr) 17 | { 18 | PrimaryComponentTick.bCanEverTick = true; 19 | } 20 | 21 | 22 | // Called when the game starts 23 | void UAsyncCodeHoverComponent::BeginPlay() 24 | { 25 | Super::BeginPlay(); 26 | 27 | // For better readability and reusability, we moved the initialization 28 | // code for the primitive component into a separate function (see below). 29 | 30 | InitializePrimitiveComponent(); 31 | } 32 | 33 | 34 | // Called every frame 35 | void UAsyncCodeHoverComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) 36 | { 37 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 38 | 39 | if (PrimitiveComponent == nullptr) 40 | { 41 | return; 42 | } 43 | 44 | UWorld* World = GetWorld(); 45 | 46 | if (World == nullptr) 47 | { 48 | return; 49 | } 50 | 51 | const FVector Start = GetComponentTransform().GetLocation(); 52 | const FVector End = FVector(Start.X, Start.Y, Start.Z - MaxHoverForceDistance); 53 | 54 | // One drawback of the line trace implementation in USimpleCodeHoverComponent 55 | // is that the trace takes place on the precious game thread. Traces are not 56 | // prohibitively expensive, but also not exactly cheap. It would be better if 57 | // we could offload this work to another thread. We can accomplish this using 58 | // so called asynchronous line traces. 59 | 60 | // Asynchronous line traces consist of two parts: queueing the desired trace 61 | // operation, and reading back the resulting data when the trace is complete. 62 | // Asynchronous traces do not complete right away. For simplicity, we will 63 | // process the results in the next tick. This means that our traces are one 64 | // frame off, but for something like a hover effect this does not matter. 65 | 66 | // In order to not overwrite the asynchronous trace handle returned from the 67 | // previous trace, we first process the trace results of the last frame. 68 | 69 | FTraceDatum TraceDatum; 70 | 71 | if (World->QueryTraceData(AsyncTrace, TraceDatum)) 72 | { 73 | if (TraceDatum.OutHits.Num() > 0) 74 | { 75 | const FHitResult& HitResult = TraceDatum.OutHits[0]; 76 | 77 | const float Distance = (Start - HitResult.ImpactPoint).Size(); 78 | const float Ratio = FMath::Clamp(Distance / MaxHoverForceDistance, 0.0f, 1.0f); 79 | const FVector Force = (1.0f - Ratio) * MaxHoverForce * HitResult.ImpactNormal; 80 | 81 | // Previously, we treated the force as is. Now we interpret it as an 82 | // acceleration instead. The latter has the advantage that the force 83 | // will become independent of the component's mass, so that our code 84 | // will still work if we scale up our hovering Actor in the Editor. 85 | 86 | PrimitiveComponent->AddForce(Force, NAME_None, true); 87 | 88 | ::DrawDebugLine(World, Start, HitResult.ImpactPoint, FColor::Red, false, 0.0f); 89 | ::DrawDebugPoint(World, HitResult.ImpactPoint, 16.0f, FColor::Red, false, 0.0f); 90 | } 91 | } 92 | 93 | // Now that the previous frame's results are processed, we can issue a new trace. 94 | // The new returned trace handle will be used in the tick of the next frame. 95 | 96 | static FName AsyncHoverTraceTag("AsyncHoverTrace"); 97 | 98 | AsyncTrace = World->AsyncLineTraceByChannel(EAsyncTraceType::Single, Start, End, ECC_WorldDynamic, FCollisionQueryParams(AsyncHoverTraceTag)); 99 | } 100 | 101 | 102 | void UAsyncCodeHoverComponent::OnAttachmentChanged() 103 | { 104 | // The USimpleCodeHoverComponent implementation has the disadvantage that 105 | // it does not support re-attaching this hover component to different 106 | // parent components. We cannot guarantee that this will never happen, so 107 | // we should not rely on the assumption that it won't. This function is 108 | // called each time this hover component is attached to a different parent. 109 | // We use it to reinitialize the new parent component. 110 | 111 | InitializePrimitiveComponent(); 112 | } 113 | 114 | 115 | void UAsyncCodeHoverComponent::InitializePrimitiveComponent() 116 | { 117 | // Instead of getting the parent component via the owning actor's root 118 | // component, we can shorten the code by using the 'AttachParent' member 119 | // of 'SceneComponent', which already caches this pointer. 120 | 121 | PrimitiveComponent = Cast(GetAttachParent()); 122 | 123 | if (PrimitiveComponent != nullptr) 124 | { 125 | PrimitiveComponent->SetSimulatePhysics(true); 126 | PrimitiveComponent->SetLinearDamping(2.0f); 127 | PrimitiveComponent->SetAngularDamping(2.0f); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Source/HoverPlugin/Private/HoverPlugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "Modules/ModuleInterface.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | #define LOCTEXT_NAMESPACE "FHoverPluginModule" 7 | 8 | 9 | class FHoverPluginModule 10 | : public IModuleInterface 11 | { 12 | public: 13 | 14 | //~ IModuleInterface interface 15 | 16 | virtual void StartupModule() override 17 | { 18 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 19 | } 20 | 21 | virtual void ShutdownModule() override 22 | { 23 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 24 | // we call this function before unloading the module. 25 | } 26 | }; 27 | 28 | 29 | #undef LOCTEXT_NAMESPACE 30 | 31 | IMPLEMENT_MODULE(FHoverPluginModule, HoverPlugin) 32 | -------------------------------------------------------------------------------- /Source/HoverPlugin/Private/SimpleCodeHoverComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "SimpleCodeHoverComponent.h" 4 | 5 | #include "Classes/Components/PrimitiveComponent.h" 6 | #include "Classes/Engine/World.h" 7 | #include "Classes/GameFramework/Actor.h" 8 | #include "DrawDebugHelpers.h" 9 | #include "Engine/EngineTypes.h" 10 | #include "Math/Vector.h" 11 | #include "UObject/NameTypes.h" 12 | 13 | 14 | USimpleCodeHoverComponent::USimpleCodeHoverComponent() 15 | : MaxHoverForce(10000.0f * 109.456337f) 16 | , MaxHoverForceDistance(200.0f) 17 | , PrimitiveComponent(nullptr) 18 | { 19 | // This constructor function is called when a hover component is instantiated. 20 | // Other than the auto-generated code below that enables the Tick() functions 21 | // to be called, it simply initializes the component's private properties, 22 | // such as MaxHoverForce with reasonable default values. 23 | 24 | // We assume that this simple hover component will be attached to a Sphere 25 | // static mesh actor in the Editor, which has a mass of 109.456337 kg. Like the 26 | // Blueprint version, this component applies the hover force in a way that is 27 | // dependent on the mass. This flaw has been improved in UAsyncHoverComponent, 28 | // but in order make this simple hover component behave in the exact same way, 29 | // we have to scale the default value of MaxHoverForce accordingly. 30 | 31 | PrimaryComponentTick.bCanEverTick = true; 32 | } 33 | 34 | 35 | void USimpleCodeHoverComponent::BeginPlay() 36 | { 37 | // This function is called when the game starts. It is equivalent to the 38 | // 'Event Begin Play' event in the Blueprint version of this component. 39 | 40 | Super::BeginPlay(); 41 | 42 | // Get and store the primitive component that owns this hover component. 43 | // This line is equivalent to the blue sub-graph in the Blueprint component 44 | // that calls the GetOwner, GetRootComponent and CastToPrimitiveComponent 45 | // Blueprint functions respectively. 46 | 47 | PrimitiveComponent = Cast(GetOwner()->GetRootComponent()); 48 | 49 | // If we have a valid primitive component then we initialize its physics. 50 | // This code is equivalent to the red sub-graph in the Blueprint component. 51 | 52 | if (PrimitiveComponent != nullptr) 53 | { 54 | PrimitiveComponent->SetSimulatePhysics(true); 55 | PrimitiveComponent->SetLinearDamping(2.0f); 56 | PrimitiveComponent->SetAngularDamping(2.0f); 57 | } 58 | 59 | // Note that, unlike the Blueprint version of this component, which stored a 60 | // "HasPrimitive" flag in a Blueprint variable, we simply kept a pointer 61 | // to the primitive component itself. We therefore do not need to convert 62 | // the red sub-graph of the Blueprint component. When we wish to check 63 | // whether a valid primitive component exists, we simply check the pointer. 64 | } 65 | 66 | 67 | void USimpleCodeHoverComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) 68 | { 69 | // This function is called every tick. It is equivalent to the "Event Tick" 70 | // event in the Blueprint version of this component. 71 | 72 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 73 | 74 | // If we don't have a valid primitive component then nothing needs to be done. 75 | // This is equivalent to the gray 'Primitive Check' block in the Blueprint. 76 | 77 | if (PrimitiveComponent == nullptr) 78 | { 79 | return; 80 | } 81 | 82 | // Get the world that this component resides in, so we can run queries against it. 83 | 84 | UWorld* World = GetWorld(); 85 | 86 | if (World == nullptr) 87 | { 88 | return; 89 | } 90 | 91 | // Let's replicate the BP code that performs the line trace each tick. First, we 92 | // have to calculate the start and end position for the trace. The SceneComponent 93 | // super class has a field called 'ComponentToWorld' which is a transformation 94 | // matrix that contains the component's location and orientation. This is equivalent 95 | // to the 'GetWorldLocation' call in the Blueprint. The trace end point is simply 96 | // underneath the component's location. 97 | 98 | const FVector Start = GetComponentTransform().GetLocation(); 99 | const FVector End = FVector(Start.X, Start.Y, Start.Z - MaxHoverForceDistance); 100 | 101 | // Now we are ready to perform the actual trace. The result of a trace operation 102 | // will be returned in a so called HitResult that contains information about if 103 | // and where the trace hit anything. 104 | 105 | FHitResult HitResult; 106 | 107 | // There are many ways to do traces in the Engine, such as using a line or a volume, 108 | // whether the trace should stop as soon as it hits something or return all hits, 109 | // and you can also specify what types of objects should be considered for collisions. 110 | // The following line is equivalent to the LineTraceByChannel call in the Blueprint. 111 | 112 | // For debugging purposes we provide a trace tag, which is just a user defined name 113 | // for the trace. 114 | 115 | static FName AsyncHoverTraceTag("HoverComponentTrace"); 116 | 117 | if (World->LineTraceSingleByChannel(HitResult, Start, End, ECC_WorldDynamic, FCollisionQueryParams(AsyncHoverTraceTag))) 118 | { 119 | // We can now calculate the hover force that should be applied to the parent 120 | // component. The following lines are equivalent to the yellow BP sub-graph. 121 | 122 | const float Distance = (Start - HitResult.ImpactPoint).Size(); 123 | const float Ratio = FMath::Clamp(Distance / MaxHoverForceDistance, 0.0f, 1.0f); 124 | const FVector Force = (1.0f - Ratio) * MaxHoverForce * HitResult.ImpactNormal; 125 | 126 | // Finally, we apply the calculated force to the component. 127 | 128 | PrimitiveComponent->AddForce(Force, NAME_None, false); 129 | 130 | // The BP node for the line trace has an option to draw a red debug line for the, 131 | // trace and a red point for the hit point. We can implement this in C++ using the 132 | // helper functions in DrawDebugHelpers.h 133 | 134 | ::DrawDebugLine(World, Start, HitResult.ImpactPoint, FColor::Red, false, 0.0f); 135 | ::DrawDebugPoint(World, HitResult.ImpactPoint, 16.0f, FColor::Red, false, 0.0f); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Source/HoverPlugin/Public/AsyncCodeHoverComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Components/SceneComponent.h" 6 | #include "UObject/ObjectMacros.h" 7 | #include "WorldCollision.h" 8 | 9 | #include "AsyncCodeHoverComponent.generated.h" 10 | 11 | 12 | /** 13 | * This class implements a component that can be attached to a movable 14 | * primitive component in order to give it hovering physics. It is similar 15 | * to USimpleCodeHoverComponent, but improves some of the code for better 16 | * performance. In particular, the following improvements have been made: 17 | * 18 | * - The line traces no longer happen on the game thread, but asynchronously 19 | * - Added support for reattaching our hover component to other parents 20 | * - Made the hover effect independent of the hovering actor's scale (and mass) 21 | * - Shortened and reformatted some of the code to be more readable 22 | * 23 | * See the code comments for an explanation of the changes. 24 | */ 25 | UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) 26 | class HOVERPLUGIN_API UAsyncCodeHoverComponent 27 | : public USceneComponent 28 | { 29 | GENERATED_BODY() 30 | 31 | /** The maximum hover force to apply. */ 32 | UPROPERTY(EditAnywhere, Category="Hover") 33 | float MaxHoverForce; 34 | 35 | /** The maximum distance at which the hover force applies. */ 36 | UPROPERTY(EditAnywhere, Category="Hover") 37 | float MaxHoverForceDistance; 38 | 39 | public: 40 | 41 | /** Create and initialize a new instance. */ 42 | UAsyncCodeHoverComponent(); 43 | 44 | public: 45 | 46 | //~ UComponent interface 47 | 48 | virtual void BeginPlay() override; 49 | virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; 50 | 51 | public: 52 | 53 | //~ USceneComponent interface 54 | 55 | virtual void OnAttachmentChanged() override; 56 | 57 | protected: 58 | 59 | /** Initialize the primitive component that owns this hover component. */ 60 | void InitializePrimitiveComponent(); 61 | 62 | private: 63 | 64 | /** The primitive component that should hover. */ 65 | UPROPERTY() 66 | UPrimitiveComponent* PrimitiveComponent; 67 | 68 | /** Handle for retrieving asynchronous line trace results. */ 69 | FTraceHandle AsyncTrace; 70 | }; 71 | -------------------------------------------------------------------------------- /Source/HoverPlugin/Public/SimpleCodeHoverComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "Components/SceneComponent.h" 6 | #include "UObject/ObjectMacros.h" 7 | 8 | #include "SimpleCodeHoverComponent.generated.h" 9 | 10 | 11 | /** 12 | * This class implements a component that can be attached to a movable 13 | * primitive component in order to give it hovering physics. It is a direct 14 | * conversion of the BlueprintHoverComponent to C++. 15 | */ 16 | UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) 17 | class HOVERPLUGIN_API USimpleCodeHoverComponent 18 | : public USceneComponent 19 | { 20 | GENERATED_BODY() 21 | 22 | /** The maximum hover force to apply. */ 23 | UPROPERTY(EditAnywhere, Category="Hover") 24 | float MaxHoverForce; 25 | 26 | /** The maximum distance at which the hover force applies. */ 27 | UPROPERTY(EditAnywhere, Category="Hover") 28 | float MaxHoverForceDistance; 29 | 30 | public: 31 | 32 | /** Create and initialize a new instance. */ 33 | USimpleCodeHoverComponent(); 34 | 35 | public: 36 | 37 | //~ UComponent interface 38 | 39 | virtual void BeginPlay() override; 40 | virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; 41 | 42 | protected: 43 | 44 | /** Initialize the primitive component that owns this hover component. */ 45 | void InitializePrimitiveComponent(); 46 | 47 | private: 48 | 49 | /** The primitive component that should hover. */ 50 | UPROPERTY() 51 | UPrimitiveComponent* PrimitiveComponent; 52 | }; 53 | --------------------------------------------------------------------------------