├── AutoTest ├── Config │ ├── DefaultEditorPerProjectUserSettings.ini │ ├── DefaultGame.ini │ ├── DefaultEditor.ini │ ├── DefaultEngine.ini │ └── DefaultInput.ini ├── Source │ ├── AutoTest │ │ ├── AutoTest.h │ │ ├── AutoTest.cpp │ │ ├── AutoTestGameMode.h │ │ ├── AutoTest.Build.cs │ │ ├── AutoTestHUD.h │ │ ├── AutoTestGameMode.cpp │ │ ├── EnemyCharacter.h │ │ ├── EnemyCharacter.cpp │ │ ├── Tests │ │ │ ├── EnemyCountTest.cpp │ │ │ ├── ANew │ │ │ │ ├── EnemyCountTest.spec.cpp │ │ │ │ ├── EnemyCountTestMulti.spec.cpp │ │ │ │ └── ShootEnemyTest.spec.cpp │ │ │ ├── EnemyCountTestMulti.cpp │ │ │ ├── MyTestUtils.h │ │ │ └── ShootEnemyTest.cpp │ │ ├── AutoTestHUD.cpp │ │ ├── AutoTestProjectile.h │ │ ├── AutoTestProjectile.cpp │ │ ├── AutoTestCharacter.h │ │ └── AutoTestCharacter.cpp │ ├── AutoTest.Target.cs │ └── AutoTestEditor.Target.cs ├── Content │ ├── Enemy.uasset │ ├── EnemyMat.uasset │ ├── Geometry │ │ └── Meshes │ │ │ ├── 1M_Cube.uasset │ │ │ └── CubeMaterial.uasset │ ├── FirstPerson │ │ ├── Meshes │ │ │ ├── BaseMaterial.uasset │ │ │ ├── FirstPersonProjectileMesh.uasset │ │ │ └── FirstPersonProjectileMaterial.uasset │ │ ├── FPWeapon │ │ │ └── Mesh │ │ │ │ ├── SK_FPGun.uasset │ │ │ │ ├── SK_FPGun_Skeleton.uasset │ │ │ │ └── SK_FPGun_PhysicsAsset.uasset │ │ └── Textures │ │ │ └── FirstPersonCrosshair.uasset │ └── FirstPersonCPP │ │ ├── Maps │ │ ├── FirstPersonExampleMap.umap │ │ ├── FirstPersonExampleMapPart2.umap │ │ ├── FirstPersonExampleMapPart3.umap │ │ ├── FirstPersonExampleMap_BuiltData.uasset │ │ ├── FirstPersonExampleMapPart2_BuiltData.uasset │ │ └── FirstPersonExampleMapPart3_BuiltData.uasset │ │ └── Blueprints │ │ ├── FirstPersonCharacter.uasset │ │ └── FirstPersonProjectile.uasset └── AutoTest.uproject ├── .gitignore ├── README.md ├── .gitattributes └── LICENSE.txt /AutoTest/Config/DefaultEditorPerProjectUserSettings.ini: -------------------------------------------------------------------------------- 1 | [ContentBrowser] 2 | ContentBrowserTab1.SelectedPaths=/Game/FirstPerson -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | *.sln 3 | Binaries 4 | DerivedDataCache 5 | Intermediate 6 | Saved 7 | Output 8 | Content/KiteDemo 9 | Build 10 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTest.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | -------------------------------------------------------------------------------- /AutoTest/Content/Enemy.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:562295531b3740fdad24653d13462005ca158b2a0a72072aa38f618ce7360234 3 | size 120785 4 | -------------------------------------------------------------------------------- /AutoTest/Content/EnemyMat.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:168a91cc18f96629aa3e3b57f142c74df79f8c44d7221f8c1abfd6e936d161bc 3 | size 110970 4 | -------------------------------------------------------------------------------- /AutoTest/Content/Geometry/Meshes/1M_Cube.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:349245bef4ee3ebbf1922aabdaf5a098a7f26f0625d48f3dfcaeb3bb2e650415 3 | size 74831 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/Meshes/BaseMaterial.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bcbd6a3c1739e97c3596de25ebba08289b524b48c8a1abfe8fecca2952d2f2ef 3 | size 112794 4 | -------------------------------------------------------------------------------- /AutoTest/Content/Geometry/Meshes/CubeMaterial.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ee28745e598a38998c78a3b8a1206fcc25967fc786f35b273682bcd26a087be6 3 | size 92524 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/FPWeapon/Mesh/SK_FPGun.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1a30acbb559acca73781639bd5930aa357ee650b7b922c09cff2a0d26dd9a149 3 | size 1906355 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/FPWeapon/Mesh/SK_FPGun_Skeleton.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ed61f2912f36a1df1eed74fed1be43399f677258837a80acfa076d2298f8bfc2 3 | size 2931 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/Textures/FirstPersonCrosshair.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dd1ace857d141872dba993c6dca0b4cf7c379daed86cf645635ab3eabd15f7bf 3 | size 3075 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Maps/FirstPersonExampleMap.umap: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0cc86827a1f4e2eb910b9ad9c4e3c32bb8e3b3066ef3ed6c3801120231a18c3c 3 | size 8527101 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/FPWeapon/Mesh/SK_FPGun_PhysicsAsset.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4278a0685e85f1b25929d2b7c09d9650d598747db33a8181fe2cbfbfddd5052d 3 | size 3326 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/Meshes/FirstPersonProjectileMesh.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0cfc1cc76f525a6183fc1edf7bbbcd5c04884a5620df6e35c924ca2a19a8d96 3 | size 123407 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Blueprints/FirstPersonCharacter.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d3d07899532ab814d84115f1c5896d282c0cd567294844de7c08b74499e2f78e 3 | size 96132 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Blueprints/FirstPersonProjectile.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1c01d1a68e4f4930395d4cfccd349ce339e6fc9000f119c34087691eab34c465 3 | size 90716 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Maps/FirstPersonExampleMapPart2.umap: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e3e2854fe786e8de4129583e07ccd9cc02e33f2744e66897f4159138cacfe64f 3 | size 8527964 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Maps/FirstPersonExampleMapPart3.umap: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:876c3fde68f3874bc4d37d8886930a3a9aa2758bbf8576b64a458889d3f30a48 3 | size 8527964 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPerson/Meshes/FirstPersonProjectileMaterial.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ae77f487e35f5ae8177b50bcdfbde5dde195b8deec312f6a1c4e0737224f7af2 3 | size 96145 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Maps/FirstPersonExampleMap_BuiltData.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bbdf6f1185aa6aff81059a03d98dfa308945c364895c07e7148ef4a14e723c3f 3 | size 1594372 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Maps/FirstPersonExampleMapPart2_BuiltData.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3fc12eae853e2871360883aac2bc8fe59a9597ed9368992e50a4def6e1129775 3 | size 1593429 4 | -------------------------------------------------------------------------------- /AutoTest/Content/FirstPersonCPP/Maps/FirstPersonExampleMapPart3_BuiltData.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:686d16b707dbdd97bb524cc959bb9b1ee792f0031e6eeec71ca69f041d513032 3 | size 1594402 4 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AutoTest.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, AutoTest, "AutoTest" ); 7 | -------------------------------------------------------------------------------- /AutoTest/Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | [ProjectSettings] 2 | ProjectID=(A=1823396784,B=1298598689,C=1743498150,D=-2048051708) 3 | ProjectName=First Person Template 4 | 5 | 6 | [/Script/EngineSettings.GeneralProjectSettings] 7 | ProjectID=730517E7450B4A94871CDE94F23EEB6B 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UE4 New Automation Test API Example 2 | ==== 3 | 4 | This project demonstrates how to write Automation Tests in Unreal Engine 4 using old and new test API. 5 | 6 | ## More 7 | More about tests and project here: https://zompidev.blogspot.com/2019/06/unreal-engine-4-automation-tests-new-api.html 8 | -------------------------------------------------------------------------------- /AutoTest/Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | [UnrealEd.SimpleMap] 2 | SimpleMapName=/Game/FirstPerson/Maps/FirstPersonExampleMap 3 | 4 | [EditoronlyBP] 5 | bAllowClassAndBlueprintPinMatching=true 6 | bReplaceBlueprintWithClass= true 7 | bDontLoadBlueprintOutsideEditor= true 8 | bBlueprintIsNotBlueprintType= true 9 | 10 | 11 | -------------------------------------------------------------------------------- /AutoTest/AutoTest.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "{ED0EEAF3-49C6-309C-10E8-BEA7FAE81BC2}", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "AutoTest", 9 | "Type": "Runtime", 10 | "LoadingPhase": "Default", 11 | "AdditionalDependencies": [ 12 | "Engine" 13 | ] 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class AutoTestTarget : TargetRules 7 | { 8 | public AutoTestTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | ExtraModuleNames.Add("AutoTest"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTestEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class AutoTestEditorTarget : TargetRules 7 | { 8 | public AutoTestEditorTarget(TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | ExtraModuleNames.Add("AutoTest"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestGameMode.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/GameModeBase.h" 7 | #include "AutoTestGameMode.generated.h" 8 | 9 | UCLASS(minimalapi) 10 | class AAutoTestGameMode : public AGameModeBase 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | AAutoTestGameMode(); 16 | }; 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTest.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class AutoTest : ModuleRules 6 | { 7 | public AutoTest(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.uasset filter=lfs diff=lfs merge=lfs -text 2 | *.umap filter=lfs diff=lfs merge=lfs -text 3 | *.png filter=lfs diff=lfs merge=lfs -text 4 | *.keystore filter=lfs diff=lfs merge=lfs -text 5 | *.wav filter=lfs diff=lfs merge=lfs -text 6 | *.fbx filter=lfs diff=lfs merge=lfs -text 7 | *.blend filter=lfs diff=lfs merge=lfs -text 8 | *.blend1 filter=lfs diff=lfs merge=lfs -text 9 | *.jpg filter=lfs diff=lfs merge=lfs -text 10 | *.PNG filter=lfs diff=lfs merge=lfs -text 11 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestHUD.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/HUD.h" 7 | #include "AutoTestHUD.generated.h" 8 | 9 | UCLASS() 10 | class AAutoTestHUD : public AHUD 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | AAutoTestHUD(); 16 | 17 | /** Primary draw call for the HUD */ 18 | virtual void DrawHUD() override; 19 | 20 | private: 21 | /** Crosshair asset pointer */ 22 | class UTexture2D* CrosshairTex; 23 | 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestGameMode.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AutoTestGameMode.h" 4 | #include "AutoTestHUD.h" 5 | #include "AutoTestCharacter.h" 6 | #include "UObject/ConstructorHelpers.h" 7 | 8 | AAutoTestGameMode::AAutoTestGameMode() 9 | : Super() 10 | { 11 | // set default pawn class to our Blueprinted character 12 | static ConstructorHelpers::FClassFinder PlayerPawnClassFinder(TEXT("/Game/FirstPersonCPP/Blueprints/FirstPersonCharacter")); 13 | DefaultPawnClass = PlayerPawnClassFinder.Class; 14 | 15 | // use our custom HUD class 16 | HUDClass = AAutoTestHUD::StaticClass(); 17 | } 18 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/EnemyCharacter.h: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Character.h" 7 | #include "EnemyCharacter.generated.h" 8 | 9 | UCLASS() 10 | class AUTOTEST_API AEnemyCharacter : public ACharacter 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | // Sets default values for this character's properties 16 | AEnemyCharacter(); 17 | 18 | protected: 19 | // Called when the game starts or when spawned 20 | virtual void BeginPlay() override; 21 | 22 | public: 23 | // Called every frame 24 | virtual void Tick(float DeltaTime) override; 25 | 26 | // Called to bind functionality to input 27 | virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/EnemyCharacter.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | 4 | #include "EnemyCharacter.h" 5 | 6 | // Sets default values 7 | AEnemyCharacter::AEnemyCharacter() 8 | { 9 | // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. 10 | PrimaryActorTick.bCanEverTick = true; 11 | 12 | } 13 | 14 | // Called when the game starts or when spawned 15 | void AEnemyCharacter::BeginPlay() 16 | { 17 | Super::BeginPlay(); 18 | 19 | } 20 | 21 | // Called every frame 22 | void AEnemyCharacter::Tick(float DeltaTime) 23 | { 24 | Super::Tick(DeltaTime); 25 | 26 | } 27 | 28 | // Called to bind functionality to input 29 | void AEnemyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) 30 | { 31 | Super::SetupPlayerInputComponent(PlayerInputComponent); 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/EnemyCountTest.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #include "MyTestUtils.h" 4 | #include "AutoTestCharacter.h" 5 | #include "EnemyCharacter.h" 6 | 7 | IMPLEMENT_SIMPLE_AUTOMATION_TEST(FEnemyCountTest, "AutoTest.EnemyCountTest", FMyTestUtils::TestsFlags) 8 | bool FEnemyCountTest::RunTest(const FString& Parameters) 9 | { 10 | AutomationOpenMap("/Game/FirstPersonCPP/Maps/FirstPersonExampleMap"); 11 | 12 | UWorld* World = FMyTestUtils::GetWorld(); 13 | TestNotNull("Check if World is properly created", World); 14 | if (!World) return false; 15 | 16 | int32 EnemiesCount = 0; 17 | for (TActorIterator It(World, AEnemyCharacter::StaticClass()); It; ++It) 18 | { 19 | EnemiesCount++; 20 | } 21 | TestTrue("Check if there are 3 enemies on the level", EnemiesCount == 3); 22 | 23 | ADD_LATENT_AUTOMATION_COMMAND(FExitGameCommand); 24 | 25 | return true; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/ANew/EnemyCountTest.spec.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #include "../MyTestUtils.h" 4 | #include "AutoTestCharacter.h" 5 | #include "EnemyCharacter.h" 6 | 7 | BEGIN_DEFINE_SPEC(FNewEnemyCountTest, "AutoTest.ANew.EnemyCountTest", FMyTestUtils::TestsFlags) 8 | 9 | UWorld* World; 10 | 11 | END_DEFINE_SPEC(FNewEnemyCountTest) 12 | 13 | void FNewEnemyCountTest::Define() 14 | { 15 | BeforeEach([this]() 16 | { 17 | AutomationOpenMap("/Game/FirstPersonCPP/Maps/FirstPersonExampleMap"); 18 | World = FMyTestUtils::GetWorld(); 19 | TestNotNull("Check if World is properly created", World); 20 | }); 21 | 22 | It("Test Enemy Count", [this]() 23 | { 24 | int32 EnemiesCount = 0; 25 | for (TActorIterator It(World, AEnemyCharacter::StaticClass()); It; ++It) 26 | { 27 | EnemiesCount++; 28 | } 29 | TestTrue("Check if there are 3 enemies on the level", EnemiesCount == 3); 30 | }); 31 | 32 | AfterEach([this]() 33 | { 34 | FMyTestUtils::Exit(); 35 | }); 36 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Damian Nowakowski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestHUD.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AutoTestHUD.h" 4 | #include "Engine/Canvas.h" 5 | #include "Engine/Texture2D.h" 6 | #include "TextureResource.h" 7 | #include "CanvasItem.h" 8 | #include "UObject/ConstructorHelpers.h" 9 | 10 | AAutoTestHUD::AAutoTestHUD() 11 | { 12 | // Set the crosshair texture 13 | static ConstructorHelpers::FObjectFinder CrosshairTexObj(TEXT("/Game/FirstPerson/Textures/FirstPersonCrosshair")); 14 | CrosshairTex = CrosshairTexObj.Object; 15 | } 16 | 17 | 18 | void AAutoTestHUD::DrawHUD() 19 | { 20 | Super::DrawHUD(); 21 | 22 | // Draw very simple crosshair 23 | 24 | // find center of the Canvas 25 | const FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f); 26 | 27 | // offset by half the texture's dimensions so that the center of the texture aligns with the center of the Canvas 28 | const FVector2D CrosshairDrawPosition( (Center.X), 29 | (Center.Y + 20.0f)); 30 | 31 | // draw the crosshair 32 | FCanvasTileItem TileItem( CrosshairDrawPosition, CrosshairTex->Resource, FLinearColor::White); 33 | TileItem.BlendMode = SE_BLEND_Translucent; 34 | Canvas->DrawItem( TileItem ); 35 | } 36 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestProjectile.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Actor.h" 7 | #include "AutoTestProjectile.generated.h" 8 | 9 | UCLASS(config=Game) 10 | class AAutoTestProjectile : public AActor 11 | { 12 | GENERATED_BODY() 13 | 14 | /** Sphere collision component */ 15 | UPROPERTY(VisibleDefaultsOnly, Category=Projectile) 16 | class USphereComponent* CollisionComp; 17 | 18 | /** Projectile movement component */ 19 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement, meta = (AllowPrivateAccess = "true")) 20 | class UProjectileMovementComponent* ProjectileMovement; 21 | 22 | public: 23 | AAutoTestProjectile(); 24 | 25 | /** called when projectile hits something */ 26 | UFUNCTION() 27 | void OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit); 28 | 29 | /** Returns CollisionComp subobject **/ 30 | FORCEINLINE class USphereComponent* GetCollisionComp() const { return CollisionComp; } 31 | /** Returns ProjectileMovement subobject **/ 32 | FORCEINLINE class UProjectileMovementComponent* GetProjectileMovement() const { return ProjectileMovement; } 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/EnemyCountTestMulti.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #include "MyTestUtils.h" 4 | #include "AutoTestCharacter.h" 5 | #include "EnemyCharacter.h" 6 | #include "AssetRegistryModule.h" 7 | 8 | IMPLEMENT_COMPLEX_AUTOMATION_TEST(FEnemyCountTestMulti, "AutoTest.EnemyCountTestMulti", FMyTestUtils::TestsFlags) 9 | 10 | void FEnemyCountTestMulti::GetTests(TArray& OutBeautifiedNames, TArray & OutTestCommands) const 11 | { 12 | FAssetRegistryModule& ARM = FModuleManager::LoadModuleChecked("AssetRegistry"); 13 | TArray AssetDataArray; 14 | ARM.Get().GetAssetsByPath(TEXT("/Game/FirstPersonCPP/Maps"), AssetDataArray); 15 | 16 | for (const auto& AssetData : AssetDataArray) 17 | { 18 | if (AssetData.AssetClass == "World") 19 | { 20 | OutBeautifiedNames.Add(AssetData.AssetName.ToString()); 21 | OutTestCommands.Add(AssetData.PackageName.ToString()); 22 | } 23 | } 24 | } 25 | 26 | bool FEnemyCountTestMulti::RunTest(const FString& Parameters) 27 | { 28 | AutomationOpenMap(Parameters); 29 | 30 | UWorld* World = FMyTestUtils::GetWorld(); 31 | TestNotNull("Check if World is properly created", World); 32 | if (!World) return false; 33 | 34 | int32 EnemiesCount = 0; 35 | for (TActorIterator It(World, AEnemyCharacter::StaticClass()); It; ++It) 36 | { 37 | EnemiesCount++; 38 | } 39 | TestTrue("Check if there are 3 enemies on the level", EnemiesCount == 3); 40 | 41 | ADD_LATENT_AUTOMATION_COMMAND(FExitGameCommand); 42 | 43 | return true; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/ANew/EnemyCountTestMulti.spec.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #include "../MyTestUtils.h" 4 | #include "AutoTestCharacter.h" 5 | #include "EnemyCharacter.h" 6 | #include "AssetRegistryModule.h" 7 | 8 | BEGIN_DEFINE_SPEC(FNewEnemyCountTestMulti, "AutoTest.ANew.EnemyCountTestMulti", FMyTestUtils::TestsFlags) 9 | 10 | UWorld* World; 11 | 12 | END_DEFINE_SPEC(FNewEnemyCountTestMulti) 13 | 14 | void FNewEnemyCountTestMulti::Define() 15 | { 16 | FAssetRegistryModule& ARM = FModuleManager::LoadModuleChecked("AssetRegistry"); 17 | TArray AssetDataArray; 18 | ARM.Get().GetAssetsByPath(TEXT("/Game/FirstPersonCPP/Maps"), AssetDataArray); 19 | 20 | for (const auto& AssetData : AssetDataArray) 21 | { 22 | if (AssetData.AssetClass == "World") 23 | { 24 | Describe(AssetData.AssetName.ToString(), [this, AssetData]() 25 | { 26 | BeforeEach([this, AssetData]() 27 | { 28 | AutomationOpenMap(AssetData.PackageName.ToString()); 29 | World = FMyTestUtils::GetWorld(); 30 | TestNotNull("Check if World is properly created", World); 31 | }); 32 | 33 | It("Check Enemy Count", [this]() 34 | { 35 | int32 EnemiesCount = 0; 36 | for (TActorIterator It(World, AEnemyCharacter::StaticClass()); It; ++It) 37 | { 38 | EnemiesCount++; 39 | } 40 | TestTrue("Check if there are 3 enemies on the level", EnemiesCount == 3); 41 | }); 42 | 43 | AfterEach([this]() 44 | { 45 | FMyTestUtils::Exit(); 46 | }); 47 | }); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/MyTestUtils.h: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #pragma once 4 | 5 | #include "Engine.h" 6 | #include "Misc/AutomationTest.h" 7 | #include "Tests/AutomationCommon.h" 8 | #include "Kismet/GameplayStatics.h" 9 | #include "GameFramework/PlayerController.h" 10 | 11 | class FMyTestUtils 12 | { 13 | public: 14 | 15 | /** The flag used when defining tests. */ 16 | static const int32 TestsFlags = EAutomationTestFlags::EditorContext | 17 | EAutomationTestFlags::ClientContext | 18 | EAutomationTestFlags::ProductFilter; 19 | 20 | /** Helper method for getting the game world. */ 21 | static UWorld* GetWorld() 22 | { 23 | if (GEngine) 24 | { 25 | if (FWorldContext* WorldContext = GEngine->GetWorldContextFromPIEInstance(0)) 26 | { 27 | return WorldContext->World(); 28 | } 29 | } 30 | 31 | return nullptr; 32 | } 33 | 34 | /** Helper method for exiting the game. */ 35 | static void Exit() 36 | { 37 | if (UWorld* World = GetWorld()) 38 | { 39 | if (APlayerController* TargetPC = UGameplayStatics::GetPlayerController(World, 0)) 40 | { 41 | TargetPC->ConsoleCommand(TEXT("Exit"), true); 42 | } 43 | } 44 | } 45 | 46 | static bool PressKey(const FName& KeyName, EInputEvent InputEvent) 47 | { 48 | if (GEngine) 49 | { 50 | if (GEngine->GameViewport) 51 | { 52 | if (FViewport* Viewport = GEngine->GameViewport->Viewport) 53 | { 54 | if (FViewportClient * ViewportClient = Viewport->GetClient()) 55 | { 56 | return ViewportClient->InputKey(FInputKeyEventArgs(Viewport, 0, KeyName, InputEvent)); 57 | } 58 | } 59 | } 60 | } 61 | 62 | return false; 63 | } 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/ShootEnemyTest.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #include "MyTestUtils.h" 4 | #include "AutoTestCharacter.h" 5 | #include "EnemyCharacter.h" 6 | 7 | IMPLEMENT_SIMPLE_AUTOMATION_TEST(FShootEnemyTest, "AutoTest.ShootEnemyTest", FMyTestUtils::TestsFlags); 8 | 9 | DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FWaitForEnemyToBeShooted, FShootEnemyTest*, Test); 10 | 11 | bool FShootEnemyTest::RunTest(const FString& Parameters) 12 | { 13 | AutomationOpenMap("/Game/FirstPersonCPP/Maps/FirstPersonExampleMap"); 14 | 15 | UWorld* World = FMyTestUtils::GetWorld(); 16 | TestNotNull("Check if World is properly created", World); 17 | if (!World) return false; 18 | 19 | int32 EnemiesCount = 0; 20 | for (TActorIterator It(World, AEnemyCharacter::StaticClass()); It; ++It) 21 | { 22 | EnemiesCount++; 23 | } 24 | TestTrue("Check if there are 3 enemies on the level", EnemiesCount == 3); 25 | 26 | const bool bFireButtonWasPressed = FMyTestUtils::PressKey(FName("LeftMouseButton"), EInputEvent::IE_Pressed); 27 | TestTrue("Fire button was properly pressed", bFireButtonWasPressed); 28 | if (!bFireButtonWasPressed) return false; 29 | 30 | ADD_LATENT_AUTOMATION_COMMAND(FEngineWaitLatentCommand(1.f)); 31 | ADD_LATENT_AUTOMATION_COMMAND(FWaitForEnemyToBeShooted(this)); 32 | ADD_LATENT_AUTOMATION_COMMAND(FExitGameCommand); 33 | 34 | return true; 35 | } 36 | 37 | bool FWaitForEnemyToBeShooted::Update() 38 | { 39 | int32 EnemiesCount = 0; 40 | for (TActorIterator It(FMyTestUtils::GetWorld(), AEnemyCharacter::StaticClass()); It; ++It) 41 | { 42 | EnemiesCount++; 43 | } 44 | Test->TestTrue("Check if there are 2 enemies on the level", EnemiesCount == 2); 45 | 46 | return true; 47 | } 48 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/Tests/ANew/ShootEnemyTest.spec.cpp: -------------------------------------------------------------------------------- 1 | // (c) 2019 Damian Nowakowski 2 | 3 | #include "../MyTestUtils.h" 4 | #include "AutoTestCharacter.h" 5 | #include "EnemyCharacter.h" 6 | #include "Async.h" 7 | 8 | BEGIN_DEFINE_SPEC(FNewShootEnemyTest, "AutoTest.ANew.ShootEnemyTest", FMyTestUtils::TestsFlags) 9 | 10 | UWorld* World; 11 | 12 | END_DEFINE_SPEC(FNewShootEnemyTest) 13 | 14 | void FNewShootEnemyTest::Define() 15 | { 16 | BeforeEach([this]() 17 | { 18 | AutomationOpenMap("/Game/FirstPersonCPP/Maps/FirstPersonExampleMap"); 19 | World = FMyTestUtils::GetWorld(); 20 | TestNotNull("Check if World is properly created", World); 21 | }); 22 | 23 | LatentIt("Test Enemy Shoot", EAsyncExecution::ThreadPool, [this](const FDoneDelegate TestDone) 24 | { 25 | AsyncTask(ENamedThreads::GameThread, [this]() { 26 | int32 EnemiesCount = 0; 27 | for (TActorIterator It(World, AEnemyCharacter::StaticClass()); It; ++It) 28 | { 29 | EnemiesCount++; 30 | } 31 | TestTrue("Check if there are 3 enemies on the level", EnemiesCount == 3); 32 | 33 | const bool bFireButtonWasPressed = FMyTestUtils::PressKey(FName("LeftMouseButton"), EInputEvent::IE_Pressed); 34 | TestTrue("Fire button was properly pressed", bFireButtonWasPressed); 35 | }); 36 | 37 | float StartTime = FPlatformTime::Seconds(); 38 | while (FPlatformTime::Seconds() - StartTime < 1.f) 39 | { 40 | FPlatformProcess::Sleep(0.1f); 41 | } 42 | 43 | AsyncTask(ENamedThreads::GameThread, [this]() { 44 | int32 EnemiesCount = 0; 45 | for (TActorIterator It(FMyTestUtils::GetWorld(), AEnemyCharacter::StaticClass()); It; ++It) 46 | { 47 | EnemiesCount++; 48 | } 49 | TestTrue("Check if there are 2 enemies on the level", EnemiesCount == 2); 50 | }); 51 | 52 | TestDone.Execute(); 53 | }); 54 | 55 | AfterEach([this]() 56 | { 57 | FMyTestUtils::Exit(); 58 | }); 59 | } -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestProjectile.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AutoTestProjectile.h" 4 | #include "GameFramework/ProjectileMovementComponent.h" 5 | #include "Components/SphereComponent.h" 6 | 7 | AAutoTestProjectile::AAutoTestProjectile() 8 | { 9 | // Use a sphere as a simple collision representation 10 | CollisionComp = CreateDefaultSubobject(TEXT("SphereComp")); 11 | CollisionComp->InitSphereRadius(5.0f); 12 | CollisionComp->BodyInstance.SetCollisionProfileName("Projectile"); 13 | CollisionComp->OnComponentHit.AddDynamic(this, &AAutoTestProjectile::OnHit); // set up a notification for when this component hits something blocking 14 | 15 | // Players can't walk on it 16 | CollisionComp->SetWalkableSlopeOverride(FWalkableSlopeOverride(WalkableSlope_Unwalkable, 0.f)); 17 | CollisionComp->CanCharacterStepUpOn = ECB_No; 18 | 19 | // Set as root component 20 | RootComponent = CollisionComp; 21 | 22 | // Use a ProjectileMovementComponent to govern this projectile's movement 23 | ProjectileMovement = CreateDefaultSubobject(TEXT("ProjectileComp")); 24 | ProjectileMovement->UpdatedComponent = CollisionComp; 25 | ProjectileMovement->InitialSpeed = 3000.f; 26 | ProjectileMovement->MaxSpeed = 3000.f; 27 | ProjectileMovement->bRotationFollowsVelocity = true; 28 | ProjectileMovement->bShouldBounce = true; 29 | 30 | // Die after 3 seconds by default 31 | InitialLifeSpan = 3.0f; 32 | } 33 | 34 | void AAutoTestProjectile::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) 35 | { 36 | // Only add impulse and destroy projectile if we hit a physics 37 | if ((OtherActor != NULL) && (OtherActor != this) && (OtherComp != NULL) && OtherComp->IsSimulatingPhysics()) 38 | { 39 | OtherComp->AddImpulseAtLocation(GetVelocity() * 100.0f, GetActorLocation()); 40 | 41 | Destroy(); 42 | } 43 | } -------------------------------------------------------------------------------- /AutoTest/Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/Engine.CollisionProfile] 2 | +Profiles=(Name="Projectile",CollisionEnabled=QueryOnly,ObjectTypeName="Projectile",CustomResponses=,HelpMessage="Preset for projectiles",bCanModify=True) 3 | +DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,Name="Projectile",DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False) 4 | +EditProfiles=(Name="Trigger",CustomResponses=((Channel=Projectile, Response=ECR_Ignore))) 5 | 6 | [/Script/EngineSettings.GameMapsSettings] 7 | EditorStartupMap=/Game/FirstPersonCPP/Maps/FirstPersonExampleMap 8 | LocalMapOptions= 9 | TransitionMap= 10 | bUseSplitscreen=True 11 | TwoPlayerSplitscreenLayout=Horizontal 12 | ThreePlayerSplitscreenLayout=FavorTop 13 | GameInstanceClass=/Script/Engine.GameInstance 14 | GameDefaultMap=/Game/FirstPersonCPP/Maps/FirstPersonExampleMap 15 | ServerDefaultMap=/Engine/Maps/Entry 16 | GlobalDefaultGameMode=/Script/AutoTest.AutoTestGameMode 17 | GlobalDefaultServerGameMode=None 18 | 19 | [/Script/IOSRuntimeSettings.IOSRuntimeSettings] 20 | MinimumiOSVersion=IOS_11 21 | 22 | 23 | [/Script/Engine.Engine] 24 | +ActiveGameNameRedirects=(OldGameName="TP_FirstPerson",NewGameName="/Script/AutoTest") 25 | +ActiveGameNameRedirects=(OldGameName="/Script/TP_FirstPerson",NewGameName="/Script/AutoTest") 26 | +ActiveClassRedirects=(OldClassName="TP_FirstPersonProjectile",NewClassName="AutoTestProjectile") 27 | +ActiveClassRedirects=(OldClassName="TP_FirstPersonHUD",NewClassName="AutoTestHUD") 28 | +ActiveClassRedirects=(OldClassName="TP_FirstPersonGameMode",NewClassName="AutoTestGameMode") 29 | +ActiveClassRedirects=(OldClassName="TP_FirstPersonCharacter",NewClassName="AutoTestCharacter") 30 | 31 | [/Script/HardwareTargeting.HardwareTargetingSettings] 32 | TargetedHardwareClass=Desktop 33 | AppliedTargetedHardwareClass=Desktop 34 | DefaultGraphicsPerformance=Maximum 35 | AppliedDefaultGraphicsPerformance=Maximum 36 | 37 | [/Script/Engine.PhysicsSettings] 38 | DefaultGravityZ=-980.000000 39 | DefaultTerminalVelocity=4000.000000 40 | DefaultFluidFriction=0.300000 41 | SimulateScratchMemorySize=262144 42 | RagdollAggregateThreshold=4 43 | TriangleMeshTriangleMinAreaThreshold=5.000000 44 | bEnableShapeSharing=False 45 | bEnablePCM=True 46 | bEnableStabilization=False 47 | bWarnMissingLocks=True 48 | bEnable2DPhysics=False 49 | PhysicErrorCorrection=(PingExtrapolation=0.100000,PingLimit=100.000000,ErrorPerLinearDifference=1.000000,ErrorPerAngularDifference=1.000000,MaxRestoredStateError=1.000000,MaxLinearHardSnapDistance=400.000000,PositionLerp=0.000000,AngleLerp=0.400000,LinearVelocityCoefficient=100.000000,AngularVelocityCoefficient=10.000000,ErrorAccumulationSeconds=0.500000,ErrorAccumulationDistanceSq=15.000000,ErrorAccumulationSimilarity=100.000000) 50 | LockedAxis=Invalid 51 | DefaultDegreesOfFreedom=Full3D 52 | BounceThresholdVelocity=200.000000 53 | FrictionCombineMode=Average 54 | RestitutionCombineMode=Average 55 | MaxAngularVelocity=3600.000000 56 | MaxDepenetrationVelocity=0.000000 57 | ContactOffsetMultiplier=0.020000 58 | MinContactOffset=2.000000 59 | MaxContactOffset=8.000000 60 | bSimulateSkeletalMeshOnDedicatedServer=True 61 | DefaultShapeComplexity=CTF_UseSimpleAndComplex 62 | bDefaultHasComplexCollision=True 63 | bSuppressFaceRemapTable=False 64 | bSupportUVFromHitResults=False 65 | bDisableActiveActors=False 66 | bDisableKinematicStaticPairs=False 67 | bDisableKinematicKinematicPairs=False 68 | bDisableCCD=False 69 | bEnableEnhancedDeterminism=False 70 | MaxPhysicsDeltaTime=0.033333 71 | bSubstepping=False 72 | bSubsteppingAsync=False 73 | MaxSubstepDeltaTime=0.016667 74 | MaxSubsteps=6 75 | SyncSceneSmoothingFactor=0.000000 76 | InitialAverageFrameRate=0.016667 77 | PhysXTreeRebuildRate=10 78 | DefaultBroadphaseSettings=(bUseMBPOnClient=False,bUseMBPOnServer=False,MBPBounds=(Min=(X=0.000000,Y=0.000000,Z=0.000000),Max=(X=0.000000,Y=0.000000,Z=0.000000),IsValid=0),MBPNumSubdivs=2) 79 | 80 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestCharacter.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Character.h" 7 | #include "AutoTestCharacter.generated.h" 8 | 9 | class UInputComponent; 10 | 11 | UCLASS(config=Game) 12 | class AAutoTestCharacter : public ACharacter 13 | { 14 | GENERATED_BODY() 15 | 16 | /** Pawn mesh: 1st person view (arms; seen only by self) */ 17 | UPROPERTY(VisibleDefaultsOnly, Category=Mesh) 18 | class USkeletalMeshComponent* Mesh1P; 19 | 20 | /** Gun mesh: 1st person view (seen only by self) */ 21 | UPROPERTY(VisibleDefaultsOnly, Category = Mesh) 22 | class USkeletalMeshComponent* FP_Gun; 23 | 24 | /** Location on gun mesh where projectiles should spawn. */ 25 | UPROPERTY(VisibleDefaultsOnly, Category = Mesh) 26 | class USceneComponent* FP_MuzzleLocation; 27 | 28 | /** Gun mesh: VR view (attached to the VR controller directly, no arm, just the actual gun) */ 29 | UPROPERTY(VisibleDefaultsOnly, Category = Mesh) 30 | class USkeletalMeshComponent* VR_Gun; 31 | 32 | /** Location on VR gun mesh where projectiles should spawn. */ 33 | UPROPERTY(VisibleDefaultsOnly, Category = Mesh) 34 | class USceneComponent* VR_MuzzleLocation; 35 | 36 | /** First person camera */ 37 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) 38 | class UCameraComponent* FirstPersonCameraComponent; 39 | 40 | /** Motion controller (right hand) */ 41 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) 42 | class UMotionControllerComponent* R_MotionController; 43 | 44 | /** Motion controller (left hand) */ 45 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) 46 | class UMotionControllerComponent* L_MotionController; 47 | 48 | public: 49 | AAutoTestCharacter(); 50 | 51 | protected: 52 | virtual void BeginPlay(); 53 | 54 | public: 55 | /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */ 56 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera) 57 | float BaseTurnRate; 58 | 59 | /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */ 60 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera) 61 | float BaseLookUpRate; 62 | 63 | /** Gun muzzle's offset from the characters location */ 64 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay) 65 | FVector GunOffset; 66 | 67 | /** Projectile class to spawn */ 68 | UPROPERTY(EditDefaultsOnly, Category=Projectile) 69 | TSubclassOf ProjectileClass; 70 | 71 | /** Sound to play each time we fire */ 72 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay) 73 | class USoundBase* FireSound; 74 | 75 | /** AnimMontage to play each time we fire */ 76 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay) 77 | class UAnimMontage* FireAnimation; 78 | 79 | /** Whether to use motion controller location for aiming. */ 80 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay) 81 | uint32 bUsingMotionControllers : 1; 82 | 83 | protected: 84 | 85 | /** Fires a projectile. */ 86 | void OnFire(); 87 | 88 | /** Resets HMD orientation and position in VR. */ 89 | void OnResetVR(); 90 | 91 | /** Handles moving forward/backward */ 92 | void MoveForward(float Val); 93 | 94 | /** Handles stafing movement, left and right */ 95 | void MoveRight(float Val); 96 | 97 | /** 98 | * Called via input to turn at a given rate. 99 | * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate 100 | */ 101 | void TurnAtRate(float Rate); 102 | 103 | /** 104 | * Called via input to turn look up/down at a given rate. 105 | * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate 106 | */ 107 | void LookUpAtRate(float Rate); 108 | 109 | struct TouchData 110 | { 111 | TouchData() { bIsPressed = false;Location=FVector::ZeroVector;} 112 | bool bIsPressed; 113 | ETouchIndex::Type FingerIndex; 114 | FVector Location; 115 | bool bMoved; 116 | }; 117 | void BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location); 118 | void EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location); 119 | void TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location); 120 | TouchData TouchItem; 121 | 122 | protected: 123 | // APawn interface 124 | virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override; 125 | // End of APawn interface 126 | 127 | /* 128 | * Configures input for touchscreen devices if there is a valid touch interface for doing so 129 | * 130 | * @param InputComponent The input component pointer to bind controls to 131 | * @returns true if touch controls were enabled. 132 | */ 133 | bool EnableTouchscreenMovement(UInputComponent* InputComponent); 134 | 135 | public: 136 | /** Returns Mesh1P subobject **/ 137 | FORCEINLINE class USkeletalMeshComponent* GetMesh1P() const { return Mesh1P; } 138 | /** Returns FirstPersonCameraComponent subobject **/ 139 | FORCEINLINE class UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; } 140 | 141 | }; 142 | 143 | -------------------------------------------------------------------------------- /AutoTest/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 | +AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Z",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 16 | +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_Z",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 17 | +AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 18 | +AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 19 | +AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 20 | +AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 21 | +AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 22 | +AxisConfig=(AxisKeyName="MotionController_Left_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 23 | +AxisConfig=(AxisKeyName="MotionController_Left_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 24 | +AxisConfig=(AxisKeyName="MotionController_Left_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 25 | +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 26 | +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 27 | +AxisConfig=(AxisKeyName="MotionController_Right_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 28 | +AxisConfig=(AxisKeyName="MotionController_Right_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 29 | +AxisConfig=(AxisKeyName="MotionController_Right_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 30 | +AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 31 | +AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 32 | +AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 33 | +AxisConfig=(AxisKeyName="OculusTouch_Left_FaceButton1",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 34 | +AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 35 | +AxisConfig=(AxisKeyName="OculusTouch_Left_FaceButton2",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 36 | +AxisConfig=(AxisKeyName="OculusTouch_Left_IndexPointing",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 37 | +AxisConfig=(AxisKeyName="OculusTouch_Left_ThumbUp",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 38 | +AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 39 | +AxisConfig=(AxisKeyName="OculusTouch_Right_FaceButton1",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 40 | +AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 41 | +AxisConfig=(AxisKeyName="OculusTouch_Right_FaceButton2",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 42 | +AxisConfig=(AxisKeyName="OculusTouch_Right_IndexPointing",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 43 | +AxisConfig=(AxisKeyName="OculusTouch_Right_ThumbUp",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 44 | +AxisConfig=(AxisKeyName="OculusTouchpad_Touchpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 45 | +AxisConfig=(AxisKeyName="OculusTouchpad_Touchpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 46 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Left_HandGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 47 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Left_IndexGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 48 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Left_MiddleGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 49 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Left_RingGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 50 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Left_PinkyGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 51 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Right_HandGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 52 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Right_IndexGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 53 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Right_MiddleGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 54 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Right_RingGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 55 | +AxisConfig=(AxisKeyName="SteamVR_Knuckles_Right_PinkyGrip",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) 56 | bAltEnterTogglesFullscreen=True 57 | bF11TogglesFullscreen=True 58 | bUseMouseForTouch=False 59 | bEnableMouseSmoothing=True 60 | bEnableFOVScaling=True 61 | bCaptureMouseOnLaunch=True 62 | bDefaultViewportMouseLock=False 63 | bAlwaysShowTouchInterface=False 64 | bShowConsoleOnFourFingerTap=True 65 | bEnableGestureRecognizer=False 66 | bUseAutocorrect=False 67 | DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown 68 | DefaultViewportMouseLockMode=LockOnCapture 69 | FOVScale=0.011110 70 | DoubleClickTime=0.200000 71 | +ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar) 72 | +ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Bottom) 73 | +ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MotionController_Left_Trigger) 74 | +ActionMappings=(ActionName="Fire",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) 75 | +ActionMappings=(ActionName="Fire",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_RightTrigger) 76 | +ActionMappings=(ActionName="Fire",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MotionController_Right_Trigger) 77 | +ActionMappings=(ActionName="ResetVR",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R) 78 | +ActionMappings=(ActionName="ResetVR",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MotionController_Left_Grip1) 79 | +ActionMappings=(ActionName="Fire",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=OculusTouchpad_Touchpad) 80 | +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) 81 | +AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) 82 | +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Up) 83 | +AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=Down) 84 | +AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Gamepad_LeftY) 85 | +AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=MotionController_Left_Thumbstick_Y) 86 | +AxisMappings=(AxisName="MoveRight",Scale=-1.000000,Key=A) 87 | +AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=D) 88 | +AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=Gamepad_LeftX) 89 | +AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=MotionController_Left_Thumbstick_X) 90 | +AxisMappings=(AxisName="TurnRate",Scale=1.000000,Key=Gamepad_RightX) 91 | +AxisMappings=(AxisName="TurnRate",Scale=-1.000000,Key=Left) 92 | +AxisMappings=(AxisName="TurnRate",Scale=1.000000,Key=Right) 93 | +AxisMappings=(AxisName="Turn",Scale=1.000000,Key=MouseX) 94 | +AxisMappings=(AxisName="LookUpRate",Scale=1.000000,Key=Gamepad_RightY) 95 | +AxisMappings=(AxisName="LookUp",Scale=-1.000000,Key=MouseY) 96 | DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks 97 | ConsoleKey=None 98 | -ConsoleKeys=Tilde 99 | +ConsoleKeys=Tilde 100 | 101 | 102 | -------------------------------------------------------------------------------- /AutoTest/Source/AutoTest/AutoTestCharacter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AutoTestCharacter.h" 4 | #include "AutoTestProjectile.h" 5 | #include "Animation/AnimInstance.h" 6 | #include "Camera/CameraComponent.h" 7 | #include "Components/CapsuleComponent.h" 8 | #include "Components/InputComponent.h" 9 | #include "GameFramework/InputSettings.h" 10 | #include "HeadMountedDisplayFunctionLibrary.h" 11 | #include "Kismet/GameplayStatics.h" 12 | #include "MotionControllerComponent.h" 13 | #include "XRMotionControllerBase.h" // for FXRMotionControllerBase::RightHandSourceId 14 | 15 | DEFINE_LOG_CATEGORY_STATIC(LogFPChar, Warning, All); 16 | 17 | ////////////////////////////////////////////////////////////////////////// 18 | // AAutoTestCharacter 19 | 20 | AAutoTestCharacter::AAutoTestCharacter() 21 | { 22 | // Set size for collision capsule 23 | GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f); 24 | 25 | // set our turn rates for input 26 | BaseTurnRate = 45.f; 27 | BaseLookUpRate = 45.f; 28 | 29 | // Create a CameraComponent 30 | FirstPersonCameraComponent = CreateDefaultSubobject(TEXT("FirstPersonCamera")); 31 | FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent()); 32 | FirstPersonCameraComponent->RelativeLocation = FVector(-39.56f, 1.75f, 64.f); // Position the camera 33 | FirstPersonCameraComponent->bUsePawnControlRotation = true; 34 | 35 | // Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn) 36 | Mesh1P = CreateDefaultSubobject(TEXT("CharacterMesh1P")); 37 | Mesh1P->SetOnlyOwnerSee(true); 38 | Mesh1P->SetupAttachment(FirstPersonCameraComponent); 39 | Mesh1P->bCastDynamicShadow = false; 40 | Mesh1P->CastShadow = false; 41 | Mesh1P->RelativeRotation = FRotator(1.9f, -19.19f, 5.2f); 42 | Mesh1P->RelativeLocation = FVector(-0.5f, -4.4f, -155.7f); 43 | 44 | // Create a gun mesh component 45 | FP_Gun = CreateDefaultSubobject(TEXT("FP_Gun")); 46 | FP_Gun->SetOnlyOwnerSee(true); // only the owning player will see this mesh 47 | FP_Gun->bCastDynamicShadow = false; 48 | FP_Gun->CastShadow = false; 49 | // FP_Gun->SetupAttachment(Mesh1P, TEXT("GripPoint")); 50 | FP_Gun->SetupAttachment(RootComponent); 51 | 52 | FP_MuzzleLocation = CreateDefaultSubobject(TEXT("MuzzleLocation")); 53 | FP_MuzzleLocation->SetupAttachment(FP_Gun); 54 | FP_MuzzleLocation->SetRelativeLocation(FVector(0.2f, 48.4f, -10.6f)); 55 | 56 | // Default offset from the character location for projectiles to spawn 57 | GunOffset = FVector(100.0f, 0.0f, 10.0f); 58 | 59 | // Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P, FP_Gun, and VR_Gun 60 | // are set in the derived blueprint asset named MyCharacter to avoid direct content references in C++. 61 | 62 | // Create VR Controllers. 63 | R_MotionController = CreateDefaultSubobject(TEXT("R_MotionController")); 64 | R_MotionController->MotionSource = FXRMotionControllerBase::RightHandSourceId; 65 | R_MotionController->SetupAttachment(RootComponent); 66 | L_MotionController = CreateDefaultSubobject(TEXT("L_MotionController")); 67 | L_MotionController->SetupAttachment(RootComponent); 68 | 69 | // Create a gun and attach it to the right-hand VR controller. 70 | // Create a gun mesh component 71 | VR_Gun = CreateDefaultSubobject(TEXT("VR_Gun")); 72 | VR_Gun->SetOnlyOwnerSee(true); // only the owning player will see this mesh 73 | VR_Gun->bCastDynamicShadow = false; 74 | VR_Gun->CastShadow = false; 75 | VR_Gun->SetupAttachment(R_MotionController); 76 | VR_Gun->SetRelativeRotation(FRotator(0.0f, -90.0f, 0.0f)); 77 | 78 | VR_MuzzleLocation = CreateDefaultSubobject(TEXT("VR_MuzzleLocation")); 79 | VR_MuzzleLocation->SetupAttachment(VR_Gun); 80 | VR_MuzzleLocation->SetRelativeLocation(FVector(0.000004, 53.999992, 10.000000)); 81 | VR_MuzzleLocation->SetRelativeRotation(FRotator(0.0f, 90.0f, 0.0f)); // Counteract the rotation of the VR gun model. 82 | 83 | // Uncomment the following line to turn motion controllers on by default: 84 | //bUsingMotionControllers = true; 85 | } 86 | 87 | void AAutoTestCharacter::BeginPlay() 88 | { 89 | // Call the base class 90 | Super::BeginPlay(); 91 | 92 | //Attach gun mesh component to Skeleton, doing it here because the skeleton is not yet created in the constructor 93 | //FP_Gun->AttachToComponent(Mesh1P, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("GripPoint")); 94 | 95 | // Show or hide the two versions of the gun based on whether or not we're using motion controllers. 96 | if (bUsingMotionControllers) 97 | { 98 | VR_Gun->SetHiddenInGame(false, true); 99 | Mesh1P->SetHiddenInGame(true, true); 100 | } 101 | else 102 | { 103 | VR_Gun->SetHiddenInGame(true, true); 104 | Mesh1P->SetHiddenInGame(false, true); 105 | } 106 | } 107 | 108 | ////////////////////////////////////////////////////////////////////////// 109 | // Input 110 | 111 | void AAutoTestCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) 112 | { 113 | // set up gameplay key bindings 114 | check(PlayerInputComponent); 115 | 116 | // Bind jump events 117 | PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump); 118 | PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping); 119 | 120 | // Bind fire event 121 | PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AAutoTestCharacter::OnFire); 122 | 123 | // Enable touchscreen input 124 | EnableTouchscreenMovement(PlayerInputComponent); 125 | 126 | PlayerInputComponent->BindAction("ResetVR", IE_Pressed, this, &AAutoTestCharacter::OnResetVR); 127 | 128 | // Bind movement events 129 | PlayerInputComponent->BindAxis("MoveForward", this, &AAutoTestCharacter::MoveForward); 130 | PlayerInputComponent->BindAxis("MoveRight", this, &AAutoTestCharacter::MoveRight); 131 | 132 | // We have 2 versions of the rotation bindings to handle different kinds of devices differently 133 | // "turn" handles devices that provide an absolute delta, such as a mouse. 134 | // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick 135 | PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput); 136 | PlayerInputComponent->BindAxis("TurnRate", this, &AAutoTestCharacter::TurnAtRate); 137 | PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput); 138 | PlayerInputComponent->BindAxis("LookUpRate", this, &AAutoTestCharacter::LookUpAtRate); 139 | } 140 | 141 | void AAutoTestCharacter::OnFire() 142 | { 143 | // try and fire a projectile 144 | if (ProjectileClass != NULL) 145 | { 146 | UWorld* const World = GetWorld(); 147 | if (World != NULL) 148 | { 149 | if (bUsingMotionControllers) 150 | { 151 | const FRotator SpawnRotation = VR_MuzzleLocation->GetComponentRotation(); 152 | const FVector SpawnLocation = VR_MuzzleLocation->GetComponentLocation(); 153 | World->SpawnActor(ProjectileClass, SpawnLocation, SpawnRotation); 154 | } 155 | else 156 | { 157 | const FRotator SpawnRotation = GetControlRotation(); 158 | // MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position 159 | const FVector SpawnLocation = ((FP_MuzzleLocation != nullptr) ? FP_MuzzleLocation->GetComponentLocation() : GetActorLocation()) + SpawnRotation.RotateVector(GunOffset); 160 | 161 | //Set Spawn Collision Handling Override 162 | FActorSpawnParameters ActorSpawnParams; 163 | ActorSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButDontSpawnIfColliding; 164 | 165 | // spawn the projectile at the muzzle 166 | World->SpawnActor(ProjectileClass, SpawnLocation, SpawnRotation, ActorSpawnParams); 167 | } 168 | } 169 | } 170 | 171 | // try and play the sound if specified 172 | if (FireSound != NULL) 173 | { 174 | UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); 175 | } 176 | 177 | // try and play a firing animation if specified 178 | if (FireAnimation != NULL) 179 | { 180 | // Get the animation object for the arms mesh 181 | UAnimInstance* AnimInstance = Mesh1P->GetAnimInstance(); 182 | if (AnimInstance != NULL) 183 | { 184 | AnimInstance->Montage_Play(FireAnimation, 1.f); 185 | } 186 | } 187 | } 188 | 189 | void AAutoTestCharacter::OnResetVR() 190 | { 191 | UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition(); 192 | } 193 | 194 | void AAutoTestCharacter::BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location) 195 | { 196 | if (TouchItem.bIsPressed == true) 197 | { 198 | return; 199 | } 200 | if ((FingerIndex == TouchItem.FingerIndex) && (TouchItem.bMoved == false)) 201 | { 202 | OnFire(); 203 | } 204 | TouchItem.bIsPressed = true; 205 | TouchItem.FingerIndex = FingerIndex; 206 | TouchItem.Location = Location; 207 | TouchItem.bMoved = false; 208 | } 209 | 210 | void AAutoTestCharacter::EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location) 211 | { 212 | if (TouchItem.bIsPressed == false) 213 | { 214 | return; 215 | } 216 | TouchItem.bIsPressed = false; 217 | } 218 | 219 | //Commenting this section out to be consistent with FPS BP template. 220 | //This allows the user to turn without using the right virtual joystick 221 | 222 | //void AAutoTestCharacter::TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location) 223 | //{ 224 | // if ((TouchItem.bIsPressed == true) && (TouchItem.FingerIndex == FingerIndex)) 225 | // { 226 | // if (TouchItem.bIsPressed) 227 | // { 228 | // if (GetWorld() != nullptr) 229 | // { 230 | // UGameViewportClient* ViewportClient = GetWorld()->GetGameViewport(); 231 | // if (ViewportClient != nullptr) 232 | // { 233 | // FVector MoveDelta = Location - TouchItem.Location; 234 | // FVector2D ScreenSize; 235 | // ViewportClient->GetViewportSize(ScreenSize); 236 | // FVector2D ScaledDelta = FVector2D(MoveDelta.X, MoveDelta.Y) / ScreenSize; 237 | // if (FMath::Abs(ScaledDelta.X) >= 4.0 / ScreenSize.X) 238 | // { 239 | // TouchItem.bMoved = true; 240 | // float Value = ScaledDelta.X * BaseTurnRate; 241 | // AddControllerYawInput(Value); 242 | // } 243 | // if (FMath::Abs(ScaledDelta.Y) >= 4.0 / ScreenSize.Y) 244 | // { 245 | // TouchItem.bMoved = true; 246 | // float Value = ScaledDelta.Y * BaseTurnRate; 247 | // AddControllerPitchInput(Value); 248 | // } 249 | // TouchItem.Location = Location; 250 | // } 251 | // TouchItem.Location = Location; 252 | // } 253 | // } 254 | // } 255 | //} 256 | 257 | void AAutoTestCharacter::MoveForward(float Value) 258 | { 259 | if (Value != 0.0f) 260 | { 261 | // add movement in that direction 262 | AddMovementInput(GetActorForwardVector(), Value); 263 | } 264 | } 265 | 266 | void AAutoTestCharacter::MoveRight(float Value) 267 | { 268 | if (Value != 0.0f) 269 | { 270 | // add movement in that direction 271 | AddMovementInput(GetActorRightVector(), Value); 272 | } 273 | } 274 | 275 | void AAutoTestCharacter::TurnAtRate(float Rate) 276 | { 277 | // calculate delta for this frame from the rate information 278 | AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds()); 279 | } 280 | 281 | void AAutoTestCharacter::LookUpAtRate(float Rate) 282 | { 283 | // calculate delta for this frame from the rate information 284 | AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds()); 285 | } 286 | 287 | bool AAutoTestCharacter::EnableTouchscreenMovement(class UInputComponent* PlayerInputComponent) 288 | { 289 | if (FPlatformMisc::SupportsTouchInput() || GetDefault()->bUseMouseForTouch) 290 | { 291 | PlayerInputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AAutoTestCharacter::BeginTouch); 292 | PlayerInputComponent->BindTouch(EInputEvent::IE_Released, this, &AAutoTestCharacter::EndTouch); 293 | 294 | //Commenting this out to be more consistent with FPS BP template. 295 | //PlayerInputComponent->BindTouch(EInputEvent::IE_Repeat, this, &AAutoTestCharacter::TouchUpdate); 296 | return true; 297 | } 298 | 299 | return false; 300 | } 301 | --------------------------------------------------------------------------------