diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index ad623c1..0000000 --- a/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -ReleaseBuilds/** filter=lfs diff=lfs merge=lfs -text -Images/** filter=lfs diff=lfs merge=lfs -text -Fonts/** filter=lfs diff=lfs merge=lfs -text -Audio/** filter=lfs diff=lfs merge=lfs -text diff --git a/Audio/.gitattributes b/Audio/.gitattributes new file mode 100644 index 0000000..521c7e3 --- /dev/null +++ b/Audio/.gitattributes @@ -0,0 +1 @@ +./** filter=lfs diff=lfs merge=lfs -text diff --git a/Documentation/README.md b/Documentation/README.md new file mode 100644 index 0000000..de06c93 --- /dev/null +++ b/Documentation/README.md @@ -0,0 +1,3 @@ +# Documentation +The always actual documentation is on [google drive](https://drive.google.com/drive/folders/1o40kh_8BgrMI3BzPyfNT0ZLG_5mrIjEy?usp=sharing). \ +There is only a dump/backup. \ No newline at end of file diff --git a/Documentation/Story.docx b/Documentation/Story.docx index a96746a..abdb2c1 100644 Binary files a/Documentation/Story.docx and b/Documentation/Story.docx differ diff --git a/Fonts/.gitattributes b/Fonts/.gitattributes new file mode 100644 index 0000000..521c7e3 --- /dev/null +++ b/Fonts/.gitattributes @@ -0,0 +1 @@ +./** filter=lfs diff=lfs merge=lfs -text diff --git a/Images/.gitattributes b/Images/.gitattributes new file mode 100644 index 0000000..521c7e3 --- /dev/null +++ b/Images/.gitattributes @@ -0,0 +1 @@ +./** filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/Images/.gitignore similarity index 100% rename from .gitignore rename to Images/.gitignore diff --git a/Models/.gitignore b/Models/.gitignore new file mode 100644 index 0000000..2621fab --- /dev/null +++ b/Models/.gitignore @@ -0,0 +1 @@ +*.blend1 \ No newline at end of file diff --git a/README.md b/README.md index 28abe29..33a0e5a 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,31 @@ # Repo structure -This repository contains all sources and data. The current unreal project is located in UnrealProject/Lost_Edge/. +This repository contains all sources and data for project Lost_Edge excluding server and network deploy configs. \ +Most of subdirectories represents individual modules and contains their own README. -# Documentation -Actualised documentation is on [google drive](https://drive.google.com/drive/folders/1o40kh_8BgrMI3BzPyfNT0ZLG_5mrIjEy?usp=sharing). +Lost_Edge/ \ +├─ [Audio/](Audio) ---> Audio data (e.g. music, sounds, dialogues) \ +├─ [Documentation/](Documentation) ---> Documentation (e.g. game and level design) \ +├─ [Fonts/](Fonts) ---> Fonts used in project \ +├─ [Images/](Images) ---> Image data (e.g. textures, postures, logo) \ +├─ [Models/](Models) ---> Models data (e.g. characters, decorations, foliages) \ +├─ [ReleaseBuilds/](ReleaseBuilds) \ +│ ├─ Legacy/ ---> Legacy build created as high school project \ +│ └─ vX.X/ ---> Current builds of Lost_Edge (university project) \ +├─ UnrealProject/ \ +│ ├─ [Lost_Edge/](UnrealProject/Lost_Edge) ---> Current unreal project of Lost_Edge \ +│ └─ Lost_Edge_Legacy/ ---> Legacy unreal project created as high school project \ +└─[VoiceGenerator/](VoiceGenerator) ---> AI voice generation module -# How to compile -It's recommended to work in Unreal Engine 5.4 and to install Visual Studio with the necessary packages as it described in the [official documentation](https://dev.epicgames.com/documentation/en-us/unreal-engine/setting-up-visual-studio-development-environment-for-cplusplus-projects-in-unreal-engine) (recommended settings aren't needed). \ -After repo cloning, the Visual Studio project files needs to be generated. It can be done in the explorer RMB context menu of file "UnrealProject/Lost_Edge/Lost_Edge.uproject". Or by typing "%UE5PATH%\Engine\Build\BatchFiles\GenerateProjectFiles.bat" "%REPOPATH%\UnrealProject\Lost_Edge\Lost_Edge.uproject". \ -After generating, "Lost_Edge.sln" can be opened and project can start building for the first time, which will fail. This is because of using OpenCV plugin that together with UnrealEngine implement their own "check()" function. This error can be used to determine that in the file "%UE5PATH%\Engine\Plugins\Runtime\OpenCV\Source\ThirdParty\OpenCV\include\opencv2\core\utility.hpp" it is necessary to comment out the warning macro on lines 52-54 and rename the function itself on line 957 to, for example, "checkcv()". -After this modification, the build should run fine and it is possible to open the project in UnrealEngine. +# Building your own project copy +Building a copy of the game requires only [UnrealProject/LostEdge/](UnrealProject/Lost_Edge) directory. \ +For that purposes you can download the directory as archive or do a sparse checkout via commands below. +- git clone --no-checkout https://pixelyfier.com/git/Pixelyfier/Lost_Edge.git +- cd Lost_Edge/ +- git sparse-checkout init +- git sparse-checkout set UnrealProject/Lost_Edge +- git checkout master # Git lfs common issues -The download can be sometimes too long which make git lfs drop the connection with error "LFS: Put "https://pixelyfier.com/git/Pixelyfier/Lost_Edge.git/info/lfs/objects/HASH": read tcp IP:PORT->pixelyfier.com:443: i/o timeout" \ +The download can be sometimes too long which makes git lfs drop the connection with error \ +`"LFS: Put "https://pixelyfier.com/git/Pixelyfier/Lost_Edge.git/info/lfs/objects/HASH": read tcp IP:PORT->pixelyfier.com:443: i/o timeout"` - To fix this set local/global repo config `git config lfs.activitytimeout 240` diff --git a/ReleaseBuilds/.gitattributes b/ReleaseBuilds/.gitattributes new file mode 100644 index 0000000..521c7e3 --- /dev/null +++ b/ReleaseBuilds/.gitattributes @@ -0,0 +1 @@ +./** filter=lfs diff=lfs merge=lfs -text diff --git a/UnrealProject/Lost_Edge/Config/DefaultEngine.ini b/UnrealProject/Lost_Edge/Config/DefaultEngine.ini index c9b460d..ab61445 100644 --- a/UnrealProject/Lost_Edge/Config/DefaultEngine.ini +++ b/UnrealProject/Lost_Edge/Config/DefaultEngine.ini @@ -84,7 +84,7 @@ CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' +ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/Lost_Edge") +ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/Lost_Edge") +ActiveClassRedirects=(OldClassName="TP_BlankGameModeBase",NewClassName="Lost_EdgeGameModeBase") -GameUserSettingsClassName=/Script/Lost_Edge.CustomGameUserSettings +GameUserSettingsClassName=/Script/Lost_Edge.CustomGameSettings LevelScriptActorClassName=/Script/Lost_Edge.LevelBase [/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] diff --git a/UnrealProject/Lost_Edge/Config/DefaultGameUserSettings.ini b/UnrealProject/Lost_Edge/Config/DefaultGameUserSettings.ini index df3d264..6c87b93 100644 --- a/UnrealProject/Lost_Edge/Config/DefaultGameUserSettings.ini +++ b/UnrealProject/Lost_Edge/Config/DefaultGameUserSettings.ini @@ -1,4 +1,4 @@ -[/Script/Lost_Edge.CustomGameUserSettings] +[/Script/Lost_Edge.CustomGameSettings] bUseMotionBlur=False bShowFps=False bMouseInverted=False diff --git a/UnrealProject/Lost_Edge/Content/Blueprints/BP_CustomGameInstance.uasset b/UnrealProject/Lost_Edge/Content/Blueprints/BP_CustomGameInstance.uasset index 67c869c..da2e0e6 100644 --- a/UnrealProject/Lost_Edge/Content/Blueprints/BP_CustomGameInstance.uasset +++ b/UnrealProject/Lost_Edge/Content/Blueprints/BP_CustomGameInstance.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9156bfa1fa7a0a42325c5cd1aad5f085d9da75143e46ce9919b54d49270bda2 -size 6180 +oid sha256:617aa7adcc34b939014b4d3e4e3442dacde726db2198f9943f13a9606a5dd12d +size 6156 diff --git a/UnrealProject/Lost_Edge/Content/Blueprints/BP_PlayerController.uasset b/UnrealProject/Lost_Edge/Content/Blueprints/BP_PlayerController.uasset index a9e9453..412628c 100644 --- a/UnrealProject/Lost_Edge/Content/Blueprints/BP_PlayerController.uasset +++ b/UnrealProject/Lost_Edge/Content/Blueprints/BP_PlayerController.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:99f94a7ef2c239b485f8383639972b1ffd3c93207656789ef9e941d5666ff14f -size 20270 +oid sha256:8b4fd4c5e50f2803d2aed9a839e942d7c029566a4e06b7248dba67221f1edb8a +size 20478 diff --git a/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/RuntimeLoadTest/BP_Test_RuntimeLoad.uasset b/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/RuntimeLoadTest/BP_Test_RuntimeLoad.uasset index aba621b..09b4397 100644 --- a/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/RuntimeLoadTest/BP_Test_RuntimeLoad.uasset +++ b/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/RuntimeLoadTest/BP_Test_RuntimeLoad.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8895891731e8da1a221aacd6a03ad0bf81128aa3a980588173be9fbd863a9244 -size 84828 +oid sha256:de2d44f87a368a36c39a9461f9316638c65ee9977b6a8338c2376826b10ad365 +size 87003 diff --git a/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/SaveTest/BP_Test_SaveLoad.uasset b/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/SaveTest/BP_Test_SaveLoad.uasset index 73ad2db..29e994d 100644 --- a/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/SaveTest/BP_Test_SaveLoad.uasset +++ b/UnrealProject/Lost_Edge/Content/Levels/Test/Actors/SaveTest/BP_Test_SaveLoad.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d826f8c420d5979f784345c77302ff514fd8c00af07196349bfc45d06b54e2b -size 40608 +oid sha256:e0bd4cf99bf84d957a019edfa375a4f0f01872fa0a9f2378f2c171cbc5582ce5 +size 41871 diff --git a/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test.umap b/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test.umap index 33667b3..f37d0f1 100644 --- a/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test.umap +++ b/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d6d75c266fe70db878a1a4c8ad461c4f31dd3c92662074f083295eff4bf0d13 -size 2265074 +oid sha256:654c333de2b64ac0da0ff144917ff839fbf97858a564007816c2aec6cc5e678a +size 2266458 diff --git a/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test_BuiltData.uasset b/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test_BuiltData.uasset index 216ce28..2100858 100644 --- a/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test_BuiltData.uasset +++ b/UnrealProject/Lost_Edge/Content/Levels/Test/L_Test_BuiltData.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6aa7b92951a49c50d63d075885fd2b0c00041360b6721a5c84d2a16f68f8c562 -size 586263 +oid sha256:4709c1328015fe0ec6ae192210f49e06972893eb6ab740df18bb7a18a181a2c0 +size 585835 diff --git a/UnrealProject/Lost_Edge/Content/UI/Blueprints/MainMenu/UI_MainMenu.uasset b/UnrealProject/Lost_Edge/Content/UI/Blueprints/MainMenu/UI_MainMenu.uasset index e12c690..22d4b4f 100644 --- a/UnrealProject/Lost_Edge/Content/UI/Blueprints/MainMenu/UI_MainMenu.uasset +++ b/UnrealProject/Lost_Edge/Content/UI/Blueprints/MainMenu/UI_MainMenu.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4828fea25aee37109fdcb3461fbbd6461bcd59ba8819809d79c88383734b883 -size 172743 +oid sha256:3ae4f8d697d46434366827562a388480f4b09f9fe022e12ba3b5f7aade8ffbc4 +size 174730 diff --git a/UnrealProject/Lost_Edge/README.md b/UnrealProject/Lost_Edge/README.md new file mode 100644 index 0000000..3e325b0 --- /dev/null +++ b/UnrealProject/Lost_Edge/README.md @@ -0,0 +1,5 @@ +# How to compile +It's recommended to work in Unreal Engine 5.4 and to install Visual Studio with the necessary packages as it described in the [official documentation](https://dev.epicgames.com/documentation/en-us/unreal-engine/setting-up-visual-studio-development-environment-for-cplusplus-projects-in-unreal-engine) (recommended settings aren't needed). \ +After repo cloning, the Visual Studio project files needs to be generated. It can be done in the explorer RMB context menu of file "UnrealProject/Lost_Edge/Lost_Edge.uproject". Or by typing "%UE5PATH%\Engine\Build\BatchFiles\GenerateProjectFiles.bat" "%REPOPATH%\UnrealProject\Lost_Edge\Lost_Edge.uproject". \ +After generating, "Lost_Edge.sln" can be opened and project can start building for the first time, which will fail. This is because of using OpenCV plugin that together with UnrealEngine implement their own "check()" function. This error can be used to determine that in the file "%UE5PATH%\Engine\Plugins\Runtime\OpenCV\Source\ThirdParty\OpenCV\include\opencv2\core\utility.hpp" it is necessary to comment out the warning macro on lines 52-54 and rename the function itself on line 957 to, for example, "checkcv()". +After this modification, the build should run fine and it is possible to open the project in UnrealEngine. \ No newline at end of file diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.cpp index 53501c4..1742346 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "CameraModeBase.h" #include "Camera/CameraComponent.h" @@ -10,12 +9,16 @@ #include "InputMappingContext.h" #include "Kismet/GameplayStatics.h" -#include "CustomGameInstanceBase.h" -#include "CustomGameUserSettings.h" +#include "CustomGameSettings.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" ACameraModeBase::ACameraModeBase() { + static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_CameraMode.IMC_CameraMode'") }; + context = asset.Object; + ACustomPlayerController::AppendInputContext(context); + PrimaryActorTick.bCanEverTick = true; } @@ -25,28 +28,11 @@ void ACameraModeBase::BeginPlay() auto world = GetWorld(); - //GetMovementComponent()->speed - // GetCharacterMovement()->MaxWalkSpeed = moveSpeed; - - auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings(); - - if(auto camera = FindComponentByClass()) + if(auto gameSettings = UCustomGameSettings::Get()) { - camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f; - } - - if(auto PC = Cast(GetController())) - { - if(auto inputSubsystem = ULocalPlayer::GetSubsystem(PC->GetLocalPlayer())) + if(auto camera = FindComponentByClass()) { - if(auto GI = Cast(GetWorld()->GetGameInstance())) - { - inputSubsystem->ClearAllMappings(); - for(auto& inputContext : GI->inputContexts) - { - inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0); - } - } + camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f; } } } @@ -66,13 +52,8 @@ void ACameraModeBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComp void ACameraModeBase::SwitchToPlayerPawn() { - if(auto gamemode_base = UGameplayStatics::GetGameMode(GetWorld())) - { - if(auto gamemode = Cast(gamemode_base)) - { - gamemode->SwitchCameraMode(); - } - } + if(auto gamemode = AMainGameModeBase::Get()) + gamemode->SwitchCameraMode(); } void ACameraModeBase::ElevatePawn(float value) diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.h index ca1ae6f..7fe4b0a 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CameraModeBase.h @@ -2,11 +2,13 @@ #pragma once -#include "CoreMinimal.h" #include "GameFramework/SpectatorPawn.h" #include "CameraModeBase.generated.h" +/** + * Cheap copy of PlayerBase for level fly spectating purposes. + */ UCLASS() class ACameraModeBase : public ASpectatorPawn { @@ -33,4 +35,8 @@ protected: float moveSpeed = 200; UPROPERTY(EditDefaultsOnly) float runSpeedMultiplier = 4; + +private: + TSoftObjectPtr context; + }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.cpp index 3a5e4fa..c45eec7 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.cpp @@ -7,7 +7,7 @@ #include "Kismet/GameplayStatics.h" #include "UObject/Object.h" -#include "CustomGameInstanceBase.h" +#include "CustomGameInstance.h" #include "Levels/LevelBase.h" #include "PlayerBase.h" @@ -53,25 +53,6 @@ TArray UCommonFunctions::GetRandomIntArray(int32 size, int32 min, int32 m -ALevelBase* UCommonFunctions::GetCurrentLevelScript(UObject* obj) -{ - if(auto world = obj->GetWorld()) - if(auto level = world->GetCurrentLevel()) - if(auto script = level->GetLevelScriptActor()) - return Cast(script); - return nullptr; -} - -APlayerBase* UCommonFunctions::GetPlayer(UObject* obj) -{ - if(auto pc = UGameplayStatics::GetPlayerController(obj->GetWorld(), 0)) - if(auto pawn = pc->GetPawn()) - return Cast(pawn); - return nullptr; -} - - - namespace SlowMotion { FTimerHandle timer; @@ -86,7 +67,7 @@ void UCommonFunctions::EnterSlowMotion(float duration) SlowMotion::targetDilation = SlowMotion::slowDilation; - auto GI = UCustomGameInstanceBase::GetGameInstance(); + auto GI = UCustomGameInstance::Get(); if(!GI) return; @@ -101,7 +82,7 @@ void UCommonFunctions::ExitSlowMotion(float duration) SlowMotion::targetDilation = SlowMotion::normalDilation; - auto GI = UCustomGameInstanceBase::GetGameInstance(); + auto GI = UCustomGameInstance::Get(); if(!GI) return; @@ -116,7 +97,7 @@ FWorldDilationChangedDelegate& UCommonFunctions::GetWorldDilationChangedDelegate void UCommonFunctions::SlowMotionTick() { - const UWorld* world = UCustomGameInstanceBase::GetGameInstance()->GetWorld(); + const UWorld* world = UCustomGameInstance::Get()->GetWorld(); const float currentDilation = UGameplayStatics::GetGlobalTimeDilation(world); float newDilation = FMath::FInterpTo(currentDilation, SlowMotion::targetDilation, 1, SlowMotion::interpolationSpeed); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.h index b5c9b17..56d9dae 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CommonFunctions.h @@ -2,34 +2,33 @@ #pragma once -#include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "CommonFunctions.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWorldDilationChangedDelegate, float, newDilation); +/** + * Collection of common/universal/without own scope/specific functions. + */ UCLASS() class UCommonFunctions : public UBlueprintFunctionLibrary { GENERATED_BODY() public: + /** Returns true if the object is UE class template (used for copy/archetype/meta system but not on the level) */ + UFUNCTION(BlueprintPure) static bool IsNonGameObject(class UObject* object); + + /** "Overload" of the built-in keys translator (to not build own engine copy) */ + UFUNCTION(BlueprintPure) static FText GetKeyDisplayName(struct FKey key); + /** Recursively destroy actor and all its childs (the default Destroy doesn't have consistent behavior) */ UFUNCTION(BlueprintCallable, Category = Actor) static void DestroyActorRecursively(class AActor* actor); - UFUNCTION(BlueprintPure) - static TArray GetRandomIntArray(int32 size = 16, int32 min = 0, int32 max = 16); - - - UFUNCTION(BlueprintCallable, Category = Level) - static class ALevelBase* GetCurrentLevelScript(class UObject* obj); - - UFUNCTION(BlueprintCallable, Category = Player) - static class APlayerBase* GetPlayer(class UObject* obj); UFUNCTION(BlueprintCallable, Category = World) @@ -41,6 +40,10 @@ public: static FWorldDilationChangedDelegate& GetWorldDilationChangedDelegate(); + + UFUNCTION(BlueprintPure) + static TArray GetRandomIntArray(int32 size = 16, int32 min = 0, int32 max = 16); + template static TArray ArrayDiff(const TArray& a, const TArray& b); template diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.cpp index 8d01c52..7e56715 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.cpp @@ -1,12 +1,12 @@ // Oleg Petruny proprietary. - #include "ContentLoader.h" -#include "CommonFunctions.h" #include "IPlatformFilePak.h" #include "Misc/FileHelper.h" +#include "CommonFunctions.h" + #include #include #include diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.h index 2263206..ba774d9 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/ContentLoader.h @@ -10,13 +10,16 @@ UENUM(BlueprintType) enum class EContentDownloadMethod : uint8 { - ClearRandom = 0, - NonRepeatRandom, - RatingOftenRandom + ClearRandom = 0, //!< Always random from 0 to n + NonRepeatRandom, //!< Download the one that isn't downloaded in current runtime (Reset on full set) + RatingOftenRandom //!< NonRepeatRandom combined with asset rating [WIP] }; DECLARE_DYNAMIC_DELEGATE_OneParam(FContentDownloadedCallback, FString, pakFilePath); +/* + * High language wrapper for Paks(Assets) download and loading. + */ UCLASS(BlueprintType) class UContentLoader : public UObject { @@ -35,12 +38,18 @@ public: protected: virtual void BeginDestroy() override; + /** Sends http get request */ void HttpGet(const FString& url, FHttpRequestCompleteDelegate requestCompleteCallback); + /** Parses assets html/json index */ TArray ParseDirectoryIndex(const TArray& content, const FString& contentType); + /** Selects item by desired method */ FString SelectContentByMethod(const TArray& content, const EContentDownloadMethod method); + /** Reads Pak content */ FString GetPakMountContent(const FString& pakFilePath, TArray* content = nullptr); + /** Returns mount path to desired content item */ UClass* GetPakClass(const FString& pakContentPath); + /** Cache of already downloaded content at runtime (used by EContentDownloadMethod::NonRepeatRandom)*/ TArray downloadedContent; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstance.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstance.cpp new file mode 100644 index 0000000..cfe6c93 --- /dev/null +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstance.cpp @@ -0,0 +1,74 @@ +// Oleg Petruny proprietary. + +#include "CustomGameInstance.h" + +#include "Kismet/GameplayStatics.h" +#include "Kismet/KismetSystemLibrary.h" + +#include "ContentLoader.h" +#include "Levels/LevelBase.h" +#include "PlayerBase.h" +#include "SaveData.h" + +UCustomGameInstance* UCustomGameInstance::instance = nullptr; + +void UCustomGameInstance::Init() +{ + UGameInstance::Init(); + + instance = this; + contentLoader = NewObject(this); + saveData = Cast(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass())); +} + +UCustomGameInstance* UCustomGameInstance::Get() +{ + return instance; +} + +UContentLoader* UCustomGameInstance::GetContentLoader() +{ + if(auto GI = Get()) + return GI->contentLoader; + + return nullptr; +} + +void UCustomGameInstance::SaveGame(FName checkpointName) +{ + auto levelScript = ALevelBase::Get(); + if(!levelScript) + return; + + auto player = APlayerBase::Get(); + if(!player) + return; + + saveData->level = GetWorld()->GetFName(); + saveData->state = levelScript->GetState(); + saveData->checkpoint = checkpointName; + if(player->leftPocketItem) + saveData->playerLeftPocketItem = player->leftPocketItem->GetFName(); + else + saveData->playerLeftPocketItem = FName(TEXT("")); + if(player->rightPocketItem) + saveData->playerRightPocketItem = player->rightPocketItem->GetFName(); + else + saveData->playerRightPocketItem = FName(TEXT("")); + + UGameplayStatics::SaveGameToSlot(saveData, TEXT("Save"), 0); +} + +void UCustomGameInstance::LoadGame() +{ + saveData = Cast(UGameplayStatics::LoadGameFromSlot(TEXT("Save"), 0)); + if(!saveData) + return; + + UGameplayStatics::OpenLevel(this, saveData->level); +} + +void UCustomGameInstance::ExitGame() +{ + UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, true); +} diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstanceBase.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstance.h similarity index 50% rename from UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstanceBase.h rename to UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstance.h index 6169ab4..a810e77 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstanceBase.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstance.h @@ -4,29 +4,29 @@ #include "Engine/GameInstance.h" -#include "CustomGameInstanceBase.generated.h" +#include "CustomGameInstance.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLevelBeginnedDelegate, FName, levelName); +/** + * Expands basic UE game instance. + * Manages saves, handles content loader and can shutdown the game. + */ UCLASS() -class UCustomGameInstanceBase : public UGameInstance +class UCustomGameInstance : public UGameInstance { GENERATED_BODY() public: + /** Instantiates content loader, dummy save data and applies settings */ virtual void Init() override; - UFUNCTION(BlueprintPure) - static UCustomGameInstanceBase* GetGameInstance(); + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Custom Game Instance")) + static UCustomGameInstance* Get(); UFUNCTION(BlueprintPure) static class UContentLoader* GetContentLoader(); - UFUNCTION(BlueprintCallable, Category = Settings) - void ApplyMouseSettings(); - - void AppendInteractableModificatorClass(TSubclassOf modificator); - UFUNCTION(BlueprintCallable, Category = Save) void SaveGame(FName checkpointName); UFUNCTION(BlueprintCallable, Category = Save) @@ -34,17 +34,11 @@ public: UFUNCTION(BlueprintCallable) void ExitGame(); - static UCustomGameInstanceBase* instance; + static UCustomGameInstance* instance; + /** Public delegate called by ALevelBase instance on instantiation */ FLevelBeginnedDelegate OnLevelBeginned; - UPROPERTY(EditDefaultsOnly) - TSet> interactionsActivators; - TSet> interactionsModificators; - - UPROPERTY(EditDefaultsOnly) - TSet> inputContexts; - UPROPERTY(VisibleAnywhere) class USaveData* saveData = nullptr; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp deleted file mode 100644 index 9c53d08..0000000 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameInstanceBase.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// Oleg Petruny proprietary. - - -#include "CustomGameInstanceBase.h" - -#include "EnhancedInputLibrary.h" -#include "EnhancedInputSubsystems.h" -#include "InputMappingContext.h" -#include "Kismet/GameplayStatics.h" -#include "Kismet/KismetSystemLibrary.h" - -#include "CommonFunctions.h" -#include "ContentLoader.h" -#include "CustomGameUserSettings.h" -#include "Interactable/Activators/InCameraInteractableActivator.h" -#include "Interactable/Activators/RaycastInteractableActivator.h" -#include "Interactable/Modificators/ActivateInteractableModificator.h" -#include "Interactable/Modificators/SawInteractableModificator.h" -#include "Levels/LevelBase.h" -#include "PlayerBase.h" -#include "SaveData.h" - -UCustomGameInstanceBase* UCustomGameInstanceBase::instance = nullptr; - -void UCustomGameInstanceBase::Init() -{ - UGameInstance::Init(); - - instance = this; - - contentLoader = NewObject(this); - - interactionsActivators.Add(URaycastInteractableActivator::StaticClass()); - interactionsActivators.Add(UInCameraInteractableActivator::StaticClass()); - - for(auto& modificator : interactionsModificators) - { - if(modificator.GetDefaultObject()->GetMappingContext()) - { - inputContexts.Add(modificator.GetDefaultObject()->GetMappingContext()); - } - } - - ApplyMouseSettings(); - - saveData = Cast(UGameplayStatics::CreateSaveGameObject(USaveData::StaticClass())); -} - -UCustomGameInstanceBase* UCustomGameInstanceBase::GetGameInstance() -{ - return instance; -} - -UContentLoader* UCustomGameInstanceBase::GetContentLoader() -{ - if(auto GI = GetGameInstance()) - return GI->contentLoader; - - return nullptr; -} - -void UCustomGameInstanceBase::ApplyMouseSettings() -{ - if(auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings()) - { - for(auto& context : inputContexts) - { - if(!context.LoadSynchronous()) - continue; - - for(auto& mapping : context.LoadSynchronous()->GetMappings()) - { - if(mapping.Key == EKeys::Mouse2D) - { - for(auto& modifier : mapping.Modifiers) - { - if(auto negate_modifier = Cast(modifier)) - { - negate_modifier->bY = !gameSettings->bMouseInverted; - } - if(auto scalar_modifier = Cast(modifier)) - { - scalar_modifier->Scalar = FVector{ gameSettings->GetMouseSensetivity() * 0.5 }; - } - } - } - } - UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext(context.LoadSynchronous()); - } - } -} - -void UCustomGameInstanceBase::AppendInteractableModificatorClass(TSubclassOf modificator) -{ - bool alreadyPresent = false; - interactionsModificators.Add(modificator, &alreadyPresent); - if(!alreadyPresent) - { - if(auto IC = modificator.GetDefaultObject()->GetMappingContext()) - { - inputContexts.Add(IC); - if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) - { - if(auto inputSubsystem = ULocalPlayer::GetSubsystem(PC->GetLocalPlayer())) - { - inputSubsystem->AddMappingContext(IC, 0); - } - } - } - } -} - -void UCustomGameInstanceBase::SaveGame(FName checkpointName) -{ - auto levelScript = UCommonFunctions::GetCurrentLevelScript(this); - if(!levelScript) - return; - - auto player = UCommonFunctions::GetPlayer(this); - if(!player) - return; - saveData->level = GetWorld()->GetFName(); - saveData->state = levelScript->GetState(); - saveData->checkpoint = checkpointName; - if(player->leftPocketItem) - saveData->playerLeftPocketItem = player->leftPocketItem->GetFName(); - else - saveData->playerLeftPocketItem = FName(TEXT("")); - if(player->rightPocketItem) - saveData->playerRightPocketItem = player->rightPocketItem->GetFName(); - else - saveData->playerRightPocketItem = FName(TEXT("")); - - UGameplayStatics::SaveGameToSlot(saveData, TEXT("Save"), 0); -} - -void UCustomGameInstanceBase::LoadGame() -{ - saveData = Cast(UGameplayStatics::LoadGameFromSlot(TEXT("Save"), 0)); - if(!saveData) - return; - - UGameplayStatics::OpenLevel(this, saveData->level); -} - -void UCustomGameInstanceBase::ExitGame() -{ - UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, true); -} diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameSettings.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameSettings.cpp new file mode 100644 index 0000000..2c17640 --- /dev/null +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameSettings.cpp @@ -0,0 +1,28 @@ +// Oleg Petruny proprietary. + +#include "CustomGameSettings.h" + +#include "Kismet/GameplayStatics.h" + +UCustomGameSettings::UCustomGameSettings(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer) +{ + bUseMotionBlur = false; + bShowFps = false; + bMouseInverted = false; + fMouseSensetivity = 1.0f; +} + +UCustomGameSettings* UCustomGameSettings::Get() +{ + return Cast(UGameUserSettings::GetGameUserSettings()); +} + +void UCustomGameSettings::SetMouseSensetivity(float value) +{ + fMouseSensetivity = FMath::Clamp(value, 0.1f, 2.0f); +} + +float UCustomGameSettings::GetMouseSensetivity() const +{ + return fMouseSensetivity; +} \ No newline at end of file diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameSettings.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameSettings.h new file mode 100644 index 0000000..fbc5795 --- /dev/null +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameSettings.h @@ -0,0 +1,49 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "GameFramework/GameUserSettings.h" + +#include "CustomGameSettings.generated.h" + +/** + * Manages custom game settings. + * Mouse sensetivity and inversion, motion blur usage, fps show. + */ +UCLASS(Config = Game, defaultconfig) +class UCustomGameSettings : public UGameUserSettings +{ + GENERATED_UCLASS_BODY() + +public: + // Is auto defined by UE but implementation is in cpp + //UCustomGameSettings(const FObjectInitializer& ObjectInitializer); + + UFUNCTION(BlueprintPure, Category = Settings, meta = (DisplayName = "Get Custom Game Settings")) + static UCustomGameSettings* Get(); + + /** + * Sets mouse sensetivity multiplier + * @param value [0.1 - 2.0] + */ + UFUNCTION(BlueprintCallable, Category = Settings) + void SetMouseSensetivity(float value); + + /** Returns mouse sensetivity multiplier in [0.1 - 2.0] */ + UFUNCTION(BlueprintCallable, Category = Settings) + float GetMouseSensetivity() const; + + UPROPERTY(Config, BlueprintReadWrite) + bool bUseMotionBlur; + + UPROPERTY(Config, BlueprintReadWrite) + bool bShowFps; + + UPROPERTY(Config, BlueprintReadWrite) + bool bMouseInverted; + +protected: + UPROPERTY(Config) + float fMouseSensetivity; + +}; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameUserSettings.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameUserSettings.cpp deleted file mode 100644 index 5afcd0c..0000000 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameUserSettings.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Oleg Petruny proprietary. - - -#include "CustomGameUserSettings.h" - -#include "Kismet/GameplayStatics.h" - -UCustomGameUserSettings::UCustomGameUserSettings(const FObjectInitializer& ObjectInitializer) :Super(ObjectInitializer) -{ - bUseMotionBlur = false; - bShowFps = false; - bMouseInverted = false; - fMouseSensetivity = 1.0f; -} - -UCustomGameUserSettings* UCustomGameUserSettings::GetCustomGameUserSettings() -{ - return Cast(UGameUserSettings::GetGameUserSettings()); -} - -void UCustomGameUserSettings::SetMouseSensetivity(float value) -{ - fMouseSensetivity = FMath::Clamp(value, 0.1f, 2.0f); -} - -float UCustomGameUserSettings::GetMouseSensetivity() const -{ - return fMouseSensetivity; -} \ No newline at end of file diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameUserSettings.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameUserSettings.h deleted file mode 100644 index ae25dfb..0000000 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomGameUserSettings.h +++ /dev/null @@ -1,41 +0,0 @@ -// Oleg Petruny proprietary. - -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/GameUserSettings.h" - -#include "CustomGameUserSettings.generated.h" - -UCLASS() -class UCustomGameUserSettings : public UGameUserSettings -{ - GENERATED_UCLASS_BODY() - -public: - UFUNCTION(BlueprintCallable, Category = Settings) - static UCustomGameUserSettings* GetCustomGameUserSettings(); - - // Sets mouse sensetivity multiplier - // @param value [0.1 - 2.0] - UFUNCTION(BlueprintCallable, Category = Settings) - void SetMouseSensetivity(float value); - - // Returns mouse sensetivity multiplier in [0.1 - 2.0] - UFUNCTION(BlueprintCallable, Category = Settings) - float GetMouseSensetivity() const; - - UPROPERTY(Config, BlueprintReadWrite) - bool bUseMotionBlur; - - UPROPERTY(Config, BlueprintReadWrite) - bool bShowFps; - - UPROPERTY(Config, BlueprintReadWrite) - bool bMouseInverted; - -protected: - UPROPERTY(Config) - float fMouseSensetivity; - -}; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomPlayerController.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomPlayerController.cpp new file mode 100644 index 0000000..386d1c6 --- /dev/null +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomPlayerController.cpp @@ -0,0 +1,116 @@ +// Oleg Petruny proprietary. + +#include "CustomPlayerController.h" + +#include "EnhancedInputComponent.h" +#include "EnhancedInputLibrary.h" +#include "EnhancedInputSubsystems.h" +#include "InputMappingContext.h" + +#include "CustomGameInstance.h" +#include "CustomGameSettings.h" + +ACustomPlayerController* ACustomPlayerController::instance = nullptr; +UEnhancedInputComponent* ACustomPlayerController::input = nullptr; +UEnhancedInputLocalPlayerSubsystem* ACustomPlayerController::subsystem = nullptr; +TSet> ACustomPlayerController::contexts = {}; +TSet> ACustomPlayerController::contextsBeforeInit = {}; + +void ACustomPlayerController::AppendInputContext(TSoftObjectPtr context) +{ + if(!context.IsValid()) + return; + + if(!UCustomGameInstance::Get()) //game settings not initialized yet + { + contextsBeforeInit.Add(context); + return; + } + + ApplyMouseSettings(context); + contexts.Add(context); + if(subsystem) + subsystem->AddMappingContext(context.LoadSynchronous(), 0); +} + +void ACustomPlayerController::BeginPlay() +{ + Super::BeginPlay(); + + instance = this; + + for(auto& context : contextsBeforeInit) + { + ApplyMouseSettings(context); + contexts.Add(context); + } + contextsBeforeInit.Empty(); + + subsystem = ULocalPlayer::GetSubsystem(GetLocalPlayer()); + if(subsystem) + { + subsystem->ClearAllMappings(); + for(auto& inputContext : contexts) + subsystem->AddMappingContext(inputContext.LoadSynchronous(), 0); + } + + input = Cast(InputComponent); + if(input) + { + ((UInputComponent*)input)->BindAction(TEXT("AnyKey"), IE_Pressed, this, &ACustomPlayerController::OnAnyKeyPressed); + ((UInputComponent*)input)->BindAction(TEXT("AnyKey"), IE_Released, this, &ACustomPlayerController::OnAnyKeyReleased); + } +} + +void ACustomPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + instance = nullptr; + input = nullptr; + subsystem = nullptr; + + Super::EndPlay(EndPlayReason); +} + +void ACustomPlayerController::ApplyMouseSettings(TSoftObjectPtr& context) +{ + auto gameSettings = UCustomGameSettings::Get(); + if(!gameSettings) + return; + + if(!context.LoadSynchronous()) + return; + + for(auto& mapping : context.LoadSynchronous()->GetMappings()) + { + if(mapping.Key != EKeys::Mouse2D) + continue; + + for(auto& modifier : mapping.Modifiers) + { + if(gameSettings->bMouseInverted) + { + if(auto negate_modifier = Cast(modifier)) + { + negate_modifier->bY = !negate_modifier->bY; + continue; + } + } + if(auto scalar_modifier = Cast(modifier)) + scalar_modifier->Scalar = FVector{ gameSettings->GetMouseSensetivity() * 0.5 }; + } + } + + UEnhancedInputLibrary::RequestRebuildControlMappingsUsingContext(context.LoadSynchronous()); +} + +void ACustomPlayerController::OnAnyKeyPressed(FKey key) +{ + if(onAnyKeyPressed.IsBound()) + onAnyKeyPressed.Broadcast(key); +} + +void ACustomPlayerController::OnAnyKeyReleased(FKey key) +{ + if(onAnyKeyReleased.IsBound()) + onAnyKeyReleased.Broadcast(key); +} diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomPlayerController.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomPlayerController.h new file mode 100644 index 0000000..191f83c --- /dev/null +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CustomPlayerController.h @@ -0,0 +1,52 @@ +// Oleg Petruny proprietary. + +#pragma once + +#include "GameFramework/PlayerController.h" + +#include "CustomPlayerController.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyPressedDelegate, FKey, key); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyReleasedDelegate, FKey, key); + +/** + * De-facto wrapper/interface of all usefull shortcuts and automatization around input system. + * Append new input context here for auto init on BeginPlay and apply user input settings. + * Also, has delegates onAnyKeyPressed/Released. + */ +UCLASS() +class ACustomPlayerController : public APlayerController +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Custom Player Controller")) + static ACustomPlayerController* Get() { return instance; } + UFUNCTION(BlueprintPure) + static class UEnhancedInputComponent* GetInput() { return input; } + UFUNCTION(BlueprintPure) + static class UEnhancedInputLocalPlayerSubsystem* GetInputSubsystem() { return subsystem; } + + UFUNCTION(BlueprintCallable) + static void AppendInputContext(TSoftObjectPtr context); + + FPlayerAnyKeyPressedDelegate onAnyKeyPressed; + FPlayerAnyKeyReleasedDelegate onAnyKeyReleased; + +protected: + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + +private: + static void ApplyMouseSettings(TSoftObjectPtr& context); + + void OnAnyKeyPressed(FKey key); + void OnAnyKeyReleased(FKey key); + + static ACustomPlayerController* instance; + static class UEnhancedInputLocalPlayerSubsystem* subsystem; + static class UEnhancedInputComponent* input; + static TSet> contexts; + /** Contexts added before game instance fully initialized cannot apply game settings because not fully initialized game */ + static TSet> contextsBeforeInit; +}; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.cpp index 953c846..469ce13 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.cpp @@ -9,7 +9,7 @@ #include "LevelSequence.h" #include "LevelSequencePlayer.h" -#include "CustomGameInstanceBase.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "PlayerBase.h" #include "Widgets/CutsceneSkipWidget.h" @@ -19,14 +19,8 @@ UCutsceneManager::UCutsceneManager() { static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Cutscene.IMC_Cutscene'") }; - _inputContext = asset.Object; - if(auto world = GetWorld()) - { - if(auto GI = Cast(world->GetGameInstance())) - { - GI->inputContexts.Add(_inputContext); - } - } + context = asset.Object; + ACustomPlayerController::AppendInputContext(context); } void UCutsceneManager::EnqueueSequence(ULevelSequence* sequence, FCutsceneEndCallback endCallback) @@ -34,106 +28,82 @@ void UCutsceneManager::EnqueueSequence(ULevelSequence* sequence, FCutsceneEndCal if(!sequence) return; - FScopeLock lock1(&_sequencesLock); - FScopeLock lock2(&_callbacksLock); + FScopeLock lock1(&sequencesLock); + FScopeLock lock2(&callbacksLock); - if(_endCallbacks.IsEmpty()) // most first sequence, so widgets and binds don't exist - { - if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) - { - _lastPlayer = Cast(PC->GetPawn()); - if(_lastPlayer) - { - _lastPlayer->LockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true }); + OnFirstCutsceneInit(); - auto& mapping = _inputContext.LoadSynchronous()->GetMapping(0); - int32 handler1 = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Started, this, &UCutsceneManager::OnInputHold).GetHandle(); - int32 handler2 = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UCutsceneManager::OnInputUnhold).GetHandle(); - _handlers = { handler1, handler2 }; - - if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { - WM->HideWidgets(); - static FSkipCutsceneDelegate skipCutsceneDelegate; - if(!skipCutsceneDelegate.IsBound()) - skipCutsceneDelegate.BindDynamic(this, &UCutsceneManager::SkipSequence); - WM->EnableCutsceneWidget(skipCutsceneDelegate); - } - } - } - } - - _nextSequences.Enqueue(sequence); - _endCallbacks.Enqueue(endCallback); + nextSequences.Enqueue(sequence); + endCallbacks.Enqueue(endCallback); PlayNextSequence(); } void UCutsceneManager::PlayNextSequence() { - if(_sequencePlayer) + if(sequencePlayer) { - if(_sequencePlayer->IsPlaying()) + if(sequencePlayer->IsPlaying()) return; else - _sequencePlayer->MarkAsGarbage(); + sequencePlayer->MarkAsGarbage(); } - FScopeLock lock(&_sequencesLock); + FScopeLock lock(&sequencesLock); ULevelSequence* sequence; - _nextSequences.Dequeue(sequence); - _sequencePlayer = ULevelSequencePlayer::CreateLevelSequencePlayer(GetWorld(), sequence, FMovieSceneSequencePlaybackSettings{}, _sequencePlayerActor); - _sequencePlayer->OnStop.AddDynamic(this, &UCutsceneManager::OnSequenceEnd); - _sequencePlayer->Play(); + nextSequences.Dequeue(sequence); + sequencePlayer = ULevelSequencePlayer::CreateLevelSequencePlayer(GetWorld(), sequence, FMovieSceneSequencePlaybackSettings{}, sequencePlayerActor); + sequencePlayer->OnStop.AddDynamic(this, &UCutsceneManager::OnSequenceEnd); + sequencePlayer->Play(); } void UCutsceneManager::SkipSequence() { - if(!_sequencePlayer || !_sequencePlayer->IsPlaying()) + if(!sequencePlayer || !sequencePlayer->IsPlaying()) return; - _lastlySkipped = true; - _sequencePlayer->GoToEndAndStop(); + lastlySkipped = true; + sequencePlayer->GoToEndAndStop(); } void UCutsceneManager::ClearQueue() { - FScopeLock lock1(&_sequencesLock); - FScopeLock lock2(&_callbacksLock); - if(!_nextSequences.IsEmpty()) - _nextSequences.Empty(); - if(!_endCallbacks.IsEmpty()) - _endCallbacks.Empty(); + FScopeLock lock1(&sequencesLock); + FScopeLock lock2(&callbacksLock); + if(!nextSequences.IsEmpty()) + nextSequences.Empty(); + if(!endCallbacks.IsEmpty()) + endCallbacks.Empty(); } void UCutsceneManager::LockCallback(bool lock) { - _lockCallback = lock; + lockCallback = lock; } void UCutsceneManager::OnSequenceEnd() { - if(_lockCallback) + if(lockCallback) return; - _sequencePlayer->MarkAsGarbage(); - _sequencePlayer = nullptr; + sequencePlayer->MarkAsGarbage(); + sequencePlayer = nullptr; - FScopeLock lock(&_callbacksLock); + FScopeLock lock(&callbacksLock); FCutsceneEndCallback callback; - _endCallbacks.Dequeue(callback); + endCallbacks.Dequeue(callback); if(callback.IsBound()) callback.Execute(); - if(!_nextSequences.IsEmpty()) + if(!nextSequences.IsEmpty()) { PlayNextSequence(); - if(_lastlySkipped) + if(lastlySkipped) { - _lastlySkipped = false; - if(_holding) + lastlySkipped = false; + if(holding) { OnInputHold(); } @@ -147,36 +117,63 @@ void UCutsceneManager::OnSequenceEnd() WM->ShowWidgets(); } - if(_lastPlayer) + if(lastPlayer) { - _lastPlayer->UnlockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true }); + lastPlayer->UnlockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true }); - _lastPlayer->inputComponent->RemoveBindingByHandle(_handlers.Key); - _lastPlayer->inputComponent->RemoveBindingByHandle(_handlers.Value); + auto input = ACustomPlayerController::GetInput(); + input->RemoveBindingByHandle(handlers.Key); + input->RemoveBindingByHandle(handlers.Value); - _lastPlayer = nullptr; + lastPlayer = nullptr; } - _lastlySkipped = false; - _holding = false; + lastlySkipped = false; + holding = false; +} + +void UCutsceneManager::OnFirstCutsceneInit() // most first sequence, so widgets and binds don't exist +{ + if(!endCallbacks.IsEmpty()) + return; + + if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) + { + lastPlayer = Cast(PC->GetPawn()); + if(lastPlayer) + { + lastPlayer->LockPlayer({ .walk = true, .jump = true, .run = true, .interaction = true, .camera = true }); + + auto& mapping = context.LoadSynchronous()->GetMapping(0); + auto input = ACustomPlayerController::GetInput(); + int32 handler1 = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &UCutsceneManager::OnInputHold).GetHandle(); + int32 handler2 = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &UCutsceneManager::OnInputUnhold).GetHandle(); + handlers = { handler1, handler2 }; + + if(auto WM = AMainGameModeBase::GetWidgetsManager()) + { + WM->HideWidgets(); + static FSkipCutsceneDelegate skipCutsceneDelegate; + if(!skipCutsceneDelegate.IsBound()) + skipCutsceneDelegate.BindDynamic(this, &UCutsceneManager::SkipSequence); + WM->EnableCutsceneWidget(skipCutsceneDelegate); + } + } + } } void UCutsceneManager::OnInputHold() { - _holding = true; + holding = true; if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->AnimateCutsceneWidget(EInputAnimatedWidgetAnimation::Hold); - } } void UCutsceneManager::OnInputUnhold() { - _holding = false; + holding = false; if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->AnimateCutsceneWidget(EInputAnimatedWidgetAnimation::Unhold); - } } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.h index 708cde2..6b9f4e8 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/CutsceneManager.h @@ -32,22 +32,23 @@ private: void PlayNextSequence(); UFUNCTION() void OnSequenceEnd(); + void OnFirstCutsceneInit(); void OnInputHold(); void OnInputUnhold(); - class ULevelSequencePlayer* _sequencePlayer = nullptr; - class ALevelSequenceActor* _sequencePlayerActor = nullptr; - TQueue _nextSequences; - FCriticalSection _sequencesLock; - TQueue _endCallbacks; - FCriticalSection _callbacksLock; + class ULevelSequencePlayer* sequencePlayer = nullptr; + class ALevelSequenceActor* sequencePlayerActor = nullptr; + TQueue nextSequences; + FCriticalSection sequencesLock; + TQueue endCallbacks; + FCriticalSection callbacksLock; - class APlayerBase* _lastPlayer = nullptr; - TSoftObjectPtr _inputContext; - TPair _handlers; + class APlayerBase* lastPlayer = nullptr; + TSoftObjectPtr context; + TPair handlers; - bool _lockCallback = false; - bool _lastlySkipped = false; - bool _holding = false; + bool lockCallback = false; + bool lastlySkipped = false; + bool holding = false; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.cpp index a9bbbd1..c4a1f44 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "DialogueManager.h" #include "Components/AudioComponent.h" @@ -11,7 +10,7 @@ #include "Kismet/KismetMathLibrary.h" #include "Sound/SoundWave.h" -#include "CustomGameInstanceBase.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "PlayerBase.h" #include "Widgets/DialogueSkipWidget.h" @@ -21,14 +20,8 @@ UDialogueManager::UDialogueManager() { static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Dialogue.IMC_Dialogue'") }; - _inputContext = asset.Object; - if(auto world = GetWorld()) - { - if(auto GI = Cast(world->GetGameInstance())) - { - GI->inputContexts.Add(_inputContext); - } - } + context = asset.Object; + ACustomPlayerController::AppendInputContext(context); } void UDialogueManager::PlayDialogue(FDialogueEnqueProperties properties, FDialogueEndCallback endCallback) @@ -49,32 +42,28 @@ void UDialogueManager::PlayDialogue(FDialogueEnqueProperties properties, FDialog FTimerHandle timer; int32 timerId; - _timersLock.Lock(); - timerId = _timers.Num(); - _timers.Add(timer); - _timersLock.Unlock(); + timersLock.Lock(); + timerId = timers.Num(); + timers.Add(timer); + timersLock.Unlock(); UGameplayStatics::PlaySound2D(this, row->wave.LoadSynchronous()); if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->ShowDialogueWidget(*row); - } - auto func = [properties = properties, - timerId = timerId, - _timersLock = &_timersLock, - _timers = &_timers, - endCallback = endCallback]() + auto func = [properties, + timerId, + timersLock = &timersLock, + timers = &timers, + endCallback]() { FDialogueRow* row = reinterpret_cast(properties.dialogue.LoadSynchronous()->FindRowUnchecked(properties.rowName)); if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->HideDialogueWidget(*row); - } - _timersLock->Lock(); - _timers->RemoveAt(timerId); - _timersLock->Unlock(); + timersLock->Lock(); + timers->RemoveAt(timerId); + timersLock->Unlock(); endCallback.Execute(); }; @@ -88,51 +77,30 @@ void UDialogueManager::EnqueDialogue(FDialogueEnqueProperties properties, FDialo if(!properties.dialogue.LoadSynchronous()) return; - FScopeLock lock1(&_dialoguesLock); - FScopeLock lock2(&_callbacksLock); + FScopeLock lock1(&dialoguesLock); + FScopeLock lock2(&callbacksLock); - if(_endCallbacks.IsEmpty()) // most first dialogue, so widgets and binds don't exist - { - if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) - { - _lastPlayer = Cast(PC->GetPawn()); - if(_lastPlayer) - { - auto& mapping = _inputContext.LoadSynchronous()->GetMapping(0); - _inputHandler = _lastPlayer->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UDialogueManager::OnInputPress).GetHandle(); + OnFirstDialogueInit(); - if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { - static FDialogueSkipDelegate skipDialogueDelegate; - if(!skipDialogueDelegate.IsBound()) - { - skipDialogueDelegate.BindDynamic(this, &UDialogueManager::SkipDialogue); - WM->SetInputDialogueWidget(mapping.Key, mapping.Action->ActionDescription, skipDialogueDelegate); - } - } - } - } - } - - _nextDialogues.Enqueue(properties); - _endCallbacks.Enqueue(endCallback); + nextDialogues.Enqueue(properties); + endCallbacks.Enqueue(endCallback); PlayNextDialogue(); } void UDialogueManager::PlayNextDialogue() { - _dialoguesLock.Lock(); + dialoguesLock.Lock(); - auto properties = _nextDialogues.Peek(); + auto properties = nextDialogues.Peek(); TArray rows = properties->dialogue.LoadSynchronous()->GetRowNames(); if(rows.Num() == 0) { FDialogueEndCallback callback; - if(_endCallbacks.Dequeue(callback)) + if(endCallbacks.Dequeue(callback)) callback.Execute(); - _nextDialogues.Pop(); + nextDialogues.Pop(); return; } @@ -146,22 +114,20 @@ void UDialogueManager::PlayNextDialogue() if(!row) { FDialogueEndCallback callback; - _endCallbacks.Dequeue(callback); + endCallbacks.Dequeue(callback); callback.ExecuteIfBound(); - _nextDialogues.Pop(); + nextDialogues.Pop(); return; } - if(properties->playMode == EDialoguePlayMode::Sequential) + if(properties->playMode == EDialoguePlayMode::Sequential + && !properties->rowName.ToString().IsNumeric()) { - if(!properties->rowName.ToString().IsNumeric()) - { - _nextDialogues.Pop(); - FDialogueEndCallback callback; - if(_endCallbacks.Dequeue(callback)) - callback.Execute(); - return; - } + nextDialogues.Pop(); + FDialogueEndCallback callback; + if(endCallbacks.Dequeue(callback)) + callback.Execute(); + return; } if(row->wave.LoadSynchronous()) @@ -170,9 +136,7 @@ void UDialogueManager::PlayNextDialogue() leadDialogueAudio = nullptr; if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->ShowDialogueWidget(*row); - } FTimerHandle timer; int32 timerId; @@ -180,27 +144,53 @@ void UDialogueManager::PlayNextDialogue() const float duration = row->wave ? row->wave->GetDuration() : row->duration; GetWorld()->GetTimerManager().SetTimer(timer, [&]() { OnDialogueEnd(); }, duration, false); - _timersLock.Lock(); - timerId = _timers.Num(); - _timers.Add(timer); - _timersLock.Unlock(); + timersLock.Lock(); + timerId = timers.Num(); + timers.Add(timer); + timersLock.Unlock(); leadDialogueTimerId = timerId; leadDialogueProperties = properties; - _dialoguesLock.Unlock(); + dialoguesLock.Unlock(); +} + +void UDialogueManager::OnFirstDialogueInit() // most first dialogue, so widgets and binds don't exist +{ + if(!endCallbacks.IsEmpty()) + return; + + if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) + { + lastPlayer = Cast(PC->GetPawn()); + if(lastPlayer) + { + auto& mapping = context.LoadSynchronous()->GetMapping(0); + inputHandler = ACustomPlayerController::GetInput()->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &UDialogueManager::OnInputPress).GetHandle(); + + if(auto WM = AMainGameModeBase::GetWidgetsManager()) + { + static FDialogueSkipDelegate skipDialogueDelegate; + if(!skipDialogueDelegate.IsBound()) + { + skipDialogueDelegate.BindDynamic(this, &UDialogueManager::SkipDialogue); + WM->SetInputDialogueWidget(mapping.Key, mapping.Action->ActionDescription, skipDialogueDelegate); + } + } + } + } } void UDialogueManager::SkipDialogue() { - if(_timers.Num() == 0 || leadDialogueTimerId < 0) + if(timers.Num() == 0 || leadDialogueTimerId < 0) return; - _timersLock.Lock(); - GetWorld()->GetTimerManager().ClearTimer(_timers[leadDialogueTimerId]); - _timers.RemoveAt(leadDialogueTimerId); + timersLock.Lock(); + GetWorld()->GetTimerManager().ClearTimer(timers[leadDialogueTimerId]); + timers.RemoveAt(leadDialogueTimerId); leadDialogueTimerId = -1; - _timersLock.Unlock(); + timersLock.Unlock(); if(leadDialogueAudio) leadDialogueAudio->Stop(); @@ -210,25 +200,25 @@ void UDialogueManager::SkipDialogue() void UDialogueManager::ClearQueue() { - if(!_nextDialogues.IsEmpty()) - _nextDialogues.Empty(); - if(!_endCallbacks.IsEmpty()) - _endCallbacks.Empty(); + if(!nextDialogues.IsEmpty()) + nextDialogues.Empty(); + if(!endCallbacks.IsEmpty()) + endCallbacks.Empty(); } void UDialogueManager::LockCallback(bool lock) { - _lockCallback = lock; + lockCallback = lock; } void UDialogueManager::BeginDestroy() { if(auto world = GetWorld()) { - _timersLock.Lock(); - for(auto& timer : _timers) + timersLock.Lock(); + for(auto& timer : timers) world->GetTimerManager().ClearTimer(timer); - _timersLock.Unlock(); + timersLock.Unlock(); } UObject::BeginDestroy(); @@ -236,41 +226,35 @@ void UDialogueManager::BeginDestroy() void UDialogueManager::OnDialogueEnd() { - _dialoguesLock.Lock(); + dialoguesLock.Lock(); FDialogueRow* row = reinterpret_cast(leadDialogueProperties->dialogue.LoadSynchronous()->FindRowUnchecked(leadDialogueProperties->rowName)); if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->HideDialogueWidget(*row); - } - if(leadDialogueProperties->playMode == EDialoguePlayMode::Sequential) + if(leadDialogueProperties->playMode == EDialoguePlayMode::Sequential + && leadDialogueProperties->rowName.ToString().IsNumeric()) { - if(leadDialogueProperties->rowName.ToString().IsNumeric()) - { - leadDialogueProperties->rowName = FName(FString::FromInt(FCString::Atoi(*(leadDialogueProperties->rowName.ToString())) + 1)); - } + leadDialogueProperties->rowName = FName(FString::FromInt(FCString::Atoi(*(leadDialogueProperties->rowName.ToString())) + 1)); } - _dialoguesLock.Unlock(); + dialoguesLock.Unlock(); - if(!_endCallbacks.IsEmpty()) + if(!endCallbacks.IsEmpty()) PlayNextDialogue(); - _dialoguesLock.Lock(); - if(_endCallbacks.IsEmpty() && _lastPlayer) + dialoguesLock.Lock(); + if(endCallbacks.IsEmpty() && lastPlayer) { - _lastPlayer->inputComponent->RemoveBindingByHandle(_inputHandler); - _lastPlayer = nullptr; + ACustomPlayerController::GetInput()->RemoveBindingByHandle(inputHandler); + lastPlayer = nullptr; } - _dialoguesLock.Unlock(); + dialoguesLock.Unlock(); } void UDialogueManager::OnInputPress() { if(auto WM = AMainGameModeBase::GetWidgetsManager()) - { WM->AnimateDialogueWidget(EInputAnimatedWidgetAnimation::Click); - } } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.h index bf5b05a..d65a0c7 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/DialogueManager.h @@ -68,7 +68,7 @@ class UDialogueManager : public UObject public: UDialogueManager(); - // Ignores play mode and force pushing dialogue + /** Ignores play mode and force pushing dialogue */ UFUNCTION(BlueprintCallable) void PlayDialogue(FDialogueEnqueProperties properties, FDialogueEndCallback endCallback); @@ -89,26 +89,28 @@ protected: private: void PlayNextDialogue(); + void OnFirstDialogueInit(); + UFUNCTION() void OnDialogueEnd(); void OnInputPress(); - TQueue _nextDialogues; - FCriticalSection _dialoguesLock; - TQueue _endCallbacks; - FCriticalSection _callbacksLock; + TQueue nextDialogues; + FCriticalSection dialoguesLock; + TQueue endCallbacks; + FCriticalSection callbacksLock; - TArray _timers; - FCriticalSection _timersLock; + TArray timers; + FCriticalSection timersLock; int32 leadDialogueTimerId = -1; FDialogueEnqueProperties* leadDialogueProperties; class UAudioComponent* leadDialogueAudio; - class APlayerBase* _lastPlayer = nullptr; - TSoftObjectPtr _inputContext; - int32 _inputHandler; + class APlayerBase* lastPlayer = nullptr; + TSoftObjectPtr context; + int32 inputHandler; - bool _lockCallback = false; + bool lockCallback = false; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.cpp index 30108f9..9103d85 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.cpp @@ -1,9 +1,9 @@ // Oleg Petruny proprietary. - #include "InCameraInteractableActivator.h" #include "CommonFunctions.h" +#include "Interactable/Interactable.h" #include "InteractableScreenCapturer.h" UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInitializer& ObjectInitializer) @@ -20,10 +20,10 @@ UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInit activatorType = EActivatorType::Saw; scanDistance = 7000; - _capturer = CreateDefaultSubobject(TEXT("UInCameraInteractableActivator_UInteractableScreenCapturer")); - _capturer->interactableInScreenDelegate.BindUObject(this, &UInCameraInteractableActivator::NewSeenInteractable_Implementation); - _capturer->SetupAttachment(this); - _capturer->scanDistance = scanDistance; + capturer = CreateDefaultSubobject(TEXT("UInCameraInteractableActivator_UInteractableScreenCapturer")); + capturer->interactableInScreenDelegate.BindUObject(this, &UInCameraInteractableActivator::NewSeenInteractable); + capturer->SetupAttachment(this); + capturer->scanDistance = scanDistance; PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.bStartWithTickEnabled = false; @@ -31,27 +31,28 @@ UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInit void UInCameraInteractableActivator::OnRegister() { - UInteractableActivator::OnRegister(); - _capturer->RegisterComponent(); - _capturer->Activate(); + Super::OnRegister(); + capturer->RegisterComponent(); + capturer->Activate(); } -void UInCameraInteractableActivator::NewSeenInteractable_Implementation(AInteractable* interactable) +void UInCameraInteractableActivator::NewSeenInteractable(AInteractable* interactable) { - _interactablesToActivate.Enqueue(interactable); + interactablesToActivate.Enqueue(interactable); SetComponentTickEnabled(true); } void UInCameraInteractableActivator::Scan_Implementation() { SetComponentTickEnabled(false); - while(!_interactablesToActivate.IsEmpty()) + while(!interactablesToActivate.IsEmpty()) { AInteractable* interactable; - _interactablesToActivate.Dequeue(interactable); + interactablesToActivate.Dequeue(interactable); if(interactableActivatedDelegate.IsBound()) { interactableActivatedDelegate.Execute(interactable, activatorType); + OnNewSeenInteractable(interactable); } } } \ No newline at end of file diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.h index 6b42bf2..4bc59ba 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InCameraInteractableActivator.h @@ -2,13 +2,14 @@ #pragma once -#include "CoreMinimal.h" - #include "InteractableActivator.h" #include "InCameraInteractableActivator.generated.h" -UCLASS(Blueprintable, BlueprintType) +/** + * Activates interactable only once if is in a camera view + */ +UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableActivator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Activates interactable only once if is in a camera view"), MinimalAPI) class UInCameraInteractableActivator : public UInteractableActivator { GENERATED_BODY() @@ -19,14 +20,30 @@ public: protected: virtual void OnRegister() override; + virtual bool AutoInstantiateInPlayer() override { return true; } + + /** + * Scan is performed independently by _capturer member object. + * This implementation just activates interactables in the game thread. + */ virtual void Scan_Implementation() override; - UFUNCTION(BlueprintNativeEvent, BlueprintCallable) - LOST_EDGE_API void NewSeenInteractable(class AInteractable* interactable); - virtual void NewSeenInteractable_Implementation(class AInteractable* interactable); + /** + * Thread safe enques interactable for activation in the next game tick + * @param interactable .. interactable to activate + */ + UFUNCTION(BlueprintCallable) + void NewSeenInteractable(class AInteractable* interactable); + + /** + * Called after interactable activation + * @param interactable .. interactable activated + */ + UFUNCTION(BlueprintImplementableEvent) + void OnNewSeenInteractable(class AInteractable* interactable); private: UPROPERTY() - class UInteractableScreenCapturer* _capturer; - TQueue _interactablesToActivate; + class UInteractableScreenCapturer* capturer; + TQueue interactablesToActivate; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.cpp index 402c680..9059521 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.cpp @@ -1,19 +1,23 @@ // Oleg Petruny proprietary. - #include "InteractableActivator.h" #include "Engine/CollisionProfile.h" +#include "Interactable/Interactable.h" #include "PlayerBase.h" UInteractableActivator::UInteractableActivator(const FObjectInitializer& ObjectInitializer) : USceneComponent(ObjectInitializer) { - if(HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) + if(GetClass() != UInteractableActivator::StaticClass()) { - return; + AInteractable::AppendActivatorClass(GetClass()); } + + if(HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject)) + return; + world = GetWorld(); player = Cast(GetOwner()); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.h index 0ac6122..0e2c4aa 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableActivator.h @@ -3,7 +3,6 @@ #pragma once #include "Components/SceneComponent.h" -#include "CoreMinimal.h" #include "Interactable/Interactable.h" @@ -12,15 +11,22 @@ DECLARE_DELEGATE_TwoParams(FInteractableActivated, AInteractable*, EActivatorType); DECLARE_DELEGATE_TwoParams(FInteractableDeactivated, AInteractable*, EActivatorType); -UCLASS(Abstract, Blueprintable, BlueprintType) +/** + * Activates interactable based on type + */ +UCLASS(Abstract, Blueprintable, BlueprintType, ClassGroup = InteractableActivator, meta = (ShortTooltip = "Activates interactable based on type"), MinimalAPI) class UInteractableActivator : public USceneComponent { GENERATED_BODY() public: + /** Append itself to CustomGameInstance modificators registry */ UInteractableActivator(const FObjectInitializer& ObjectInitializer); virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + virtual bool AutoInstantiateInPlayer() { return false; } + + /** Resets activator state forcing to rescan */ UFUNCTION(BlueprintNativeEvent, BlueprintCallable) LOST_EDGE_API void Rescan(); virtual void Rescan_Implementation() {} @@ -29,6 +35,7 @@ public: FInteractableActivated interactableDeactivatedDelegate; protected: + /** Activator scan function in game thread tick */ UFUNCTION(BlueprintNativeEvent, BlueprintCallable) LOST_EDGE_API void Scan(); virtual void Scan_Implementation() PURE_VIRTUAL(UInteractableActivator::Scan_Implementation, ); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.cpp index ea2fd42..a5d24d2 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "InteractableScreenCapturer.h" #include "Engine/Texture.h" @@ -16,9 +15,12 @@ #include "Interactable/Interactable.h" #include "InteractableScreenCapturerBitMapCS.h" -constexpr float tickInterval = 1.0f / 5; -constexpr float textureWidth = 1280 / 2; -constexpr float textureHeight = 720 / 2; +namespace +{ + constexpr float tickInterval = 1.0f / 5; + constexpr float textureWidth = 1280 / 2; + constexpr float textureHeight = 720 / 2; +} UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer) : USceneCaptureComponent2D(ObjectInitializer) @@ -85,7 +87,7 @@ void UInteractableScreenCapturer::TickComponent(float DeltaTime, enum ELevelTick { USceneCaptureComponent2D::TickComponent(DeltaTime, TickType, ThisTickFunction); CaptureScene(); - GetCameraView(DeltaTime, _view); + GetCameraView(DeltaTime, view); Process(); } break; @@ -104,7 +106,7 @@ void UInteractableScreenCapturer::Process() [ capture = TextureTarget->GetResource()->TextureRHI, world = GetWorld(), - view = _view, + view = view, //output = _output->GetResource()->TextureRHI, this ] @@ -262,6 +264,7 @@ void UInteractableScreenCapturer::Process() AsyncTask(ENamedThreads::GameThread, [=, this]() { interactableInScreenDelegate.Execute(interactable); + OnInteractableInScreen(interactable); }); } } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.h index 9bcd52a..19a69bf 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/InteractableScreenCapturer.h @@ -9,7 +9,10 @@ DECLARE_DELEGATE_OneParam(FInteractableInScreen, class AInteractable*); -UCLASS(hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent), MinimalAPI) +/** + * Notifies only once about interactable is in a camera view + */ +UCLASS(BlueprintType, hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent, ShortTooltip = "Notifies only once about interactable is in a camera view"), MinimalAPI) class UInteractableScreenCapturer : public USceneCaptureComponent2D { GENERATED_BODY() @@ -19,15 +22,18 @@ public: virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; FInteractableInScreen interactableInScreenDelegate; + UFUNCTION(BlueprintImplementableEvent) + void OnInteractableInScreen(class AInteractable* interactable); UPROPERTY(EditAnywhere) float scanDistance = 7000; protected: + /** Enques render thread task to find obect on screen */ void Process(); private: - FMinimalViewInfo _view; + FMinimalViewInfo view; //!< Camera view cache TSet _sawInteractables; //class UTextureRenderTarget2D* _output; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.cpp index d9be978..60f10e0 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "RaycastInteractableActivator.h" #include "DrawDebugHelpers.h" @@ -14,12 +13,12 @@ URaycastInteractableActivator::URaycastInteractableActivator(const FObjectInitia void URaycastInteractableActivator::Rescan_Implementation() { - _last = nullptr; + lastInteractable = nullptr; } void URaycastInteractableActivator::Scan_Implementation() { - FHitResult result{}; + FHitResult result; FVector startLocation = GetComponentLocation(); FVector endLocation = startLocation + (GetComponentRotation().Vector() * scanDistance); @@ -32,17 +31,17 @@ void URaycastInteractableActivator::Scan_Implementation() if(result.bBlockingHit) { - if(_last != result.GetActor()) + if(lastInteractable != result.GetActor()) { - if(_last) + if(lastInteractable) { - interactableDeactivatedDelegate.Execute(_last, activatorType); - _last = nullptr; + interactableDeactivatedDelegate.Execute(lastInteractable, activatorType); + lastInteractable = nullptr; } - _activated = true; + activated = true; if(auto interactable = Cast(result.GetActor())) { - _last = interactable; + lastInteractable = interactable; if(interactableActivatedDelegate.IsBound()) { interactableActivatedDelegate.Execute(interactable, activatorType); @@ -53,21 +52,21 @@ void URaycastInteractableActivator::Scan_Implementation() #ifdef INTERACTABLE_ACTIVATOR_DEBUG DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Green, false, PrimaryComponentTick.TickInterval, 0, 0.1f); #endif // INTERACTABLE_ACTIVATOR_DEBUG - } + } else { - if(_activated) + if(activated) { if(interactableDeactivatedDelegate.IsBound()) { - interactableDeactivatedDelegate.Execute(_last, activatorType); + interactableDeactivatedDelegate.Execute(lastInteractable, activatorType); } - _activated = false; - _last = nullptr; + activated = false; + lastInteractable = nullptr; } #ifdef INTERACTABLE_ACTIVATOR_DEBUG DrawDebugLine(GetWorld(), startLocation, endLocation, FColor::Red, false, PrimaryComponentTick.TickInterval, 10, 0.1f); #endif // INTERACTABLE_ACTIVATOR_DEBUG - } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.h index 66d09fd..7eb128b 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Activators/RaycastInteractableActivator.h @@ -2,12 +2,14 @@ #pragma once -#include "CoreMinimal.h" #include "InteractableActivator.h" #include "RaycastInteractableActivator.generated.h" -UCLASS(Blueprintable, BlueprintType) +/** + * Activates interactable with a single raycast from a camera center + */ +UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableActivator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Activates interactable with a single raycast from a camera center"), MinimalAPI) class URaycastInteractableActivator : public UInteractableActivator { GENERATED_BODY() @@ -15,12 +17,14 @@ class URaycastInteractableActivator : public UInteractableActivator public: URaycastInteractableActivator(const FObjectInitializer& ObjectInitializer); + virtual bool AutoInstantiateInPlayer() override { return true; } + virtual void Rescan_Implementation() override; protected: virtual void Scan_Implementation() override; private: - class AInteractable* _last = nullptr; - bool _activated = false; + class AInteractable* lastInteractable = nullptr; + bool activated = false; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.cpp index 1094c03..0f09ddf 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.cpp @@ -1,15 +1,38 @@ // Oleg Petruny proprietary. - #include "Interactable.h" #include "Kismet/GameplayStatics.h" +#include "Activators/InteractableActivator.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "Modificators/InteractableModificator.h" #include "PlayerBase.h" #include "Widgets/WidgetsManager.h" +TSet> AInteractable::interactionActivators = {}; +TSet> AInteractable::interactionModificators = {}; + +void AInteractable::AppendActivatorClass(TSubclassOf activator) +{ + if(interactionActivators.Contains(activator)) + return; + + interactionActivators.Add(activator); +} + +void AInteractable::AppendModificatorClass(TSubclassOf modificator) +{ + if(interactionModificators.Contains(modificator)) + return; + + interactionModificators.Add(modificator); + + auto IC = modificator.GetDefaultObject()->GetMappingContext(); + ACustomPlayerController::AppendInputContext(IC); +} + int32 AInteractable::GetActivatedFlags() { return activated; @@ -86,13 +109,13 @@ void AInteractable::EndPlay(const EEndPlayReason::Type EndPlayReason) if(activated) { activationLockers.Empty(); - _Deactivate(static_cast(activated)); + Deactivate(static_cast(activated)); } Super::EndPlay(EndPlayReason); } -void AInteractable::_Activate(EActivatorType type) +void AInteractable::Activate(EActivatorType type) { #ifdef INTERACTABLE_DEBUG GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Cyan, TEXT("Player activate: ") + this->GetName() @@ -113,7 +136,7 @@ void AInteractable::_Activate(EActivatorType type) if(static_cast(modificator.Value->GetActivatorTypes()) & static_cast(type)) { WM->ShowInteractionHints(modificator.Value); - modificator.Value->Bind(player->inputComponent); + modificator.Value->Bind(ACustomPlayerController::GetInput()); } } } @@ -124,10 +147,10 @@ void AInteractable::_Activate(EActivatorType type) collision->SetCustomDepthStencilValue(132); } - Activate(type); + OnActivate(type); } -void AInteractable::_Deactivate(EActivatorType type) +void AInteractable::Deactivate(EActivatorType type) { #ifdef INTERACTABLE_DEBUG GEngine->AddOnScreenDebugMessage(30 + (int)type, 5.0f, FColor::Magenta, TEXT("Player deactivate: ") + this->GetName() @@ -159,5 +182,5 @@ void AInteractable::_Deactivate(EActivatorType type) collision->SetCustomDepthStencilValue(0); } - Deactivate(type); + OnDeactivate(type); } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.h index 1b84e93..9a977c3 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Interactable.h @@ -2,15 +2,18 @@ #pragma once -#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Interactable.generated.h" +/** Turns on debug of interactable objects */ //#define INTERACTABLE_DEBUG +/** Turns on debug of interactable activator components */ //#define INTERACTABLE_ACTIVATOR_DEBUG +/** Turns on debug of interactable modificator components */ //#define INTERACTABLE_MODIFICATOR_DEBUG +/** Defines activation types */ UENUM(BlueprintType, meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true")) enum class EActivatorType : uint8 { @@ -27,38 +30,61 @@ enum class EActivatorType : uint8 }; ENUM_CLASS_FLAGS(EActivatorType); +/** + * Object capable of reacting to activators and execute modificators. + * Sets all needed settings as collision layers on begin play. + */ UCLASS(Blueprintable, BlueprintType, MinimalAPI) class AInteractable : public AActor { GENERATED_BODY() public: + static void AppendActivatorClass(TSubclassOf activator); + static void AppendModificatorClass(TSubclassOf modificator); + + /** Interactables shared cache */ + static TSet> interactionActivators; + static TSet> interactionModificators; + +public: + + /** Returns flags mask of activated types */ int32 GetActivatedFlags(); - void _Activate(EActivatorType type); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + /** Receives activate signal from activator of specific type and activates all modificators of that type */ + UFUNCTION(BlueprintCallable) void Activate(EActivatorType type); - virtual void Activate_Implementation(EActivatorType type) {} - void _Deactivate(EActivatorType type); - UFUNCTION(BlueprintNativeEvent, BlueprintCallable) + /** Receives deactivate signal from activator of specific type and deactivates all modificators of that type */ + UFUNCTION(BlueprintCallable) void Deactivate(EActivatorType type); - virtual void Deactivate_Implementation(EActivatorType type) {} + /** + * All modificators that requires (de)activation lock for current interactable. + * Used manually by modificators to handle operations which can be continued after physical deactivation. + * Eg. MoveModificator movement while mouse buttons are down even if player don't activating interactable anymore. + */ TSet activationLockers; protected: virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + UFUNCTION(BlueprintImplementableEvent) + void OnActivate(EActivatorType type); + UFUNCTION(BlueprintImplementableEvent) + void OnDeactivate(EActivatorType type); + + /** Mask of active activator types */ UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Bitmask, BitmaskEnum = "EActivatorType")) int32 activated = 0; + /** Map of modificators to activator types initialized on BeginPlay */ UPROPERTY() TMap modificators; - class APlayerBase* player = nullptr; TArray collisions; - + class APlayerBase* player = nullptr; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.cpp index 0e8a784..a9acd4f 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "ActivateInteractableModificator.h" #include "EnhancedInputComponent.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.h index ee9cbb2..5c50ae0 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/ActivateInteractableModificator.h @@ -2,14 +2,16 @@ #pragma once -#include "CoreMinimal.h" #include "InteractableModificator.h" #include "ActivateInteractableModificator.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE(FActivateInteractableModificatorActivatedDelegate); -UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) +/** + * Basic modificator for type Use + */ +UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Basic modificator for type Use"), MinimalAPI) class UActivateInteractableModificator : public UInteractableModificator { GENERATED_BODY() diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.cpp index 7f706b2..ae7f4fb 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.cpp @@ -1,14 +1,11 @@ // Oleg Petruny proprietary. - #include "EditInteractableModificator.h" #include "Interactable/Interactable.h" -UEditInteractableModificator::UEditInteractableModificator(const FObjectInitializer& ObjectInitializer) - : UInteractableModificator(ObjectInitializer) -{ - activatorTypes |= static_cast(EActivatorType::Collide); - - -} +//UEditInteractableModificator::UEditInteractableModificator(const FObjectInitializer& ObjectInitializer) +// : UInteractableModificator(ObjectInitializer) +//{ +// activatorTypes |= static_cast(EActivatorType::Collide); +//} diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.h index d2a6a4b..ffb4f32 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/EditInteractableModificator.h @@ -2,17 +2,20 @@ #pragma once -#include "CoreMinimal.h" #include "InteractableModificator.h" -#include "EditInteractableModificator.generated.h" +//#include "EditInteractableModificator.generated.h" -UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) -class UEditInteractableModificator : public UInteractableModificator -{ - GENERATED_BODY() - -public: - UEditInteractableModificator(const FObjectInitializer& ObjectInitializer); - -}; +/** + * + * Edits object topology on collision + */ + //UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Edits object topology on collision"), MinimalAPI) + //class UEditInteractableModificator : public UInteractableModificator + //{ + // GENERATED_BODY() + // + //public: + // UEditInteractableModificator(const FObjectInitializer& ObjectInitializer); + // + //}; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.cpp index 784dc35..d2f061a 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.cpp @@ -1,29 +1,20 @@ // Oleg Petruny proprietary. - #include "InteractableModificator.h" -#include "InputMappingContext.h" - -#include "CustomGameInstanceBase.h" +#include "Interactable/Interactable.h" #include "Widgets/InteractableHintWidget.h" void UInteractableModificator::OnRegister() { UActorComponent::OnRegister(); - if(auto world = GetWorld()) - { - if(auto GI = Cast(world->GetGameInstance())) - { - GI->AppendInteractableModificatorClass(this->GetClass()); - } - } + AInteractable::AppendModificatorClass(GetClass()); } -const UInputMappingContext* UInteractableModificator::GetMappingContext() const +const TSoftObjectPtr UInteractableModificator::GetMappingContext() const { - return inputMapping.LoadSynchronous(); + return inputMapping; } EActivatorType UInteractableModificator::GetActivatorTypes() const diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.h index fbc173f..a765b4c 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InteractableModificator.h @@ -3,29 +3,37 @@ #pragma once #include "Components/ActorComponent.h" -#include "CoreMinimal.h" #include "InteractableModificator.generated.h" enum class EActivatorType : uint8; -UCLASS(Abstract, Blueprintable, BlueprintType) +/** + * Do something on activation by specified activator types + */ +UCLASS(Abstract, Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Do something on activation by specified activator types"), MinimalAPI) class UInteractableModificator : public UActorComponent { GENERATED_BODY() public: - void OnRegister() override; + /** Append itself to CustomGameInstance modificators registry */ + virtual void OnRegister() override; + /** Returns input mappings assigned in constructor */ UFUNCTION(BlueprintCallable) - const class UInputMappingContext* GetMappingContext() const; + const TSoftObjectPtr GetMappingContext() const; + + /** Filters activation type in interractable */ UFUNCTION(BlueprintCallable) EActivatorType GetActivatorTypes() const; + /** Called from interactable on activation (mostly used to bind input context to internal modificator functions) */ UFUNCTION(BlueprintNativeEvent, BlueprintCallable) void Bind(class UEnhancedInputComponent* input); virtual void Bind_Implementation(class UEnhancedInputComponent* input) {} + /** Called from interactable on deactivation (mostly used to unbind input context from internal functions) */ UFUNCTION(BlueprintNativeEvent, BlueprintCallable) void Unbind(); virtual void Unbind_Implementation() {} diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.cpp index ac90f8c..57ea051 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "InventoryInteractableModificator.h" #include "EnhancedInputComponent.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.h index b23cc72..d5b3fcb 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/InventoryInteractableModificator.h @@ -2,12 +2,14 @@ #pragma once -#include "CoreMinimal.h" #include "InteractableModificator.h" #include "InventoryInteractableModificator.generated.h" -UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) +/** + * Modificator of type Use for storing items in a APlayerBase + */ +UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Modificator of type Use for storing items in a APlayerBase"), MinimalAPI) class UInventoryInteractableModificator : public UInteractableModificator { GENERATED_BODY() diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.cpp index 5aef7c9..a38c87f 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "MoveInteractableModificator.h" #include "EnhancedInputComponent.h" @@ -90,7 +89,7 @@ void UMoveInteractableModificator::Unbind_Implementation() bindindingHandlers.Empty(); SetComponentTickEnabled(false); - actor->_Deactivate(GetActivatorTypes()); + actor->Deactivate(GetActivatorTypes()); OnMoveDeactivated.Broadcast(); } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.h index 8413435..d50e920 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/MoveInteractableModificator.h @@ -2,7 +2,6 @@ #pragma once -#include "CoreMinimal.h" #include "InputActionValue.h" #include "InteractableModificator.h" @@ -13,7 +12,10 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDeactivateMoveInteractableModificatorActivat DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHoldingMoveInteractableModificatorActivatedDelegate); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRotatingMoveInteractableModificatorActivatedDelegate); -UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) +/** + * Basic modificator for Move type activator + */ +UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Basic modificator for Move type activator"), MinimalAPI) class UMoveInteractableModificator : public UInteractableModificator { GENERATED_BODY() diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.cpp index 3166fde..4644427 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "SawInteractableModificator.h" #include "Interactable/Interactable.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.h index 368d213..fd3f7c2 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Interactable/Modificators/SawInteractableModificator.h @@ -2,14 +2,16 @@ #pragma once -#include "CoreMinimal.h" #include "InteractableModificator.h" #include "SawInteractableModificator.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE(FSawInteractableModificatorActivatedDelegate); -UCLASS(ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent), Blueprintable, BlueprintType) +/** + * Basic modificator for Saw type activator + */ +UCLASS(Blueprintable, BlueprintType, ClassGroup = InteractableModificator, meta = (BlueprintSpawnableComponent, ShortTooltip = "Basic modificator for Saw type activator"), MinimalAPI) class USawInteractableModificator : public UInteractableModificator { GENERATED_BODY() diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.cpp index 7cca7d5..f32339b 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.cpp @@ -1,12 +1,11 @@ // Oleg Petruny proprietary. - #include "Checkpoint.h" -#include "CustomGameInstanceBase.h" +#include "CustomGameInstance.h" void ACheckpoint::SaveGame() { - if(auto GI = Cast(GetWorld()->GetGameInstance())) + if(auto GI = UCustomGameInstance::Get()) GI->SaveGame(GetFName()); } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.h index 6f452f8..ebe7b9a 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Checkpoint.h @@ -6,6 +6,7 @@ #include "Checkpoint.generated.h" +/** Simple actor for game save */ UCLASS(Blueprintable, BlueprintType, MinimalAPI) class ACheckpoint : public AActor { diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level1.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level1.cpp index 9a4c982..3d7fd6d 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level1.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level1.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "Level1.h" #include "Atmosphere/AtmosphericFog.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level2.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level2.cpp index 5c6a12e..9915566 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level2.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level2.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "Level2.h" void ALevel2::BeginPlay() diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level3.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level3.cpp index b80c2f3..82126eb 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level3.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level3.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "Level3.h" #include "Atmosphere/AtmosphericFog.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level4.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level4.cpp index 9851fce..6622d1f 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level4.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level4.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "Level4.h" #include "Atmosphere/AtmosphericFog.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level5.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level5.cpp index cfe7740..cf35120 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level5.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/Level5.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "Level5.h" #include "Atmosphere/AtmosphericFog.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.cpp index 9686572..6ee3b48 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "LevelBase.h" #include "Engine/StaticMesh.h" @@ -10,8 +9,8 @@ #include "Kismet/GameplayStatics.h" #include "LevelSequencePlayer.h" -#include "CommonFunctions.h" -#include "CustomGameInstanceBase.h" +#include "CustomGameInstance.h" +#include "CustomPlayerController.h" #include "Interactable/Interactable.h" #include "Levels/Checkpoint.h" #include "MainGameModeBase.h" @@ -19,21 +18,17 @@ #include "PlayerBase.h" #include "SaveData.h" +ALevelBase* ALevelBase::Get() +{ + if(auto GM = AMainGameModeBase::Get()) + return GM->leadLevel.Get(); + return nullptr; +} + void ALevelBase::BeginPlay() { AMainGameModeBase::leadLevel = TStrongObjectPtr{ this }; - if(auto world = GetWorld()) - { - if(auto GI = Cast(world->GetGameInstance())) - { - for(TActorIterator it(GetWorld()); it; ++it) - { - GI->inputContexts.Add(it->GetInputMappings()); - } - } - } - ALevelScriptActor::BeginPlay(); BroadcastNewLevelBeginPlay(); @@ -62,7 +57,7 @@ void ALevelBase::IterateToState(int32 to) void ALevelBase::BroadcastNewLevelBeginPlay() { - if(auto GI = Cast(GetWorld()->GetGameInstance())) + if(auto GI = UCustomGameInstance::Get()) GI->OnLevelBeginned.Broadcast(GetFName()); } @@ -83,13 +78,13 @@ void ALevelBase::StartLevelAnimations() void ALevelBase::ApplySaveData() { - auto GI = UCustomGameInstanceBase::GetGameInstance(); + auto GI = UCustomGameInstance::Get(); if(!GI || !GI->saveData || GI->saveData->level != GetWorld()->GetFName()) return; IterateToState(GI->saveData->state); - auto player = UCommonFunctions::GetPlayer(this); + auto player = APlayerBase::Get(); if(!player) return; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.h index 6536b3f..ea28374 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Levels/LevelBase.h @@ -6,15 +6,28 @@ #include "LevelBase.generated.h" +/** + * Expands basic UE level script actor. + * Has int type level states and events. + * Brodcasts level instantiation by CustomGameInstance::OnLevelBeginned(FName). + * On BeginPlay applies last save data if valid, + * and instantiate all sequencers from array onBeginPlaySequences. + */ UCLASS(BlueprintType) class ALevelBase : public ALevelScriptActor { GENERATED_BODY() public: + /** Returns lead level script */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Lead Level Script")) + static ALevelBase* Get(); + + /** Iterates throught level states */ UFUNCTION(BlueprintCallable) inline void CallNextState() { ++state; NextState(); } + /** Calls specific event id in level */ UFUNCTION(BlueprintImplementableEvent) void CallEvent(int32 id); @@ -23,9 +36,11 @@ public: protected: virtual void BeginPlay() override; + /** Notifies level to process current state */ UFUNCTION(BlueprintImplementableEvent) void NextState(); + /** Shortcut for iterating from current to expected state */ UFUNCTION(BlueprintCallable) void IterateToState(int32 to); @@ -33,12 +48,13 @@ protected: void StartLevelAnimations(); void ApplySaveData(); + /** List of level animations for instantiation on level BeginPlay */ UPROPERTY(EditDefaultsOnly) TArray> onBeginPlaySequences; + /** Cache of actors that hold instantiated animations on BeginPlay */ TArray onBeginPlaySequencesActors; + /** Current state of level */ UPROPERTY(BlueprintReadOnly) int32 state = -1; - UPROPERTY(EditDefaultsOnly) - TArray> stateSequences; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.cpp index 5517836..f3ff4cd 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "MainGameModeBase.h" #include "Engine/World.h" @@ -8,7 +7,6 @@ #include "Kismet/GameplayStatics.h" #include "UObject/ScriptInterface.h" -#include "CustomGameInstanceBase.h" #include "CutsceneManager.h" #include "DialogueManager.h" #include "Levels/LevelBase.h" @@ -16,66 +14,71 @@ #include "QuickTimeEvent.h" #include "Widgets/WidgetsManager.h" -AMainGameModeBase* AMainGameModeBase::_instance = nullptr; -TStrongObjectPtr AMainGameModeBase::_widgetsManager = nullptr; -TStrongObjectPtr AMainGameModeBase::_cutsceneManager = nullptr; -TStrongObjectPtr AMainGameModeBase::_quickTimeEventManager = nullptr; -TStrongObjectPtr AMainGameModeBase::_dialogueManager = nullptr; +AMainGameModeBase* AMainGameModeBase::instance = nullptr; +TStrongObjectPtr AMainGameModeBase::widgetsManager = nullptr; +TStrongObjectPtr AMainGameModeBase::cutsceneManager = nullptr; +TStrongObjectPtr AMainGameModeBase::quickTimeEventManager = nullptr; +TStrongObjectPtr AMainGameModeBase::dialogueManager = nullptr; TStrongObjectPtr AMainGameModeBase::leadLevel = nullptr; void AMainGameModeBase::StartPlay() { - _instance = this; - _widgetsManager = TStrongObjectPtr{ NewObject(this, widgetManagerClass) }; - _cutsceneManager = TStrongObjectPtr{ NewObject(this) }; - _quickTimeEventManager = TStrongObjectPtr{ NewObject(this) }; - _dialogueManager = TStrongObjectPtr{ NewObject(this) }; + instance = this; + widgetsManager = TStrongObjectPtr{ NewObject(this, widgetManagerClass) }; + cutsceneManager = TStrongObjectPtr{ NewObject(this) }; + quickTimeEventManager = TStrongObjectPtr{ NewObject(this) }; + dialogueManager = TStrongObjectPtr{ NewObject(this) }; AGameModeBase::StartPlay(); - _widgetsManager->Init(); + widgetsManager->Init(); } void AMainGameModeBase::EndPlay(const EEndPlayReason::Type EndPlayReason) { - _cutsceneManager->LockCallback(true); - //_cutsceneManager->ClearQueue(); + cutsceneManager->LockCallback(true); + //cutsceneManager->ClearQueue(); // condition race segfault? } bool AMainGameModeBase::SetPause(APlayerController* PC, FCanUnpause CanUnpauseDelegate) { - if(_widgetsManager) + if(widgetsManager) { if(IsPaused()) { - _widgetsManager->HideWidgets(); + widgetsManager->HideWidgets(); } else { - _widgetsManager->ShowWidgets(); + widgetsManager->ShowWidgets(); } } return AGameModeBase::SetPause(PC, CanUnpauseDelegate); } +AMainGameModeBase* AMainGameModeBase::Get() +{ + return instance; +} + UWidgetsManager* AMainGameModeBase::GetWidgetsManager() { - return _widgetsManager.Get(); + return widgetsManager.Get(); } UCutsceneManager* AMainGameModeBase::GetCutsceneManager() { - return _cutsceneManager.Get(); + return cutsceneManager.Get(); } UQuickTimeEventManager* AMainGameModeBase::GetQuickTimeEventManager() { - return _quickTimeEventManager.Get(); + return quickTimeEventManager.Get(); } UDialogueManager* AMainGameModeBase::GetDialogueManager() { - return _dialogueManager.Get(); + return dialogueManager.Get(); } void AMainGameModeBase::CallNextLevelState() @@ -92,39 +95,37 @@ void AMainGameModeBase::CallLevelEvent(int32 id) void AMainGameModeBase::UpdateQuests(TArray items) { - if(_instance && _instance->questsUpdateDelegate.IsBound()) - _instance->questsUpdateDelegate.Broadcast(items); + if(instance && instance->questsUpdateDelegate.IsBound()) + instance->questsUpdateDelegate.Broadcast(items); } void AMainGameModeBase::SwitchCameraMode() { - static TWeakObjectPtr _playerPawn = nullptr; + static TWeakObjectPtr playerPawn = nullptr; if(auto PC = UGameplayStatics::GetPlayerController(GetWorld(), 0)) { if(auto pawn = PC->GetPawn()) { - if(!_playerPawn.IsValid()) + if(!playerPawn.IsValid()) { auto spawnLoc = pawn->GetActorLocation(); auto spawnRot = pawn->GetActorRotation(); if(auto cameraPawn = GetWorld()->SpawnActor(SpectatorClass, spawnLoc, spawnRot)) { - _playerPawn = pawn; + playerPawn = pawn; PC->Possess(cameraPawn); } } else { - PC->Possess(_playerPawn.Get()); + PC->Possess(playerPawn.Get()); pawn->Destroy(); - _playerPawn = nullptr; + playerPawn = nullptr; } } } - if(_widgetsManager) - { - _widgetsManager->UpdateWidgetsOwner(); - } + if(widgetsManager.IsValid()) + widgetsManager->UpdateWidgetsOwner(); } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.h index 4aee14b..a630654 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/MainGameModeBase.h @@ -8,6 +8,11 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FQuestsUpdateDelegate, TArray, quests); +/* + * Manager of most gameplay systems. + * Widgets, custcenes, QTE, dialogues, quests, camera mode, level. + * Please, use MainGameMode SetPause to pause the game. + */ UCLASS() class AMainGameModeBase : public AGameModeBase { @@ -18,6 +23,8 @@ public: virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; virtual bool SetPause(APlayerController* PC, FCanUnpause CanUnpauseDelegate = FCanUnpause()) override; + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Main Game Mode")) + static AMainGameModeBase* Get(); UFUNCTION(BlueprintPure) static class UWidgetsManager* GetWidgetsManager(); UFUNCTION(BlueprintPure) @@ -46,9 +53,9 @@ protected: TSubclassOf widgetManagerClass; private: - static AMainGameModeBase* _instance; - static TStrongObjectPtr _widgetsManager; - static TStrongObjectPtr _cutsceneManager; - static TStrongObjectPtr _quickTimeEventManager; - static TStrongObjectPtr _dialogueManager; + static AMainGameModeBase* instance; + static TStrongObjectPtr widgetsManager; + static TStrongObjectPtr cutsceneManager; + static TStrongObjectPtr quickTimeEventManager; + static TStrongObjectPtr dialogueManager; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarManager.cpp index 659903b..25e6951 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "AgeOfWarManager.h" #include "Camera/CameraComponent.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarUnit.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarUnit.cpp index 88a4826..d09c3bb 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarUnit.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/AgeOfWar/AgeOfWarUnit.cpp @@ -1,12 +1,11 @@ // Oleg Petruny proprietary. - #include "AgeOfWarUnit.h" +#include "Components/BoxComponent.h" #include "Components/StaticMeshComponent.h" #include "AgeOfWarManager.h" -#include namespace { diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadManager.cpp index c7794e6..31ab03a 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "CrossyRoadManager.h" #include "Camera/CameraComponent.h" @@ -10,7 +9,7 @@ #include "InputMappingContext.h" #include "CrossyRoadObstacle.h" -#include "CustomGameInstanceBase.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "PlayerBase.h" #include "Widgets/WidgetsManager.h" @@ -19,7 +18,7 @@ ACrossyRoadManager::ACrossyRoadManager() : AMinigame() { static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_Minigame_CrossyRoad.IMC_Minigame_CrossyRoad'") }; - input = asset.Object; + context = asset.Object; auto root = CreateDefaultSubobject(TEXT("Scene")); @@ -43,16 +42,17 @@ void ACrossyRoadManager::Start(APlayerBase* playerPawn, FMinigameEndCallback del player->LockPlayer(FPlayerLock::All()); player->SwitchToView(this); - for(auto& mapping : input.LoadSynchronous()->GetMappings()) + auto input = ACustomPlayerController::GetInput(); + for(auto& mapping : context.LoadSynchronous()->GetMappings()) { if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Up")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Up).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Up).GetHandle()); else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Down")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Down).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Down).GetHandle()); else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Left")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Left).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Left).GetHandle()); else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Right")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Right).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ACrossyRoadManager::Right).GetHandle()); } playerPos->SetWorldLocation(lines[0]->GetLocationAtTime(lines[0]->Duration * playerLineTime, ESplineCoordinateSpace::World)); @@ -70,7 +70,7 @@ void ACrossyRoadManager::End() PrimaryActorTick.SetTickFunctionEnable(false); for(int32 handler : inputHandlers) - player->inputComponent->RemoveBindingByHandle(handler); + ACustomPlayerController::GetInput()->RemoveBindingByHandle(handler); player->UnlockPlayer(FPlayerLock::All()); player->ReturnPlayerView(); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadObstacle.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadObstacle.cpp index ea3af7e..6b87dd7 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadObstacle.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/CrossyRoad/CrossyRoadObstacle.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "CrossyRoadObstacle.h" #include "CrossyRoadManager.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Fishing/FishingManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Fishing/FishingManager.cpp index b5f5a69..f30d2b4 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Fishing/FishingManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Fishing/FishingManager.cpp @@ -1,18 +1,18 @@ // Oleg Petruny proprietary. - #include "FishingManager.h" #include "EnhancedInputComponent.h" #include "InputMappingContext.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "PlayerBase.h" AFishingManager::AFishingManager() { static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_Minigame_Fishing.IMC_Minigame_Fishing'") }; - input = asset.Object; + context = asset.Object; } void AFishingManager::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate) @@ -24,15 +24,17 @@ void AFishingManager::Start(APlayerBase* playerPawn, FMinigameEndCallback delega player->LockPlayer(FPlayerLock::All()); - auto& mapping = input.LoadSynchronous()->GetMapping(0); - handler1 = player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Started, this, &AFishingManager::OnInputHold).GetHandle(); - handler2 = player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Completed, this, &AFishingManager::OnInputUnhold).GetHandle(); + auto input = ACustomPlayerController::GetInput(); + auto& mapping = context.LoadSynchronous()->GetMapping(0); + handler1 = input->BindAction(mapping.Action, ETriggerEvent::Started, this, &AFishingManager::OnInputHold).GetHandle(); + handler2 = input->BindAction(mapping.Action, ETriggerEvent::Completed, this, &AFishingManager::OnInputUnhold).GetHandle(); } void AFishingManager::End() { - player->inputComponent->RemoveBindingByHandle(handler1); - player->inputComponent->RemoveBindingByHandle(handler2); + auto input = ACustomPlayerController::GetInput(); + input->RemoveBindingByHandle(handler1); + input->RemoveBindingByHandle(handler2); player->UnlockPlayer(FPlayerLock::All()); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.cpp index eb49fc5..04186f4 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.cpp @@ -1,11 +1,10 @@ // Oleg Petruny proprietary. - #include "Minigame.h" -#include "EnhancedInputSubsystems.h" #include "InputMappingContext.h" +#include "CustomPlayerController.h" #include "PlayerBase.h" AMinigame::AMinigame() @@ -22,23 +21,13 @@ void AMinigame::End() OnEnd(); } -void AMinigame::Restart() -{} - -UInputMappingContext* AMinigame::GetInputMappings() -{ - return input.LoadSynchronous(); -} - void AMinigame::Start(APlayerBase* playerPawn, FMinigameEndCallback delegate) { player = playerPawn; callback = delegate; - if(input) - if(auto PC = Cast(playerPawn->GetController())) - if(auto inputSubsystem = ULocalPlayer::GetSubsystem(PC->GetLocalPlayer())) - inputSubsystem->AddMappingContext(input.LoadSynchronous(), 0); + if(context.IsValid()) + ACustomPlayerController::AppendInputContext(context); OnStart(); } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.h index e103c50..f1f7fdc 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/Minigame.h @@ -15,7 +15,14 @@ enum class EMinigameResult : uint8 DECLARE_DYNAMIC_DELEGATE_TwoParams(FMinigameEndCallback, EMinigameResult, result, int32, score); -UCLASS(Blueprintable, BlueprintType, MinimalAPI, Abstract) +/** + * Interface for all minigame classes. + * Any minigame is started/ended/restarted by executing Start()/End()/Restart() on specific instance. + * Each call is after broadcasted into a blueprint event also. + * On start the caller can pass a OnEndCallback delegate to receive result and score on a minigame end. + * Each minigame can have its own contextInput + */ +UCLASS(Abstract, Blueprintable, BlueprintType, MinimalAPI) class AMinigame : public AActor { GENERATED_BODY() @@ -25,21 +32,21 @@ public: UFUNCTION(BlueprintCallable) virtual void Start(class APlayerBase* playerPawn, FMinigameEndCallback delegate); - UFUNCTION(BlueprintImplementableEvent) void OnStart(); UFUNCTION(BlueprintCallable) virtual void End(); - - UFUNCTION(BlueprintCallable) - virtual void Restart(); - UFUNCTION(BlueprintImplementableEvent) void OnEnd(); + UFUNCTION(BlueprintCallable) + virtual void Restart() {} + UFUNCTION(BlueprintImplementableEvent) + void OnRestart(); + UFUNCTION(BlueprintPure) - class UInputMappingContext* GetInputMappings(); + TSoftObjectPtr GetInputMappings() { return context; } protected: FMinigameEndCallback callback; @@ -55,6 +62,6 @@ protected: bool ended = false; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) - TSoftObjectPtr input = nullptr; + TSoftObjectPtr context = nullptr; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/RythmClick/RythmClickManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/RythmClick/RythmClickManager.cpp index 297e092..c664b22 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/RythmClick/RythmClickManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/RythmClick/RythmClickManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "RythmClickManager.h" #include "MainGameModeBase.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfManager.cpp index 9b0746a..35bde19 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "SubwaySurfManager.h" #include "Camera/CameraComponent.h" @@ -9,7 +8,7 @@ #include "EnhancedInputComponent.h" #include "InputMappingContext.h" -#include "CustomGameInstanceBase.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "PlayerBase.h" #include "SubwaySurfObstacle.h" @@ -19,7 +18,7 @@ ASubwaySurfManager::ASubwaySurfManager() : AMinigame() { static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/Minigame/IMC_Minigame_SubwaySurf.IMC_Minigame_SubwaySurf'") }; - input = asset.Object; + context = asset.Object; auto root = CreateDefaultSubobject(TEXT("Scene")); @@ -43,16 +42,17 @@ void ASubwaySurfManager::Start(APlayerBase* playerPawn, FMinigameEndCallback del player->LockPlayer(FPlayerLock::All()); player->SwitchToView(this); - for(auto& mapping : input.LoadSynchronous()->GetMappings()) + auto input = ACustomPlayerController::GetInput(); + for(auto& mapping : context.LoadSynchronous()->GetMappings()) { if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Up")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Up).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Up).GetHandle()); else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Down")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Down).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Down).GetHandle()); else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Left")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Left).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Left).GetHandle()); else if(mapping.Action->ActionDescription.EqualTo(FText::AsCultureInvariant(TEXT("Right")))) - inputHandlers.Add(player->inputComponent->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Right).GetHandle()); + inputHandlers.Add(input->BindAction(mapping.Action, ETriggerEvent::Triggered, this, &ASubwaySurfManager::Right).GetHandle()); } playerPos->SetRelativeLocation(lines[1]->GetLocationAtTime(lines[1]->Duration * 0.01f, ESplineCoordinateSpace::Local)); @@ -66,7 +66,7 @@ void ASubwaySurfManager::End() PrimaryActorTick.SetTickFunctionEnable(false); for(int32 handler : inputHandlers) - player->inputComponent->RemoveBindingByHandle(handler); + ACustomPlayerController::GetInput()->RemoveBindingByHandle(handler); player->UnlockPlayer(FPlayerLock::All()); player->ReturnPlayerView(); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfObstacle.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfObstacle.cpp index 5d0c284..254c31c 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfObstacle.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Minigame/SubwaySurf/SubwaySurfObstacle.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "SubwaySurfObstacle.h" #include "SubwaySurfManager.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.cpp index b866fbb..853d6ba 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.cpp @@ -1,19 +1,16 @@ // Oleg Petruny proprietary. - #include "PlayerBase.h" #include "Camera/CameraComponent.h" -#include "EnhancedInputComponent.h" -#include "EnhancedInputSubsystems.h" #include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/SpringArmComponent.h" #include "InputMappingContext.h" #include "Kismet/GameplayStatics.h" #include "Kismet/KismetMathLibrary.h" -#include "CustomGameInstanceBase.h" -#include "CustomGameUserSettings.h" +#include "CustomGameSettings.h" +#include "CustomPlayerController.h" #include "Interactable/Activators/InteractableActivator.h" #include "Interactable/Interactable.h" #include "Interactable/Modificators/InteractableModificator.h" @@ -28,6 +25,10 @@ namespace APlayerBase::APlayerBase() : ACharacter() { + static ConstructorHelpers::FObjectFinder asset{ TEXT("/Script/EnhancedInput.InputMappingContext'/Game/Input/IMC_Player.IMC_Player'") }; + context = asset.Object; + ACustomPlayerController::AppendInputContext(context); + PrimaryActorTick.bCanEverTick = true; camera = CreateDefaultSubobject(TEXT("Camera")); @@ -61,6 +62,13 @@ void APlayerBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponen ACharacter::SetupPlayerInputComponent(PlayerInputComponent); } +APlayerBase* APlayerBase::Get() +{ + if(auto PC = ACustomPlayerController::Get()) + return Cast(PC->GetPawn()); + return nullptr; +} + void APlayerBase::BeginPlay() { ACharacter::BeginPlay(); @@ -77,51 +85,15 @@ void APlayerBase::BeginPlay() cameraManager->ViewPitchMax = maxPitch; } - auto gameSettings = UCustomGameUserSettings::GetCustomGameUserSettings(); - - if(camera) + auto gameSettings = UCustomGameSettings::Get(); + if(gameSettings && camera) { camera->PostProcessSettings.MotionBlurAmount = gameSettings->bUseMotionBlur ? 1.0f : 0.0f; } - playerController = Cast(GetController()); - if(playerController) - { - if(auto inputSubsystem = ULocalPlayer::GetSubsystem(playerController->GetLocalPlayer())) - { - if(auto GI = Cast(GetWorld()->GetGameInstance())) - { - inputSubsystem->ClearAllMappings(); - for(auto& inputContext : GI->inputContexts) - { - inputSubsystem->AddMappingContext(inputContext.LoadSynchronous(), 0); - } - } - } - - inputComponent = Cast(playerController->InputComponent); - if(inputComponent) - { - ((UInputComponent*)inputComponent)->BindAction(TEXT("AnyKey"), IE_Pressed, this, &APlayerBase::OnAnyKeyPressed); - ((UInputComponent*)inputComponent)->BindAction(TEXT("AnyKey"), IE_Released, this, &APlayerBase::OnAnyKeyReleased); - } - } - LoadInteractablesActivators(); } -void APlayerBase::OnAnyKeyPressed(FKey key) -{ - if(onAnyKeyPressedDelegate.IsBound()) - onAnyKeyPressedDelegate.Broadcast(key); -} - -void APlayerBase::OnAnyKeyReleased(FKey key) -{ - if(onAnyKeyReleasedDelegate.IsBound()) - onAnyKeyReleasedDelegate.Broadcast(key); -} - bool APlayerBase::IsMoving() { return bIsMoving; @@ -142,7 +114,7 @@ void APlayerBase::LockPlayer(FPlayerLock lock) inventoryLocked += lock.inventory; if(interactionLocked) - ResetIntractions(); + ResetInteractions(); } void APlayerBase::UnlockPlayer(FPlayerLock lock) @@ -155,7 +127,7 @@ void APlayerBase::UnlockPlayer(FPlayerLock lock) inventoryLocked -= lock.inventory; if(!interactionLocked) - ResetIntractions(); + ResetInteractions(); } void APlayerBase::FlyMode(bool on) @@ -163,7 +135,7 @@ void APlayerBase::FlyMode(bool on) GetCharacterMovement()->GravityScale = on ? 0.0f : 1.0f; } -void APlayerBase::ResetIntractions() +void APlayerBase::ResetInteractions() { InteractableDeactivated(lastInteractable, static_cast(0xFF)); for(auto activator : interactableActivators) @@ -257,22 +229,24 @@ void APlayerBase::UpdatePitch(float min, float max) void APlayerBase::LoadInteractablesActivators() { - if(auto GI = Cast(GetWorld()->GetGameInstance())) + TSet instancedActivators; + for(auto& act : AInteractable::interactionActivators) { - TSet instancedActivators; - for(auto& act : GI->interactionsActivators) - { - if(instancedActivators.Contains(act)) - continue; - instancedActivators.Add(act); + if(act.Get()) + if(auto obj = Cast(act.Get()->GetDefaultObject())) + if(!obj->AutoInstantiateInPlayer()) + continue; - auto component = NewObject(this, act); - component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated); - component->interactableDeactivatedDelegate.BindUObject(this, &APlayerBase::InteractableDeactivated); - component->SetupAttachment(camera); - component->RegisterComponent(); - interactableActivators.Add(component); - } + if(instancedActivators.Contains(act.Get())) + continue; + instancedActivators.Add(act.Get()); + + auto component = NewObject(this, act); + component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated); + component->interactableDeactivatedDelegate.BindUObject(this, &APlayerBase::InteractableDeactivated); + component->SetupAttachment(camera); + component->RegisterComponent(); + interactableActivators.Add(component); } } @@ -284,7 +258,7 @@ void APlayerBase::InteractableActivated(AInteractable* interactable, EActivatorT if(interactionLocked || interactable->IsHidden()) return; - interactable->_Activate(type); + interactable->Activate(type); if(interactable != lastInteractable) lastInteractable = interactable; @@ -295,7 +269,7 @@ void APlayerBase::InteractableDeactivated(AInteractable* interactable, EActivato if(!interactable) return; - interactable->_Deactivate(type); + interactable->Deactivate(type); if(interactable->GetActivatedFlags() == 0) lastInteractable = nullptr; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.h index 5fd59dd..7d3c691 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/PlayerBase.h @@ -8,10 +8,9 @@ enum class EActivatorType : uint8; -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyPressedDelegate, FKey, key); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyReleasedDelegate, FKey, key); -DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPlayerMovedDelegate); - +/** + * Bit collection of player locks. + */ USTRUCT(BlueprintType) struct FPlayerLock { @@ -27,17 +26,27 @@ struct FPlayerLock static FPlayerLock All(); }; +/** + * Base class for player pawn. + * Synchronizes movement speed with fps, manages camera and inventory, + * prepares for work with interactables, and manages basic player input. + */ UCLASS(Blueprintable, BlueprintType) class APlayerBase : public ACharacter { GENERATED_BODY() public: + /** setup input context, camera and inventory */ APlayerBase(); + virtual void Tick(float DeltaTime) override; virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Player Base Pawn")) + static APlayerBase* Get(); + UFUNCTION(BlueprintPure) bool IsMoving(); UFUNCTION(BlueprintPure) @@ -48,38 +57,35 @@ public: void LockPlayer(const FPlayerLock lock); void UnlockPlayer(const FPlayerLock lock); void FlyMode(bool on); - void ResetIntractions(); + /** Force interactable activators reset */ + void ResetInteractions(); + + /** Switch camera possesion to passed Actor */ UFUNCTION(BlueprintCallable, Category = Character) void SwitchToView(class AActor* target); + /** Posess player camera */ UFUNCTION(BlueprintCallable, Category = Character) void ReturnPlayerView(); + /** Place item into first inventory */ UFUNCTION(BlueprintCallable, Category = Character) void TakeItemToLeftHand(class AActor* actor); + /** Place item into second inventory */ UFUNCTION(BlueprintCallable, Category = Character) void TakeItemToRightHand(class AActor* actor); + /** Check if Actor is in inventory */ UFUNCTION(BlueprintCallable, Category = Character) bool IsInInventory(const class AActor* actor); - UPROPERTY(BlueprintAssignable) - FPlayerMovedDelegate OnPlayerMoved; FVector moveVector; - FPlayerAnyKeyPressedDelegate onAnyKeyPressedDelegate; - FPlayerAnyKeyReleasedDelegate onAnyKeyReleasedDelegate; - - class UEnhancedInputComponent* inputComponent = nullptr; - class AActor* leftPocketItem = nullptr; class AActor* rightPocketItem = nullptr; protected: virtual void BeginPlay() override; - void OnAnyKeyPressed(FKey key); - void OnAnyKeyReleased(FKey key); - UFUNCTION(BlueprintCallable, Category = CameraMode) void SwitchToCameraPawn(); @@ -91,6 +97,7 @@ protected: UFUNCTION(BlueprintCallable, Category = Character) void SwitchRun(bool run); + /** Sets camera pitch range */ UFUNCTION(BlueprintCallable, Category = Character) void UpdatePitch(float min, float max); @@ -153,4 +160,6 @@ private: bool itemDropLocked = false; FTimerHandle itemDropLockTimer; + + TSoftObjectPtr context; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.cpp index b9c0742..6374f20 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.cpp @@ -1,29 +1,19 @@ // Oleg Petruny proprietary. - #include "QuestManager.h" -#include "Kismet/GameplayStatics.h" - -#include "Levels/LevelBase.h" #include "MainGameModeBase.h" #include "Widgets/WidgetsManager.h" void AQuestManager::BeginPlay() { - if(auto gamemode_base = UGameplayStatics::GetGameMode(GetWorld())) - { - gamemode = Cast(gamemode_base); - if(gamemode) - { - gamemode->questsUpdateDelegate.AddDynamic(this, &AQuestManager::Update); - } - } + if(auto gamemode = AMainGameModeBase::Get()) + gamemode->questsUpdateDelegate.AddDynamic(this, &AQuestManager::Update); } void AQuestManager::EndPlay(const EEndPlayReason::Type EndPlayReason) { - if(gamemode) + if(auto gamemode = AMainGameModeBase::Get()) gamemode->questsUpdateDelegate.RemoveDynamic(this, &AQuestManager::Update); } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.h index 28c10d8..26a6f8a 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuestManager.h @@ -6,6 +6,9 @@ #include "QuestManager.generated.h" +/** + * "Manages" quests. In fact takes string rows from a level and push them to Journal widget. + */ UCLASS(Blueprintable, BlueprintType) class AQuestManager : public AActor { @@ -21,6 +24,4 @@ protected: UFUNCTION() void Update(TArray quests); - class AMainGameModeBase* gamemode = nullptr; - }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.cpp index 333f9d3..2881328 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.cpp @@ -1,11 +1,11 @@ // Oleg Petruny proprietary. - #include "QuickTimeEvent.h" #include "Kismet/GameplayStatics.h" #include "CommonFunctions.h" +#include "CustomPlayerController.h" #include "MainGameModeBase.h" #include "PlayerBase.h" #include "Widgets/WidgetsManager.h" @@ -14,7 +14,7 @@ int32 Event::counter = 0; Event::Event() { - _id = counter++; + id = counter++; } Event::Event(EQuickTimeEventType type, FKey& key, FQuickTimeEventEndCallback& callback, bool sequence) @@ -28,14 +28,14 @@ Event::Event(EQuickTimeEventType type, FKey& key, FQuickTimeEventEndCallback& ca inline int32 Event::GetId() { - return _id; + return id; } void UQuickTimeEventManager::ShowQuickTimeEvent(FQuickTimeEventEnqueProperties properties) { UE_LOG(LogTemp, Log, TEXT("ShowQuickTimeEvent Start")); OnFirstEventInit(); - FScopeLock lock1(&_lock); + FScopeLock lock1(&lock); CreateEvent(properties, false); UE_LOG(LogTemp, Log, TEXT("ShowQuickTimeEvent End")); } @@ -45,8 +45,8 @@ void UQuickTimeEventManager::EnqueQuickTimeEvent(FQuickTimeEventEnqueProperties UE_LOG(LogTemp, Log, TEXT("EnqueQuickTimeEvent Start")); OnFirstEventInit(); { - FScopeLock lock1(&_lock); - _nextEvents.Enqueue(properties); + FScopeLock lock1(&lock); + nextEvents.Enqueue(properties); } ShowNextEvent(); UE_LOG(LogTemp, Log, TEXT("EnqueQuickTimeEvent End")); @@ -55,9 +55,9 @@ void UQuickTimeEventManager::EnqueQuickTimeEvent(FQuickTimeEventEnqueProperties void UQuickTimeEventManager::ShowNextEvent() { UE_LOG(LogTemp, Log, TEXT("ShowNextEvent Start")); - FScopeLock lock1(&_lock); + FScopeLock lock1(&lock); FQuickTimeEventEnqueProperties properties; - _nextEvents.Dequeue(properties); + nextEvents.Dequeue(properties); CreateEvent(properties, true); UE_LOG(LogTemp, Log, TEXT("ShowNextEvent End")); } @@ -65,9 +65,9 @@ void UQuickTimeEventManager::ShowNextEvent() void UQuickTimeEventManager::OnEventEnd(int32 id, EQuickTimeEventResult result) { UE_LOG(LogTemp, Log, TEXT("OnEventEnd Start")); - FScopeLock lock1(&_lock); + FScopeLock lock1(&lock); Event event; - if(!_events.RemoveAndCopyValue(id, event)) + if(!events.RemoveAndCopyValue(id, event)) return; GetWorld()->GetTimerManager().ClearTimer(event.timer); @@ -75,19 +75,19 @@ void UQuickTimeEventManager::OnEventEnd(int32 id, EQuickTimeEventResult result) if(event.callback.IsBound()) event.callback.Execute(result); - if(event.sequence && !_nextEvents.IsEmpty()) + if(event.sequence && !nextEvents.IsEmpty()) { ShowNextEvent(); UE_LOG(LogTemp, Log, TEXT("OnEventEnd End")); return; } - if(_events.IsEmpty()) + if(events.IsEmpty()) { - if(auto player = UCommonFunctions::GetPlayer(this)) + if(auto PC = ACustomPlayerController::Get()) { - player->onAnyKeyPressedDelegate.RemoveDynamic(this, &UQuickTimeEventManager::OnInputPressed); - player->onAnyKeyReleasedDelegate.RemoveDynamic(this, &UQuickTimeEventManager::OnInputReleased); + PC->onAnyKeyPressed.RemoveDynamic(this, &UQuickTimeEventManager::OnInputPressed); + PC->onAnyKeyReleased.RemoveDynamic(this, &UQuickTimeEventManager::OnInputReleased); } UCommonFunctions::ExitSlowMotion(); } @@ -96,29 +96,29 @@ void UQuickTimeEventManager::OnEventEnd(int32 id, EQuickTimeEventResult result) void UQuickTimeEventManager::OnInput(const FKey& key, bool released) { - for(auto eventMapping : _events) + for(auto eventMapping : events) { - if(eventMapping.Value.key == key) + if(eventMapping.Value.key != key) + continue; + + EQuickTimeEventResult result = EQuickTimeEventResult::Success; + + if(auto WM = AMainGameModeBase::GetWidgetsManager()) { - EQuickTimeEventResult result = EQuickTimeEventResult::Success; + result = WM->ProcessQuickTimeEvent(eventMapping.Key, released); - if(auto WM = AMainGameModeBase::GetWidgetsManager()) + switch(result) { - result = WM->ProcessQuickTimeEvent(eventMapping.Key, released); - - switch(result) - { - case EQuickTimeEventResult::FailedKey: // its not a failed key, but special state to do nothing (eg. holding event) - return; - default: - // the result is success or failed time and widget is self removed - break; - } + case EQuickTimeEventResult::FailedKey: // its not a failed key, but special state to do nothing (eg. holding event) + return; + default: + // the result is success or failed time and widget is self removed + break; } - - OnEventEnd(eventMapping.Key, result); - return; } + + OnEventEnd(eventMapping.Key, result); + return; } if(released) @@ -126,16 +126,16 @@ void UQuickTimeEventManager::OnInput(const FKey& key, bool released) if(auto WM = AMainGameModeBase::GetWidgetsManager()) { - while(_events.Num() > 0) + while(events.Num() > 0) { - WM->RemoveQuickTimeEvent(_events.begin()->Key); - OnEventEnd(_events.begin()->Key, EQuickTimeEventResult::FailedKey); + WM->RemoveQuickTimeEvent(events.begin()->Key); + OnEventEnd(events.begin()->Key, EQuickTimeEventResult::FailedKey); } } else { - while(_events.Num() > 0) - OnEventEnd(_events.begin()->Key, EQuickTimeEventResult::FailedKey); + while(events.Num() > 0) + OnEventEnd(events.begin()->Key, EQuickTimeEventResult::FailedKey); } } @@ -151,31 +151,31 @@ void UQuickTimeEventManager::OnInputReleased(FKey key) void UQuickTimeEventManager::OnFirstEventInit() { - if(_events.IsEmpty()) + if(!events.IsEmpty()) + return; + + if(auto PC = ACustomPlayerController::Get()) { - if(auto player = UCommonFunctions::GetPlayer(this)) - { - GetWorld()->GetTimerManager().SetTimerForNextTick([manager = this, player = player]() - { - player->onAnyKeyPressedDelegate.AddDynamic(manager, &UQuickTimeEventManager::OnInputPressed); - player->onAnyKeyReleasedDelegate.AddDynamic(manager, &UQuickTimeEventManager::OnInputReleased); - }); - } - UCommonFunctions::EnterSlowMotion(); + GetWorld()->GetTimerManager().SetTimerForNextTick([=, this]() + { + PC->onAnyKeyPressed.AddDynamic(this, &UQuickTimeEventManager::OnInputPressed); + PC->onAnyKeyReleased.AddDynamic(this, &UQuickTimeEventManager::OnInputReleased); + }); } + UCommonFunctions::EnterSlowMotion(); } void UQuickTimeEventManager::CreateEvent(FQuickTimeEventEnqueProperties& properties, bool sequence) { Event event{ properties.type, properties.key, properties.callback, sequence }; - GetWorld()->GetTimerManager().SetTimer(event.timer, [id = event.GetId(), manager = this]() + GetWorld()->GetTimerManager().SetTimer(event.timer, [id = event.GetId(), this]() { EQuickTimeEventResult result = EQuickTimeEventResult::FailedTime; if(auto WM = AMainGameModeBase::GetWidgetsManager()) result = WM->RemoveQuickTimeEvent(id); - manager->OnEventEnd(id, result); + this->OnEventEnd(id, result); }, properties.duration, false); - _events.Add(event.GetId(), event); + events.Add(event.GetId(), event); if(auto WM = AMainGameModeBase::GetWidgetsManager()) WM->ShowQuickTimeEvent(event.GetId(), properties); diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.h index bdc0006..09f828c 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/QuickTimeEvent.h @@ -60,7 +60,7 @@ public: bool sequence; private: - int32 _id; + int32 id; static int32 counter; }; @@ -89,7 +89,7 @@ protected: void OnFirstEventInit(); void CreateEvent(FQuickTimeEventEnqueProperties& properties, bool sequence); - TQueue _nextEvents; - TMap _events; - FCriticalSection _lock; + TQueue nextEvents; + TMap events; + FCriticalSection lock; }; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/SaveData.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/SaveData.h index d356364..5ffa553 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/SaveData.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/SaveData.h @@ -6,18 +6,24 @@ #include "SaveData.generated.h" +/** + * Custom game save object + */ UCLASS(BlueprintType) class USaveData : public USaveGame { GENERATED_BODY() public: + /** Level to load */ UPROPERTY(VisibleAnywhere) FName level; + /** State of the level */ UPROPERTY(VisibleAnywhere) int32 state; + /** Checkpoint object name in level */ UPROPERTY(VisibleAnywhere) FName checkpoint; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.cpp index 9a9a46d..7fb9b72 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "AutohideWidget.h" #include "Animation/WidgetAnimation.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.h index 28597e2..1cdc664 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/AutohideWidget.h @@ -6,6 +6,9 @@ #include "AutohideWidget.generated.h" +/** + * Automatically hides itself after some period + */ UCLASS() class UAutohideWidget : public UResolutionResponsiveUserWidget { diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/DialogueRowWidgetManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/DialogueRowWidgetManager.cpp index 244c9b4..f046524 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/DialogueRowWidgetManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/DialogueRowWidgetManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "DialogueRowWidgetManager.h" #include "Blueprint/WidgetTree.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/InteractableHintWidgetManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/InteractableHintWidgetManager.cpp index 0e3a7ce..da185b9 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/InteractableHintWidgetManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/InteractableHintWidgetManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "InteractableHintWidgetManager.h" #include "Blueprint/WidgetTree.h" @@ -23,10 +22,10 @@ void UInteractableHintWidgetManager::Append(const UInteractableModificator* modi return; } - if(hintsMap.Contains(modificator) || !modificator->GetMappingContext()) + if(hintsMap.Contains(modificator) || !modificator->GetMappingContext().IsValid()) return; - const auto& mappings = modificator->GetMappingContext()->GetMappings(); + const auto& mappings = modificator->GetMappingContext().LoadSynchronous()->GetMappings(); for(int32 i = hints->GetChildrenCount() - count - mappings.Num(); i < 0; ++i) { diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/JournalWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/JournalWidget.cpp index 3c7ebcf..ee24222 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/JournalWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/JournalWidget.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "JournalWidget.h" #include "Blueprint/WidgetTree.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuButtonWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuButtonWidget.cpp index b6ef69e..153fc08 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuButtonWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuButtonWidget.cpp @@ -1,5 +1,4 @@ // Oleg Petruny proprietary. - #include "MainMenuButtonWidget.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuWidget.cpp index 9943ef7..f9c190c 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/MainMenu/MainMenuWidget.cpp @@ -1,11 +1,10 @@ // Oleg Petruny proprietary. - #include "MainMenuWidget.h" #include "Animation/WidgetAnimation.h" -#include "CustomGameInstanceBase.h" +#include "CustomGameInstance.h" #include "MainGameModeBase.h" #include "MainMenuButtonWidget.h" #include "Widgets/WidgetsManager.h" @@ -14,13 +13,11 @@ bool UMainMenuWidget::Initialize() { if(ButtonLoadLastSave) { - if(auto GI = UCustomGameInstanceBase::GetGameInstance()) + auto GI = UCustomGameInstance::Get(); + if(GI && GI->saveData) { - if(GI->saveData) - { - ButtonLoadLastSave->SetIsEnabled(true); - ButtonLoadLastSave->SetRenderOpacity(1.0f); - } + ButtonLoadLastSave->SetIsEnabled(true); + ButtonLoadLastSave->SetRenderOpacity(1.0f); } } diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidget.cpp index b34b551..56923d7 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidget.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "QuickTimeEventWidget.h" #include "Animation/WidgetAnimation.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidgetManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidgetManager.cpp index dfce74d..142247c 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidgetManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/QuickTimeEventWidgetManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "QuickTimeEventWidgetManager.h" #include "Animation/UMGSequencePlayer.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.cpp index 43fe3a5..fbfedde 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "ResolutionResponsiveUserWidget.h" #include "Components/PanelSlot.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.h index b6c15f1..159a5d4 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/ResolutionResponsiveUserWidget.h @@ -3,17 +3,18 @@ #pragma once #include "Blueprint/UserWidget.h" -#include "CoreMinimal.h" #include "ResolutionResponsiveUserWidget.generated.h" +/** + * Automatically scale itself for current resolution to keep UI sizes universal. + */ UCLASS() class UResolutionResponsiveUserWidget : public UUserWidget { GENERATED_BODY() public: - //UResolutionResponsiveUserWidget(const FObjectInitializer& ObjectInitializer); virtual bool Initialize() override; virtual void BeginDestroy() override; diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.cpp index 9921317..1bf8772 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "WidgetsManager.h" #include "Blueprint/UserWidget.h" @@ -10,7 +9,7 @@ #include "Kismet/GameplayStatics.h" #include "UObject/ScriptInterface.h" -#include "CustomGameInstanceBase.h" +#include "CustomGameInstance.h" #include "Interactable/Interactable.h" #include "Interactable/Modificators/InteractableModificator.h" #include "Interactable/Modificators/InventoryInteractableModificator.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.h index 0f51e29..d421895 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WidgetsManager.h @@ -9,6 +9,11 @@ enum class EInputAnimatedWidgetAnimation : uint8; enum class EQuickTimeEventResult : uint8; +/** + * Manager/Wrapper of most of UI widgets. + * Please, don't create your own widgets but instead append manager class and us it as upper layer. + * At Init instantiate (non)permanent overlays widgets. + */ UCLASS(Blueprintable) class UWidgetsManager : public UObject { diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.cpp b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.cpp index 1216c89..e427bd5 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.cpp +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.cpp @@ -1,6 +1,5 @@ // Oleg Petruny proprietary. - #include "WorldDilationResponsiveUserWidget.h" #include "Animation/UMGSequencePlayer.h" diff --git a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.h b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.h index 243df6e..c6535bc 100644 --- a/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.h +++ b/UnrealProject/Lost_Edge/Source/Lost_Edge/Private/Widgets/WorldDilationResponsiveUserWidget.h @@ -6,6 +6,9 @@ #include "WorldDilationResponsiveUserWidget.generated.h" +/** + * Automatically update animations speed to sync with world time dilation + */ UCLASS() class UWorldDilationResponsiveUserWidget : public UUserWidget { diff --git a/VoiceGenerator/.gitignore b/VoiceGenerator/.gitignore index 7a22e39..a5d2b02 100644 --- a/VoiceGenerator/.gitignore +++ b/VoiceGenerator/.gitignore @@ -1,7 +1,9 @@ * !.gitignore !.gitattributes +!README.md !GenerateDialogue.py -!install.ps1 +!Install.ps1 +!Uninstall.ps1 !voices/ !voices/** \ No newline at end of file diff --git a/VoiceGenerator/Install.ps1 b/VoiceGenerator/Install.ps1 index ac15c7b..857e289 100644 --- a/VoiceGenerator/Install.ps1 +++ b/VoiceGenerator/Install.ps1 @@ -54,12 +54,12 @@ function Setup-Python-Environment { function Install-Espeakng { Write-Output "Installing eSpeak-ng $espeakngVersion..." Invoke-WebRequest -Uri $espeakngInstallerUrl -OutFile $espeakngInstallerPath - Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$espeakngInstallerPath`" /passive" -Wait + Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$espeakngInstallerPath`" /passive /norestart" -Wait Remove-Item $espeakngInstallerPath -Force } function Install-MsBuildTools { - Write-Output "Installing MS Build Tools $msBuildToolsVersion..." + Write-Output "Installing Visual Studio Build Tools $msBuildToolsVersion..." Invoke-WebRequest -Uri $msBuildToolsInstallerUrl -OutFile $msBuildToolsInstallerPath Start-Process -FilePath $msBuildToolsInstallerPath -ArgumentList ` "--passive --wait --norestart --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" -Wait @@ -107,5 +107,5 @@ Install-CUDA Install-PyTorch Install-Coqui mkdir output -Write-Output "Setup finished. Please restart your machine before first startup." +Write-Output "Install finished. Please restart your machine before first startup." Write-Output "To generate dialogue type in PS terminal in VoiceGenerator directory:`n 1] .\Scripts\Activate.ps1`n 2] py GenerateDialogue.py." diff --git a/VoiceGenerator/README.md b/VoiceGenerator/README.md new file mode 100644 index 0000000..04819a0 --- /dev/null +++ b/VoiceGenerator/README.md @@ -0,0 +1,32 @@ +# Voice Generator +Before using the installation is needed. \ +For generation type within directory in PowerShell: + - `.\Scripts\Activate.ps1` + - `py GenerateDialogue.py` +For your own voices create a directory with custom name containing a voice line with the same name. \ +Edit voice name in `GenerateDialogue.py` script. + +# System requirements +OS: Windows 10 or 11 \ +GPU: NVIDIA \ +Storage: ~15GB + +# Install.ps1 +By executing the PowerShell script `Install.ps1` the following packages are installed: + - [Python](https://www.python.org/downloads/) 3.11.9 + - [eSpeak-ng](https://github.com/espeak-ng/espeak-ng) 1.51 + - [Visual Studio Build Tools](https://visualstudio.microsoft.com/cs/downloads/?q=build+tools) 17 module "Desktop development with C++" + - [CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) 12.4.1 + - [PyTorch CUDA](https://pytorch.org/get-started/locally/) 12.4 + - [Coqui TTS](https://github.com/idiap/coqui-ai-TTS) 0.25.1 + - [Suno-ai/bark](https://github.com/suno-ai/bark) +It's recommended to run installation script as administrator and restart machine after install completion. + +# Uninstall.ps1 +The uninstall script will try to remove most of the files created during installation. \ +The following packages/data aren't removed: + - Python + - Visual Studio Installer + - voices/ + - _Something will of course left_ +It's recommended to run uninstallat script as administrator and restart machine after uninstall completion. diff --git a/VoiceGenerator/Uninstall.ps1 b/VoiceGenerator/Uninstall.ps1 new file mode 100644 index 0000000..24fc5d2 --- /dev/null +++ b/VoiceGenerator/Uninstall.ps1 @@ -0,0 +1,44 @@ +$msBuildToolsVersion = "17" +$msBuildToolsInstallerUrl = "https://aka.ms/vs/${msBuildToolsVersion}/release/vs_BuildTools.exe" +$msBuildToolsInstallerPath = "$env:TEMP\vs_BuildTools${msBuildToolsVersion}.exe" + +function Uninstall-Espeakng { + Write-Output "Uninstalling eSpeak NG..." + $app = (Get-WmiObject -Class Win32_Product | Where-Object{$_.Name -like "*eSpeak NG*"}) + Start-Process -FilePath "msiexec.exe" -ArgumentList "/x ${app.IdentifyingNumber} /passive /norestart" +} + +function Uninstall-MsBuildTools { + Write-Output "Uninstalling Visual Studio Build Tools..." + Invoke-WebRequest -Uri $msBuildToolsInstallerUrl -OutFile $msBuildToolsInstallerPath + Start-Process -FilePath $msBuildToolsInstallerPath -ArgumentList ` + "--remove Microsoft.VisualStudio.Workload.VCTools --passive --wait" -Wait + Remove-Item $msBuildToolsInstallerPath -Force +} + +function Uninstall-CUDA { + Write-Output "Uninstalling CUDA Toolkit..." + $uninstall = (gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" ` + | foreach { gp $_.PSPath } | ? { $_ -like "*CUDA Toolkit*" } | select UninstallString) + $uninstall = ($uninstall.UninstallString -Replace '^"[^"]+"\s+', '') + Start-Process -FilePath "rundll32.exe" -ArgumentList "$uninstall -silent -deviceinitiated" +} + +function Remove-Local-Files { + Write-Output "Removing local files..." + $ExcludeFiles = @(".gitattributes", ".gitignore", "README.md", "GenerateDialogue.py", ` + "Install.ps1", "Uninstall.ps1", "voices") + $FilesToDelete = Get-ChildItem -Path . -File | Where-Object { $_.Name -notin $ExcludeFiles } + foreach ($File in $FilesToDelete) { + Remove-Item -Path $File.FullName -Force + } +} + + + +Write-Output "Starting voice environment uninstall process." +Uninstall-Espeakng +Uninstall-MsBuildTools +Uninstall-CUDA +Remove-Local-Files +Write-Output "Uninstall finished. Please restart your machine to clear temp files."